From c8084a89bd91b05f51a36bff61f63a94c800b0d6 Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Sun, 19 Jan 2025 16:43:12 +0800 Subject: [PATCH 0001/1090] Input: wdt87xx_i2c - fix compiler warning As reported by the kernel test robot, the following warning occur: >> drivers/input/touchscreen/wdt87xx_i2c.c:1166:36: warning: 'wdt87xx_acpi_id' defined but not used [-Wunused-const-variable=] 1166 | static const struct acpi_device_id wdt87xx_acpi_id[] = { | ^~~~~~~~~~~~~~~ The 'wdt87xx_acpi_id' array is only used when CONFIG_ACPI is enabled. Wrapping its definition and 'MODULE_DEVICE_TABLE' in '#ifdef CONFIG_ACPI' prevents a compiler warning when ACPI is disabled. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501181549.uzdlBwuN-lkp@intel.com/ Signed-off-by: Yu-Chun Lin Link: https://lore.kernel.org/r/20250119084312.1851486-1-eleanor15x@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wdt87xx_i2c.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 27941245e962..88d376090e6e 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -1153,11 +1153,13 @@ static const struct i2c_device_id wdt87xx_dev_id[] = { }; MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id wdt87xx_acpi_id[] = { { "WDHT0001", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); +#endif static struct i2c_driver wdt87xx_driver = { .probe = wdt87xx_ts_probe, From 5b4288792ff246cf2bda0c81cebcc02d1f631ca3 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 22 Jan 2025 18:41:26 +0200 Subject: [PATCH 0002/1090] ASoC: cpcap: Implement .set_bias_level With VAUDIO regulator being always on, we have to put it in low-power mode when codec is not in use to decrease power usage. Do so by implementing driver .set_bias_level callback. Signed-off-by: Ivaylo Dimitrov Link: https://patch.msgid.link/20250122164129.807247-3-ivo.g.dimitrov.75@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cpcap.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index 04304a7ad915..53f549ede6a6 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ struct cpcap_audio { int codec_clk_id; int codec_freq; int codec_format; + struct regulator *vaudio; }; static int cpcap_st_workaround(struct snd_soc_dapm_widget *w, @@ -1637,6 +1639,11 @@ static int cpcap_soc_probe(struct snd_soc_component *component) snd_soc_component_set_drvdata(component, cpcap); cpcap->component = component; + cpcap->vaudio = devm_regulator_get(component->dev, "VAUDIO"); + if (IS_ERR(cpcap->vaudio)) + return dev_err_probe(component->dev, PTR_ERR(cpcap->vaudio), + "Cannot get VAUDIO regulator\n"); + cpcap->regmap = dev_get_regmap(component->dev->parent, NULL); if (!cpcap->regmap) return -ENODEV; @@ -1649,6 +1656,27 @@ static int cpcap_soc_probe(struct snd_soc_component *component) return cpcap_audio_reset(component, false); } +static int cpcap_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + + switch (level) { + case SND_SOC_BIAS_OFF: + break; + case SND_SOC_BIAS_PREPARE: + regulator_set_mode(cpcap->vaudio, REGULATOR_MODE_NORMAL); + break; + case SND_SOC_BIAS_STANDBY: + regulator_set_mode(cpcap->vaudio, REGULATOR_MODE_STANDBY); + break; + case SND_SOC_BIAS_ON: + break; + } + + return 0; +} + static const struct snd_soc_component_driver soc_codec_dev_cpcap = { .probe = cpcap_soc_probe, .controls = cpcap_snd_controls, @@ -1657,6 +1685,7 @@ static const struct snd_soc_component_driver soc_codec_dev_cpcap = { .num_dapm_widgets = ARRAY_SIZE(cpcap_dapm_widgets), .dapm_routes = intercon, .num_dapm_routes = ARRAY_SIZE(intercon), + .set_bias_level = cpcap_set_bias_level, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, From 02d4a97ce30c0494ce6a614cd54d583caa0f8016 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 22 Jan 2025 18:41:27 +0200 Subject: [PATCH 0003/1090] dt-bindings: mfd: motorola-cpcap: Document audio-codec interrupts Add DT binding for the audio-codec headset detection interrupts. Signed-off-by: Ivaylo Dimitrov Link: https://patch.msgid.link/20250122164129.807247-4-ivo.g.dimitrov.75@gmail.com Acked-by: Rob Herring (Arm) Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/mfd/motorola-cpcap.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt index 190230216de8..f00827c9b67f 100644 --- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt +++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt @@ -31,6 +31,10 @@ node must be named "audio-codec". Required properties for the audio-codec subnode: - #sound-dai-cells = <1>; +- interrupts : should contain jack detection interrupts, with headset + detect interrupt matching "hs" and microphone bias 2 + detect interrupt matching "mb2" in interrupt-names. +- interrupt-names : Contains "hs", "mb2" The audio-codec provides two DAIs. The first one is connected to the Stereo HiFi DAC and the second one is connected to the Voice DAC. @@ -52,6 +56,8 @@ Example: audio-codec { #sound-dai-cells = <1>; + interrupts-extended = <&cpcap 9 0>, <&cpcap 10 0>; + interrupt-names = "hs", "mb2"; /* HiFi */ port@0 { From 7ed1b265021dd13ce5619501b388e489ddc8e204 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 22 Jan 2025 18:41:29 +0200 Subject: [PATCH 0004/1090] ASoC: cpcap: Implement jack detection cpcap has headphones/microphone and PTT button detection logic, implement code to support it. Signed-off-by: Ivaylo Dimitrov Link: https://patch.msgid.link/20250122164129.807247-6-ivo.g.dimitrov.75@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cpcap.c | 171 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index 53f549ede6a6..3eb862643b53 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -14,9 +14,18 @@ #include #include #include +#include +#include #include #include +/* Register 8 - CPCAP_REG_INTS1 --- Interrupt Sense 1 */ +#define CPCAP_BIT_HS_S 9 /* Headset */ +#define CPCAP_BIT_MB2_S 10 /* Mic Bias2 */ + +/* Register 9 - CPCAP_REG_INTS2 --- Interrupt Sense 2 */ +#define CPCAP_BIT_PTT_S 11 /* Push To Talk */ + /* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */ #define CPCAP_BIT_AUDIO_LOW_PWR 6 #define CPCAP_BIT_AUD_LOWPWR_SPEED 5 @@ -262,6 +271,9 @@ struct cpcap_audio { int codec_freq; int codec_format; struct regulator *vaudio; + int hsirq; + int mb2irq; + struct snd_soc_jack jack; }; static int cpcap_st_workaround(struct snd_soc_dapm_widget *w, @@ -1628,14 +1640,105 @@ static int cpcap_audio_reset(struct snd_soc_component *component, return 0; } +static irqreturn_t cpcap_hs_irq_thread(int irq, void *data) +{ + struct snd_soc_component *component = data; + struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + struct regmap *regmap = cpcap->regmap; + int status = 0; + int mask = SND_JACK_HEADSET; + int val; + + if (!regmap_test_bits(regmap, CPCAP_REG_INTS1, BIT(CPCAP_BIT_HS_S))) { + val = BIT(CPCAP_BIT_MB_ON2) | BIT(CPCAP_BIT_PTT_CMP_EN); + regmap_update_bits(regmap, CPCAP_REG_TXI, val, val); + + val = BIT(CPCAP_BIT_ST_HS_CP_EN); + regmap_update_bits(regmap, CPCAP_REG_RXOA, val, val); + + regulator_set_mode(cpcap->vaudio, REGULATOR_MODE_NORMAL); + + /* Give PTTS time to settle */ + msleep(20); + + if (!regmap_test_bits(regmap, CPCAP_REG_INTS2, + BIT(CPCAP_BIT_PTT_S))) { + /* Headphones detected. (May also be a headset with the + * MFB pressed.) + */ + status = SND_JACK_HEADPHONE; + dev_info(component->dev, "HP plugged in\n"); + } else if (regmap_test_bits(regmap, CPCAP_REG_INTS1, + BIT(CPCAP_BIT_MB2_S)) == 1) { + status = SND_JACK_HEADSET; + dev_info(component->dev, "HS plugged in\n"); + } else + dev_info(component->dev, "Unsupported HS plugged in\n"); + } else { + bool mic = cpcap->jack.status & SND_JACK_MICROPHONE; + + dev_info(component->dev, "H%s disconnect\n", mic ? "S" : "P"); + val = BIT(CPCAP_BIT_MB_ON2) | BIT(CPCAP_BIT_PTT_CMP_EN); + regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI, val, 0); + + val = BIT(CPCAP_BIT_ST_HS_CP_EN); + regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA, val, 0); + + regulator_set_mode(cpcap->vaudio, REGULATOR_MODE_STANDBY); + + mask |= SND_JACK_BTN_0; + } + + snd_soc_jack_report(&cpcap->jack, status, mask); + + return IRQ_HANDLED; +} + +static irqreturn_t cpcap_mb2_irq_thread(int irq, void *data) +{ + struct snd_soc_component *component = data; + struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + struct regmap *regmap = cpcap->regmap; + int status = 0; + int mb2; + int ptt; + + if (regmap_test_bits(regmap, CPCAP_REG_INTS1, BIT(CPCAP_BIT_HS_S)) == 1) + return IRQ_HANDLED; + + mb2 = regmap_test_bits(regmap, CPCAP_REG_INTS1, BIT(CPCAP_BIT_MB2_S)); + ptt = regmap_test_bits(regmap, CPCAP_REG_INTS2, BIT(CPCAP_BIT_PTT_S)); + + /* Initial detection might have been with MFB pressed */ + if (!(cpcap->jack.status & SND_JACK_MICROPHONE)) { + if (ptt == 1 && mb2 == 1) { + dev_info(component->dev, "MIC plugged in\n"); + snd_soc_jack_report(&cpcap->jack, SND_JACK_MICROPHONE, + SND_JACK_MICROPHONE); + } + + return IRQ_HANDLED; + } + + if (!mb2 || !ptt) + status = SND_JACK_BTN_0; + + snd_soc_jack_report(&cpcap->jack, status, SND_JACK_BTN_0); + + return IRQ_HANDLED; +} + static int cpcap_soc_probe(struct snd_soc_component *component) { + struct platform_device *pdev = to_platform_device(component->dev); + struct snd_soc_card *card = component->card; struct cpcap_audio *cpcap; int err; cpcap = devm_kzalloc(component->dev, sizeof(*cpcap), GFP_KERNEL); if (!cpcap) return -ENOMEM; + snd_soc_component_set_drvdata(component, cpcap); cpcap->component = component; @@ -1644,6 +1747,16 @@ static int cpcap_soc_probe(struct snd_soc_component *component) return dev_err_probe(component->dev, PTR_ERR(cpcap->vaudio), "Cannot get VAUDIO regulator\n"); + err = snd_soc_card_jack_new(card, "Headphones", + SND_JACK_HEADSET | SND_JACK_BTN_0, + &cpcap->jack); + if (err < 0) { + dev_err(component->dev, "Cannot create HS jack: %i\n", err); + return err; + } + + snd_jack_set_key(cpcap->jack.jack, SND_JACK_BTN_0, KEY_MEDIA); + cpcap->regmap = dev_get_regmap(component->dev->parent, NULL); if (!cpcap->regmap) return -ENODEV; @@ -1653,7 +1766,58 @@ static int cpcap_soc_probe(struct snd_soc_component *component) if (err) return err; - return cpcap_audio_reset(component, false); + cpcap->hsirq = platform_get_irq_byname(pdev, "hs"); + if (cpcap->hsirq < 0) + return cpcap->hsirq; + + err = devm_request_threaded_irq(component->dev, cpcap->hsirq, NULL, + cpcap_hs_irq_thread, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "cpcap-codec-hs", + component); + if (err) { + dev_warn(component->dev, "no HS irq%i: %i\n", + cpcap->hsirq, err); + return err; + } + + cpcap->mb2irq = platform_get_irq_byname(pdev, "mb2"); + if (cpcap->mb2irq < 0) + return cpcap->mb2irq; + + err = devm_request_threaded_irq(component->dev, cpcap->mb2irq, NULL, + cpcap_mb2_irq_thread, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "cpcap-codec-mb2", + component); + if (err) { + dev_warn(component->dev, "no MB2 irq%i: %i\n", + cpcap->mb2irq, err); + return err; + } + + err = cpcap_audio_reset(component, false); + if (err) + return err; + + cpcap_hs_irq_thread(cpcap->hsirq, component); + + enable_irq_wake(cpcap->hsirq); + enable_irq_wake(cpcap->mb2irq); + + return 0; +} + +static void cpcap_soc_remove(struct snd_soc_component *component) +{ + struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + + disable_irq_wake(cpcap->hsirq); + disable_irq_wake(cpcap->mb2irq); } static int cpcap_set_bias_level(struct snd_soc_component *component, @@ -1661,6 +1825,10 @@ static int cpcap_set_bias_level(struct snd_soc_component *component, { struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component); + /* VAIDIO should be kept in normal mode in order MIC/PTT to work */ + if (cpcap->jack.status & SND_JACK_MICROPHONE) + return 0; + switch (level) { case SND_SOC_BIAS_OFF: break; @@ -1679,6 +1847,7 @@ static int cpcap_set_bias_level(struct snd_soc_component *component, static const struct snd_soc_component_driver soc_codec_dev_cpcap = { .probe = cpcap_soc_probe, + .remove = cpcap_soc_remove, .controls = cpcap_snd_controls, .num_controls = ARRAY_SIZE(cpcap_snd_controls), .dapm_widgets = cpcap_dapm_widgets, From c9ccb88f534ca760d06590b67571c353a2f0cbcd Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sat, 1 Feb 2025 12:43:24 +0100 Subject: [PATCH 0005/1090] Input: ads7846 - fix gpiod allocation commit 767d83361aaa ("Input: ads7846 - Convert to use software nodes") has simplified the code but accidentially converted a devm_gpiod_get() to gpiod_get(). This leaves the gpio reserved on module remove and the driver can no longer be loaded again. Fixes: 767d83361aaa ("Input: ads7846 - Convert to use software nodes") Cc: stable@vger.kernel.org Signed-off-by: H. Nikolaus Schaller Link: https://lore.kernel.org/r/6e9b143f19cdfda835711a8a7a3966e5a2494cff.1738410204.git.hns@goldelico.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 066dc04003fa..67264c5b49cb 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1021,7 +1021,7 @@ static int ads7846_setup_pendown(struct spi_device *spi, if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; } else { - ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN); + ts->gpio_pendown = devm_gpiod_get(&spi->dev, "pendown", GPIOD_IN); if (IS_ERR(ts->gpio_pendown)) { dev_err(&spi->dev, "failed to request pendown GPIO\n"); return PTR_ERR(ts->gpio_pendown); From c9e9aa80022c6db71bc097a621a6145f39aa0ade Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Sat, 1 Feb 2025 00:50:21 +0000 Subject: [PATCH 0006/1090] ASoC: mediatek: Remove unused mtk_memif_set_rate mtk_memif_set_rate() has been unused since it was added in the 2019 commit 9cdf85a19b3a ("ASoC: mediatek: common: add some helpers to control mtk_memif") Remove it. (The _substream version is used, and is left in) Signed-off-by: Dr. David Alan Gilbert Link: https://patch.msgid.link/20250201005021.447726-1-linux@treblig.org Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-afe-fe-dai.c | 20 -------------------- sound/soc/mediatek/common/mtk-afe-fe-dai.h | 2 -- 2 files changed, 22 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 3044d9ab3d4d..3809068f5620 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -500,26 +500,6 @@ static int mtk_memif_set_rate_fs(struct mtk_base_afe *afe, return 0; } -int mtk_memif_set_rate(struct mtk_base_afe *afe, - int id, unsigned int rate) -{ - int fs = 0; - - if (!afe->get_dai_fs) { - dev_err(afe->dev, "%s(), error, afe->get_dai_fs == NULL\n", - __func__); - return -EINVAL; - } - - fs = afe->get_dai_fs(afe, id, rate); - - if (fs < 0) - return -EINVAL; - - return mtk_memif_set_rate_fs(afe, id, fs); -} -EXPORT_SYMBOL_GPL(mtk_memif_set_rate); - int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, int id, unsigned int rate) { diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.h b/sound/soc/mediatek/common/mtk-afe-fe-dai.h index 8cec90671827..b6d0f2b27e86 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.h @@ -42,8 +42,6 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, size_t dma_bytes); int mtk_memif_set_channel(struct mtk_base_afe *afe, int id, unsigned int channel); -int mtk_memif_set_rate(struct mtk_base_afe *afe, - int id, unsigned int rate); int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, int id, unsigned int rate); int mtk_memif_set_format(struct mtk_base_afe *afe, From f9a5c4b6afc79073491acdab7f1e943ee3a19fbb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 7 Jan 2025 15:44:07 +0000 Subject: [PATCH 0007/1090] ASoC: rt722-sdca: Add some missing readable registers Add a few missing registers from the readable register callback. Suggested-by: Shuming Fan Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250107154408.814455-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt722-sdca-sdw.c | 49 +++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 25fc13687bc8..602547c5fb3f 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -28,9 +28,50 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) 0): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, 0): - case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, - 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, - RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU03, RT722_SDCA_CTL_SELECTED_MODE, + 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_XU0D, + RT722_SDCA_CTL_SELECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, + RT722_SDCA_CTL_FU_MUTE, CH_01) ... + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, + RT722_SDCA_CTL_FU_MUTE, CH_04): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, + RT722_SDCA_CTL_VENDOR_DEF, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... + SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_L) ... + SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, + RT722_SDCA_CTL_VENDOR_DEF, CH_08): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, + RT722_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, + RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: return true; default: @@ -74,6 +115,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x5600000 ... 0x5600007: case 0x5700000 ... 0x5700004: case 0x5800000 ... 0x5800004: + case 0x5810000: case 0x5b00003: case 0x5c00011: case 0x5d00006: @@ -81,6 +123,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x5f00030: case 0x6100000 ... 0x6100051: case 0x6100055 ... 0x6100057: + case 0x6100060: case 0x6100062: case 0x6100064 ... 0x6100065: case 0x6100067: From 299ce4beaf714abe76e3ad106f2e745748f693e9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 7 Jan 2025 15:44:08 +0000 Subject: [PATCH 0008/1090] ASoC: rt722-sdca: Make use of new expanded MBQ regmap Now the MBQ regmap implementation handles multiple sizes, this driver can combine its two register maps into one. So remove mbq_regmap and combine all the registers into regmap. Also as rt722_sdca_adc_mux_get/put() only exist to access mbq_regmap, rather than doing any processing, these can now be dropped and the normal DAPM helpers used. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250107154408.814455-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt722-sdca-sdw.c | 81 ++++++------------ sound/soc/codecs/rt722-sdca-sdw.h | 99 +++++++++++----------- sound/soc/codecs/rt722-sdca.c | 135 +++++++----------------------- sound/soc/codecs/rt722-sdca.h | 4 +- 4 files changed, 105 insertions(+), 214 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 602547c5fb3f..2b0f82697b47 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -16,7 +16,7 @@ #include "rt722-sdca.h" #include "rt722-sdca-sdw.h" -static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) +static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg) { switch (reg) { case 0x2f01 ... 0x2f0a: @@ -73,32 +73,7 @@ static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: - return true; - default: - return false; - } -} - -static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x2f01: - case 0x2f54: - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, - 0): - case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, - 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, - RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): - case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: - return true; - default: - return false; - } -} - -static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { + return 1; case 0x2000000 ... 0x2000024: case 0x2000029 ... 0x200004a: case 0x2000051 ... 0x2000052: @@ -151,15 +126,32 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re RT722_SDCA_CTL_FU_CH_GAIN, CH_L): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_R): - return true; + return 2; default: - return false; + return 0; } } -static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) +static struct regmap_sdw_mbq_cfg rt722_mbq_config = { + .mbq_size = rt722_sdca_mbq_size, +}; + +static bool rt722_sdca_readable_register(struct device *dev, unsigned int reg) +{ + return rt722_sdca_mbq_size(dev, reg) > 0; +} + +static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case 0x2f01: + case 0x2f54: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_GE49, RT722_SDCA_CTL_DETECTED_MODE, + 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, RT722_SDCA_CTL_HIDTX_CURRENT_OWNER, + 0) ... SDW_SDCA_CTL(FUNC_NUM_HID, RT722_SDCA_ENT_HID01, + RT722_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: case 0x2000000: case 0x200000d: case 0x2000019: @@ -178,7 +170,7 @@ static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int re static const struct regmap_config rt722_sdca_regmap = { .reg_bits = 32, - .val_bits = 8, + .val_bits = 16, .readable_reg = rt722_sdca_readable_register, .volatile_reg = rt722_sdca_volatile_register, .max_register = 0x44ffffff, @@ -189,20 +181,6 @@ static const struct regmap_config rt722_sdca_regmap = { .use_single_write = true, }; -static const struct regmap_config rt722_sdca_mbq_regmap = { - .name = "sdw-mbq", - .reg_bits = 32, - .val_bits = 16, - .readable_reg = rt722_sdca_mbq_readable_register, - .volatile_reg = rt722_sdca_mbq_volatile_register, - .max_register = 0x41000312, - .reg_defaults = rt722_sdca_mbq_defaults, - .num_reg_defaults = ARRAY_SIZE(rt722_sdca_mbq_defaults), - .cache_type = REGCACHE_MAPLE, - .use_single_read = true, - .use_single_write = true, -}; - static int rt722_sdca_update_status(struct sdw_slave *slave, enum sdw_slave_status status) { @@ -412,18 +390,14 @@ static const struct sdw_slave_ops rt722_sdca_slave_ops = { static int rt722_sdca_sdw_probe(struct sdw_slave *slave, const struct sdw_device_id *id) { - struct regmap *regmap, *mbq_regmap; + struct regmap *regmap; /* Regmap Initialization */ - mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt722_sdca_mbq_regmap); - if (IS_ERR(mbq_regmap)) - return PTR_ERR(mbq_regmap); - - regmap = devm_regmap_init_sdw(slave, &rt722_sdca_regmap); + regmap = devm_regmap_init_sdw_mbq_cfg(slave, &rt722_sdca_regmap, &rt722_mbq_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); - return rt722_sdca_init(&slave->dev, regmap, mbq_regmap, slave); + return rt722_sdca_init(&slave->dev, regmap, slave); } static int rt722_sdca_sdw_remove(struct sdw_slave *slave) @@ -461,7 +435,6 @@ static int __maybe_unused rt722_sdca_dev_suspend(struct device *dev) cancel_delayed_work_sync(&rt722->jack_btn_check_work); regcache_cache_only(rt722->regmap, true); - regcache_cache_only(rt722->mbq_regmap, true); return 0; } @@ -531,8 +504,6 @@ regmap_sync: slave->unattach_request = 0; regcache_cache_only(rt722->regmap, false); regcache_sync(rt722->regmap); - regcache_cache_only(rt722->mbq_regmap, false); - regcache_sync(rt722->mbq_regmap); return 0; } diff --git a/sound/soc/codecs/rt722-sdca-sdw.h b/sound/soc/codecs/rt722-sdca-sdw.h index 5b43e86f75d1..80b014456940 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.h +++ b/sound/soc/codecs/rt722-sdca-sdw.h @@ -31,50 +31,9 @@ static const struct reg_default rt722_sdca_reg_defaults[] = { { 0x2f5b, 0x07 }, { 0x2f5c, 0x27 }, { 0x2f5d, 0x07 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, RT722_SDCA_CTL_REQ_POWER_STATE, - 0), 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, RT722_SDCA_CTL_REQ_POWER_STATE, - 0), 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, - 0), 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_01), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_02), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_03), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_04), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, RT722_SDCA_CTL_REQ_POWER_STATE, 0), - 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, RT722_SDCA_CTL_VENDOR_DEF, 0), - 0x00 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), - 0x09 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_L), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_R), - 0x01 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_REQ_POWER_STATE, 0), - 0x03 }, - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, RT722_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, -}; - -static const struct reg_default rt722_sdca_mbq_defaults[] = { { 0x200003c, 0xc214 }, { 0x2000046, 0x8004 }, + { 0x5810000, 0x702d }, { 0x6100006, 0x0005 }, { 0x6100010, 0x2630 }, { 0x6100011, 0x152f }, @@ -86,27 +45,34 @@ static const struct reg_default rt722_sdca_mbq_defaults[] = { { 0x6100028, 0x2a2a }, { 0x6100029, 0x4141 }, { 0x6100055, 0x0000 }, - { 0x5810000, 0x702d }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU05, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_USER_FU0F, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE12, RT722_SDCA_CTL_REQ_POWER_STATE, + 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS01, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_CS11, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PDE40, RT722_SDCA_CTL_REQ_POWER_STATE, + 0), 0x03 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT722_SDCA_ENT_PLATFORM_FU44, RT722_SDCA_CTL_FU_CH_GAIN, CH_R), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_01), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_02), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_03), 0x0000 }, - { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, - CH_04), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_02), @@ -115,10 +81,41 @@ static const struct reg_default rt722_sdca_mbq_defaults[] = { 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_FU15, RT722_SDCA_CTL_FU_CH_GAIN, CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_01), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_02), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_03), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_MUTE, CH_04), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_01), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_02), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_03), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_USER_FU1E, RT722_SDCA_CTL_FU_VOLUME, + CH_04), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_PDE2A, RT722_SDCA_CTL_REQ_POWER_STATE, 0), + 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_CS1F, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, + 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT722_SDCA_ENT_IT26, RT722_SDCA_CTL_VENDOR_DEF, 0), + 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_L), + 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_MUTE, CH_R), + 0x01 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_REQ_POWER_STATE, 0), + 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_OT23, RT722_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, }; #endif /* __RT722_SDW_H__ */ diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index e17a142d03b9..f093ce841b3f 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -25,11 +25,13 @@ #include "rt722-sdca.h" +#define RT722_NID_ADDR(nid, reg) ((nid) << 20 | (reg)) + int rt722_sdca_index_write(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int value) { - struct regmap *regmap = rt722->mbq_regmap; - unsigned int addr = (nid << 20) | reg; + struct regmap *regmap = rt722->regmap; + unsigned int addr = RT722_NID_ADDR(nid, reg); int ret; ret = regmap_write(regmap, addr, value); @@ -45,8 +47,8 @@ int rt722_sdca_index_read(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int *value) { int ret; - struct regmap *regmap = rt722->mbq_regmap; - unsigned int addr = (nid << 20) | reg; + struct regmap *regmap = rt722->regmap; + unsigned int addr = RT722_NID_ADDR(nid, reg); ret = regmap_read(regmap, addr, value); if (ret < 0) @@ -361,8 +363,8 @@ static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol, strstr(ucontrol->id.name, "FU0F Capture Volume")) adc_vol_flag = 1; - regmap_read(rt722->mbq_regmap, mc->reg, &lvalue); - regmap_read(rt722->mbq_regmap, mc->rreg, &rvalue); + regmap_read(rt722->regmap, mc->reg, &lvalue); + regmap_read(rt722->regmap, mc->rreg, &rvalue); /* L Channel */ gain_l_val = ucontrol->value.integer.value[0]; @@ -402,13 +404,13 @@ static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol, return 0; /* Lch*/ - regmap_write(rt722->mbq_regmap, mc->reg, gain_l_val); + regmap_write(rt722->regmap, mc->reg, gain_l_val); /* Rch */ - regmap_write(rt722->mbq_regmap, mc->rreg, gain_r_val); + regmap_write(rt722->regmap, mc->rreg, gain_r_val); - regmap_read(rt722->mbq_regmap, mc->reg, &read_l); - regmap_read(rt722->mbq_regmap, mc->rreg, &read_r); + regmap_read(rt722->regmap, mc->reg, &read_l); + regmap_read(rt722->regmap, mc->rreg, &read_r); if (read_r == gain_r_val && read_l == gain_l_val) return changed; @@ -431,8 +433,8 @@ static int rt722_sdca_set_gain_get(struct snd_kcontrol *kcontrol, strstr(ucontrol->id.name, "FU0F Capture Volume")) adc_vol_flag = 1; - regmap_read(rt722->mbq_regmap, mc->reg, &read_l); - regmap_read(rt722->mbq_regmap, mc->rreg, &read_r); + regmap_read(rt722->regmap, mc->reg, &read_l); + regmap_read(rt722->regmap, mc->rreg, &read_r); if (mc->shift == 8) /* boost gain */ ctl_l = read_l / tendB; @@ -604,7 +606,7 @@ static int rt722_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, /* check all channels */ for (i = 0; i < p->count; i++) { - regmap_read(rt722->mbq_regmap, p->reg_base + i, ®value); + regmap_read(rt722->regmap, p->reg_base + i, ®value); if (!adc_vol_flag) /* boost gain */ ctl = regvalue / boost_step; @@ -637,7 +639,7 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, /* check all channels */ for (i = 0; i < p->count; i++) { - regmap_read(rt722->mbq_regmap, p->reg_base + i, ®value[i]); + regmap_read(rt722->regmap, p->reg_base + i, ®value[i]); gain_val[i] = ucontrol->value.integer.value[i]; if (gain_val[i] > p->max) @@ -658,7 +660,7 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, return 0; for (i = 0; i < p->count; i++) { - err = regmap_write(rt722->mbq_regmap, p->reg_base + i, gain_val[i]); + err = regmap_write(rt722->regmap, p->reg_base + i, gain_val[i]); if (err < 0) dev_err(&rt722->slave->dev, "%s: %#08x can't be set\n", __func__, p->reg_base + i); @@ -739,77 +741,6 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = { 4, 3, boost_vol_tlv), }; -static int rt722_sdca_adc_mux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); - unsigned int val = 0, mask_sft; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - rt722_sdca_index_read(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, &val); - - ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; - - return 0; -} - -static int rt722_sdca_adc_mux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct snd_soc_dapm_context *dapm = - snd_soc_dapm_kcontrol_dapm(kcontrol); - struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int *item = ucontrol->value.enumerated.item; - unsigned int val, val2 = 0, change, mask_sft; - - if (item[0] >= e->items) - return -EINVAL; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; - - rt722_sdca_index_read(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, &val2); - val2 = (0x7 << mask_sft) & val2; - - if (val == val2) - change = 0; - else - change = 1; - - if (change) - rt722_sdca_index_update_bits(rt722, RT722_VENDOR_HDA_CTL, - RT722_HDA_LEGACY_MUX_CTL0, 0x7 << mask_sft, - val << mask_sft); - - snd_soc_dapm_mux_update_power(dapm, kcontrol, - item[0], e, NULL); - - return change; -} - static const char * const adc22_mux_text[] = { "MIC2", "LINE1", @@ -821,26 +752,26 @@ static const char * const adc07_10_mux_text[] = { "DMIC2", }; -static SOC_ENUM_SINGLE_DECL( - rt722_adc22_enum, SND_SOC_NOPM, 0, adc22_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc22_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 12, adc22_mux_text); -static SOC_ENUM_SINGLE_DECL( - rt722_adc24_enum, SND_SOC_NOPM, 0, adc07_10_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc24_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 4, adc07_10_mux_text); -static SOC_ENUM_SINGLE_DECL( - rt722_adc25_enum, SND_SOC_NOPM, 0, adc07_10_mux_text); +static SOC_ENUM_SINGLE_DECL(rt722_adc25_enum, + RT722_NID_ADDR(RT722_VENDOR_HDA_CTL, RT722_HDA_LEGACY_MUX_CTL0), + 0, adc07_10_mux_text); static const struct snd_kcontrol_new rt722_sdca_adc22_mux = - SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt722_adc22_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 22 Mux", rt722_adc22_enum); static const struct snd_kcontrol_new rt722_sdca_adc24_mux = - SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt722_adc24_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 24 Mux", rt722_adc24_enum); static const struct snd_kcontrol_new rt722_sdca_adc25_mux = - SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt722_adc25_enum, - rt722_sdca_adc_mux_get, rt722_sdca_adc_mux_put); + SOC_DAPM_ENUM("ADC 25 Mux", rt722_adc25_enum); static int rt722_sdca_fu42_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1335,8 +1266,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = { } }; -int rt722_sdca_init(struct device *dev, struct regmap *regmap, - struct regmap *mbq_regmap, struct sdw_slave *slave) +int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave) { struct rt722_sdca_priv *rt722; @@ -1347,7 +1277,6 @@ int rt722_sdca_init(struct device *dev, struct regmap *regmap, dev_set_drvdata(dev, rt722); rt722->slave = slave; rt722->regmap = regmap; - rt722->mbq_regmap = mbq_regmap; mutex_init(&rt722->calibrate_mutex); mutex_init(&rt722->disable_irq_lock); @@ -1521,8 +1450,6 @@ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) if (rt722->first_hw_init) { regcache_cache_only(rt722->regmap, false); regcache_cache_bypass(rt722->regmap, true); - regcache_cache_only(rt722->mbq_regmap, false); - regcache_cache_bypass(rt722->mbq_regmap, true); } else { /* * PM runtime is only enabled when a Slave reports as Attached @@ -1550,8 +1477,6 @@ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) if (rt722->first_hw_init) { regcache_cache_bypass(rt722->regmap, false); regcache_mark_dirty(rt722->regmap); - regcache_cache_bypass(rt722->mbq_regmap, false); - regcache_mark_dirty(rt722->mbq_regmap); } else rt722->first_hw_init = true; diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h index 2464361a7958..04c3b4232ef3 100644 --- a/sound/soc/codecs/rt722-sdca.h +++ b/sound/soc/codecs/rt722-sdca.h @@ -17,7 +17,6 @@ struct rt722_sdca_priv { struct regmap *regmap; - struct regmap *mbq_regmap; struct snd_soc_component *component; struct sdw_slave *slave; struct sdw_bus_params params; @@ -229,8 +228,7 @@ enum rt722_sdca_jd_src { }; int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave); -int rt722_sdca_init(struct device *dev, struct regmap *regmap, - struct regmap *mbq_regmap, struct sdw_slave *slave); +int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave); int rt722_sdca_index_write(struct rt722_sdca_priv *rt722, unsigned int nid, unsigned int reg, unsigned int value); int rt722_sdca_index_read(struct rt722_sdca_priv *rt722, From 4a91fe4c0d683c56044579fb263c660f5d18efac Mon Sep 17 00:00:00 2001 From: Sheetal Date: Mon, 3 Feb 2025 10:53:04 +0000 Subject: [PATCH 0009/1090] ASoC: tegra: Add interconnect support Add interconnect framework support to set required audio bandwidth based on PCM device usage. The maximum bandwidth is determined by the number of APE PCM devices and maximum audio format supported. If interconnect property is not defined or INTERCONNECT config is not enabled then the audio usecase will still function. Validate bandwidth updates by reading the interconnect summary sysfs node during PCM device open and close operations. Signed-off-by: Sheetal Link: https://patch.msgid.link/20250203105304.4155542-1-sheetal@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/Makefile | 2 +- sound/soc/tegra/tegra210_admaif.c | 24 +++++- sound/soc/tegra/tegra210_admaif.h | 9 +- sound/soc/tegra/tegra_isomgr_bw.c | 132 ++++++++++++++++++++++++++++++ sound/soc/tegra/tegra_isomgr_bw.h | 31 +++++++ 5 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 sound/soc/tegra/tegra_isomgr_bw.c create mode 100644 sound/soc/tegra/tegra_isomgr_bw.h diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index cea4b0d54378..defea7f53f11 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -13,7 +13,7 @@ snd-soc-tegra210-dmic-y := tegra210_dmic.o snd-soc-tegra210-i2s-y := tegra210_i2s.o snd-soc-tegra186-asrc-y := tegra186_asrc.o snd-soc-tegra186-dspk-y := tegra186_dspk.o -snd-soc-tegra210-admaif-y := tegra210_admaif.o +snd-soc-tegra210-admaif-y := tegra210_admaif.o tegra_isomgr_bw.o snd-soc-tegra210-mvc-y := tegra210_mvc.o snd-soc-tegra210-sfc-y := tegra210_sfc.o snd-soc-tegra210-amx-y := tegra210_amx.o diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index 58fdb0e79954..f56d1e03239d 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. +// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. // All rights reserved. // // tegra210_admaif.c - Tegra ADMAIF driver @@ -13,6 +13,7 @@ #include #include #include +#include "tegra_isomgr_bw.h" #include "tegra210_admaif.h" #include "tegra_cif.h" #include "tegra_pcm.h" @@ -262,6 +263,18 @@ static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg, return 0; } +static int tegra_admaif_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return tegra_isomgr_adma_setbw(substream, dai, true); +} + +static void tegra_admaif_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + tegra_isomgr_adma_setbw(substream, dai, false); +} + static int tegra_admaif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -554,6 +567,8 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { .probe = tegra_admaif_dai_probe, .hw_params = tegra_admaif_hw_params, .trigger = tegra_admaif_trigger, + .shutdown = tegra_admaif_shutdown, + .prepare = tegra_admaif_prepare, }; #define DAI(dai_name) \ @@ -800,6 +815,12 @@ static int tegra_admaif_probe(struct platform_device *pdev) regcache_cache_only(admaif->regmap, true); + err = tegra_isomgr_adma_register(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "Failed to add interconnect path\n"); + return err; + } + regmap_update_bits(admaif->regmap, admaif->soc_data->global_base + TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1); @@ -851,6 +872,7 @@ static int tegra_admaif_probe(struct platform_device *pdev) static void tegra_admaif_remove(struct platform_device *pdev) { + tegra_isomgr_adma_unregister(&pdev->dev); pm_runtime_disable(&pdev->dev); } diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h index 96686dc92081..748f886ee74e 100644 --- a/sound/soc/tegra/tegra210_admaif.h +++ b/sound/soc/tegra/tegra210_admaif.h @@ -1,8 +1,8 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * tegra210_admaif.h - Tegra ADMAIF registers +/* SPDX-License-Identifier: GPL-2.0-only + * SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. * - * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. + * tegra210_admaif.h - Tegra ADMAIF registers * */ @@ -157,6 +157,7 @@ struct tegra_admaif { unsigned int *mono_to_stereo[ADMAIF_PATHS]; unsigned int *stereo_to_mono[ADMAIF_PATHS]; struct regmap *regmap; + struct tegra_adma_isomgr *adma_isomgr; }; #endif diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c new file mode 100644 index 000000000000..7789efe13873 --- /dev/null +++ b/sound/soc/tegra/tegra_isomgr_bw.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. +// All rights reserved. +// +// ADMA bandwidth calculation + +#include +#include +#include +#include +#include "tegra_isomgr_bw.h" +#include "tegra210_admaif.h" + +/* Max possible rate is 192KHz x 16channel x 4bytes */ +#define MAX_BW_PER_DEV 12288 + +int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, bool is_running) +{ + struct device *dev = dai->dev; + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); + struct tegra_adma_isomgr *adma_isomgr = admaif->adma_isomgr; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm *pcm = substream->pcm; + u32 type = substream->stream, bandwidth = 0; + int sample_bytes; + + if (!adma_isomgr) + return 0; + + if (!runtime || !pcm) + return -EINVAL; + + if (pcm->device >= adma_isomgr->max_pcm_device) { + dev_err(dev, "%s: PCM device number %d is greater than %d\n", __func__, + pcm->device, adma_isomgr->max_pcm_device); + return -EINVAL; + } + + /* + * No action if stream is running and bandwidth is already set or + * stream is not running and bandwidth is already reset + */ + if ((adma_isomgr->bw_per_dev[type][pcm->device] && is_running) || + (!adma_isomgr->bw_per_dev[type][pcm->device] && !is_running)) + return 0; + + if (is_running) { + sample_bytes = snd_pcm_format_width(runtime->format) / 8; + if (sample_bytes < 0) + return sample_bytes; + + /* KB/s kilo bytes per sec */ + bandwidth = runtime->channels * (runtime->rate / 1000) * + sample_bytes; + } + + mutex_lock(&adma_isomgr->mutex); + + if (is_running) { + if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw) + bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth; + + adma_isomgr->current_bandwidth += bandwidth; + } else { + adma_isomgr->current_bandwidth -= adma_isomgr->bw_per_dev[type][pcm->device]; + } + + mutex_unlock(&adma_isomgr->mutex); + + adma_isomgr->bw_per_dev[type][pcm->device] = bandwidth; + + dev_dbg(dev, "Setting up bandwidth to %d KBps\n", adma_isomgr->current_bandwidth); + + return icc_set_bw(adma_isomgr->icc_path_handle, + adma_isomgr->current_bandwidth, adma_isomgr->max_bw); +} +EXPORT_SYMBOL(tegra_isomgr_adma_setbw); + +int tegra_isomgr_adma_register(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + struct tegra_adma_isomgr *adma_isomgr; + int i; + + adma_isomgr = devm_kzalloc(dev, sizeof(struct tegra_adma_isomgr), GFP_KERNEL); + if (!adma_isomgr) + return -ENOMEM; + + adma_isomgr->icc_path_handle = devm_of_icc_get(dev, "write"); + if (IS_ERR(adma_isomgr->icc_path_handle)) + return dev_err_probe(dev, PTR_ERR(adma_isomgr->icc_path_handle), + "failed to acquire interconnect path\n"); + + /* Either INTERCONNECT config OR interconnect property is not defined */ + if (!adma_isomgr->icc_path_handle) { + devm_kfree(dev, adma_isomgr); + return 0; + } + + adma_isomgr->max_pcm_device = admaif->soc_data->num_ch; + adma_isomgr->max_bw = STREAM_TYPE * MAX_BW_PER_DEV * adma_isomgr->max_pcm_device; + + for (i = 0; i < STREAM_TYPE; i++) { + adma_isomgr->bw_per_dev[i] = devm_kzalloc(dev, adma_isomgr->max_pcm_device * + sizeof(u32), GFP_KERNEL); + if (!adma_isomgr->bw_per_dev[i]) + return -ENOMEM; + } + + adma_isomgr->current_bandwidth = 0; + mutex_init(&adma_isomgr->mutex); + admaif->adma_isomgr = adma_isomgr; + + return 0; +} +EXPORT_SYMBOL(tegra_isomgr_adma_register); + +void tegra_isomgr_adma_unregister(struct device *dev) +{ + struct tegra_admaif *admaif = dev_get_drvdata(dev); + + if (!admaif->adma_isomgr) + return; + + mutex_destroy(&admaif->adma_isomgr->mutex); +} +EXPORT_SYMBOL(tegra_isomgr_adma_unregister); + +MODULE_AUTHOR("Mohan Kumar "); +MODULE_DESCRIPTION("Tegra ADMA Bandwidth Request driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_isomgr_bw.h b/sound/soc/tegra/tegra_isomgr_bw.h new file mode 100644 index 000000000000..86db3cfd4e43 --- /dev/null +++ b/sound/soc/tegra/tegra_isomgr_bw.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + * + * tegra_isomgr_bw.h - Definitions for ADMA bandwidth calculation + * + */ + +#ifndef __TEGRA_ISOMGR_BW_H__ +#define __TEGRA_ISOMGR_BW_H__ + +/* Playback and Capture streams */ +#define STREAM_TYPE 2 + +struct tegra_adma_isomgr { + /* Protect pcm devices bandwidth */ + struct mutex mutex; + /* interconnect path handle */ + struct icc_path *icc_path_handle; + u32 *bw_per_dev[STREAM_TYPE]; + u32 current_bandwidth; + u32 max_pcm_device; + u32 max_bw; +}; + +int tegra_isomgr_adma_register(struct device *dev); +void tegra_isomgr_adma_unregister(struct device *dev); +int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, bool is_running); + +#endif From a05143a8f713d9ae6abc41141dac52c66fca8b06 Mon Sep 17 00:00:00 2001 From: Zhang Heng Date: Fri, 17 Jan 2025 09:43:43 +0800 Subject: [PATCH 0010/1090] ASoC: SOF: topology: Use krealloc_array() to replace krealloc() Use krealloc_array() to replace krealloc() with multiplication. krealloc_array() has multiply overflow check, which will be safer. Signed-off-by: Zhang Heng Link: https://patch.msgid.link/20250117014343.451503-1-zhangheng@kylinos.cn Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 688cc7ac1714..dc9cb8324067 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1273,8 +1273,8 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s struct snd_sof_tuple *new_tuples; num_tuples += token_list[object_token_list[i]].count * (num_sets - 1); - new_tuples = krealloc(swidget->tuples, - sizeof(*new_tuples) * num_tuples, GFP_KERNEL); + new_tuples = krealloc_array(swidget->tuples, + num_tuples, sizeof(*new_tuples), GFP_KERNEL); if (!new_tuples) { ret = -ENOMEM; goto err; From fb6ec1d27608c008bfe1ab0dfec3720990eb2451 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Tue, 28 Jan 2025 00:52:43 +0000 Subject: [PATCH 0011/1090] ASoC: mediatek: mt6358: Remove unused functions The functions: mt6358_mtkaif_calibration_disable() mt6358_mtkaif_calibration_enable() mt6358_set_mtkaif_calibration_phase() were added in the 2019 commit 6a8d4198ca80 ("ASoC: mediatek: mt6358: add codec driver") but never used. Remove them. This leaves mt6358_set_dcxo(), mt6358_set_clksq(), mt6358_set_aud_global_bias(), also unused. Remove them. Signed-off-by: Dr. David Alan Gilbert Link: https://patch.msgid.link/20250128005243.295977-1-linux@treblig.org Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 104 -------------------------------------- sound/soc/codecs/mt6358.h | 4 -- 2 files changed, 108 deletions(-) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 9247b90d1b99..e033027fd4c7 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -162,47 +162,6 @@ static void capture_gpio_reset(struct mt6358_priv *priv) 0xf << 12, 0x0); } -/* use only when not govern by DAPM */ -static int mt6358_set_dcxo(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_DCXO_CW14, - 0x1 << RG_XO_AUDIO_EN_M_SFT, - (enable ? 1 : 0) << RG_XO_AUDIO_EN_M_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_clksq(struct mt6358_priv *priv, bool enable) -{ - /* audio clk source from internal dcxo */ - regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON6, - RG_CLKSQ_IN_SEL_TEST_MASK_SFT, - 0x0); - - /* Enable/disable CLKSQ 26MHz */ - regmap_update_bits(priv->regmap, MT6358_AUDENC_ANA_CON6, - RG_CLKSQ_EN_MASK_SFT, - (enable ? 1 : 0) << RG_CLKSQ_EN_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_aud_global_bias(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_AUDDEC_ANA_CON13, - RG_AUDGLB_PWRDN_VA28_MASK_SFT, - (enable ? 0 : 1) << RG_AUDGLB_PWRDN_VA28_SFT); - return 0; -} - -/* use only when not govern by DAPM */ -static int mt6358_set_topck(struct mt6358_priv *priv, bool enable) -{ - regmap_update_bits(priv->regmap, MT6358_AUD_TOP_CKPDN_CON0, - 0x0066, enable ? 0x0 : 0x66); - return 0; -} - static int mt6358_mtkaif_tx_enable(struct mt6358_priv *priv) { switch (priv->mtkaif_protocol) { @@ -252,69 +211,6 @@ static int mt6358_mtkaif_tx_disable(struct mt6358_priv *priv) return 0; } -int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - playback_gpio_set(priv); - capture_gpio_set(priv); - mt6358_mtkaif_tx_enable(priv); - - mt6358_set_dcxo(priv, true); - mt6358_set_aud_global_bias(priv, true); - mt6358_set_clksq(priv, true); - mt6358_set_topck(priv, true); - - /* set dat_miso_loopback on */ - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, - 1 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, - 1 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); - return 0; -} -EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_enable); - -int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - /* set dat_miso_loopback off */ - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT, - 0 << RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT, - 0 << RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT); - - mt6358_set_topck(priv, false); - mt6358_set_clksq(priv, false); - mt6358_set_aud_global_bias(priv, false); - mt6358_set_dcxo(priv, false); - - mt6358_mtkaif_tx_disable(priv); - playback_gpio_reset(priv); - capture_gpio_reset(priv); - return 0; -} -EXPORT_SYMBOL_GPL(mt6358_mtkaif_calibration_disable); - -int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt, - int phase_1, int phase_2) -{ - struct mt6358_priv *priv = snd_soc_component_get_drvdata(cmpnt); - - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_PHASE_MODE_MASK_SFT, - phase_1 << RG_AUD_PAD_TOP_PHASE_MODE_SFT); - regmap_update_bits(priv->regmap, MT6358_AUDIO_DIG_CFG, - RG_AUD_PAD_TOP_PHASE_MODE2_MASK_SFT, - phase_2 << RG_AUD_PAD_TOP_PHASE_MODE2_SFT); - return 0; -} -EXPORT_SYMBOL_GPL(mt6358_set_mtkaif_calibration_phase); - /* dl pga gain */ enum { DL_GAIN_8DB = 0, diff --git a/sound/soc/codecs/mt6358.h b/sound/soc/codecs/mt6358.h index a5953315eaa2..b729c3899b7e 100644 --- a/sound/soc/codecs/mt6358.h +++ b/sound/soc/codecs/mt6358.h @@ -2307,8 +2307,4 @@ enum { /* set only during init */ int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, int mtkaif_protocol); -int mt6358_mtkaif_calibration_enable(struct snd_soc_component *cmpnt); -int mt6358_mtkaif_calibration_disable(struct snd_soc_component *cmpnt); -int mt6358_set_mtkaif_calibration_phase(struct snd_soc_component *cmpnt, - int phase_1, int phase_2); #endif /* __MT6358_H__ */ From 1a4a5a752fcd60797ed2cb7c06253c6433d13f63 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Feb 2025 06:04:40 +0000 Subject: [PATCH 0012/1090] ASoC: soc-ops: remove soc-dpcm.h soc-ops is not using soc-dpcm.h. Remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j1bsgw7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 19928f098d8d..c6601ef16f84 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -24,7 +24,6 @@ #include #include #include -#include #include /** From 6eab7034579917f207ca6d8e3f4e11e85e0ab7d5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 22 Jan 2025 09:21:27 +0100 Subject: [PATCH 0013/1090] ASoC: soc-core: Stop using of_property_read_bool() for non-boolean properties On R-Car: OF: /sound: Read of boolean property 'simple-audio-card,bitclock-master' with a value. OF: /sound: Read of boolean property 'simple-audio-card,frame-master' with a value. or: OF: /soc/sound@ec500000/ports/port@0/endpoint: Read of boolean property 'bitclock-master' with a value. OF: /soc/sound@ec500000/ports/port@0/endpoint: Read of boolean property 'frame-master' with a value. The use of of_property_read_bool() for non-boolean properties is deprecated in favor of of_property_present() when testing for property presence. Replace testing for presence before calling of_property_read_u32() by testing for an -EINVAL return value from the latter, to simplify the code. Signed-off-by: Geert Uytterhoeven Link: https://patch.msgid.link/db10e96fbda121e7456d70e97a013cbfc9755f4d.1737533954.git.geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3c6d8aef4130..26b34b688508 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3046,7 +3046,7 @@ int snd_soc_of_parse_pin_switches(struct snd_soc_card *card, const char *prop) unsigned int i, nb_controls; int ret; - if (!of_property_read_bool(dev->of_node, prop)) + if (!of_property_present(dev->of_node, prop)) return 0; strings = devm_kcalloc(dev, nb_controls_max, @@ -3120,23 +3120,17 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, if (rx_mask) snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", rx_mask); - if (of_property_read_bool(np, "dai-tdm-slot-num")) { - ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); - if (ret) - return ret; + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret && ret != -EINVAL) + return ret; + if (!ret && slots) + *slots = val; - if (slots) - *slots = val; - } - - if (of_property_read_bool(np, "dai-tdm-slot-width")) { - ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); - if (ret) - return ret; - - if (slot_width) - *slot_width = val; - } + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret && ret != -EINVAL) + return ret; + if (!ret && slot_width) + *slot_width = val; return 0; } @@ -3403,12 +3397,12 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, * check "[prefix]frame-master" */ snprintf(prop, sizeof(prop), "%sbitclock-master", prefix); - bit = of_property_read_bool(np, prop); + bit = of_property_present(np, prop); if (bit && bitclkmaster) *bitclkmaster = of_parse_phandle(np, prop, 0); snprintf(prop, sizeof(prop), "%sframe-master", prefix); - frame = of_property_read_bool(np, prop); + frame = of_property_present(np, prop); if (frame && framemaster) *framemaster = of_parse_phandle(np, prop, 0); From dc561ab16d8be9cbe8f07a49a7b2f5428fbcfeea Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:41 +0100 Subject: [PATCH 0014/1090] ASoC: codecs: pcm3168a: Add ACPI match table Support ACPI-based systems by adding relevant match table. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a-i2c.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c index 7052cc0c97d1..4da608ba514d 100644 --- a/sound/soc/codecs/pcm3168a-i2c.c +++ b/sound/soc/codecs/pcm3168a-i2c.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -37,6 +38,13 @@ static const struct i2c_device_id pcm3168a_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, pcm3168a_i2c_id); +static const struct acpi_device_id pcm3168a_acpi_match[] = { + { "PCM3168A" }, + { "104C3168" }, + {} +}; +MODULE_DEVICE_TABLE(acpi, pcm3168a_acpi_match); + static const struct of_device_id pcm3168a_of_match[] = { { .compatible = "ti,pcm3168a", }, { } @@ -49,6 +57,7 @@ static struct i2c_driver pcm3168a_i2c_driver = { .id_table = pcm3168a_i2c_id, .driver = { .name = "pcm3168a", + .acpi_match_table = pcm3168a_acpi_match, .of_match_table = pcm3168a_of_match, .pm = &pcm3168a_pm_ops, }, From e92f042642aed6f6206caace892d9df2d0166841 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:42 +0100 Subject: [PATCH 0015/1090] ASoC: codecs: pcm3168a: Relax probing conditions On ACPI-based systems with Intel MalibouLake there is no "scki" clock entry defined. Make that initialization part optional and default to 24.576 MHz rate if not set. The rate is the default for both TI and Intel devices. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index fac0617ab95b..43c0cb5e538e 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -743,7 +743,7 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) return dev_err_probe(dev, PTR_ERR(pcm3168a->gpio_rst), "failed to acquire RST gpio\n"); - pcm3168a->scki = devm_clk_get(dev, "scki"); + pcm3168a->scki = devm_clk_get_optional(dev, "scki"); if (IS_ERR(pcm3168a->scki)) return dev_err_probe(dev, PTR_ERR(pcm3168a->scki), "failed to acquire clock 'scki'\n"); @@ -755,6 +755,9 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) } pcm3168a->sysclk = clk_get_rate(pcm3168a->scki); + /* Fallback to the default if no clk entry available. */ + if (!pcm3168a->sysclk) + pcm3168a->sysclk = 24576000; for (i = 0; i < ARRAY_SIZE(pcm3168a->supplies); i++) pcm3168a->supplies[i].supply = pcm3168a_supply_names[i]; From 7d92a38d67e5d937b64b20aa4fd14451ee1772f3 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:43 +0100 Subject: [PATCH 0016/1090] ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode As per codec device specification, 24-bit is allowed in provider mode. Update the code to reflect that. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 43c0cb5e538e..df6836a652ef 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -493,9 +493,9 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, } break; case 24: - if (provider_mode || (format == SND_SOC_DAIFMT_DSP_A) || - (format == SND_SOC_DAIFMT_DSP_B)) { - dev_err(component->dev, "24-bit slots not supported in provider mode, or consumer mode using DSP\n"); + if (!provider_mode && ((format == SND_SOC_DAIFMT_DSP_A) || + (format == SND_SOC_DAIFMT_DSP_B))) { + dev_err(component->dev, "24-bit slots not supported in consumer mode using DSP\n"); return -EINVAL; } break; From 79ebb596201c86712fe38b0ef73d25d07b932664 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:44 +0100 Subject: [PATCH 0017/1090] ASoC: Intel: avs: Add pcm3168a machine board To support AVS-pcm3168a configuration add machine board connecting AVS platform component driver with pcm3168a codec one. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/pcm3168a.c | 143 ++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 sound/soc/intel/avs/boards/pcm3168a.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 00b0f6c176d6..ba4bee42124c 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -87,6 +87,16 @@ config SND_SOC_INTEL_AVS_MACH_NAU8825 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_PCM3168A + tristate "pcm3168a I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_PCM3168A_I2C + help + This adds support for AVS with PCM3168A I2C codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_PROBE tristate "Probing (data) board" depends on DEBUG_FS diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 4fbd936ffb3e..a95256b94dc8 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -9,6 +9,7 @@ snd-soc-avs-max98927-y := max98927.o snd-soc-avs-max98357a-y := max98357a.o snd-soc-avs-max98373-y := max98373.o snd-soc-avs-nau8825-y := nau8825.o +snd-soc-avs-pcm3168a-y := pcm3168a.o snd-soc-avs-probe-y := probe.o snd-soc-avs-rt274-y := rt274.o snd-soc-avs-rt286-y := rt286.o @@ -27,6 +28,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98927) += snd-soc-avs-max98927.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PCM3168A) += snd-soc-avs-pcm3168a.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_PROBE) += snd-soc-avs-probe.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o diff --git a/sound/soc/intel/avs/boards/pcm3168a.c b/sound/soc/intel/avs/boards/pcm3168a.c new file mode 100644 index 000000000000..5d0e7a5bdc74 --- /dev/null +++ b/sound/soc/intel/avs/boards/pcm3168a.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2024-2025 Intel Corporation +// +// Author: Cezary Rojewski +// + +#include +#include +#include +#include +#include +#include + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("CPB Stereo HP 1", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 2", NULL), + SND_SOC_DAPM_HP("CPB Stereo HP 3", NULL), + SND_SOC_DAPM_LINE("CPB Line Out", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 1", NULL), + SND_SOC_DAPM_MIC("CPB Stereo Mic 2", NULL), + SND_SOC_DAPM_LINE("CPB Line In", NULL), +}; + +static const struct snd_soc_dapm_route card_routes[] = { + { "CPB Stereo HP 1", NULL, "AOUT1L" }, + { "CPB Stereo HP 1", NULL, "AOUT1R" }, + { "CPB Stereo HP 2", NULL, "AOUT2L" }, + { "CPB Stereo HP 2", NULL, "AOUT2R" }, + { "CPB Stereo HP 3", NULL, "AOUT3L" }, + { "CPB Stereo HP 3", NULL, "AOUT3R" }, + { "CPB Line Out", NULL, "AOUT4L" }, + { "CPB Line Out", NULL, "AOUT4R" }, + + { "AIN1L", NULL, "CPB Stereo Mic 1" }, + { "AIN1R", NULL, "CPB Stereo Mic 1" }, + { "AIN2L", NULL, "CPB Stereo Mic 2" }, + { "AIN2R", NULL, "CPB Stereo Mic 2" }, + { "AIN3L", NULL, "CPB Line In" }, + { "AIN3R", NULL, "CPB Line In" }, +}; + +static int avs_pcm3168a_be_fixup(struct snd_soc_pcm_runtime *runtime, + struct snd_pcm_hw_params *params) +{ + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* Set SSP to 24 bit. */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +SND_SOC_DAILINK_DEF(pcm3168a_dac, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-dac"))); +SND_SOC_DAILINK_DEF(pcm3168a_adc, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-PCM3168A:00", "pcm3168a-adc"))); +SND_SOC_DAILINK_DEF(cpu_ssp0, DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); +SND_SOC_DAILINK_DEF(cpu_ssp2, DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin"))); + +static int avs_create_dai_links(struct device *dev, struct snd_soc_dai_link **links, int *num_links) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + const int num_dl = 2; + + dl = devm_kcalloc(dev, num_dl, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = dev_name(dev); + dl[0].num_cpus = 1; + dl[0].num_codecs = 1; + dl[0].platforms = platform; + dl[0].num_platforms = 1; + dl[0].dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + dl[0].be_hw_params_fixup = avs_pcm3168a_be_fixup; + dl[0].nonatomic = 1; + dl[0].no_pcm = 1; + memcpy(&dl[1], &dl[0], sizeof(*dl)); + + dl[0].name = "SSP0-Codec-dac"; + dl[0].cpus = cpu_ssp0; + dl[0].codecs = pcm3168a_dac; + dl[1].name = "SSP2-Codec-adc"; + dl[1].cpus = cpu_ssp2; + dl[1].codecs = pcm3168a_adc; + + *links = dl; + *num_links = num_dl; + return 0; +} + +static int avs_pcm3168a_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct snd_soc_card *card; + int ret; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + ret = avs_create_dai_links(dev, &card->dai_link, &card->num_links); + if (ret) + return ret; + + card->name = "avs_pcm3168a"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = card_routes; + card->num_dapm_routes = ARRAY_SIZE(card_routes); + card->fully_routed = true; + + return devm_snd_soc_register_card(dev, card); +} + +static const struct platform_device_id avs_pcm3168a_driver_ids[] = { + { + .name = "avs_pcm3168a", + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, avs_pcm3168a_driver_ids); + +static struct platform_driver avs_pcm3168a_driver = { + .probe = avs_pcm3168a_probe, + .driver = { + .name = "avs_pcm3168a", + .pm = &snd_soc_pm_ops, + }, + .id_table = avs_pcm3168a_driver_ids, +}; + +module_platform_driver(avs_pcm3168a_driver); + +MODULE_DESCRIPTION("Intel pcm3168a machine driver"); +MODULE_AUTHOR("Cezary Rojewski "); +MODULE_LICENSE("GPL"); From b9fb91692af881736f8fa1741fa0dbadf07d99ee Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:45 +0100 Subject: [PATCH 0018/1090] ASoC: Intel: avs: pcm3168a board selection Populate board table with avs_pcm3168a machine driver for RPL-M-based and ADL-N-based platforms with pcm3168a codec onboard to allow the sound card to enumerate. While at it, drop comma the terminator entries to align with the coding standard. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/board_selection.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 0266edeafc19..2d706edcbf92 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -312,6 +312,18 @@ static struct snd_soc_acpi_mach avs_tgl_i2s_machines[] = { {}, }; +static struct snd_soc_acpi_mach avs_mbl_i2s_machines[] = { + { + .id = "PCM3168A", + .drv_name = "avs_pcm3168a", + .mach_params = { + .i2s_link_mask = AVS_SSP(0) | AVS_SSP(2), + }, + .tplg_filename = "pcm3168a-tplg.bin", + }, + {} +}; + static struct snd_soc_acpi_mach avs_test_i2s_machines[] = { { .drv_name = "avs_i2s_test", @@ -378,10 +390,11 @@ static const struct avs_acpi_boards i2s_boards[] = { AVS_MACH_ENTRY(HDA_ICL_LP, avs_icl_i2s_machines), AVS_MACH_ENTRY(HDA_TGL_LP, avs_tgl_i2s_machines), AVS_MACH_ENTRY(HDA_EHL_0, avs_tgl_i2s_machines), + AVS_MACH_ENTRY(HDA_ADL_N, avs_mbl_i2s_machines), AVS_MACH_ENTRY(HDA_ADL_P, avs_tgl_i2s_machines), AVS_MACH_ENTRY(HDA_RPL_P_0, avs_tgl_i2s_machines), - AVS_MACH_ENTRY(HDA_RPL_M, avs_tgl_i2s_machines), - {}, + AVS_MACH_ENTRY(HDA_RPL_M, avs_mbl_i2s_machines), + {} }; static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev) From e995c51903384be1c7aead246dc30cb5244179ac Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:46 +0100 Subject: [PATCH 0019/1090] ASoC: Intel: avs: Move DSP-boot steps into individual functions To make DSP-boot code more readable, move each logical step into an individual function and add the configure step which will be utilized by follow up changes. To summarize, the steps are: loading the firmware code, configuring the base firmware and, allocating driver resources based on FW and HW capabilities. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/avs.h | 1 + sound/soc/intel/avs/loader.c | 74 +++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index eca6ec0428bb..585543f872fc 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -51,6 +51,7 @@ struct avs_dsp_ops { int (* const load_basefw)(struct avs_dev *, struct firmware *); int (* const load_lib)(struct avs_dev *, struct firmware *, u32); int (* const transfer_mods)(struct avs_dev *, bool, struct avs_module_entry *, u32); + int (* const config_basefw)(struct avs_dev *); int (* const enable_logs)(struct avs_dev *, enum avs_log_enable, u32, u32, unsigned long, u32 *); int (* const log_buffer_offset)(struct avs_dev *, u32); diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 9ff7818395cd..0b29941feb0e 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -603,7 +603,7 @@ release_fw: return ret; } -int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) +static int avs_load_firmware(struct avs_dev *adev, bool purge) { struct avs_soc_component *acomp; int ret, i; @@ -657,29 +657,34 @@ reenable_gating: return 0; } -int avs_dsp_first_boot_firmware(struct avs_dev *adev) +static int avs_config_basefw(struct avs_dev *adev) +{ + int ret; + + if (adev->spec->dsp_ops->config_basefw) { + ret = avs_dsp_op(adev, config_basefw); + if (ret) + return ret; + } + + return 0; +} + +int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge) +{ + int ret; + + ret = avs_load_firmware(adev, purge); + if (ret) + return ret; + + return avs_config_basefw(adev); +} + +static int avs_dsp_alloc_resources(struct avs_dev *adev) { int ret, i; - if (avs_platattr_test(adev, CLDMA)) { - ret = hda_cldma_init(&code_loader, &adev->base.core, - adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE); - if (ret < 0) { - dev_err(adev->dev, "cldma init failed: %d\n", ret); - return ret; - } - } - - ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); - if (ret < 0) - return ret; - - ret = avs_dsp_boot_firmware(adev, true); - if (ret < 0) { - dev_err(adev->dev, "firmware boot failed: %d\n", ret); - return ret; - } - ret = avs_ipc_get_hw_config(adev, &adev->hw_cfg); if (ret) return AVS_IPC_RET(ret); @@ -705,6 +710,31 @@ int avs_dsp_first_boot_firmware(struct avs_dev *adev) strscpy(adev->lib_names[0], "BASEFW", AVS_LIB_NAME_SIZE); ida_init(&adev->ppl_ida); - return 0; } + +int avs_dsp_first_boot_firmware(struct avs_dev *adev) +{ + int ret; + + if (avs_platattr_test(adev, CLDMA)) { + ret = hda_cldma_init(&code_loader, &adev->base.core, + adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE); + if (ret < 0) { + dev_err(adev->dev, "cldma init failed: %d\n", ret); + return ret; + } + } + + ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK); + if (ret < 0) + return ret; + + ret = avs_dsp_boot_firmware(adev, true); + if (ret < 0) { + dev_err(adev->dev, "firmware boot failed: %d\n", ret); + return ret; + } + + return avs_dsp_alloc_resources(adev); +} From cbe37a4d2b3c25d2e2a94097e09b6d87461b8833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 3 Feb 2025 15:10:47 +0100 Subject: [PATCH 0020/1090] ASoC: Intel: avs: Configure basefw on TGL-based platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AudioDSP firmware requires additional information about the configuration on selected devices. That information is unaccessible from the DSP side and shall be sent before any streaming starts. To achieve the goal, introduce FW_CONFIG_SET request. FW_CONFIG_SET message allows driver to modify firmware's configuration. Multiple parameters can be modified at once, thanks to payload being an array of TLVs. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/messages.c | 38 ++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/messages.h | 9 ++++++++ sound/soc/intel/avs/tgl.c | 33 +++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index 30b666f8909b..242a175381c2 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -510,6 +510,44 @@ err: return ret; } +int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...) +{ + struct avs_tlv *tlv; + void *payload; + size_t offset; + va_list args; + int ret, i; + + payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!payload) + return -ENOMEM; + + va_start(args, num_tlvs); + for (offset = i = 0; i < num_tlvs && offset < AVS_MAILBOX_SIZE - sizeof(*tlv); i++) { + tlv = (struct avs_tlv *)(payload + offset); + tlv->type = va_arg(args, u32); + tlv->length = va_arg(args, u32); + + offset += sizeof(*tlv) + tlv->length; + if (offset > AVS_MAILBOX_SIZE) + break; + + memcpy(tlv->value, va_arg(args, u8*), tlv->length); + } + + if (i == num_tlvs) + ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID, + AVS_BASEFW_FIRMWARE_CONFIG, payload, offset); + else + ret = -ERANGE; + + va_end(args); + kfree(payload); + if (ret) + dev_err(adev->dev, "set fw cfg failed: %d\n", ret); + return ret; +} + int avs_ipc_get_hw_config(struct avs_dev *adev, struct avs_hw_cfg *cfg) { struct avs_tlv *tlv; diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 0378633c7f96..84b0d4b69ecb 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -451,6 +451,8 @@ enum avs_fw_cfg_params { AVS_FW_CFG_RESERVED, AVS_FW_CFG_POWER_GATING_POLICY, AVS_FW_CFG_ASSERT_MODE, + AVS_FW_CFG_RESERVED2, + AVS_FW_CFG_BUS_HARDWARE_ID, }; struct avs_fw_cfg { @@ -475,7 +477,14 @@ struct avs_fw_cfg { u32 power_gating_policy; }; +struct avs_bus_hwid { + u32 device; + u32 subsystem; + u8 revision; +}; + int avs_ipc_get_fw_config(struct avs_dev *adev, struct avs_fw_cfg *cfg); +int avs_ipc_set_fw_config(struct avs_dev *adev, size_t num_tlvs, ...); enum avs_hw_cfg_params { AVS_HW_CFG_AVS_VER, diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index a9019ff5e3af..56905f2b9eb2 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -6,7 +6,11 @@ // Amadeusz Slawinski // +#include #include "avs.h" +#include "messages.h" + +#define CPUID_TSC_LEAF 0x15 static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) { @@ -35,6 +39,34 @@ static int avs_tgl_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stal return avs_dsp_core_stall(adev, core_mask, stall); } +static int avs_tgl_config_basefw(struct avs_dev *adev) +{ + struct pci_dev *pci = adev->base.pci; + struct avs_bus_hwid hwid; + int ret; +#ifdef CONFIG_X86 + unsigned int ecx; + +#include + ecx = cpuid_ecx(CPUID_TSC_LEAF); + if (ecx) { + ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_XTAL_FREQ_HZ, sizeof(ecx), &ecx); + if (ret) + return AVS_IPC_RET(ret); + } +#endif + + hwid.device = pci->device; + hwid.subsystem = pci->subsystem_vendor | (pci->subsystem_device << 16); + hwid.revision = pci->revision; + + ret = avs_ipc_set_fw_config(adev, 1, AVS_FW_CFG_BUS_HARDWARE_ID, sizeof(hwid), &hwid); + if (ret) + return AVS_IPC_RET(ret); + + return 0; +} + const struct avs_dsp_ops avs_tgl_dsp_ops = { .power = avs_tgl_dsp_core_power, .reset = avs_tgl_dsp_core_reset, @@ -44,6 +76,7 @@ const struct avs_dsp_ops avs_tgl_dsp_ops = { .load_basefw = avs_icl_load_basefw, .load_lib = avs_hda_load_library, .transfer_mods = avs_hda_transfer_modules, + .config_basefw = avs_tgl_config_basefw, .log_buffer_offset = avs_icl_log_buffer_offset, .log_buffer_status = avs_apl_log_buffer_status, .coredump = avs_apl_coredump, From f0173cbe7fa79eafbdf32eed32337209f84ddacd Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:48 +0100 Subject: [PATCH 0021/1090] ASoC: Intel: avs: New gateway configuration mechanism Creation of a module which contains gateway configuration consists of few additional steps, namely: - assigning ID (node_id) for the gateway - attaching hardware configuration from the NHLT table (optional) By splitting the steps into separate functions code becomes easier to read and understand. Any redundancy created by this patch will be addressed by follow up changes. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 150 +++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index f31d5e2caa7b..698a3d542244 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -115,6 +115,156 @@ avs_path_find_variant(struct avs_dev *adev, return NULL; } +static void avs_init_node_id(union avs_connector_node_id *node_id, + struct avs_tplg_modcfg_ext *te, u32 dma_id) +{ + node_id->val = 0; + node_id->dma_type = te->copier.dma_type; + + switch (node_id->dma_type) { + case AVS_DMA_DMIC_LINK_INPUT: + case AVS_DMA_I2S_LINK_OUTPUT: + case AVS_DMA_I2S_LINK_INPUT: + /* Gateway's virtual index is statically assigned in the topology. */ + node_id->vindex = te->copier.vindex.val; + break; + + case AVS_DMA_HDA_HOST_OUTPUT: + case AVS_DMA_HDA_HOST_INPUT: + /* Gateway's virtual index is dynamically assigned with DMA ID */ + node_id->vindex = dma_id; + break; + + case AVS_DMA_HDA_LINK_OUTPUT: + case AVS_DMA_HDA_LINK_INPUT: + node_id->vindex = te->copier.vindex.val | dma_id; + break; + + default: + *node_id = INVALID_NODE_ID; + break; + } +} + +/* Every BLOB contains at least gateway attributes. */ +static struct acpi_nhlt_config *default_blob = (struct acpi_nhlt_config *)&(u32[2]) {4}; + +static struct acpi_nhlt_config * +avs_nhlt_config_or_default(struct avs_dev *adev, struct avs_tplg_module *t) +{ + struct acpi_nhlt_format_config *fmtcfg; + struct avs_tplg_modcfg_ext *te; + struct avs_audio_format *fmt; + int link_type, dev_type; + int bus_id, dir; + + te = t->cfg_ext; + + switch (te->copier.dma_type) { + case AVS_DMA_I2S_LINK_OUTPUT: + link_type = ACPI_NHLT_LINKTYPE_SSP; + dev_type = ACPI_NHLT_DEVICETYPE_CODEC; + bus_id = te->copier.vindex.i2s.instance; + dir = SNDRV_PCM_STREAM_PLAYBACK; + fmt = te->copier.out_fmt; + break; + + case AVS_DMA_I2S_LINK_INPUT: + link_type = ACPI_NHLT_LINKTYPE_SSP; + dev_type = ACPI_NHLT_DEVICETYPE_CODEC; + bus_id = te->copier.vindex.i2s.instance; + dir = SNDRV_PCM_STREAM_CAPTURE; + fmt = t->in_fmt; + break; + + case AVS_DMA_DMIC_LINK_INPUT: + link_type = ACPI_NHLT_LINKTYPE_PDM; + dev_type = -1; /* ignored */ + bus_id = 0; + dir = SNDRV_PCM_STREAM_CAPTURE; + fmt = t->in_fmt; + break; + + default: + return default_blob; + } + + /* Override format selection if necessary. */ + if (te->copier.blob_fmt) + fmt = te->copier.blob_fmt; + + fmtcfg = acpi_nhlt_find_fmtcfg(link_type, dev_type, dir, bus_id, + fmt->num_channels, fmt->sampling_freq, fmt->valid_bit_depth, + fmt->bit_depth); + if (!fmtcfg) { + dev_warn(adev->dev, "Endpoint format configuration not found.\n"); + return ERR_PTR(-ENOENT); + } + + if (fmtcfg->config.capabilities_size < default_blob->capabilities_size) + return ERR_PTR(-ETOOSMALL); + /* The firmware expects the payload to be DWORD-aligned. */ + if (fmtcfg->config.capabilities_size % sizeof(u32)) + return ERR_PTR(-EINVAL); + + return &fmtcfg->config; +} + +static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg *gtw, + struct avs_tplg_module *t, size_t *cfg_size) +{ + struct acpi_nhlt_config *blob; + size_t gtw_size; + + blob = avs_nhlt_config_or_default(adev, t); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + gtw_size = blob->capabilities_size; + if (*cfg_size + gtw_size > AVS_MAILBOX_SIZE) + return -E2BIG; + + gtw->config_length = gtw_size / sizeof(u32); + memcpy(gtw->config.blob, blob->capabilities, blob->capabilities_size); + *cfg_size += gtw_size; + + return 0; +} + +static __maybe_unused int avs_copier_create2(struct avs_dev *adev, struct avs_path_module *mod) +{ + struct avs_tplg_module *t = mod->template; + struct avs_tplg_modcfg_ext *te; + struct avs_copier_cfg *cfg; + size_t cfg_size; + u32 dma_id; + int ret; + + te = t->cfg_ext; + cfg = adev->modcfg_buf; + dma_id = mod->owner->owner->dma_id; + cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config); + + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + if (ret) + return ret; + + cfg->base.cpc = t->cfg_base->cpc; + cfg->base.ibs = t->cfg_base->ibs; + cfg->base.obs = t->cfg_base->obs; + cfg->base.is_pages = t->cfg_base->is_pages; + cfg->base.audio_fmt = *t->in_fmt; + cfg->out_fmt = *te->copier.out_fmt; + cfg->feature_mask = te->copier.feature_mask; + avs_init_node_id(&cfg->gtw_cfg.node_id, te, dma_id); + cfg->gtw_cfg.dma_buffer_size = te->copier.dma_buffer_size; + mod->gtw_attrs = cfg->gtw_cfg.config.attrs; + + ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, + t->domain, cfg, cfg_size, &mod->instance_id); + return ret; +} + __maybe_unused static bool avs_dma_type_is_host(u32 dma_type) { From 320155a61f7fc810a915644e9e2a451bdcea90b1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:49 +0100 Subject: [PATCH 0022/1090] ASoC: Intel: avs: Remove unused gateway configuration code Switch to new copier module constructor and remove code that becomes unused because of that. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 149 +-------------------------------- sound/soc/intel/avs/topology.h | 2 - 2 files changed, 1 insertion(+), 150 deletions(-) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 698a3d542244..cfa19e4820d2 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -231,7 +231,7 @@ static int avs_fill_gtw_config(struct avs_dev *adev, struct avs_copier_gtw_cfg * return 0; } -static __maybe_unused int avs_copier_create2(struct avs_dev *adev, struct avs_path_module *mod) +static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; struct avs_tplg_modcfg_ext *te; @@ -265,153 +265,6 @@ static __maybe_unused int avs_copier_create2(struct avs_dev *adev, struct avs_pa return ret; } -__maybe_unused -static bool avs_dma_type_is_host(u32 dma_type) -{ - return dma_type == AVS_DMA_HDA_HOST_OUTPUT || - dma_type == AVS_DMA_HDA_HOST_INPUT; -} - -__maybe_unused -static bool avs_dma_type_is_link(u32 dma_type) -{ - return !avs_dma_type_is_host(dma_type); -} - -__maybe_unused -static bool avs_dma_type_is_output(u32 dma_type) -{ - return dma_type == AVS_DMA_HDA_HOST_OUTPUT || - dma_type == AVS_DMA_HDA_LINK_OUTPUT || - dma_type == AVS_DMA_I2S_LINK_OUTPUT; -} - -__maybe_unused -static bool avs_dma_type_is_input(u32 dma_type) -{ - return !avs_dma_type_is_output(dma_type); -} - -static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) -{ - struct avs_tplg_module *t = mod->template; - struct avs_copier_cfg *cfg; - struct acpi_nhlt_format_config *ep_blob; - struct acpi_nhlt_endpoint *ep; - union avs_connector_node_id node_id = {0}; - size_t cfg_size, data_size; - void *data = NULL; - u32 dma_type; - int ret; - - data_size = sizeof(cfg->gtw_cfg.config); - dma_type = t->cfg_ext->copier.dma_type; - node_id.dma_type = dma_type; - - switch (dma_type) { - struct avs_audio_format *fmt; - int direction; - - case AVS_DMA_I2S_LINK_OUTPUT: - case AVS_DMA_I2S_LINK_INPUT: - if (avs_dma_type_is_input(dma_type)) - direction = SNDRV_PCM_STREAM_CAPTURE; - else - direction = SNDRV_PCM_STREAM_PLAYBACK; - - if (t->cfg_ext->copier.blob_fmt) - fmt = t->cfg_ext->copier.blob_fmt; - else if (direction == SNDRV_PCM_STREAM_CAPTURE) - fmt = t->in_fmt; - else - fmt = t->cfg_ext->copier.out_fmt; - - ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, - ACPI_NHLT_DEVICETYPE_CODEC, direction, - t->cfg_ext->copier.vindex.i2s.instance); - ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq, - fmt->valid_bit_depth, fmt->bit_depth); - if (!ep_blob) { - dev_err(adev->dev, "no I2S ep_blob found\n"); - return -ENOENT; - } - - data = ep_blob->config.capabilities; - data_size = ep_blob->config.capabilities_size; - /* I2S gateway's vindex is statically assigned in topology */ - node_id.vindex = t->cfg_ext->copier.vindex.val; - - break; - - case AVS_DMA_DMIC_LINK_INPUT: - direction = SNDRV_PCM_STREAM_CAPTURE; - - if (t->cfg_ext->copier.blob_fmt) - fmt = t->cfg_ext->copier.blob_fmt; - else - fmt = t->in_fmt; - - ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, direction, 0); - ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq, - fmt->valid_bit_depth, fmt->bit_depth); - if (!ep_blob) { - dev_err(adev->dev, "no DMIC ep_blob found\n"); - return -ENOENT; - } - - data = ep_blob->config.capabilities; - data_size = ep_blob->config.capabilities_size; - /* DMIC gateway's vindex is statically assigned in topology */ - node_id.vindex = t->cfg_ext->copier.vindex.val; - - break; - - case AVS_DMA_HDA_HOST_OUTPUT: - case AVS_DMA_HDA_HOST_INPUT: - /* HOST gateway's vindex is dynamically assigned with DMA id */ - node_id.vindex = mod->owner->owner->dma_id; - break; - - case AVS_DMA_HDA_LINK_OUTPUT: - case AVS_DMA_HDA_LINK_INPUT: - node_id.vindex = t->cfg_ext->copier.vindex.val | - mod->owner->owner->dma_id; - break; - - case INVALID_OBJECT_ID: - default: - node_id = INVALID_NODE_ID; - break; - } - - cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config) + data_size; - if (cfg_size > AVS_MAILBOX_SIZE) - return -EINVAL; - - cfg = adev->modcfg_buf; - memset(cfg, 0, cfg_size); - cfg->base.cpc = t->cfg_base->cpc; - cfg->base.ibs = t->cfg_base->ibs; - cfg->base.obs = t->cfg_base->obs; - cfg->base.is_pages = t->cfg_base->is_pages; - cfg->base.audio_fmt = *t->in_fmt; - cfg->out_fmt = *t->cfg_ext->copier.out_fmt; - cfg->feature_mask = t->cfg_ext->copier.feature_mask; - cfg->gtw_cfg.node_id = node_id; - cfg->gtw_cfg.dma_buffer_size = t->cfg_ext->copier.dma_buffer_size; - /* config_length in DWORDs */ - cfg->gtw_cfg.config_length = DIV_ROUND_UP(data_size, 4); - if (data) - memcpy(&cfg->gtw_cfg.config.blob, data, data_size); - - mod->gtw_attrs = cfg->gtw_cfg.config.attrs; - - ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, - t->core_id, t->domain, cfg, cfg_size, - &mod->instance_id); - return ret; -} - static struct avs_control_data *avs_get_module_control(struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index 7892e3797f63..dcfc568081a3 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -74,8 +74,6 @@ struct avs_tplg_modcfg_ext { union avs_virtual_index vindex; u32 dma_type; u32 dma_buffer_size; - u32 config_length; - /* config_data part of priv data */ } copier; struct { u32 out_channel_config; From 4343af66b8e1df1d3a2e6f1f8612506cb45b2afd Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:50 +0100 Subject: [PATCH 0023/1090] ASoC: Intel: avs: Add WHM module support WovHostModule (WHM) is used in wake-on-voice scenarios to optimize power consumption. It combines capabilities of Copier, KeyPhraseBuffer, WakeOnVoice and Muxer modules. Signed-off-by: Piotr Maziarz Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-11-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/uapi/sound/intel/avs/tokens.h | 7 +++++ sound/soc/intel/avs/messages.h | 13 +++++++++ sound/soc/intel/avs/path.c | 36 +++++++++++++++++++++++ sound/soc/intel/avs/topology.c | 42 +++++++++++++++++++++++++++ sound/soc/intel/avs/topology.h | 9 ++++++ 5 files changed, 107 insertions(+) diff --git a/include/uapi/sound/intel/avs/tokens.h b/include/uapi/sound/intel/avs/tokens.h index 3e3fb258dd54..06ff30537f47 100644 --- a/include/uapi/sound/intel/avs/tokens.h +++ b/include/uapi/sound/intel/avs/tokens.h @@ -77,6 +77,13 @@ enum avs_tplg_token { AVS_TKN_MODCFG_UPDOWN_MIX_CHAN_MAP_U32 = 430, AVS_TKN_MODCFG_EXT_NUM_INPUT_PINS_U16 = 431, AVS_TKN_MODCFG_EXT_NUM_OUTPUT_PINS_U16 = 432, + AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32 = 433, + AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32 = 434, + AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32 = 435, + AVS_TKN_MODCFG_WHM_VINDEX_U8 = 436, + AVS_TKN_MODCFG_WHM_DMA_TYPE_U32 = 437, + AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32 = 438, + AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32 = 439, /* struct avs_tplg_pplcfg */ AVS_TKN_PPLCFG_ID_U32 = 1401, diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 84b0d4b69ecb..f44fcfc81de7 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -652,6 +652,9 @@ int avs_ipc_set_system_time(struct avs_dev *adev); #define AVS_INTELWOV_MOD_UUID \ GUID_INIT(0xEC774FA9, 0x28D3, 0x424A, 0x90, 0xE4, 0x69, 0xF9, 0x84, 0xF1, 0xEE, 0xB7) +#define AVS_WOVHOSTM_MOD_UUID \ + GUID_INIT(0xF9ED62B7, 0x092E, 0x4A90, 0x8F, 0x4D, 0x82, 0xDA, 0xA8, 0xB3, 0x8F, 0x3B) + /* channel map */ enum avs_channel_index { AVS_CHANNEL_LEFT = 0, @@ -881,6 +884,16 @@ struct avs_wov_cfg { } __packed; static_assert(sizeof(struct avs_wov_cfg) == 44); +struct avs_whm_cfg { + struct avs_modcfg_base base; + /* Audio format for output pin 0 */ + struct avs_audio_format ref_fmt; + struct avs_audio_format out_fmt; + u32 wake_tick_period; + struct avs_copier_gtw_cfg gtw_cfg; +} __packed; +static_assert(sizeof(struct avs_whm_cfg) == 108); + /* Module runtime parameters */ enum avs_copier_runtime_param { diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index cfa19e4820d2..dfb85bd2b665 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -265,6 +265,41 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) return ret; } +static int avs_whm_create(struct avs_dev *adev, struct avs_path_module *mod) +{ + struct avs_tplg_module *t = mod->template; + struct avs_tplg_modcfg_ext *te; + struct avs_whm_cfg *cfg; + size_t cfg_size; + u32 dma_id; + int ret; + + te = t->cfg_ext; + cfg = adev->modcfg_buf; + dma_id = mod->owner->owner->dma_id; + cfg_size = offsetof(struct avs_whm_cfg, gtw_cfg.config); + + ret = avs_fill_gtw_config(adev, &cfg->gtw_cfg, t, &cfg_size); + if (ret) + return ret; + + cfg->base.cpc = t->cfg_base->cpc; + cfg->base.ibs = t->cfg_base->ibs; + cfg->base.obs = t->cfg_base->obs; + cfg->base.is_pages = t->cfg_base->is_pages; + cfg->base.audio_fmt = *t->in_fmt; + cfg->ref_fmt = *te->whm.ref_fmt; + cfg->out_fmt = *te->whm.out_fmt; + cfg->wake_tick_period = te->whm.wake_tick_period; + avs_init_node_id(&cfg->gtw_cfg.node_id, te, dma_id); + cfg->gtw_cfg.dma_buffer_size = te->whm.dma_buffer_size; + mod->gtw_attrs = cfg->gtw_cfg.config.attrs; + + ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, + t->domain, cfg, cfg_size, &mod->instance_id); + return ret; +} + static struct avs_control_data *avs_get_module_control(struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; @@ -536,6 +571,7 @@ static struct avs_module_create avs_module_create[] = { { &AVS_ASRC_MOD_UUID, avs_asrc_create }, { &AVS_INTELWOV_MOD_UUID, avs_wov_create }, { &AVS_PROBE_MOD_UUID, avs_probe_create }, + { &AVS_WOVHOSTM_MOD_UUID, avs_whm_create }, }; static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_module *mod) diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index d612f20ed989..471b00b9a149 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -815,6 +815,48 @@ static const struct avs_tplg_token_parser modcfg_ext_parsers[] = { .offset = offsetof(struct avs_tplg_modcfg_ext, generic.num_output_pins), .parse = avs_parse_short_token, }, + { + .token = AVS_TKN_MODCFG_WHM_REF_AFMT_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.ref_fmt), + .parse = avs_parse_audio_format_ptr, + }, + { + .token = AVS_TKN_MODCFG_WHM_OUT_AFMT_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.out_fmt), + .parse = avs_parse_audio_format_ptr, + }, + { + .token = AVS_TKN_MODCFG_WHM_WAKE_TICK_PERIOD_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.wake_tick_period), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_MODCFG_WHM_VINDEX_U8, + .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.vindex), + .parse = avs_parse_byte_token, + }, + { + .token = AVS_TKN_MODCFG_WHM_DMA_TYPE_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_type), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.dma_buffer_size), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, whm.blob_fmt), + .parse = avs_parse_audio_format_ptr, + }, }; static const struct avs_tplg_token_parser pin_format_parsers[] = { diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index dcfc568081a3..23d5ccd19959 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -75,6 +75,15 @@ struct avs_tplg_modcfg_ext { u32 dma_type; u32 dma_buffer_size; } copier; + struct { + struct avs_audio_format *ref_fmt; + struct avs_audio_format *out_fmt; + u32 wake_tick_period; + union avs_virtual_index vindex; + u32 dma_type; + u32 dma_buffer_size; + struct avs_audio_format *blob_fmt; /* optional override */ + } whm; struct { u32 out_channel_config; u32 coefficients_select; From 856366dc924a9561dae39f252b45dfd6cc6895ce Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 3 Feb 2025 15:10:51 +0100 Subject: [PATCH 0024/1090] ALSA: hda: Select avs-driver by default on MBL The avs-driver is the recommended solution for MalibouLake (MBL, also known as RPL-M) platform. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250203141051.2361323-12-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/hda/intel-dsp-config.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index f564ec7af194..9a8ead75be17 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -108,6 +108,10 @@ static const struct config_entry config_table[] = { {} } }, + { + .flags = FLAG_SST, + .device = PCI_DEVICE_ID_INTEL_HDA_RPL_M, + }, #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) { From 36e093c8dcc585d0a9e79a005f721f01f3365eba Mon Sep 17 00:00:00 2001 From: Nilton Perim Neto Date: Mon, 3 Feb 2025 07:13:09 -0800 Subject: [PATCH 0025/1090] Input: xpad - add 8BitDo SN30 Pro, Hyperkin X91 and Gamesir G7 SE controllers Add 8BitDo SN30 Pro, Hyperkin X91 and Gamesir G7 SE to the list of recognized controllers, and update vendor comments to match. Signed-off-by: Nilton Perim Neto Link: https://lore.kernel.org/r/20250122214814.102311-2-niltonperimneto@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 8fe2a51df649..652afb37bf77 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -376,8 +376,10 @@ static const struct xpad_device { { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE }, { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE }, { 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x6001, "8BitDo SN30 Pro", 0, XTYPE_XBOX360 }, { 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 }, { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x2e24, 0x1688, "Hyperkin X91 X-Box One pad", 0, XTYPE_XBOXONE }, { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 }, @@ -389,6 +391,7 @@ static const struct xpad_device { { 0x3285, 0x0646, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, { 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE }, { 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 }, + { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } @@ -528,12 +531,12 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */ XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */ XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */ - XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */ + XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */ XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */ - XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */ - XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */ - XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke Xbox One pad */ - XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */ + XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Controllers */ + XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Controllers */ + XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Controllers */ + XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */ From 3492321e2e60ddfe91aa438bb9ac209016f48f7a Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Mon, 3 Feb 2025 07:22:27 -0800 Subject: [PATCH 0026/1090] Input: xpad - add multiple supported devices This is based on multiple commits at https://github.com/paroj/xpad that had bouncing email addresses and were not signed off. Signed-off-by: Pavel Rojtberg Link: https://lore.kernel.org/r/20250123175404.23254-1-rojtberg@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 652afb37bf77..16493235bf9e 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -140,6 +140,7 @@ static const struct xpad_device { { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, + { 0x044f, 0xd01e, "ThrustMaster, Inc. ESWAP X 2 ELDEN RING EDITION", 0, XTYPE_XBOXONE }, { 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX }, { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, @@ -177,6 +178,7 @@ static const struct xpad_device { { 0x06a3, 0x0200, "Saitek Racing Wheel", 0, XTYPE_XBOX }, { 0x06a3, 0x0201, "Saitek Adrenalin", 0, XTYPE_XBOX }, { 0x06a3, 0xf51a, "Saitek P3600", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4503, "Mad Catz Racing Wheel", 0, XTYPE_XBOXONE }, { 0x0738, 0x4506, "Mad Catz 4506 Wireless Controller", 0, XTYPE_XBOX }, { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, { 0x0738, 0x4520, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, @@ -238,6 +240,7 @@ static const struct xpad_device { { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0147, "PDP Marvel Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x015c, "PDP Xbox One Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0e6f, 0x015d, "PDP Mirror's Edge Official Wired Controller for Xbox One", XTYPE_XBOXONE }, { 0x0e6f, 0x0161, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0162, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0163, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, @@ -276,12 +279,15 @@ static const struct xpad_device { { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x00dc, "HORIPAD FPS for Nintendo Switch", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0151, "Hori Racing Wheel Overdrive for Xbox Series X", 0, XTYPE_XBOXONE }, + { 0x0f0d, 0x0152, "Hori Racing Wheel Overdrive for Xbox Series X", 0, XTYPE_XBOXONE }, { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, + { 0x10f5, 0x7005, "Turtle Beach Recon Controller", 0, XTYPE_XBOXONE }, { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, { 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 }, { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, @@ -366,6 +372,7 @@ static const struct xpad_device { { 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x581a, "ThrustMaster XB1 Classic Controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, @@ -376,10 +383,12 @@ static const struct xpad_device { { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE }, { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE }, { 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, - { 0x2dc8, 0x6001, "8BitDo SN30 Pro", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x3109, "8BitDo Ultimate Wireless Bluetooth", 0, XTYPE_XBOX360 }, { 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x6001, "8BitDo SN30 Pro", 0, XTYPE_XBOX360 }, { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, { 0x2e24, 0x1688, "Hyperkin X91 X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x2e95, 0x0504, "SCUF Gaming Controller", MAP_SELECT_BUTTON, XTYPE_XBOXONE }, { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 }, @@ -387,12 +396,16 @@ static const struct xpad_device { { 0x31e3, 0x1230, "Wooting Two HE (ARM)", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0603, "Nacon Pro Compact controller for Xbox", 0, XTYPE_XBOXONE }, { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0614, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, { 0x3285, 0x0646, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, + { 0x3285, 0x0662, "Nacon Revolution5 Pro", 0, XTYPE_XBOX360 }, { 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE }, { 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 }, { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, + { 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -491,6 +504,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x03f0), /* HP HyperX Xbox 360 controllers */ XPAD_XBOXONE_VENDOR(0x03f0), /* HP HyperX Xbox One controllers */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ + XPAD_XBOXONE_VENDOR(0x044f), /* Thrustmaster Xbox One controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */ @@ -537,11 +551,13 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Controllers */ XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Controllers */ XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ + XPAD_XBOXONE_VENDOR(0x2e95), /* SCUF Gaming Controller */ XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */ XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ + XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */ { } }; @@ -694,7 +710,9 @@ static const struct xboxone_init_packet xboxone_init_packets[] = { XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init), XBOXONE_INIT_PKT(0x045e, 0x0b00, extra_input_packet_init), XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_led_on), + XBOXONE_INIT_PKT(0x20d6, 0xa01a, xboxone_pdp_led_on), XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_auth), + XBOXONE_INIT_PKT(0x20d6, 0xa01a, xboxone_pdp_auth), XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), From b2f10aa2eb18d289e48097e0ed973e714322175b Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 10 Dec 2024 16:16:50 +0100 Subject: [PATCH 0027/1090] x86/entry: Add __init to ia32_emulation_override_cmdline() ia32_emulation_override_cmdline() is an early_param() arg and these are only needed at boot time. In fact, all other early_param() functions in arch/x86 seem to have '__init' annotation and ia32_emulation_override_cmdline() is the only exception. Fixes: a11e097504ac ("x86: Make IA32_EMULATION boot time configurable") Signed-off-by: Vitaly Kuznetsov Signed-off-by: Dave Hansen Reviewed-by: Nikolay Borisov Link: https://lore.kernel.org/all/20241210151650.1746022-1-vkuznets%40redhat.com --- arch/x86/entry/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 94941c5a10ac..51efd2da4d7f 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -142,7 +142,7 @@ static __always_inline int syscall_32_enter(struct pt_regs *regs) #ifdef CONFIG_IA32_EMULATION bool __ia32_enabled __ro_after_init = !IS_ENABLED(CONFIG_IA32_EMULATION_DEFAULT_DISABLED); -static int ia32_emulation_override_cmdline(char *arg) +static int __init ia32_emulation_override_cmdline(char *arg) { return kstrtobool(arg, &__ia32_enabled); } From a96d3e2beca0e51c8444d0a3b6b3ec484c4c5a8f Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Sun, 12 Jan 2025 01:08:11 +0100 Subject: [PATCH 0028/1090] iio: light: apds9306: fix max_scale_nano values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two provided max_scale_nano values must be multiplied by 100 and 10 respectively to achieve nano units. According to the comments: Max scale for apds0306 is 16.326432 → the fractional part is 0.326432, which is 326432000 in NANO. The current value is 3264320. Max scale for apds0306-065 is 14.09721 → the fractional part is 0.09712, which is 97120000 in NANO. The current value is 9712000. Update max_scale_nano initialization to use the right NANO fractional parts. Cc: stable@vger.kernel.org Fixes: 620d1e6c7a3f ("iio: light: Add support for APDS9306 Light Sensor") Signed-off-by: Javier Carrasco Tested-by: subhajit.ghosh@tweaklogic.com Link: https://patch.msgid.link/20250112-apds9306_nano_vals-v1-1-82fb145d0b16@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/light/apds9306.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c index 69a0d609cffc..5ed7e17f49e7 100644 --- a/drivers/iio/light/apds9306.c +++ b/drivers/iio/light/apds9306.c @@ -108,11 +108,11 @@ static const struct part_id_gts_multiplier apds9306_gts_mul[] = { { .part_id = 0xB1, .max_scale_int = 16, - .max_scale_nano = 3264320, + .max_scale_nano = 326432000, }, { .part_id = 0xB3, .max_scale_int = 14, - .max_scale_nano = 9712000, + .max_scale_nano = 97120000, }, }; From 34d93804199fea23da2645dde35d0feb38a5d445 Mon Sep 17 00:00:00 2001 From: Victor Duicu Date: Fri, 17 Jan 2025 08:53:14 +0200 Subject: [PATCH 0029/1090] iio: adc: pac1921: Move ACPI_FREE() to cover all branches This patch moves ACPI_FREE() in pac1921_match_acpi_device() in order to cover all branches. Reported-by: Andy Shevchenko Fixes: 9fdf1d033316 ("iio: adc: pac1921: Add ACPI support to Microchip pac1921") Acked-by: Matteo Martelli Signed-off-by: Victor Duicu Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250117065314.4431-1-victor.duicu@microchip.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/pac1921.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c index 90f61c47b1c4..63f518215156 100644 --- a/drivers/iio/adc/pac1921.c +++ b/drivers/iio/adc/pac1921.c @@ -1198,11 +1198,11 @@ static int pac1921_match_acpi_device(struct iio_dev *indio_dev) label = devm_kstrdup(dev, status->package.elements[0].string.pointer, GFP_KERNEL); + ACPI_FREE(status); if (!label) return -ENOMEM; indio_dev->label = label; - ACPI_FREE(status); return 0; } From aa5119c36d19639397d29ef305aa53a5ecd72b27 Mon Sep 17 00:00:00 2001 From: Nayab Sayed Date: Wed, 15 Jan 2025 11:37:04 +0530 Subject: [PATCH 0030/1090] iio: adc: at91-sama5d2_adc: fix sama7g5 realbits value The number of valid bits in SAMA7G5 ADC channel data register are 16. Hence changing the realbits value to 16 Fixes: 840bf6cb983f ("iio: adc: at91-sama5d2_adc: add support for sama7g5 device") Signed-off-by: Nayab Sayed Link: https://patch.msgid.link/20250115-fix-sama7g5-adc-realbits-v2-1-58a6e4087584@microchip.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 68 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 8e5aaf15a921..c3a1dea2aa82 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -329,7 +329,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = { #define AT91_HWFIFO_MAX_SIZE_STR "128" #define AT91_HWFIFO_MAX_SIZE 128 -#define AT91_SAMA5D2_CHAN_SINGLE(index, num, addr) \ +#define AT91_SAMA_CHAN_SINGLE(index, num, addr, rbits) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ @@ -337,7 +337,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = { .scan_index = index, \ .scan_type = { \ .sign = 'u', \ - .realbits = 14, \ + .realbits = rbits, \ .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ @@ -350,7 +350,13 @@ static const struct at91_adc_reg_layout sama7g5_layout = { .indexed = 1, \ } -#define AT91_SAMA5D2_CHAN_DIFF(index, num, num2, addr) \ +#define AT91_SAMA5D2_CHAN_SINGLE(index, num, addr) \ + AT91_SAMA_CHAN_SINGLE(index, num, addr, 14) + +#define AT91_SAMA7G5_CHAN_SINGLE(index, num, addr) \ + AT91_SAMA_CHAN_SINGLE(index, num, addr, 16) + +#define AT91_SAMA_CHAN_DIFF(index, num, num2, addr, rbits) \ { \ .type = IIO_VOLTAGE, \ .differential = 1, \ @@ -360,7 +366,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = { .scan_index = index, \ .scan_type = { \ .sign = 's', \ - .realbits = 14, \ + .realbits = rbits, \ .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ @@ -373,6 +379,12 @@ static const struct at91_adc_reg_layout sama7g5_layout = { .indexed = 1, \ } +#define AT91_SAMA5D2_CHAN_DIFF(index, num, num2, addr) \ + AT91_SAMA_CHAN_DIFF(index, num, num2, addr, 14) + +#define AT91_SAMA7G5_CHAN_DIFF(index, num, num2, addr) \ + AT91_SAMA_CHAN_DIFF(index, num, num2, addr, 16) + #define AT91_SAMA5D2_CHAN_TOUCH(num, name, mod) \ { \ .type = IIO_POSITIONRELATIVE, \ @@ -666,30 +678,30 @@ static const struct iio_chan_spec at91_sama5d2_adc_channels[] = { }; static const struct iio_chan_spec at91_sama7g5_adc_channels[] = { - AT91_SAMA5D2_CHAN_SINGLE(0, 0, 0x60), - AT91_SAMA5D2_CHAN_SINGLE(1, 1, 0x64), - AT91_SAMA5D2_CHAN_SINGLE(2, 2, 0x68), - AT91_SAMA5D2_CHAN_SINGLE(3, 3, 0x6c), - AT91_SAMA5D2_CHAN_SINGLE(4, 4, 0x70), - AT91_SAMA5D2_CHAN_SINGLE(5, 5, 0x74), - AT91_SAMA5D2_CHAN_SINGLE(6, 6, 0x78), - AT91_SAMA5D2_CHAN_SINGLE(7, 7, 0x7c), - AT91_SAMA5D2_CHAN_SINGLE(8, 8, 0x80), - AT91_SAMA5D2_CHAN_SINGLE(9, 9, 0x84), - AT91_SAMA5D2_CHAN_SINGLE(10, 10, 0x88), - AT91_SAMA5D2_CHAN_SINGLE(11, 11, 0x8c), - AT91_SAMA5D2_CHAN_SINGLE(12, 12, 0x90), - AT91_SAMA5D2_CHAN_SINGLE(13, 13, 0x94), - AT91_SAMA5D2_CHAN_SINGLE(14, 14, 0x98), - AT91_SAMA5D2_CHAN_SINGLE(15, 15, 0x9c), - AT91_SAMA5D2_CHAN_DIFF(16, 0, 1, 0x60), - AT91_SAMA5D2_CHAN_DIFF(17, 2, 3, 0x68), - AT91_SAMA5D2_CHAN_DIFF(18, 4, 5, 0x70), - AT91_SAMA5D2_CHAN_DIFF(19, 6, 7, 0x78), - AT91_SAMA5D2_CHAN_DIFF(20, 8, 9, 0x80), - AT91_SAMA5D2_CHAN_DIFF(21, 10, 11, 0x88), - AT91_SAMA5D2_CHAN_DIFF(22, 12, 13, 0x90), - AT91_SAMA5D2_CHAN_DIFF(23, 14, 15, 0x98), + AT91_SAMA7G5_CHAN_SINGLE(0, 0, 0x60), + AT91_SAMA7G5_CHAN_SINGLE(1, 1, 0x64), + AT91_SAMA7G5_CHAN_SINGLE(2, 2, 0x68), + AT91_SAMA7G5_CHAN_SINGLE(3, 3, 0x6c), + AT91_SAMA7G5_CHAN_SINGLE(4, 4, 0x70), + AT91_SAMA7G5_CHAN_SINGLE(5, 5, 0x74), + AT91_SAMA7G5_CHAN_SINGLE(6, 6, 0x78), + AT91_SAMA7G5_CHAN_SINGLE(7, 7, 0x7c), + AT91_SAMA7G5_CHAN_SINGLE(8, 8, 0x80), + AT91_SAMA7G5_CHAN_SINGLE(9, 9, 0x84), + AT91_SAMA7G5_CHAN_SINGLE(10, 10, 0x88), + AT91_SAMA7G5_CHAN_SINGLE(11, 11, 0x8c), + AT91_SAMA7G5_CHAN_SINGLE(12, 12, 0x90), + AT91_SAMA7G5_CHAN_SINGLE(13, 13, 0x94), + AT91_SAMA7G5_CHAN_SINGLE(14, 14, 0x98), + AT91_SAMA7G5_CHAN_SINGLE(15, 15, 0x9c), + AT91_SAMA7G5_CHAN_DIFF(16, 0, 1, 0x60), + AT91_SAMA7G5_CHAN_DIFF(17, 2, 3, 0x68), + AT91_SAMA7G5_CHAN_DIFF(18, 4, 5, 0x70), + AT91_SAMA7G5_CHAN_DIFF(19, 6, 7, 0x78), + AT91_SAMA7G5_CHAN_DIFF(20, 8, 9, 0x80), + AT91_SAMA7G5_CHAN_DIFF(21, 10, 11, 0x88), + AT91_SAMA7G5_CHAN_DIFF(22, 12, 13, 0x90), + AT91_SAMA7G5_CHAN_DIFF(23, 14, 15, 0x98), IIO_CHAN_SOFT_TIMESTAMP(24), AT91_SAMA5D2_CHAN_TEMP(AT91_SAMA7G5_ADC_TEMP_CHANNEL, "temp", 0xdc), }; From 5d702aa2a47bbab6231382f9ead5be40a287a53b Mon Sep 17 00:00:00 2001 From: Dheeraj Reddy Jonnalagadda Date: Tue, 7 Jan 2025 18:05:10 +0530 Subject: [PATCH 0031/1090] iio: proximity: Fix use-after-free in hx9023s_send_cfg() Reorder the assignment of fw_size to happen before release_firmware() to avoid accessing the firmware structure after it's been freed. Fixes: e9ed97be4fcc ("iio: proximity: hx9023s: Added firmware file parsing functionality") Closes: https://scan7.scan.coverity.com/#/project-view/52337/11354?selectedIssue=1602791 Signed-off-by: Dheeraj Reddy Jonnalagadda Reviewed-by: David Lechner Link: https://patch.msgid.link/20250107123510.44978-1-dheeraj.linuxdev@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/hx9023s.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c index e092a935dbac..5aa8e5a22f32 100644 --- a/drivers/iio/proximity/hx9023s.c +++ b/drivers/iio/proximity/hx9023s.c @@ -1036,12 +1036,13 @@ static int hx9023s_send_cfg(const struct firmware *fw, struct hx9023s_data *data return -ENOMEM; memcpy(bin->data, fw->data, fw->size); - release_firmware(fw); bin->fw_size = fw->size; bin->fw_ver = bin->data[FW_VER_OFFSET]; bin->reg_count = get_unaligned_le16(bin->data + FW_REG_CNT_OFFSET); + release_firmware(fw); + return hx9023s_bin_load(data, bin); } From 4eba4d92906c3814ca3ec65c16af27c46c12342e Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 16 Dec 2024 10:05:53 +0000 Subject: [PATCH 0032/1090] iio: hid-sensor-prox: Split difference from multiple channels When the driver was originally created, it was decided that sampling_frequency and hysteresis would be shared_per_type instead of shared_by_all (even though it is internally shared by all). Eg: in_proximity_raw in_proximity_sampling_frequency When we introduced support for more channels, we continued with shared_by_type which. Eg: in_proximity0_raw in_proximity1_raw in_proximity_sampling_frequency in_attention_raw in_attention_sampling_frequency Ideally we should change to shared_by_all, but it is not an option, because the current naming has been a stablished ABI by now. Luckily we can use separate instead. That will be more consistent: in_proximity0_raw in_proximity0_sampling_frequency in_proximity1_raw in_proximity1_sampling_frequency in_attention_raw in_attention_sampling_frequency Fixes: 596ef5cf654b ("iio: hid-sensor-prox: Add support for more channels") Signed-off-by: Ricardo Ribalda Link: https://patch.msgid.link/20241216-fix-hid-sensor-v2-1-ff8c1959ec4a@chromium.org Signed-off-by: Jonathan Cameron --- drivers/iio/light/hid-sensor-prox.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 7ab64f5c623c..76b76d12b388 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -49,9 +49,10 @@ static const u32 prox_sensitivity_addresses[] = { #define PROX_CHANNEL(_is_proximity, _channel) \ {\ .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\ - .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\ - BIT(IIO_CHAN_INFO_PROCESSED),\ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\ + .info_mask_separate = \ + (_is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\ + BIT(IIO_CHAN_INFO_PROCESSED)) |\ + BIT(IIO_CHAN_INFO_OFFSET) |\ BIT(IIO_CHAN_INFO_SCALE) |\ BIT(IIO_CHAN_INFO_SAMP_FREQ) |\ BIT(IIO_CHAN_INFO_HYSTERESIS),\ From 21d7241faf406e8aee3ce348451cc362d5db6a02 Mon Sep 17 00:00:00 2001 From: Markus Burri Date: Fri, 24 Jan 2025 16:07:03 +0100 Subject: [PATCH 0033/1090] iio: adc: ad7192: fix channel select MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Channel configuration doesn't work as expected. For FIELD_PREP the bit mask is needed and not the bit number. Fixes: 874bbd1219c7 ("iio: adc: ad7192: Use bitfield access macros") Signed-off-by: Markus Burri Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250124150703.97848-1-markus.burri@mt.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7192.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index e96a5ae92375..cfaf8f7e0a07 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -1084,7 +1084,7 @@ static int ad7192_update_scan_mode(struct iio_dev *indio_dev, const unsigned lon conf &= ~AD7192_CONF_CHAN_MASK; for_each_set_bit(i, scan_mask, 8) - conf |= FIELD_PREP(AD7192_CONF_CHAN_MASK, i); + conf |= FIELD_PREP(AD7192_CONF_CHAN_MASK, BIT(i)); ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, conf); if (ret < 0) From e17b9f20da7d2bc1f48878ab2230523b2512d965 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sat, 25 Jan 2025 17:24:32 +0100 Subject: [PATCH 0034/1090] iio: dac: ad3552r: clear reset status flag Clear reset status flag, to keep error status register clean after reset (ad3552r manual, rev B table 38). Reset error flag was left to 1, so debugging registers, the "Error Status Register" was dirty (0x01). It is important to clear this bit, so if there is any reset event over normal working mode, it is possible to detect it. Fixes: 8f2b54824b28 ("drivers:iio:dac: Add AD3552R driver support") Signed-off-by: Angelo Dureghello Link: https://patch.msgid.link/20250125-wip-bl-ad3552r-clear-reset-v2-1-aa3a27f3ff8c@baylibre.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad3552r.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c index e7206af53af6..7944f5c1d264 100644 --- a/drivers/iio/dac/ad3552r.c +++ b/drivers/iio/dac/ad3552r.c @@ -410,6 +410,12 @@ static int ad3552r_reset(struct ad3552r_desc *dac) return ret; } + /* Clear reset error flag, see ad3552r manual, rev B table 38. */ + ret = ad3552r_write_reg(dac, AD3552R_REG_ADDR_ERR_STATUS, + AD3552R_MASK_RESET_STATUS); + if (ret) + return ret; + return ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_INTERFACE_CONFIG_A, AD3552R_MASK_ADDR_ASCENSION, From 02ccd7e5d81af4ae20852fc1ad67e7d943fa5778 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Wed, 29 Jan 2025 12:03:02 +0100 Subject: [PATCH 0035/1090] dt-bindings: iio: dac: adi-axi-adc: fix ad7606 pwm-names Fix make dt_binding_check warning: DTC [C] Documentation/devicetree/bindings/iio/adc/adi,axi-adc.example.dtb .../adc/adi,axi-adc.example.dtb: adc@0: pwm-names: ['convst1'] is too short from schema $id: http://devicetree.org/schemas/iio/adc/adi,ad7606.yaml# Add "minItems" to pwm-names, it allows to use one single pwm when connected to both adc conversion inputs. Fixes: 7c2357b10490 ("dt-bindings: iio: adc: ad7606: Add iio backend bindings") Signed-off-by: Angelo Dureghello Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250129-wip-bl-ad7606_add_backend_sw_mode-v3-1-c3aec77c0ab7@baylibre.com Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml index ab5881d0d017..52d3f1ce3367 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -146,6 +146,7 @@ properties: maxItems: 2 pwm-names: + minItems: 1 items: - const: convst1 - const: convst2 From bead181694df16de464ca2392d0cec2cf15fb978 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Wed, 29 Jan 2025 12:03:04 +0100 Subject: [PATCH 0036/1090] iio: adc: ad7606: fix wrong scale available Fix wrong scale available list since only one value is returned: ... iio:device1: ad7606b (buffer capable) 8 channels found: voltage0: (input, index: 0, format: le:S16/16>>0) 2 channel-specific attributes found: attr 0: scale value: 0.305176 attr 1: scale_available value: 0.076293 Fix as: voltage0: (input, index: 0, format: le:S16/16>>0) 2 channel-specific attributes found: attr 0: scale value: 0.305176 attr 1: scale_available value: 0.076293 0.152588 0.305176 Fixes: 97c6d857041d ("iio: adc: ad7606: rework scale-available to be static") Signed-off-by: Angelo Dureghello Link: https://patch.msgid.link/20250129-wip-bl-ad7606_add_backend_sw_mode-v3-3-c3aec77c0ab7@baylibre.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index d8e3c7a43678..d39354afd539 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -1047,7 +1047,7 @@ static int ad7606_read_avail(struct iio_dev *indio_dev, cs = &st->chan_scales[ch]; *vals = (int *)cs->scale_avail; - *length = cs->num_scales; + *length = cs->num_scales * 2; *type = IIO_VAL_INT_PLUS_MICRO; return IIO_AVAIL_LIST; From 8478dadc8148af311c3d43d4867cfb6632686ede Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Mon, 9 Dec 2024 15:09:05 +0300 Subject: [PATCH 0037/1090] ASoC: dt-bindings: Add bindings for WCD934x DAIs Add bindings for the DAIs available in WCD934x to avoid having to use unclear number indices in device trees. Signed-off-by: Dzmitry Sankouski Acked-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20241209-starqltechn_integration_upstream-v8-1-ec604481d691@gmail.com Signed-off-by: Mark Brown --- MAINTAINERS | 1 + include/dt-bindings/sound/qcom,wcd934x.h | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 include/dt-bindings/sound/qcom,wcd934x.h diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..28bf01c466d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19149,6 +19149,7 @@ F: Documentation/devicetree/bindings/soc/qcom/qcom,apr* F: Documentation/devicetree/bindings/sound/qcom,* F: drivers/soc/qcom/apr.c F: include/dt-bindings/sound/qcom,wcd9335.h +F: include/dt-bindings/sound/qcom,wcd934x.h F: sound/soc/codecs/lpass-rx-macro.* F: sound/soc/codecs/lpass-tx-macro.* F: sound/soc/codecs/lpass-va-macro.c diff --git a/include/dt-bindings/sound/qcom,wcd934x.h b/include/dt-bindings/sound/qcom,wcd934x.h new file mode 100644 index 000000000000..8b30d34fcc87 --- /dev/null +++ b/include/dt-bindings/sound/qcom,wcd934x.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef __DT_SOUND_QCOM_WCD934x_H +#define __DT_SOUND_QCOM_WCD934x_H + +#define AIF1_PB 0 +#define AIF1_CAP 1 +#define AIF2_PB 2 +#define AIF2_CAP 3 +#define AIF3_PB 4 +#define AIF3_CAP 5 +#define AIF4_PB 6 +#define AIF4_VIFEED 7 +#define AIF4_MAD_TX 8 + +#endif From e27c125040b1e1f26d910b46daabbe55e67fdf3b Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Mon, 9 Dec 2024 15:09:06 +0300 Subject: [PATCH 0038/1090] ASoC: codecs: wcd934x: use wcd934x binding header Replace AIF* enum with binding header include. This allow to get rid of mysterious indeces in dts. Signed-off-by: Dzmitry Sankouski Link: https://patch.msgid.link/20241209-starqltechn_integration_upstream-v8-2-ec604481d691@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 910852eb9698..dd0cda394bf1 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -23,6 +23,8 @@ #include "wcd-clsh-v2.h" #include "wcd-mbhc-v2.h" +#include + #define WCD934X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) @@ -307,6 +309,7 @@ {"SLIM TX" #id, NULL, "CDC_IF TX" #id " MUX"} #define WCD934X_MAX_MICBIAS MIC_BIAS_4 +#define NUM_CODEC_DAIS 9 enum { SIDO_SOURCE_INTERNAL, @@ -434,19 +437,6 @@ enum { COMPANDER_MAX, }; -enum { - AIF1_PB = 0, - AIF1_CAP, - AIF2_PB, - AIF2_CAP, - AIF3_PB, - AIF3_CAP, - AIF4_PB, - AIF4_VIFEED, - AIF4_MAD_TX, - NUM_CODEC_DAIS, -}; - enum { INTn_1_INP_SEL_ZERO = 0, INTn_1_INP_SEL_DEC0, From e3cd85963a20d2b92e77046a8d9f0777815f1f71 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Fri, 17 Jan 2025 15:48:59 +0100 Subject: [PATCH 0039/1090] x86/mtrr: Use str_enabled_disabled() helper in print_mtrr_state() Remove hard-coded strings by using the str_enabled_disabled() helper function. Suggested-by: Christophe JAILLET Signed-off-by: Thorsten Blum Signed-off-by: Dave Hansen Link: https://lore.kernel.org/all/20250117144900.171684-2-thorsten.blum%40linux.dev --- arch/x86/kernel/cpu/mtrr/generic.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 2fdfda2b60e4..6be3cade4134 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -646,10 +647,10 @@ static void __init print_mtrr_state(void) pr_info("MTRR default type: %s\n", mtrr_attrib_to_str(mtrr_state.def_type)); if (mtrr_state.have_fixed) { - pr_info("MTRR fixed ranges %sabled:\n", - ((mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && - (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) ? - "en" : "dis"); + pr_info("MTRR fixed ranges %s:\n", + str_enabled_disabled( + (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && + (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))); print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0); for (i = 0; i < 2; ++i) print_fixed(0x80000 + i * 0x20000, 0x04000, @@ -661,8 +662,8 @@ static void __init print_mtrr_state(void) /* tail */ print_fixed_last(); } - pr_info("MTRR variable ranges %sabled:\n", - mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis"); + pr_info("MTRR variable ranges %s:\n", + str_enabled_disabled(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED)); high_width = (boot_cpu_data.x86_phys_bits - (32 - PAGE_SHIFT) + 3) / 4; for (i = 0; i < num_var_ranges; ++i) { From 678681828bf4abfd3c31f36390d2097682141d11 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 5 Feb 2025 14:24:44 +0800 Subject: [PATCH 0040/1090] ASoC: dmic: Add DSD big endian format support Add DSD big endian format support in this generic dmic driver: DSD_U16_BE and DSD_U32_BE. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20250205062444.1694810-1-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/dmic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index 4fd6f97e5a49..0388f115470c 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -85,7 +85,9 @@ static struct snd_soc_dai_driver dmic_dai = { | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_DSD_U8 | SNDRV_PCM_FMTBIT_DSD_U16_LE - | SNDRV_PCM_FMTBIT_DSD_U32_LE, + | SNDRV_PCM_FMTBIT_DSD_U32_LE + | SNDRV_PCM_FMTBIT_DSD_U16_BE + | SNDRV_PCM_FMTBIT_DSD_U32_BE, }, .ops = &dmic_dai_ops, }; From b3d993c7566fed1c027c5c18f3ef482ba8e6307a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 4 Feb 2025 16:33:32 +0100 Subject: [PATCH 0041/1090] ASoC: amd: acp: Use str_low_high() helper function Remove hard-coded strings by using the str_low_high() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250204153333.3045-3-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c index 2b0aa270a3e9..eb5d4a5baef2 100644 --- a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c +++ b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "../acp-mach.h" #include "acp3x-es83xx.h" @@ -241,9 +242,9 @@ static int acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private *priv) dev_info(priv->codec_dev, "speaker gpio %d active %s, headphone gpio %d active %s\n", priv->enable_spk_gpio.crs_entry_index, - priv->enable_spk_gpio.active_low ? "low" : "high", + str_low_high(priv->enable_spk_gpio.active_low), priv->enable_hp_gpio.crs_entry_index, - priv->enable_hp_gpio.active_low ? "low" : "high"); + str_low_high(priv->enable_hp_gpio.active_low)); return 0; } From 3f75771987f32a9f512c8944e70e343f8c6d71c1 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 4 Feb 2025 16:38:04 +0100 Subject: [PATCH 0042/1090] ASoC: SOF: mediatek: Use str_on_off() helper function Remove hard-coded strings by using the str_on_off() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250204153806.3587-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195-clk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/mediatek/mt8195/mt8195-clk.c b/sound/soc/sof/mediatek/mt8195/mt8195-clk.c index 7cffcad00f9b..2c2c4cd323fc 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195-clk.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195-clk.c @@ -8,6 +8,7 @@ #include #include +#include #include "mt8195.h" #include "mt8195-clk.h" #include "../adsp_helper.h" @@ -114,7 +115,7 @@ static int adsp_default_clk_init(struct snd_sof_dev *sdev, bool enable) struct adsp_priv *priv = sdev->pdata->hw_pdata; int ret; - dev_dbg(dev, "%s: %s\n", __func__, enable ? "on" : "off"); + dev_dbg(dev, "%s: %s\n", __func__, str_on_off(enable)); if (enable) { ret = clk_set_parent(priv->clk[CLK_TOP_ADSP], From 185ac20a7b055e025027d303b63dab456b4f5d5e Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 4 Feb 2025 15:52:24 +0800 Subject: [PATCH 0043/1090] ASoC: rt722: get lane mapping property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rt722 supports multi-lane and the driver doesn't call sdw_slave_read_prop() to get all properties. Add sdw_slave_read_lane_mapping() to get the required lane mapping property. Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250204075224.162661-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt722-sdca-sdw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 2b0f82697b47..7a38fcf63143 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -224,6 +224,8 @@ static int rt722_sdca_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn; + sdw_slave_read_lane_mapping(slave); + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; From 6603c5133daadbb3277fbd93be0d0d5b8ec928e8 Mon Sep 17 00:00:00 2001 From: Andrei Simion Date: Mon, 3 Feb 2025 11:11:12 +0200 Subject: [PATCH 0044/1090] ASoC: dt-bindings: atmel,at91-ssc: Convert to YAML format Convert devicetree binding atmel-ssc.txt to YAML format. Update the documentation supported file for MICROCHIP SSC DRIVER. Signed-off-by: Andrei Simion Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250203091111.21667-1-andrei.simion@microchip.com Signed-off-by: Mark Brown --- .../devicetree/bindings/misc/atmel-ssc.txt | 50 --------- .../bindings/sound/atmel,at91-ssc.yaml | 104 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 105 insertions(+), 51 deletions(-) delete mode 100644 Documentation/devicetree/bindings/misc/atmel-ssc.txt create mode 100644 Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt deleted file mode 100644 index f9fb412642fe..000000000000 --- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt +++ /dev/null @@ -1,50 +0,0 @@ -* Atmel SSC driver. - -Required properties: -- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc" - - atmel,at91rm9200-ssc: support pdc transfer - - atmel,at91sam9g45-ssc: support dma transfer -- reg: Should contain SSC registers location and length -- interrupts: Should contain SSC interrupt -- clock-names: tuple listing input clock names. - Required elements: "pclk" -- clocks: phandles to input clocks. - - -Required properties for devices compatible with "atmel,at91sam9g45-ssc": -- dmas: DMA specifier, consisting of a phandle to DMA controller node, - the memory interface and SSC DMA channel ID (for tx and rx). - See Documentation/devicetree/bindings/dma/atmel-dma.txt for details. -- dma-names: Must be "tx", "rx". - -Optional properties: - - atmel,clk-from-rk-pin: bool property. - - When SSC works in slave mode, according to the hardware design, the - clock can get from TK pin, and also can get from RK pin. So, add - this parameter to choose where the clock from. - - By default the clock is from TK pin, if the clock from RK pin, this - property is needed. - - #sound-dai-cells: Should contain <0>. - - This property makes the SSC into an automatically registered DAI. - -Examples: -- PDC transfer: -ssc0: ssc@fffbc000 { - compatible = "atmel,at91rm9200-ssc"; - reg = <0xfffbc000 0x4000>; - interrupts = <14 4 5>; - clocks = <&ssc0_clk>; - clock-names = "pclk"; -}; - -- DMA transfer: -ssc0: ssc@f0010000 { - compatible = "atmel,at91sam9g45-ssc"; - reg = <0xf0010000 0x4000>; - interrupts = <28 4 5>; - dmas = <&dma0 1 13>, - <&dma0 1 14>; - dma-names = "tx", "rx"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>; -}; diff --git a/Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml b/Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml new file mode 100644 index 000000000000..a05e61431824 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/atmel,at91-ssc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel Serial Synchronous Serial (SSC) + +maintainers: + - Andrei Simion + +description: + The Atmel Synchronous Serial Controller (SSC) provides a versatile + synchronous communication link for audio and telecom applications, + supporting protocols like I2S, Short Frame Sync, and Long Frame Sync. + +properties: + compatible: + enum: + - atmel,at91rm9200-ssc + - atmel,at91sam9g45-ssc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: pclk + + dmas: + items: + - description: TX DMA Channel + - description: RX DMA Channel + + dma-names: + items: + - const: tx + - const: rx + + atmel,clk-from-rk-pin: + description: + Specify the clock source for the SSC (Synchronous Serial Controller) + when operating in slave mode. By default, the clock is sourced from + the TK pin. + type: boolean + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + contains: + enum: + - atmel,at91sam9g45-ssc + then: + required: + - dmas + - dma-names + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + ssc@100000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0x100000 0x4000>; + interrupts = <28 IRQ_TYPE_LEVEL_HIGH 5>; + dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(38))>, + <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(39))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 28>; + clock-names = "pclk"; + #sound-dai-cells = <0>; + }; + + ssc@c00000 { + compatible = "atmel,at91rm9200-ssc"; + reg = <0xc00000 0x4000>; + interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 14>; + clock-names = "pclk"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..02f694180faa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15632,7 +15632,7 @@ M: Claudiu Beznea M: Andrei Simion L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported -F: Documentation/devicetree/bindings/misc/atmel-ssc.txt +F: Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml F: drivers/misc/atmel-ssc.c F: include/linux/atmel-ssc.h From 169ec0a541aac8afb215ab591b0fd53276686014 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 11:28:25 +0200 Subject: [PATCH 0045/1090] ASoC: SOF: Relocate and rework functionality for PCM stream freeing Move the sof_pcm_stream_free() from sof-audio.c to pcm.c as static function and add wrapper to free all active stream, which is going to be used in ipc3/4 topology code (removes duplicated code). With this change most of the PCM stream related code is located in one source file for easier lookup and simplified flow. Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206092828.7569-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-topology.c | 20 ++------- sound/soc/sof/ipc4-topology.c | 18 +------- sound/soc/sof/pcm.c | 78 +++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.c | 49 ---------------------- sound/soc/sof/sof-audio.h | 3 +- 5 files changed, 84 insertions(+), 84 deletions(-) diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index e98b53b67d12..473d416bc910 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2386,28 +2386,16 @@ static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) { struct snd_sof_widget *swidget; - struct snd_sof_pcm *spcm; - int dir, ret; + int ret; /* * free all PCMs and their associated DAPM widgets if their connected DAPM widget * list is not NULL. This should only be true for paused streams at this point. * This is equivalent to the handling of FE DAI suspend trigger for running streams. */ - list_for_each_entry(spcm, &sdev->pcm_list, list) { - for_each_pcm_streams(dir) { - struct snd_pcm_substream *substream = spcm->stream[dir].substream; - - if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored) - continue; - - if (spcm->stream[dir].list) { - ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); - if (ret < 0) - return ret; - } - } - } + ret = sof_pcm_free_all_streams(sdev); + if (ret) + return ret; /* * free any left over DAI widgets. This is equivalent to the handling of suspend trigger diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c04c62478827..21e29bfd4b22 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -3401,9 +3401,6 @@ static int sof_ipc4_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai * static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) { - struct snd_sof_pcm *spcm; - int dir, ret; - /* * This function is called during system suspend, we need to make sure * that all streams have been freed up. @@ -3415,21 +3412,8 @@ static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif * * This will also make sure that paused streams handled correctly. */ - list_for_each_entry(spcm, &sdev->pcm_list, list) { - for_each_pcm_streams(dir) { - struct snd_pcm_substream *substream = spcm->stream[dir].substream; - if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored) - continue; - - if (spcm->stream[dir].list) { - ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); - if (ret < 0) - return ret; - } - } - } - return 0; + return sof_pcm_free_all_streams(sdev); } static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 35a7462d8b69..709baa1b0bd6 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -191,6 +191,84 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, return 0; } +static int sof_pcm_stream_free(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + struct snd_sof_pcm *spcm, int dir, + bool free_widget_list) +{ + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); + int ret; + int err = 0; + + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, + SNDRV_PCM_TRIGGER_STOP); + + /* free PCM in the DSP */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(sdev->component, substream); + if (ret < 0) { + dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n", + __func__, ret); + err = ret; + } + } + + spcm->prepared[substream->stream] = false; + spcm->pending_stop[substream->stream] = false; + } + + /* reset the DMA */ + ret = snd_sof_pcm_platform_hw_free(sdev, substream); + if (ret < 0) { + dev_err(sdev->dev, "%s: platform hw free failed %d\n", + __func__, ret); + if (!err) + err = ret; + } + + /* free widget list */ + if (free_widget_list) { + ret = sof_widget_list_free(sdev, spcm, dir); + if (ret < 0) { + dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n", + __func__, ret); + if (!err) + err = ret; + } + } + + return err; +} + +int sof_pcm_free_all_streams(struct snd_sof_dev *sdev) +{ + struct snd_pcm_substream *substream; + struct snd_sof_pcm *spcm; + int dir, ret; + + list_for_each_entry(spcm, &sdev->pcm_list, list) { + for_each_pcm_streams(dir) { + substream = spcm->stream[dir].substream; + + if (!substream || !substream->runtime || + spcm->stream[dir].suspend_ignored) + continue; + + if (spcm->stream[dir].list) { + ret = sof_pcm_stream_free(sdev, substream, spcm, + dir, true); + if (ret < 0) + return ret; + } + } + } + + return 0; +} + static int sof_pcm_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 9a52781bf8d8..a9664b4cf43f 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -829,55 +829,6 @@ bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev) return false; } -int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, - struct snd_sof_pcm *spcm, int dir, bool free_widget_list) -{ - const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); - int ret; - int err = 0; - - if (spcm->prepared[substream->stream]) { - /* stop DMA first if needed */ - if (pcm_ops && pcm_ops->platform_stop_during_hw_free) - snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); - - /* free PCM in the DSP */ - if (pcm_ops && pcm_ops->hw_free) { - ret = pcm_ops->hw_free(sdev->component, substream); - if (ret < 0) { - dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n", - __func__, ret); - err = ret; - } - } - - spcm->prepared[substream->stream] = false; - spcm->pending_stop[substream->stream] = false; - } - - /* reset the DMA */ - ret = snd_sof_pcm_platform_hw_free(sdev, substream); - if (ret < 0) { - dev_err(sdev->dev, "%s: platform hw free failed %d\n", - __func__, ret); - if (!err) - err = ret; - } - - /* free widget list */ - if (free_widget_list) { - ret = sof_widget_list_free(sdev, spcm, dir); - if (ret < 0) { - dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n", - __func__, ret); - if (!err) - err = ret; - } - } - - return err; -} - /* * Generic object lookup APIs. */ diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 62f3c11a9216..7d4810924682 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -649,8 +649,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); -int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, - struct snd_sof_pcm *spcm, int dir, bool free_widget_list); +int sof_pcm_free_all_streams(struct snd_sof_dev *sdev); int get_token_u32(void *elem, void *object, u32 offset); int get_token_u16(void *elem, void *object, u32 offset); int get_token_comp_format(void *elem, void *object, u32 offset); From 4d2ea16576c8aa1437048cf436bff85653f139fe Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 11:28:26 +0200 Subject: [PATCH 0046/1090] ASoC: SOF: pcm: Move period/buffer configuration print after platform open The platform specific pcm_open call via snd_sof_pcm_platform_open() can modify the initial buffer configuration via constraints. Move the prints as last step in the sof_pcm_open() function to reflect the final setup. Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206092828.7569-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 709baa1b0bd6..d09be241e95e 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -536,15 +536,6 @@ static int sof_pcm_open(struct snd_soc_component *component, */ runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); - dev_dbg(component->dev, "period min %zd max %zd bytes\n", - runtime->hw.period_bytes_min, - runtime->hw.period_bytes_max); - dev_dbg(component->dev, "period count %d max %d\n", - runtime->hw.periods_min, - runtime->hw.periods_max); - dev_dbg(component->dev, "buffer max %zd bytes\n", - runtime->hw.buffer_bytes_max); - /* set wait time - TODO: come from topology */ substream->wait_time = 500; @@ -554,10 +545,21 @@ static int sof_pcm_open(struct snd_soc_component *component, spcm->prepared[substream->stream] = false; ret = snd_sof_pcm_platform_open(sdev, substream); - if (ret < 0) + if (ret < 0) { dev_err(component->dev, "error: pcm open failed %d\n", ret); + return ret; + } - return ret; + dev_dbg(component->dev, "period bytes min %zd, max %zd\n", + runtime->hw.period_bytes_min, + runtime->hw.period_bytes_max); + dev_dbg(component->dev, "period count min %d, max %d\n", + runtime->hw.periods_min, + runtime->hw.periods_max); + dev_dbg(component->dev, "buffer bytes max %zd\n", + runtime->hw.buffer_bytes_max); + + return 0; } static int sof_pcm_close(struct snd_soc_component *component, From 860693187c597645b28a421d8acb26428b8afd3f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 11:28:27 +0200 Subject: [PATCH 0047/1090] ASoC: SOF: pcm: Add snd_sof_pcm specific wrappers for dev_dbg() and dev_err() Introduce spcm_dbg() and spcm_err() macros to provide consistent printing for debug and error messages which includes usable information in the print's prefix. Update the prints in pcm.c, ipc3-pcm.c and ipc4-pcm.c to take advantage of the features provided by the macros. Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206092828.7569-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-pcm.c | 13 +++--- sound/soc/sof/ipc4-pcm.c | 16 ++++--- sound/soc/sof/pcm.c | 95 +++++++++++++++++---------------------- sound/soc/sof/sof-audio.h | 14 ++++++ 4 files changed, 72 insertions(+), 66 deletions(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index 1c1b8f595367..90ef5d99f626 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -117,22 +117,23 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, if (platform_params->cont_update_posn) pcm.params.cont_update_posn = 1; - dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); + spcm_dbg(spcm, substream->stream, "stream_tag %d\n", + pcm.params.stream_tag); /* send hw_params IPC to the DSP */ ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm), &ipc_params_reply, sizeof(ipc_params_reply)); if (ret < 0) { - dev_err(component->dev, "HW params ipc failed for stream %d\n", - pcm.params.stream_tag); + spcm_err(spcm, substream->stream, + "STREAM_PCM_PARAMS ipc failed for stream_tag %d\n", + pcm.params.stream_tag); return ret; } ret = snd_sof_set_stream_data_offset(sdev, &spcm->stream[substream->stream], ipc_params_reply.posn_offset); if (ret < 0) { - dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n", - __func__, spcm->pcm.pcm_id); + spcm_err(spcm, substream->stream, "invalid stream data offset\n"); return ret; } @@ -171,7 +172,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; break; default: - dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); + spcm_err(spcm, substream->stream, "Unhandled trigger cmd %d\n", cmd); return -EINVAL; } diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 18fff2df76f9..5ec109094031 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -313,7 +313,7 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, set_fifo_size = false; break; default: - dev_err(sdev->dev, "Unexpected state %d", state); + spcm_err(spcm, direction, "Unexpected pipeline state %d\n", state); return -EINVAL; } @@ -333,8 +333,8 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, struct sof_ipc4_pipeline *pipeline = pipe_widget->private; if (!pipeline->use_chain_dma) { - dev_err(sdev->dev, - "All pipelines in chained DMA stream should have use_chain_dma attribute set."); + spcm_err(spcm, direction, + "All pipelines in chained DMA path should have use_chain_dma attribute set."); return -EINVAL; } @@ -389,12 +389,12 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, int ret; int i; - dev_dbg(sdev->dev, "trigger cmd: %d state: %d\n", cmd, state); - spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return -EINVAL; + spcm_dbg(spcm, substream->stream, "cmd: %d, state: %d\n", cmd, state); + pipeline_list = &spcm->stream[substream->stream].pipeline_list; /* nothing to trigger if the list is empty */ @@ -465,7 +465,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, */ ret = sof_ipc4_set_multi_pipeline_state(sdev, SOF_IPC4_PIPE_PAUSED, trigger_list); if (ret < 0) { - dev_err(sdev->dev, "failed to pause all pipelines\n"); + spcm_err(spcm, substream->stream, "failed to pause all pipelines\n"); goto free; } @@ -494,7 +494,9 @@ skip_pause_transition: /* else set the RUNNING/RESET state in the DSP */ ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list); if (ret < 0) { - dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state); + spcm_err(spcm, substream->stream, + "failed to set final state %d for all pipelines\n", + state); /* * workaround: if the firmware is crashed while setting the * pipelines to reset state we must ignore the error code and diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d09be241e95e..372ed71a17aa 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -99,8 +99,8 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list, dpcm_end_walk_at_be); if (ret < 0) { - dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name, - snd_pcm_direction_name(dir)); + spcm_err(spcm, dir, "dai %s has no valid %s path\n", + dai->name, snd_pcm_direction_name(dir)); return ret; } @@ -108,8 +108,7 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir); if (ret < 0) { - dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n", - spcm->pcm.pcm_id, dir); + spcm_err(spcm, dir, "Widget list set up failed\n"); spcm->stream[dir].list = NULL; snd_soc_dapm_dai_free_widgets(&list); return ret; @@ -139,6 +138,8 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, if (!spcm) return -EINVAL; + spcm_dbg(spcm, substream->stream, "Entry: hw_params\n"); + /* * Handle repeated calls to hw_params() without free_pcm() in * between. At least ALSA OSS emulation depends on this. @@ -151,12 +152,9 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, spcm->prepared[substream->stream] = false; } - dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", - spcm->pcm.pcm_id, substream->stream); - ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params); if (ret < 0) { - dev_err(component->dev, "platform hw params failed\n"); + spcm_err(spcm, substream->stream, "platform hw params failed\n"); return ret; } @@ -210,8 +208,8 @@ static int sof_pcm_stream_free(struct snd_sof_dev *sdev, if (pcm_ops && pcm_ops->hw_free) { ret = pcm_ops->hw_free(sdev->component, substream); if (ret < 0) { - dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n", - __func__, ret); + spcm_err(spcm, substream->stream, + "pcm_ops->hw_free failed %d\n", ret); err = ret; } } @@ -223,8 +221,8 @@ static int sof_pcm_stream_free(struct snd_sof_dev *sdev, /* reset the DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) { - dev_err(sdev->dev, "%s: platform hw free failed %d\n", - __func__, ret); + spcm_err(spcm, substream->stream, + "platform hw free failed %d\n", ret); if (!err) err = ret; } @@ -233,8 +231,8 @@ static int sof_pcm_stream_free(struct snd_sof_dev *sdev, if (free_widget_list) { ret = sof_widget_list_free(sdev, spcm, dir); if (ret < 0) { - dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n", - __func__, ret); + spcm_err(spcm, substream->stream, + "sof_widget_list_free failed %d\n", ret); if (!err) err = ret; } @@ -285,8 +283,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, if (!spcm) return -EINVAL; - dev_dbg(component->dev, "pcm: free stream %d dir %d\n", - spcm->pcm.pcm_id, substream->stream); + spcm_dbg(spcm, substream->stream, "Entry: hw_free\n"); ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); @@ -311,6 +308,8 @@ static int sof_pcm_prepare(struct snd_soc_component *component, if (!spcm) return -EINVAL; + spcm_dbg(spcm, substream->stream, "Entry: prepare\n"); + if (spcm->prepared[substream->stream]) { if (!spcm->pending_stop[substream->stream]) return 0; @@ -324,15 +323,12 @@ static int sof_pcm_prepare(struct snd_soc_component *component, return ret; } - dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", - spcm->pcm.pcm_id, substream->stream); - /* set hw_params */ ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]); if (ret < 0) { - dev_err(component->dev, - "error: set pcm hw_params after resume\n"); + spcm_err(spcm, substream->stream, + "failed to set hw_params after resume\n"); return ret; } @@ -362,8 +358,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, if (!spcm) return -EINVAL; - dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", - spcm->pcm.pcm_id, substream->stream, cmd); + spcm_dbg(spcm, substream->stream, "Entry: trigger (cmd: %d)\n", cmd); spcm->pending_stop[substream->stream] = false; @@ -412,7 +407,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, reset_hw_params = true; break; default: - dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); + spcm_err(spcm, substream->stream, "Unhandled trigger cmd %d\n", cmd); return -EINVAL; } @@ -514,9 +509,7 @@ static int sof_pcm_open(struct snd_soc_component *component, if (!spcm) return -EINVAL; - dev_dbg(component->dev, "pcm: open stream %d dir %d\n", - spcm->pcm.pcm_id, substream->stream); - + spcm_dbg(spcm, substream->stream, "Entry: open\n"); caps = &spcm->pcm.caps[substream->stream]; @@ -546,18 +539,16 @@ static int sof_pcm_open(struct snd_soc_component *component, ret = snd_sof_pcm_platform_open(sdev, substream); if (ret < 0) { - dev_err(component->dev, "error: pcm open failed %d\n", ret); + spcm_err(spcm, substream->stream, + "platform pcm open failed %d\n", ret); return ret; } - dev_dbg(component->dev, "period bytes min %zd, max %zd\n", - runtime->hw.period_bytes_min, - runtime->hw.period_bytes_max); - dev_dbg(component->dev, "period count min %d, max %d\n", - runtime->hw.periods_min, - runtime->hw.periods_max); - dev_dbg(component->dev, "buffer bytes max %zd\n", - runtime->hw.buffer_bytes_max); + spcm_dbg(spcm, substream->stream, "period bytes min %zd, max %zd\n", + runtime->hw.period_bytes_min, runtime->hw.period_bytes_max); + spcm_dbg(spcm, substream->stream, "period count min %d, max %d\n", + runtime->hw.periods_min, runtime->hw.periods_max); + spcm_dbg(spcm, substream->stream, "buffer bytes max %zd\n", runtime->hw.buffer_bytes_max); return 0; } @@ -578,13 +569,12 @@ static int sof_pcm_close(struct snd_soc_component *component, if (!spcm) return -EINVAL; - dev_dbg(component->dev, "pcm: close stream %d dir %d\n", - spcm->pcm.pcm_id, substream->stream); + spcm_dbg(spcm, substream->stream, "Entry: close\n"); err = snd_sof_pcm_platform_close(sdev, substream); if (err < 0) { - dev_err(component->dev, "error: pcm close failed %d\n", - err); + spcm_err(spcm, substream->stream, + "platform pcm close failed %d\n", err); /* * keep going, no point in preventing the close * from happening @@ -616,7 +606,8 @@ static int sof_pcm_new(struct snd_soc_component *component, return 0; } - dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); + dev_dbg(spcm->scomp->dev, "pcm%u (%s): Entry: pcm_construct\n", + spcm->pcm.pcm_id, spcm->pcm.pcm_name); /* do we need to pre-allocate playback audio buffer pages */ if (!spcm->pcm.playback) @@ -624,16 +615,15 @@ static int sof_pcm_new(struct snd_soc_component *component, caps = &spcm->pcm.caps[stream]; - /* pre-allocate playback audio buffer pages */ - dev_dbg(component->dev, - "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n", - caps->name, caps->buffer_size_min, caps->buffer_size_max); - if (!pcm->streams[stream].substream) { - dev_err(component->dev, "error: NULL playback substream!\n"); + spcm_err(spcm, stream, "NULL playback substream!\n"); return -EINVAL; } + /* pre-allocate playback audio buffer pages */ + spcm_dbg(spcm, stream, "allocate %s playback DMA buffer size 0x%x max 0x%x\n", + caps->name, caps->buffer_size_min, caps->buffer_size_max); + snd_pcm_set_managed_buffer(pcm->streams[stream].substream, SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 0, le32_to_cpu(caps->buffer_size_max)); @@ -646,16 +636,15 @@ capture: caps = &spcm->pcm.caps[stream]; - /* pre-allocate capture audio buffer pages */ - dev_dbg(component->dev, - "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", - caps->name, caps->buffer_size_min, caps->buffer_size_max); - if (!pcm->streams[stream].substream) { - dev_err(component->dev, "error: NULL capture substream!\n"); + spcm_err(spcm, stream, "NULL capture substream!\n"); return -EINVAL; } + /* pre-allocate capture audio buffer pages */ + spcm_dbg(spcm, stream, "allocate %s capture DMA buffer size 0x%x max 0x%x\n", + caps->name, caps->buffer_size_min, caps->buffer_size_max); + snd_pcm_set_managed_buffer(pcm->streams[stream].substream, SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 0, le32_to_cpu(caps->buffer_size_max)); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 7d4810924682..36ab75e11779 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -617,6 +617,20 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_soc_component *scomp, void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream); void snd_sof_pcm_init_elapsed_work(struct work_struct *work); +/* + * snd_sof_pcm specific wrappers for dev_dbg() and dev_err() to provide + * consistent and useful prints. + */ +#define spcm_dbg(__spcm, __dir, __fmt, ...) \ + dev_dbg((__spcm)->scomp->dev, "pcm%u (%s), dir %d: " __fmt, \ + (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \ + ##__VA_ARGS__) + +#define spcm_err(__spcm, __dir, __fmt, ...) \ + dev_err((__spcm)->scomp->dev, "%s: pcm%u (%s), dir %d: " __fmt, \ + __func__, (__spcm)->pcm.pcm_id, (__spcm)->pcm.pcm_name, __dir, \ + ##__VA_ARGS__) + #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream); void snd_sof_compr_init_elapsed_work(struct work_struct *work); From 583348bd65ceaf4a5067a6267dd236929e1b4b37 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 11:28:28 +0200 Subject: [PATCH 0048/1090] ASoC: SOF: ipc4-topology: Improve the information in prepare_copier prints It is useful to know the explicit type and if the copier (host/dai) is configured to use ChainDMA or not and also the stream_tag for the host copier. Change the prints to carry more information for debugging purposes. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206092828.7569-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 21e29bfd4b22..a23f55ed5696 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1815,15 +1815,19 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, bool single_output_bitdepth; int i; - dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); - switch (swidget->id) { case snd_soc_dapm_aif_in: case snd_soc_dapm_aif_out: { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; struct sof_ipc4_gtw_attributes *gtw_attr; - struct snd_sof_widget *pipe_widget; - struct sof_ipc4_pipeline *pipeline; + + dev_dbg(sdev->dev, + "Host copier %s, type %d, ChainDMA: %s, stream_tag: %d\n", + swidget->widget->name, swidget->id, + str_yes_no(pipeline->use_chain_dma), + platform_params->stream_tag); /* parse the deep buffer dma size */ ret = sof_update_ipc_object(scomp, &deep_buffer_dma_ms, @@ -1840,9 +1844,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - pipe_widget = swidget->spipe->pipe_widget; - pipeline = pipe_widget->private; - if (pipeline->use_chain_dma) { u32 host_dma_id; u32 fifo_size; @@ -1896,6 +1897,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + dev_dbg(sdev->dev, "Dai copier %s, type %d, ChainDMA: %s\n", + swidget->widget->name, swidget->id, + str_yes_no(pipeline->use_chain_dma)); + if (pipeline->use_chain_dma) return 0; @@ -1929,6 +1934,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } case snd_soc_dapm_buffer: { + dev_dbg(sdev->dev, "Module copier %s, type %d\n", + swidget->widget->name, swidget->id); + ipc4_copier = (struct sof_ipc4_copier *)swidget->private; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; From 72826381215e2f9d2bd2f32f63f76a80942b7fdf Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 6 Feb 2025 16:52:22 +0530 Subject: [PATCH 0049/1090] ASoC: dt-bindings: wcd937x-sdw: Add static channel mapping support Add static channel mapping between master and slave rx/tx ports for Qualcomm wcd937x soundwire codec. Currently, the channel map index value for each soundwire port is hardcoded in the wcd937x-sdw driver, and the same channel map index value is configured in the soundwire master. The Qualcomm board like the QCM6490-IDP require static channel map settings for the soundwire master and slave ports. If another boards which are using enable wcd937x, the channel mapping index values between master and slave may be different depending on the board hw design and requirements. If the above properties are not used in a SoC specific device tree, the channel mapping index values are set to default. With the introduction of the following channel mapping properties, it is now possible to configure the master channel mapping directly from the device tree. The qcom,tx-channel-mapping property specifies the static channel mapping between the slave and master tx ports in the order of slave port channels which is adc1, adc2, adc3, adc4, dmic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7. The qcom,rx-channel-mapping property specifies the static channel mapping between the slave and master rx ports in the order of slave port channels which is hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l. Signed-off-by: Mohammad Rafi Shaik Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250206112225.3270400-2-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- .../bindings/sound/qcom,wcd937x-sdw.yaml | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd937x-sdw.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd937x-sdw.yaml index d3cf8f59cb23..c8543f969ebb 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wcd937x-sdw.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wcd937x-sdw.yaml @@ -58,6 +58,40 @@ properties: items: enum: [1, 2, 3, 4, 5] + qcom,tx-channel-mapping: + description: | + Specifies static channel mapping between slave and master tx port + channels. + In the order of slave port channels which is adc1, adc2, adc3, + dmic0, dmic1, mbhc, dmic2, dmic3, dmci4, dmic5, dmic6, dmic7. + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 12 + maxItems: 12 + additionalItems: false + items: + enum: + - 1 # WCD9370_SWRM_CH1 + - 2 # WCD9370_SWRM_CH2 + - 3 # WCD9370_SWRM_CH3 + - 4 # WCD9370_SWRM_CH4 + + qcom,rx-channel-mapping: + description: | + Specifies static channels mapping between slave and master rx port + channels. + In the order of slave port channels, which is + hph_l, hph_r, clsh, comp_l, comp_r, lo, dsd_r, dsd_l. + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 8 + maxItems: 8 + additionalItems: false + items: + enum: + - 1 # WCD9370_SWRM_CH1 + - 2 # WCD9370_SWRM_CH2 + - 3 # WCD9370_SWRM_CH3 + - 4 # WCD9370_SWRM_CH4 + required: - compatible - reg @@ -74,6 +108,7 @@ examples: compatible = "sdw20217010a00"; reg = <0 4>; qcom,rx-port-mapping = <1 2 3 4 5>; + qcom,rx-channel-mapping = /bits/ 8 <1 2 1 1 2 1 1 2>; }; }; @@ -85,6 +120,7 @@ examples: compatible = "sdw20217010a00"; reg = <0 3>; qcom,tx-port-mapping = <2 2 3 4>; + qcom,tx-channel-mapping = /bits/ 8 <1 2 1 1 2 3 3 4 1 2 3 4>; }; }; From c06c4f7cbea1d8dc71485bfddef2849a1b721e67 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 6 Feb 2025 16:52:23 +0530 Subject: [PATCH 0050/1090] ASoC: codecs: wcd937x: Add static channel mapping support in wcd937x-sdw Add static channel mapping between master and slave ports in wcd937x-sdw driver. Currently, the channel mask for each soundwire port is hardcoded in the wcd937x-sdw driver, and the same channel mask value is configured in the soundwire master. The Qualcomm boards like the QCM6490-IDP require different channel mask settings for the soundwire master and slave ports. Implemented logic to read TX/RX channel mappings from device tree properties (qcom,tx-channel-mapping and qcom,rx-channel-mapping). Modified the wcd937x_connect_port to handle master channel masks during port enable/disable operations. Added wcd937x_get_channel_map api to retrieve the current master channel map for TX and RX paths. Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20250206112225.3270400-3-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd937x-sdw.c | 39 ++++++++++++++++++++++--- sound/soc/codecs/wcd937x.c | 53 ++++++++++++++++++++++++++++++++-- sound/soc/codecs/wcd937x.h | 7 ++++- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c index 0c33f7f3dc25..1fbff313b965 100644 --- a/sound/soc/codecs/wcd937x-sdw.c +++ b/sound/soc/codecs/wcd937x-sdw.c @@ -19,7 +19,7 @@ #include #include "wcd937x.h" -static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { +static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD937X_HPH_L, WCD937X_HPH_PORT, BIT(0)), WCD_SDW_CH(WCD937X_HPH_R, WCD937X_HPH_PORT, BIT(1)), WCD_SDW_CH(WCD937X_CLSH, WCD937X_CLSH_PORT, BIT(0)), @@ -30,7 +30,7 @@ static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { WCD_SDW_CH(WCD937X_DSD_R, WCD937X_DSD_PORT, BIT(1)), }; -static const struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = { +static struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = { WCD_SDW_CH(WCD937X_ADC1, WCD937X_ADC_1_PORT, BIT(0)), WCD_SDW_CH(WCD937X_ADC2, WCD937X_ADC_2_3_PORT, BIT(0)), WCD_SDW_CH(WCD937X_ADC3, WCD937X_ADC_2_3_PORT, BIT(0)), @@ -1019,7 +1019,9 @@ static int wcd9370_probe(struct sdw_slave *pdev, { struct device *dev = &pdev->dev; struct wcd937x_sdw_priv *wcd; - int ret; + u8 master_ch_mask[WCD937X_MAX_SWR_CH_IDS]; + int master_ch_mask_size = 0; + int ret, i; wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); if (!wcd) @@ -1048,10 +1050,36 @@ static int wcd9370_probe(struct sdw_slave *pdev, SDW_SCP_INT1_PARITY; pdev->prop.lane_control_support = true; pdev->prop.simple_clk_stop_capable = true; + + memset(master_ch_mask, 0, WCD937X_MAX_SWR_CH_IDS); + if (wcd->is_tx) { - pdev->prop.source_ports = GENMASK(WCD937X_MAX_TX_SWR_PORTS - 1, 0); + master_ch_mask_size = of_property_count_u8_elems(dev->of_node, + "qcom,tx-channel-mapping"); + + if (master_ch_mask_size) + ret = of_property_read_u8_array(dev->of_node, "qcom,tx-channel-mapping", + master_ch_mask, master_ch_mask_size); + } else { + master_ch_mask_size = of_property_count_u8_elems(dev->of_node, + "qcom,rx-channel-mapping"); + + if (master_ch_mask_size) + ret = of_property_read_u8_array(dev->of_node, "qcom,rx-channel-mapping", + master_ch_mask, master_ch_mask_size); + } + + if (ret < 0) + dev_info(dev, "Static channel mapping not specified using device channel maps\n"); + + if (wcd->is_tx) { + pdev->prop.source_ports = GENMASK(WCD937X_MAX_TX_SWR_PORTS, 0); pdev->prop.src_dpn_prop = wcd937x_dpn_prop; wcd->ch_info = &wcd937x_sdw_tx_ch_info[0]; + + for (i = 0; i < master_ch_mask_size; i++) + wcd->ch_info[i].master_ch_mask = WCD937X_SWRM_CH_MASK(master_ch_mask[i]); + pdev->prop.wake_capable = true; wcd->regmap = devm_regmap_init_sdw(pdev, &wcd937x_regmap_config); @@ -1065,6 +1093,9 @@ static int wcd9370_probe(struct sdw_slave *pdev, pdev->prop.sink_ports = GENMASK(WCD937X_MAX_SWR_PORTS - 1, 0); pdev->prop.sink_dpn_prop = wcd937x_dpn_prop; wcd->ch_info = &wcd937x_sdw_rx_ch_info[0]; + + for (i = 0; i < master_ch_mask_size; i++) + wcd->ch_info[i].master_ch_mask = WCD937X_SWRM_CH_MASK(master_ch_mask[i]); } diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index c9d5e67bf66e..e8d3fddbc7b1 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -1197,13 +1197,21 @@ static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id]; u8 port_num = ch_info->port_num; u8 ch_mask = ch_info->ch_mask; + u8 mstr_port_num, mstr_ch_mask; + struct sdw_slave *sdev = wcd->sdev; port_config->num = port_num; - if (enable) + mstr_port_num = sdev->m_port_map[port_num]; + mstr_ch_mask = ch_info->master_ch_mask; + + if (enable) { port_config->ch_mask |= ch_mask; - else + wcd->master_channel_map[mstr_port_num] |= mstr_ch_mask; + } else { port_config->ch_mask &= ~ch_mask; + wcd->master_channel_map[mstr_port_num] &= ~mstr_ch_mask; + } return 0; } @@ -2689,10 +2697,51 @@ static int wcd937x_codec_set_sdw_stream(struct snd_soc_dai *dai, return 0; } +static int wcd937x_get_channel_map(const struct snd_soc_dai *dai, + unsigned int *tx_num, unsigned int *tx_slot, + unsigned int *rx_num, unsigned int *rx_slot) +{ + struct wcd937x_priv *wcd937x = dev_get_drvdata(dai->dev); + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[dai->id]; + int i; + + switch (dai->id) { + case AIF1_PB: + if (!rx_slot || !rx_num) { + dev_err(dai->dev, "Invalid rx_slot %p or rx_num %p\n", + rx_slot, rx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + rx_slot[i] = wcd->master_channel_map[i]; + + *rx_num = i; + break; + case AIF1_CAP: + if (!tx_slot || !tx_num) { + dev_err(dai->dev, "Invalid tx_slot %p or tx_num %p\n", + tx_slot, tx_num); + return -EINVAL; + } + + for (i = 0; i < SDW_MAX_PORTS; i++) + tx_slot[i] = wcd->master_channel_map[i]; + + *tx_num = i; + break; + default: + break; + } + + return 0; +} + static const struct snd_soc_dai_ops wcd937x_sdw_dai_ops = { .hw_params = wcd937x_codec_hw_params, .hw_free = wcd937x_codec_free, .set_stream = wcd937x_codec_set_sdw_stream, + .get_channel_map = wcd937x_get_channel_map, }; static struct snd_soc_dai_driver wcd937x_dais[] = { diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h index 4afa48dcaf74..4ef57c496c37 100644 --- a/sound/soc/codecs/wcd937x.h +++ b/sound/soc/codecs/wcd937x.h @@ -489,6 +489,7 @@ #define WCD937X_MAX_MICBIAS 3 #define WCD937X_MAX_BULK_SUPPLY 4 #define WCD937X_MAX_SWR_CH_IDS 15 +#define WCD937X_SWRM_CH_MASK(ch_idx) BIT(ch_idx - 1) enum wcd937x_tx_sdw_ports { WCD937X_ADC_1_PORT = 1, @@ -510,12 +511,14 @@ enum wcd937x_rx_sdw_ports { struct wcd937x_sdw_ch_info { int port_num; unsigned int ch_mask; + unsigned int master_ch_mask; }; #define WCD_SDW_CH(id, pn, cmask) \ [id] = { \ .port_num = pn, \ .ch_mask = cmask, \ + .master_ch_mask = cmask, \ } struct wcd937x_priv; @@ -524,9 +527,11 @@ struct wcd937x_sdw_priv { struct sdw_stream_config sconfig; struct sdw_stream_runtime *sruntime; struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS]; - const struct wcd937x_sdw_ch_info *ch_info; + struct wcd937x_sdw_ch_info *ch_info; bool port_enable[WCD937X_MAX_SWR_CH_IDS]; + unsigned int master_channel_map[SDW_MAX_PORTS]; int active_ports; + int num_ports; bool is_tx; struct wcd937x_priv *wcd937x; struct irq_domain *slave_irq; From 7796c97df6b1b2206681a07f3c80f6023a6593d5 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 6 Feb 2025 16:52:24 +0530 Subject: [PATCH 0051/1090] soundwire: qcom: Add set_channel_map api support Added qcom_swrm_set_channel_map api to set the master channel mask for TX and RX paths based on the provided slots. Added a new field ch_mask to the qcom_swrm_port_config structure. This field is used to store the master channel mask, which allows more flexible to configure channel mask in runtime for specific active soundwire ports. Modified the qcom_swrm_port_enable function to configure master channel mask. If the ch_mask is set to SWR_INVALID_PARAM or is zero, the function will use the default channel mask. Signed-off-by: Mohammad Rafi Shaik Acked-by: Vinod Koul Link: https://patch.msgid.link/20250206112225.3270400-4-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- drivers/soundwire/qcom.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 0f45e3404756..295a46dc2be7 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -156,6 +156,7 @@ struct qcom_swrm_port_config { u8 word_length; u8 blk_group_count; u8 lane_control; + u8 ch_mask; }; /* @@ -1048,9 +1049,13 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus, { u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank); struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); + struct qcom_swrm_port_config *pcfg; u32 val; + pcfg = &ctrl->pconfig[enable_ch->port_num]; ctrl->reg_read(ctrl, reg, &val); + if (pcfg->ch_mask != SWR_INVALID_PARAM && pcfg->ch_mask != 0) + enable_ch->ch_mask = pcfg->ch_mask; if (enable_ch->enable) val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); @@ -1270,6 +1275,26 @@ static void *qcom_swrm_get_sdw_stream(struct snd_soc_dai *dai, int direction) return ctrl->sruntime[dai->id]; } +static int qcom_swrm_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot) +{ + struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); + int i; + + if (tx_slot) { + for (i = 0; i < tx_num; i++) + ctrl->pconfig[i].ch_mask = tx_slot[i]; + } + + if (rx_slot) { + for (i = 0; i < rx_num; i++) + ctrl->pconfig[i].ch_mask = rx_slot[i]; + } + + return 0; +} + static int qcom_swrm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -1306,6 +1331,7 @@ static const struct snd_soc_dai_ops qcom_swrm_pdm_dai_ops = { .shutdown = qcom_swrm_shutdown, .set_stream = qcom_swrm_set_sdw_stream, .get_stream = qcom_swrm_get_sdw_stream, + .set_channel_map = qcom_swrm_set_channel_map, }; static const struct snd_soc_component_driver qcom_swrm_dai_component = { From 0e9a970d7b2cb98d741bc0e32ad8c8f30c009c63 Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Thu, 6 Feb 2025 16:52:25 +0530 Subject: [PATCH 0052/1090] ASoC: qcom: sdw: Add get and set channel maps support from codec to cpu dais Add get and set channel maps support from codec to cpu dais. Implemented logic to get the channel map in case of only sdw stream and set channel map only for specific cpu dais. Signed-off-by: Mohammad Rafi Shaik Link: https://patch.msgid.link/20250206112225.3270400-5-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- sound/soc/qcom/sdw.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index f2eda2ff46c0..1d01b9329e08 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -23,9 +23,11 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + u32 rx_ch[SDW_MAX_PORTS], tx_ch[SDW_MAX_PORTS]; struct sdw_stream_runtime *sruntime; struct snd_soc_dai *codec_dai; - int ret, i; + u32 rx_ch_cnt = 0, tx_ch_cnt = 0; + int ret, i, j; sruntime = sdw_alloc_stream(cpu_dai->name); if (!sruntime) @@ -35,9 +37,35 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream) ret = snd_soc_dai_set_stream(codec_dai, sruntime, substream->stream); if (ret < 0 && ret != -ENOTSUPP) { - dev_err(rtd->dev, "Failed to set sdw stream on %s\n", - codec_dai->name); + dev_err(rtd->dev, "Failed to set sdw stream on %s\n", codec_dai->name); goto err_set_stream; + } else if (ret == -ENOTSUPP) { + /* Ignore unsupported */ + continue; + } + + ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, + &rx_ch_cnt, rx_ch); + if (ret != 0 && ret != -ENOTSUPP) { + dev_err(rtd->dev, "Failed to get codec chan map %s\n", codec_dai->name); + goto err_set_stream; + } else if (ret == -ENOTSUPP) { + /* Ignore unsupported */ + continue; + } + } + + switch (cpu_dai->id) { + case RX_CODEC_DMA_RX_0: + case TX_CODEC_DMA_TX_3: + if (tx_ch_cnt || rx_ch_cnt) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { + ret = snd_soc_dai_set_channel_map(codec_dai, + tx_ch_cnt, tx_ch, + rx_ch_cnt, rx_ch); + if (ret != 0 && ret != -ENOTSUPP) + goto err_set_stream; + } } } From 78e66dd5f32a1a8e5ee6decadd4e4dffa7d2c40d Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 6 Feb 2025 01:40:28 +0000 Subject: [PATCH 0053/1090] ASoC: mediatek: mt8186: Remove unused mt8186_afe_(suspend|resume)_clock mt8186_afe_resume_clock() and mt8186_afe_suspend_clock() were added in 2022 by commit 55b423d5623c ("ASoC: mediatek: mt8186: support audio clock control in platform driver") but have remained unused. Remove them. Signed-off-by: Dr. David Alan Gilbert Link: https://patch.msgid.link/20250206014028.237423-1-linux@treblig.org Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 55 ---------------------- sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 2 - 2 files changed, 57 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c index 70ec101890d3..daaca36a2d08 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c @@ -329,61 +329,6 @@ void mt8186_afe_disable_clock(struct mtk_base_afe *afe) clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); } -int mt8186_afe_suspend_clock(struct mtk_base_afe *afe) -{ - struct mt8186_afe_private *afe_priv = afe->platform_priv; - int ret; - - /* set audio int bus to 26M */ - ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - if (ret) { - dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", - __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); - goto clk_mux_audio_intbus_err; - } - ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); - if (ret) - goto clk_mux_audio_intbus_parent_err; - - clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - - return 0; - -clk_mux_audio_intbus_parent_err: - mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4); -clk_mux_audio_intbus_err: - clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - return ret; -} - -int mt8186_afe_resume_clock(struct mtk_base_afe *afe) -{ - struct mt8186_afe_private *afe_priv = afe->platform_priv; - int ret; - - /* set audio int bus to normal working clock */ - ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - if (ret) { - dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", - __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); - goto clk_mux_audio_intbus_err; - } - ret = mt8186_set_audio_int_bus_parent(afe, - CLK_TOP_MAINPLL_D2_D4); - if (ret) - goto clk_mux_audio_intbus_parent_err; - - clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - - return 0; - -clk_mux_audio_intbus_parent_err: - mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); -clk_mux_audio_intbus_err: - clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); - return ret; -} - int mt8186_apll1_enable(struct mtk_base_afe *afe) { struct mt8186_afe_private *afe_priv = afe->platform_priv; diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h index a9d59e506d9a..e524833ce780 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h @@ -85,8 +85,6 @@ int mt8186_afe_enable_cgs(struct mtk_base_afe *afe); void mt8186_afe_disable_cgs(struct mtk_base_afe *afe); int mt8186_afe_enable_clock(struct mtk_base_afe *afe); void mt8186_afe_disable_clock(struct mtk_base_afe *afe); -int mt8186_afe_suspend_clock(struct mtk_base_afe *afe); -int mt8186_afe_resume_clock(struct mtk_base_afe *afe); int mt8186_apll1_enable(struct mtk_base_afe *afe); void mt8186_apll1_disable(struct mtk_base_afe *afe); From ecfcee245cc99def0f6bf84ac75ac372f8ab65eb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 6 Feb 2025 01:52:16 +0900 Subject: [PATCH 0054/1090] ASoC: dapm: unexport snd_soc_dapm_init() The symbol provider (sound/soc/soc-dapm.c) and the symbol consumer (sound/soc/soc-core.c) belong to the same module, snd-soc-core.ko. There is no need to export it. Signed-off-by: Masahiro Yamada Link: https://patch.msgid.link/20250205165226.3466137-1-masahiroy@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b5116b700d73..3fa53ce80189 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4865,7 +4865,6 @@ void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, /* see for_each_card_dapms */ list_add(&dapm->list, &card->dapm_list); } -EXPORT_SYMBOL_GPL(snd_soc_dapm_init); static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) { From 3f78762d17701f0435ad958b2821dc3243ff34b3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 6 Feb 2025 01:53:34 +0900 Subject: [PATCH 0055/1090] ASoC: dapm: unexport snd_soc_dapm_update_dai() The symbol provider (sound/soc/soc-dapm.c) and the symbol consumer (sound/soc/soc-pcm.c) belong to the same module, snd-soc-core.ko. There is no need to export it. Signed-off-by: Masahiro Yamada Link: https://patch.msgid.link/20250205165337.3466336-1-masahiroy@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 3fa53ce80189..a4d78af45e4b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2783,7 +2783,6 @@ int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, return ret; } -EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai); int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s) { From 5ea46b4360791345bd0bf4c7bf8fff5151374ea1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 11:49:14 +0200 Subject: [PATCH 0056/1090] ASoC: SOF: ipc4-pcm: Move out be_rate initialization from for loop in fixup Instead of initializing the be_rate within the loop by checking i == 0 at each iteration, move the be_rate reference initialization from the loop. For BE single rate check we will have single comparison done at each iteration compared to two in case the num_input_formats were higher than 1. We still need to run the loop from index 0 to check for FE-BE rate match. The patch also fixes bogus reports from gcc static analyzer thinking that be_rate is used uninitialized later in the function (which was not true). Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206094914.21135-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 18fff2df76f9..dc05e7490e6d 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -610,12 +610,11 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev, * Copier does not change sampling rate, so we * need to only consider the input pin information. */ + be_rate = pin_fmts[0].audio_fmt.sampling_frequency; for (i = 0; i < num_input_formats; i++) { unsigned int val = pin_fmts[i].audio_fmt.sampling_frequency; - if (i == 0) - be_rate = val; - else if (val != be_rate) + if (val != be_rate) single_be_rate = false; if (val == fe_rate) { From 2466b62268c020606d20b45e007c166399e639ee Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 6 Feb 2025 01:53:08 +0900 Subject: [PATCH 0057/1090] ASoC: dapm: unexport dapm_mark_endpoints_dirty() The symbol provider (sound/soc/soc-dapm.c) and the symbol consumer (sound/soc/soc-core.c) belong to the same module, snd-soc-core.ko. There is no need to export it. I deleted the comment, as other modules cannot use it any more. Signed-off-by: Masahiro Yamada Link: https://patch.msgid.link/20250205165310.3466254-1-masahiroy@kernel.org Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 2 -- sound/soc/soc-dapm.c | 1 - 2 files changed, 3 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 12cd7b5a2202..7cf52c8c9cf3 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -514,8 +514,6 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); - -/* Mostly internal - should not normally be used */ void dapm_mark_endpoints_dirty(struct snd_soc_card *card); /* dapm path query */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a4d78af45e4b..420fe7dea31e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -317,7 +317,6 @@ void dapm_mark_endpoints_dirty(struct snd_soc_card *card) snd_soc_dapm_mutex_unlock(card); } -EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); /* create a new dapm widget */ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( From 4c7518062d638837cea915e0ffe30f846780639a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 6 Feb 2025 10:52:37 +0200 Subject: [PATCH 0058/1090] ASoC: SOF: ipc4: Add support for split firmware releases A split SOF release consists of a base firmware and two libraries: -openmodules.ri for processing (audio) modules -debug.ri for debug and developer modules To handle this new release model add infrastructure to try to load the two library after boot optionally. This approach will allow flexibility on handling platforms in sof-bin with single or split configuration: single release: base firmware only split release: base firmware + openmodules + debug The files for the split firmware are located at the firmware directory. Signed-off-by: Peter Ujfalusi Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Link: https://patch.msgid.link/20250206085237.19214-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-loader.c | 143 +++++++++++++++++++++++++++++------- sound/soc/sof/ipc4-priv.h | 1 + sound/soc/sof/ipc4.c | 8 +- 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index bcdb33d03682..6ad1ef0e53e8 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -169,21 +169,14 @@ static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev) return payload_offset; } -static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, - unsigned long lib_id, const guid_t *uuid) +static int sof_ipc4_load_library(struct snd_sof_dev *sdev, unsigned long lib_id, + const char *lib_filename, bool optional) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct sof_ipc4_fw_library *fw_lib; - const char *fw_filename; ssize_t payload_offset; int ret, i, err; - if (!sdev->pdata->fw_lib_prefix) { - dev_err(sdev->dev, - "Library loading is not supported due to not set library path\n"); - return -EINVAL; - } - if (!ipc4_data->load_library) { dev_err(sdev->dev, "Library loading is not supported on this platform\n"); return -EOPNOTSUPP; @@ -193,20 +186,25 @@ static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, if (!fw_lib) return -ENOMEM; - fw_filename = kasprintf(GFP_KERNEL, "%s/%pUL.bin", - sdev->pdata->fw_lib_prefix, uuid); - if (!fw_filename) { - ret = -ENOMEM; - goto free_fw_lib; + if (optional) { + ret = firmware_request_nowarn(&fw_lib->sof_fw.fw, lib_filename, + sdev->dev); + if (ret < 0) { + /* optional library, override the error */ + ret = 0; + goto free_fw_lib; + } + } else { + ret = request_firmware(&fw_lib->sof_fw.fw, lib_filename, + sdev->dev); + if (ret < 0) { + dev_err(sdev->dev, "Library file '%s' is missing\n", + lib_filename); + goto free_fw_lib; + } } - ret = request_firmware(&fw_lib->sof_fw.fw, fw_filename, sdev->dev); - if (ret < 0) { - dev_err(sdev->dev, "Library file '%s' is missing\n", fw_filename); - goto free_filename; - } else { - dev_dbg(sdev->dev, "Library file '%s' loaded\n", fw_filename); - } + dev_dbg(sdev->dev, "Library file '%s' loaded\n", lib_filename); payload_offset = sof_ipc4_fw_parse_ext_man(sdev, fw_lib); if (payload_offset <= 0) { @@ -251,22 +249,117 @@ static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, if (unlikely(ret)) goto release; - kfree(fw_filename); - return 0; release: release_firmware(fw_lib->sof_fw.fw); /* Allocated within sof_ipc4_fw_parse_ext_man() */ devm_kfree(sdev->dev, fw_lib->modules); -free_filename: - kfree(fw_filename); free_fw_lib: devm_kfree(sdev->dev, fw_lib); return ret; } +/** + * sof_ipc4_complete_split_release - loads the library parts of a split firmware + * @sdev: SOF device + * + * With IPC4 the firmware can be a single binary or a split release. + * - single binary: only the basefw + * - split release: basefw and two libraries (openmodules, debug) + * + * With split firmware release it is also allowed that for example only the + * debug library is present (the openmodules content is built in the basefw). + * + * To handle the permutations try to load the openmodules then the debug + * libraries as optional ones after the basefw boot. + * + * The libraries for the split release are stored alongside the basefw on the + * filesystem. + */ +int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev) +{ + static const char * const lib_bundle[] = { "openmodules", "debug" }; + const char *fw_filename = sdev->pdata->fw_filename; + const char *lib_filename, *p; + size_t lib_name_base_size; + unsigned long lib_id = 1; + char *lib_name_base; + int i; + + p = strstr(fw_filename, ".ri"); + if (!p || strlen(p) != 3) { + dev_info(sdev->dev, + "%s: Firmware name '%s' is missing .ri extension\n", + __func__, fw_filename); + return 0; + } + + /* Space for the firmware basename + '\0', without the extension */ + lib_name_base_size = strlen(fw_filename) - 2; + lib_name_base = kzalloc(lib_name_base_size, GFP_KERNEL); + if (!lib_name_base) + return -ENOMEM; + + /* + * strscpy will 0 terminate the copied string, removing the '.ri' from + * the end of the fw_filename, for example: + * fw_filename: "sof-ptl.ri\0" + * lib_name_base: "sof-ptl\0" + */ + strscpy(lib_name_base, fw_filename, lib_name_base_size); + + for (i = 0; i < ARRAY_SIZE(lib_bundle); i++) { + int ret; + + lib_filename = kasprintf(GFP_KERNEL, "%s/%s-%s.ri", + sdev->pdata->fw_filename_prefix, + lib_name_base, lib_bundle[i]); + if (!lib_filename) { + kfree(lib_name_base); + return -ENOMEM; + } + + ret = sof_ipc4_load_library(sdev, lib_id, lib_filename, true); + if (ret) + dev_warn(sdev->dev, "%s: Failed to load %s: %d\n", + __func__, lib_filename, ret); + else + lib_id++; + + kfree(lib_filename); + } + + kfree(lib_name_base); + + return 0; +} + +static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev, + unsigned long lib_id, const guid_t *uuid) +{ + const char *lib_filename; + int ret; + + if (!sdev->pdata->fw_lib_prefix) { + dev_err(sdev->dev, + "Library loading is not supported due to not set library path\n"); + return -EINVAL; + } + + lib_filename = kasprintf(GFP_KERNEL, "%s/%pUL.bin", + sdev->pdata->fw_lib_prefix, uuid); + if (!lib_filename) + return -ENOMEM; + + ret = sof_ipc4_load_library(sdev, lib_id, lib_filename, false); + + kfree(lib_filename); + + return ret; +} + struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, const guid_t *uuid) { diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index ea3323b90343..b798810eff91 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -101,6 +101,7 @@ extern const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops; int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 instance_id, u32 state); int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core); +int sof_ipc4_complete_split_release(struct snd_sof_dev *sdev); int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev); int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev); struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 4386cbae16d4..2ed0c52fb2f1 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -825,8 +825,14 @@ static void sof_ipc4_exit(struct snd_sof_dev *sdev) static int sof_ipc4_post_boot(struct snd_sof_dev *sdev) { - if (sdev->first_boot) + if (sdev->first_boot) { + int ret = sof_ipc4_complete_split_release(sdev); + + if (ret) + return ret; + return sof_ipc4_query_fw_configuration(sdev); + } return sof_ipc4_reload_fw_libraries(sdev); } From 943116ba2a6ab472e8ad2d1e57a3f10f13485cc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:10 +0000 Subject: [PATCH 0059/1090] ASoC: add common snd_soc_ret() and use it Each soc-xxx.c is using own snd_xxx_ret(), but we want to share it. Let's add common snd_soc_ret() for it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frkt2qlx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-card.c | 14 ++------------ sound/soc/soc-component.c | 36 ++++++++++++------------------------ sound/soc/soc-dai.c | 18 ++---------------- sound/soc/soc-link.c | 18 ++---------------- sound/soc/soc-pcm.c | 18 ++---------------- sound/soc/soc-utils.c | 26 ++++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 84 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index fcdb5adfcd5e..16e4e488521c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -539,6 +539,7 @@ int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms); int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, int tdm_width, int tdm_slots, int slot_multiple); +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...); /* set runtime hw params */ static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index e6eb71b3010a..235427d69061 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -15,18 +15,8 @@ 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; + return snd_soc_ret(card->dev, ret, + "at %s() on %s\n", func, card->name); } struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index b67ef78f405c..25f5e543ae8d 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -13,32 +13,20 @@ #include #include -#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret, -1) -#define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret(dai, __func__, ret, reg) -static inline int _soc_component_ret(struct snd_soc_component *component, - const char *func, int ret, int reg) +#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) +static inline int _soc_component_ret(struct snd_soc_component *component, const char *func, int ret) { - /* Positive/Zero values are not errors */ - if (ret >= 0) - return ret; + return snd_soc_ret(component->dev, ret, + "at %s() on %s\n", func, component->name); +} - /* Negative values might be errors */ - switch (ret) { - case -EPROBE_DEFER: - case -ENOTSUPP: - break; - default: - if (reg == -1) - dev_err(component->dev, - "ASoC: error at %s on %s: %d\n", - func, component->name, ret); - else - dev_err(component->dev, - "ASoC: error at %s on %s for register: [0x%08x] %d\n", - func, component->name, reg, ret); - } - - return ret; +#define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret_reg_rw(dai, __func__, ret, reg) +static inline int _soc_component_ret_reg_rw(struct snd_soc_component *component, + const char *func, int ret, int reg) +{ + return snd_soc_ret(component->dev, ret, + "at %s() on %s for register: [0x%08x]\n", + func, component->name, reg); } static inline int soc_component_field_shift(struct snd_soc_component *component, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index ca0308f6d41c..7c4c9127e5f3 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -14,22 +14,8 @@ static inline int _soc_dai_ret(const struct snd_soc_dai *dai, const char *func, int ret) { - /* Positive, Zero values are not errors */ - if (ret >= 0) - return ret; - - /* Negative values might be errors */ - switch (ret) { - case -EPROBE_DEFER: - case -ENOTSUPP: - break; - default: - dev_err(dai->dev, - "ASoC: error at %s on %s: %d\n", - func, dai->name, ret); - } - - return ret; + return snd_soc_ret(dai->dev, ret, + "at %s() on %s\n", func, dai->name); } /* diff --git a/sound/soc/soc-link.c b/sound/soc/soc-link.c index 7f1f1bc717e2..02fd68f2e702 100644 --- a/sound/soc/soc-link.c +++ b/sound/soc/soc-link.c @@ -12,22 +12,8 @@ static inline int _soc_link_ret(struct snd_soc_pcm_runtime *rtd, const char *func, int ret) { - /* Positive, Zero values are not errors */ - if (ret >= 0) - return ret; - - /* Negative values might be errors */ - switch (ret) { - case -EPROBE_DEFER: - case -ENOTSUPP: - break; - default: - dev_err(rtd->dev, - "ASoC: error at %s on %s: %d\n", - func, rtd->dai_link->name, ret); - } - - return ret; + return snd_soc_ret(rtd->dev, ret, + "at %s() on %s\n", func, rtd->dai_link->name); } /* diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 88b3ad5a2552..a2caa146cac2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -30,22 +30,8 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, const char *func, int ret) { - /* Positive, Zero values are not errors */ - if (ret >= 0) - return ret; - - /* Negative values might be errors */ - switch (ret) { - case -EPROBE_DEFER: - case -ENOTSUPP: - break; - default: - dev_err(rtd->dev, - "ASoC: error at %s on %s: %d\n", - func, rtd->dai_link->name, ret); - } - - return ret; + return snd_soc_ret(rtd->dev, ret, + "at %s() on %s\n", func, rtd->dai_link->name); } /* is the current PCM operation for this FE ? */ diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index aa93e77ac937..e8958158acc1 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -15,6 +15,32 @@ #include #include +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + /* Positive, Zero values are not errors */ + if (ret >= 0) + return ret; + + /* Negative values might be errors */ + switch (ret) { + case -EPROBE_DEFER: + case -ENOTSUPP: + break; + default: + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + + dev_err(dev, "ASoC error (%d): %pV", ret, &vaf); + } + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_ret); + int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots) { return sample_size * channels * tdm_slots; From 062b7ef6b103dcbcb3c084e8ace8e74e260b2346 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:14 +0000 Subject: [PATCH 0060/1090] ASoC: soc-utils: care -EOPNOTSUPP on snd_soc_ret() We get below warning by checkpatch on soc-utils. Adds EOPNOTSUPP, but not remove existing ENOTSUPP. WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ed0d2qlt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e8958158acc1..318b141c00b3 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -28,6 +28,7 @@ int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...) switch (ret) { case -EPROBE_DEFER: case -ENOTSUPP: + case -EOPNOTSUPP: break; default: va_start(args, fmt); From be61cd4242e4a53f5cf989ee7573121d041444bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:19 +0000 Subject: [PATCH 0061/1090] ASoC: soc-pcm: use snd_soc_ret() Many functions uses below style for error return dev_err(dev, "message"); return -Exxxx; We can merge these into snd_soc_ret() which can use same error format. Let's cleaup code. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyfx2qlo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 96 ++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 57 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a2caa146cac2..ebe99d369ca9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -238,11 +238,9 @@ static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf, int stream; char *buf; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } buf = kmalloc(out_count, GFP_KERNEL); if (!buf) @@ -460,12 +458,9 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, ret = snd_pcm_hw_constraint_single(substream->runtime, \ SNDRV_PCM_HW_PARAM_##NAME,\ soc_dai->symmetric_##name); \ - if (ret < 0) { \ - dev_err(soc_dai->dev, \ - "ASoC: Unable to apply %s constraint: %d\n",\ - #name, ret); \ - return ret; \ - } \ + if (ret < 0) \ + return snd_soc_ret(soc_dai->dev, ret, \ + "Unable to apply %s constraint\n", #name); \ } __soc_pcm_apply_symmetry(rate, RATE); @@ -496,12 +491,11 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ if (!snd_soc_dai_is_dummy(cpu_dai) && \ cpu_dai->symmetric_##xxx && \ - cpu_dai->symmetric_##xxx != d.symmetric_##xxx) { \ - dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \ - #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \ - d.name, d.symmetric_##xxx); \ - return -EINVAL; \ - } + cpu_dai->symmetric_##xxx != d.symmetric_##xxx) \ + return snd_soc_ret(rtd->dev, -EINVAL, \ + "unmatched %s symmetry: %s:%d - %s:%d\n", \ + #xxx, cpu_dai->name, cpu_dai->symmetric_##xxx, \ + d.name, d.symmetric_##xxx); /* reject unmatched parameters when applying symmetry */ __soc_pcm_params_symmetry(rate); @@ -846,9 +840,8 @@ static int soc_hw_sanity_check(struct snd_pcm_substream *substream) return 0; config_err: - dev_err(dev, "ASoC: %s <-> %s No matching %s\n", - name_codec, name_cpu, err_msg); - return -EINVAL; + return snd_soc_ret(dev, -EINVAL, + "%s <-> %s No matching %s\n", name_codec, name_cpu, err_msg); } /* @@ -1319,11 +1312,11 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, fe_substream = snd_soc_dpcm_get_substream(fe, stream); be_substream = snd_soc_dpcm_get_substream(be, stream); - if (!fe_substream->pcm->nonatomic && be_substream->pcm->nonatomic) { - dev_err(be->dev, "%s: FE is atomic but BE is nonatomic, invalid configuration\n", - __func__); - return -EINVAL; - } + if (!fe_substream->pcm->nonatomic && be_substream->pcm->nonatomic) + return snd_soc_ret(be->dev, -EINVAL, + "%s: %s is atomic but %s is nonatomic, invalid configuration\n", + __func__, fe->dai_link->name, be->dai_link->name); + if (fe_substream->pcm->nonatomic && !be_substream->pcm->nonatomic) { dev_dbg(be->dev, "FE is nonatomic but BE is not, forcing BE as nonatomic\n"); be_substream->pcm->nonatomic = 1; @@ -1493,11 +1486,9 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0); int paths; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } /* get number of valid DAI paths and their widgets */ paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list, @@ -2388,23 +2379,23 @@ static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, ret = soc_pcm_trigger(substream, cmd); if (ret < 0) - return ret; + goto end; ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); - return ret; + goto end; } /* call trigger on the frontend after the backend. */ ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); if (ret < 0) - return ret; + goto end; dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", fe->dai_link->name, cmd); ret = soc_pcm_trigger(substream, cmd); - - return ret; +end: + return snd_soc_ret(fe->dev, ret, "trigger FE cmd: %d failed\n", cmd); } static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) @@ -2460,11 +2451,8 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) goto out; } - if (ret < 0) { - dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n", - cmd, ret); + if (ret < 0) goto out; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -2693,11 +2681,9 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) if (!fe->dai_link->dynamic) return 0; - if (fe->dai_link->num_cpus > 1) { - dev_err(fe->dev, + if (fe->dai_link->num_cpus > 1) + return snd_soc_ret(fe->dev, -EINVAL, "%s doesn't support Multi CPU yet\n", __func__); - return -EINVAL; - } /* only check active links */ if (!snd_soc_dai_active(snd_soc_rtd_to_cpu(fe, 0))) @@ -2768,7 +2754,8 @@ int snd_soc_dpcm_runtime_update(struct snd_soc_card *card) out: snd_soc_dpcm_mutex_unlock(card); - return ret; + + return snd_soc_ret(card->dev, ret, "%s() failed\n", __func__); } EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update); @@ -2842,10 +2829,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, int has_capture = 0; int i; - if (dai_link->dynamic && dai_link->num_cpus > 1) { - dev_err(rtd->dev, "DPCM doesn't support Multi CPU for Front-Ends yet\n"); - return -EINVAL; - } + if (dai_link->dynamic && dai_link->num_cpus > 1) + return snd_soc_ret(rtd->dev, -EINVAL, + "DPCM doesn't support Multi CPU for Front-Ends yet\n"); /* Adapt stream for codec2codec links */ cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE); @@ -2887,12 +2873,9 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, if (dai_link->capture_only) has_playback = 0; - if (!has_playback && !has_capture) { - dev_err(rtd->dev, "substream %s has no playback, no capture\n", - dai_link->stream_name); - - return -EINVAL; - } + if (!has_playback && !has_capture) + return snd_soc_ret(rtd->dev, -EINVAL, + "substream %s has no playback, no capture\n", dai_link->stream_name); *playback = has_playback; *capture = has_capture; @@ -2932,11 +2915,10 @@ static int soc_create_pcm(struct snd_pcm **pcm, ret = snd_pcm_new(rtd->card->snd_card, new_name, rtd->id, playback, capture, pcm); } - if (ret < 0) { - dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n", - new_name, rtd->dai_link->name, ret); - return ret; - } + if (ret < 0) + return snd_soc_ret(rtd->dev, ret, + "can't create pcm %s for dailink %s\n", new_name, rtd->dai_link->name); + dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n", rtd->id, new_name); return 0; From a0ef5b4b101424b8a666ed56bf1717dafe2d37f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:23 +0000 Subject: [PATCH 0062/1090] ASoC: simple-card: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjvh2qlk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 130 +++++++++++++++++--------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index afe7e79ffdbd..004fda4504c4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -29,7 +29,16 @@ static const struct snd_soc_ops simple_ops = { .hw_params = simple_util_hw_params, }; -static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_link_component *dlc) +#define simple_ret(priv, ret) _simple_ret(priv, __func__, ret) +static inline int _simple_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + +static int simple_parse_platform(struct simple_util_priv *priv, + struct device_node *node, + struct snd_soc_dai_link_component *dlc) { struct of_phandle_args args; int ret; @@ -43,7 +52,7 @@ static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_li */ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); if (ret) - return ret; + return simple_ret(priv, ret); /* dai_name is not required and may not exist for plat component */ @@ -52,11 +61,12 @@ static int simple_parse_platform(struct device_node *node, struct snd_soc_dai_li return 0; } -static int simple_parse_dai(struct device *dev, +static int simple_parse_dai(struct simple_util_priv *priv, struct device_node *node, struct snd_soc_dai_link_component *dlc, int *is_single_link) { + struct device *dev = simple_priv_to_dev(priv); struct of_phandle_args args; struct snd_soc_dai *dai; int ret; @@ -70,17 +80,18 @@ static int simple_parse_dai(struct device *dev, */ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); if (ret) - return ret; + goto end; /* * Try to find from DAI args */ dai = snd_soc_get_dai_via_args(&args); if (dai) { + ret = -ENOMEM; dlc->dai_name = snd_soc_dai_name_get(dai); dlc->dai_args = snd_soc_copy_dai_args(dev, &args); if (!dlc->dai_args) - return -ENOMEM; + goto end; goto parse_dai_end; } @@ -106,13 +117,14 @@ static int simple_parse_dai(struct device *dev, */ ret = snd_soc_get_dlc(&args, dlc); if (ret < 0) - return ret; + goto end; parse_dai_end: if (is_single_link) *is_single_link = !args.args_count; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static void simple_parse_convert(struct device *dev, @@ -149,19 +161,17 @@ static int simple_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - ret = simple_parse_dai(dev, np, dlc, cpu); + ret = simple_parse_dai(priv, np, dlc, cpu); if (ret) - return ret; + goto end; ret = simple_util_parse_clk(dev, np, dai, dlc); if (ret) - return ret; + goto end; ret = simple_util_parse_tdm(np, dai); - if (ret) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } static int simple_link_init(struct simple_util_priv *priv, @@ -183,7 +193,7 @@ static int simple_link_init(struct simple_util_priv *priv, ret = simple_util_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto end; graph_util_parse_link_direction(top, &playback_only, &capture_only); graph_util_parse_link_direction(node, &playback_only, &capture_only); @@ -213,7 +223,9 @@ static int simple_link_init(struct simple_util_priv *priv, dai_link->init = simple_util_dai_init; dai_link->ops = &simple_ops; - return simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(dev, dai_link, name); +end: + return simple_ret(priv, ret); } static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -290,7 +302,7 @@ static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, out_put_node: li->link++; - return ret; + return simple_ret(priv, ret); } static int simple_dai_link_of(struct simple_util_priv *priv, @@ -330,7 +342,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = simple_parse_platform(plat, platforms); + ret = simple_parse_platform(priv, plat, platforms); if (ret < 0) goto dai_link_of_err; @@ -345,7 +357,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv, dai_link_of_err: li->link++; - return ret; + return simple_ret(priv, ret); } static int __simple_for_each_link(struct simple_util_priv *priv, @@ -443,10 +455,10 @@ static int __simple_for_each_link(struct simple_util_priv *priv, node = of_get_next_child(top, node); } while (!is_top && node); - error: +error: of_node_put(node); - return ret; + return simple_ret(priv, ret); } static int simple_for_each_link(struct simple_util_priv *priv, @@ -479,7 +491,7 @@ static int simple_for_each_link(struct simple_util_priv *priv, break; } - return ret; + return simple_ret(priv, ret); } static void simple_depopulate_aux(void *data) @@ -500,9 +512,11 @@ static int simple_populate_aux(struct simple_util_priv *priv) ret = of_platform_populate(node, NULL, NULL, dev); if (ret) - return ret; + goto end; - return devm_add_action_or_reset(dev, simple_depopulate_aux, priv); + ret = devm_add_action_or_reset(dev, simple_depopulate_aux, priv); +end: + return simple_ret(priv, ret); } static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) @@ -512,15 +526,15 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) ret = simple_util_parse_widgets(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_routing(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_pin_switches(card, PREFIX); if (ret < 0) - return ret; + goto end; /* Single/Muti DAI link(s) & New style of DT node */ memset(li, 0, sizeof(*li)); @@ -528,19 +542,19 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) simple_dai_link_of, simple_dai_link_of_dpcm); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_card_name(card, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_populate_aux(priv); if (ret < 0) - return ret; + goto end; ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs"); - - return ret; +end: + return simple_ret(priv, ret); } static int simple_count_noml(struct simple_util_priv *priv, @@ -548,12 +562,10 @@ static int simple_count_noml(struct simple_util_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MAX_LINKS) { - struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; /* * DON'T REMOVE platforms @@ -575,8 +587,9 @@ static int simple_count_noml(struct simple_util_priv *priv, li->num[li->link].codecs = 1; li->link += 1; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static int simple_count_dpcm(struct simple_util_priv *priv, @@ -584,12 +597,10 @@ static int simple_count_dpcm(struct simple_util_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MAX_LINKS) { - struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; if (li->cpu) { /* @@ -606,8 +617,9 @@ static int simple_count_dpcm(struct simple_util_priv *priv, li->link++; /* dummy-Codec */ } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static int simple_get_dais_count(struct simple_util_priv *priv, @@ -683,17 +695,15 @@ static int simple_soc_probe(struct snd_soc_card *card) ret = simple_util_init_hp(card, &priv->hp_jack, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_init_mic(card, &priv->mic_jack, PREFIX); if (ret < 0) - return ret; + goto end; ret = simple_util_init_aux_jacks(priv, PREFIX); - if (ret < 0) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } static int simple_probe(struct platform_device *pdev) @@ -715,20 +725,22 @@ static int simple_probe(struct platform_device *pdev) card->probe = simple_soc_probe; card->driver_name = "simple-card"; + ret = -ENOMEM; struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); if (!li) - return -ENOMEM; + goto end; ret = simple_get_dais_count(priv, li); if (ret < 0) - return ret; + goto end; + ret = -EINVAL; if (!li->link) - return -EINVAL; + goto end; ret = simple_util_init_priv(priv, li); if (ret < 0) - return ret; + goto end; if (np && of_device_is_available(np)) { @@ -795,8 +807,8 @@ static int simple_probe(struct platform_device *pdev) return 0; err: simple_util_clean_reference(card); - - return ret; +end: + return dev_err_probe(dev, ret, "parse error\n"); } static const struct of_device_id simple_of_match[] = { From 2d7395b23dbf4c2d60be49b73e4c4705fc446662 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:27 +0000 Subject: [PATCH 0063/1090] ASoC: simple-card-utils: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5b12qlg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 8 +- sound/soc/generic/audio-graph-card.c | 6 +- sound/soc/generic/audio-graph-card2.c | 14 +-- sound/soc/generic/simple-card-utils.c | 170 +++++++++++++++----------- sound/soc/generic/simple-card.c | 4 +- 5 files changed, 115 insertions(+), 87 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 892f70532363..69a9c9c4d0e9 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -142,14 +142,14 @@ int simple_util_parse_daifmt(struct device *dev, struct device_node *codec, char *prefix, unsigned int *retfmt); -int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, +int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np, struct simple_util_dai *dai); __printf(3, 4) -int simple_util_set_dailink_name(struct device *dev, +int simple_util_set_dailink_name(struct simple_util_priv *priv, struct snd_soc_dai_link *dai_link, const char *fmt, ...); -int simple_util_parse_card_name(struct snd_soc_card *card, +int simple_util_parse_card_name(struct simple_util_priv *priv, char *prefix); int simple_util_parse_clk(struct device *dev, @@ -201,7 +201,7 @@ void simple_util_remove(struct platform_device *pdev); int graph_util_card_probe(struct snd_soc_card *card); int graph_util_is_ports0(struct device_node *port); -int graph_util_parse_dai(struct device *dev, struct device_node *ep, +int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link); void graph_util_parse_link_direction(struct device_node *np, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 7c422535b01a..bd7ebbec0fc9 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -111,7 +111,7 @@ static int graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - ret = graph_util_parse_dai(dev, ep, dlc, cpu); + ret = graph_util_parse_dai(priv, ep, dlc, cpu); if (ret < 0) return ret; @@ -183,7 +183,7 @@ static int graph_link_init(struct simple_util_priv *priv, if (priv->ops) dai_link->ops = priv->ops; - return simple_util_set_dailink_name(dev, dai_link, name); + return simple_util_set_dailink_name(priv, dai_link, name); } static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -586,7 +586,7 @@ int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) if (ret < 0) goto err; - ret = simple_util_parse_card_name(card, NULL); + ret = simple_util_parse_card_name(priv, NULL); if (ret < 0) goto err; diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index ee94b256b770..945a16e6d691 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -409,7 +409,7 @@ static int __graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, idx); } - ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links); + ret = graph_util_parse_dai(priv, ep, dlc, &is_single_links); if (ret < 0) return ret; @@ -417,7 +417,7 @@ static int __graph_parse_node(struct simple_util_priv *priv, if (ret < 0) return ret; - ret = simple_util_parse_tdm_width_map(dev, ep, dai); + ret = simple_util_parse_tdm_width_map(priv, ep, dai); if (ret < 0) return ret; @@ -443,22 +443,22 @@ static int __graph_parse_node(struct simple_util_priv *priv, case GRAPH_NORMAL: /* run is_cpu only. see audio_graph2_link_normal() */ if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "%s%s-%s%s", + simple_util_set_dailink_name(priv, dai_link, "%s%s-%s%s", cpus->dai_name, cpu_multi, codecs->dai_name, codec_multi); break; case GRAPH_DPCM: if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "fe.%pOFP.%s%s", + simple_util_set_dailink_name(priv, dai_link, "fe.%pOFP.%s%s", cpus->of_node, cpus->dai_name, cpu_multi); else - simple_util_set_dailink_name(dev, dai_link, "be.%pOFP.%s%s", + simple_util_set_dailink_name(priv, dai_link, "be.%pOFP.%s%s", codecs->of_node, codecs->dai_name, codec_multi); break; case GRAPH_C2C: /* run is_cpu only. see audio_graph2_link_c2c() */ if (is_cpu) - simple_util_set_dailink_name(dev, dai_link, "c2c.%s%s-%s%s", + simple_util_set_dailink_name(priv, dai_link, "c2c.%s%s-%s%s", cpus->dai_name, cpu_multi, codecs->dai_name, codec_multi); break; @@ -1332,7 +1332,7 @@ int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev, if (ret < 0) goto err; - ret = simple_util_parse_card_name(card, NULL); + ret = simple_util_parse_card_name(priv, NULL); if (ret < 0) goto err; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index c2445c5ccd84..51e0e434514d 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -15,6 +15,13 @@ #include #include +#define simple_ret(priv, ret) _simple_ret(priv, __func__, ret) +static inline int _simple_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + int simple_util_get_sample_fmt(struct simple_util_data *data) { int i; @@ -133,33 +140,42 @@ int simple_util_parse_daifmt(struct device *dev, } EXPORT_SYMBOL_GPL(simple_util_parse_daifmt); -int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, +int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np, struct simple_util_dai *dai) { + struct device *dev = simple_priv_to_dev(priv); int n, i, ret; u32 *p; + /* + * NOTE + * + * Clang doesn't allow to use "goto end" before calling __free(), + * because it bypasses the initialization. Use simple_ret() directly. + */ + n = of_property_count_elems_of_size(np, "dai-tdm-slot-width-map", sizeof(u32)); if (n <= 0) return 0; + if (n % 3) { dev_err(dev, "Invalid number of cells for dai-tdm-slot-width-map\n"); - return -EINVAL; + return simple_ret(priv, -EINVAL); /* see NOTE */ } + ret = -ENOMEM; dai->tdm_width_map = devm_kcalloc(dev, n, sizeof(*dai->tdm_width_map), GFP_KERNEL); if (!dai->tdm_width_map) - return -ENOMEM; + return simple_ret(priv, ret); /* see NOTE */ - u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), - GFP_KERNEL); + u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), GFP_KERNEL); if (!array_values) - return -ENOMEM; + goto end; ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n); if (ret < 0) { dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret); - return ret; + goto end; } p = array_values; @@ -170,15 +186,17 @@ int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, } dai->n_tdm_widths = i; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_parse_tdm_width_map); -int simple_util_set_dailink_name(struct device *dev, +int simple_util_set_dailink_name(struct simple_util_priv *priv, struct snd_soc_dai_link *dai_link, const char *fmt, ...) { + struct device *dev = simple_priv_to_dev(priv); va_list ap; char *name = NULL; int ret = -ENOMEM; @@ -194,13 +212,14 @@ int simple_util_set_dailink_name(struct device *dev, dai_link->stream_name = name; } - return ret; + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_set_dailink_name); -int simple_util_parse_card_name(struct snd_soc_card *card, +int simple_util_parse_card_name(struct simple_util_priv *priv, char *prefix) { + struct snd_soc_card *card = simple_priv_to_card(priv); int ret; if (!prefix) @@ -214,13 +233,13 @@ int simple_util_parse_card_name(struct snd_soc_card *card, snprintf(prop, sizeof(prop), "%sname", prefix); ret = snd_soc_of_parse_card_name(card, prop); if (ret < 0) - return ret; + goto end; } if (!card->name && card->dai_link) card->name = card->dai_link->name; - - return 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_parse_card_name); @@ -348,7 +367,8 @@ cpu_err: break; simple_clk_disable(dai); } - return ret; + + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_startup); @@ -379,16 +399,19 @@ void simple_util_shutdown(struct snd_pcm_substream *substream) } EXPORT_SYMBOL_GPL(simple_util_shutdown); -static int simple_set_clk_rate(struct device *dev, - struct simple_util_dai *simple_dai, - unsigned long rate) +static int simple_set_clk_rate(struct simple_util_priv *priv, + struct simple_util_dai *simple_dai, + unsigned long rate) { + struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; + if (!simple_dai) return 0; if (simple_dai->clk_fixed && rate != simple_dai->sysclk) { dev_err(dev, "dai %s invalid clock rate %lu\n", simple_dai->name, rate); - return -EINVAL; + goto end; } if (!simple_dai->clk) @@ -397,12 +420,15 @@ static int simple_set_clk_rate(struct device *dev, if (clk_get_rate(simple_dai->clk) == rate) return 0; - return clk_set_rate(simple_dai->clk, rate); + ret = clk_set_rate(simple_dai->clk, rate); +end: + return simple_ret(priv, ret); } -static int simple_set_tdm(struct snd_soc_dai *dai, - struct simple_util_dai *simple_dai, - struct snd_pcm_hw_params *params) +static int simple_set_tdm(struct simple_util_priv *priv, + struct snd_soc_dai *dai, + struct simple_util_dai *simple_dai, + struct snd_pcm_hw_params *params) { int sample_bits = params_width(params); int slot_width, slot_count; @@ -430,12 +456,8 @@ static int simple_set_tdm(struct snd_soc_dai *dai, simple_dai->rx_slot_mask, slot_count, slot_width); - if (ret && ret != -ENOTSUPP) { - dev_err(dai->dev, "simple-card: set_tdm_slot error: %d\n", ret); - return ret; - } - return 0; + return simple_ret(priv, ret); } int simple_util_hw_params(struct snd_pcm_substream *substream, @@ -457,15 +479,15 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, mclk = params_rate(params) * mclk_fs; for_each_prop_dai_codec(props, i, pdai) { - ret = simple_set_clk_rate(rtd->dev, pdai, mclk); + ret = simple_set_clk_rate(priv, pdai, mclk); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, pdai) { - ret = simple_set_clk_rate(rtd->dev, pdai, mclk); + ret = simple_set_clk_rate(priv, pdai, mclk); if (ret < 0) - return ret; + goto end; } /* Ensure sysclk is set on all components in case any @@ -476,39 +498,40 @@ int simple_util_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_component_set_sysclk(component, 0, 0, mclk, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } for_each_rtd_codec_dais(rtd, i, sdai) { pdai = simple_props_to_dai_codec(props, i); ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } for_each_rtd_cpu_dais(rtd, i, sdai) { pdai = simple_props_to_dai_cpu(props, i); ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, pdai->clk_direction); if (ret && ret != -ENOTSUPP) - return ret; + goto end; } } for_each_prop_dai_codec(props, i, pdai) { sdai = snd_soc_rtd_to_codec(rtd, i); - ret = simple_set_tdm(sdai, pdai, params); + ret = simple_set_tdm(priv, sdai, pdai, params); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, pdai) { sdai = snd_soc_rtd_to_cpu(rtd, i); - ret = simple_set_tdm(sdai, pdai, params); + ret = simple_set_tdm(priv, sdai, pdai, params); if (ret < 0) - return ret; + goto end; } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_hw_params); @@ -536,7 +559,8 @@ int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } EXPORT_SYMBOL_GPL(simple_util_be_hw_params_fixup); -static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simple_dai) +static int simple_init_dai(struct simple_util_priv *priv, + struct snd_soc_dai *dai, struct simple_util_dai *simple_dai) { int ret; @@ -548,7 +572,7 @@ static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simp simple_dai->clk_direction); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); - return ret; + goto end; } } @@ -560,11 +584,12 @@ static int simple_init_dai(struct snd_soc_dai *dai, struct simple_util_dai *simp simple_dai->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); - return ret; + goto end; } } - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } static inline int simple_component_is_codec(struct snd_soc_component *component) @@ -572,7 +597,8 @@ static inline int simple_component_is_codec(struct snd_soc_component *component) return component->driver->endianness; } -static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, +static int simple_init_for_codec2codec(struct simple_util_priv *priv, + struct snd_soc_pcm_runtime *rtd, struct simple_dai_props *dai_props) { struct snd_soc_dai_link *dai_link = rtd->dai_link; @@ -604,12 +630,13 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, if (ret < 0) { dev_err(rtd->dev, "simple-card: no valid dai_link params\n"); - return ret; + goto end; } + ret = -ENOMEM; c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL); if (!c2c_params) - return -ENOMEM; + goto end; c2c_params->formats = hw.formats; c2c_params->rates = hw.rates; @@ -621,7 +648,9 @@ static int simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, dai_link->c2c_params = c2c_params; dai_link->num_c2c_params = 1; - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) @@ -632,21 +661,19 @@ int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd) int i, ret; for_each_prop_dai_codec(props, i, dai) { - ret = simple_init_dai(snd_soc_rtd_to_codec(rtd, i), dai); + ret = simple_init_dai(priv, snd_soc_rtd_to_codec(rtd, i), dai); if (ret < 0) - return ret; + goto end; } for_each_prop_dai_cpu(props, i, dai) { - ret = simple_init_dai(snd_soc_rtd_to_cpu(rtd, i), dai); + ret = simple_init_dai(priv, snd_soc_rtd_to_cpu(rtd, i), dai); if (ret < 0) - return ret; + goto end; } - ret = simple_init_for_codec2codec(rtd, props); - if (ret < 0) - return ret; - - return 0; + ret = simple_init_for_codec2codec(priv, rtd, props); +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(simple_util_dai_init); @@ -831,7 +858,7 @@ int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix) priv->aux_jacks = devm_kcalloc(card->dev, num, sizeof(struct snd_soc_jack), GFP_KERNEL); if (!priv->aux_jacks) - return -ENOMEM; + return simple_ret(priv, -ENOMEM); for_each_card_auxs(card, component) { char id[128]; @@ -992,13 +1019,11 @@ int graph_util_card_probe(struct snd_soc_card *card) ret = simple_util_init_hp(card, &priv->hp_jack, NULL); if (ret < 0) - return ret; + goto end; ret = simple_util_init_mic(card, &priv->mic_jack, NULL); - if (ret < 0) - return ret; - - return 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(graph_util_card_probe); @@ -1074,9 +1099,10 @@ static int graph_get_dai_id(struct device_node *ep) return id; } -int graph_util_parse_dai(struct device *dev, struct device_node *ep, +int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link) { + struct device *dev = simple_priv_to_dev(priv); struct of_phandle_args args = {}; struct snd_soc_dai *dai; int ret; @@ -1092,11 +1118,12 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, args.np = ep; dai = snd_soc_get_dai_via_args(&args); if (dai) { + ret = -ENOMEM; dlc->of_node = node; dlc->dai_name = snd_soc_dai_name_get(dai); dlc->dai_args = snd_soc_copy_dai_args(dev, &args); if (!dlc->dai_args) - return -ENOMEM; + goto end; goto parse_dai_end; } @@ -1127,13 +1154,14 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, */ ret = snd_soc_get_dlc(&args, dlc); if (ret < 0) - return ret; + goto end; parse_dai_end: if (is_single_link) *is_single_link = of_graph_get_endpoint_count(node) == 1; - - return 0; + ret = 0; +end: + return simple_ret(priv, ret); } EXPORT_SYMBOL_GPL(graph_util_parse_dai); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 004fda4504c4..5af6d1b308f2 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -223,7 +223,7 @@ static int simple_link_init(struct simple_util_priv *priv, dai_link->init = simple_util_dai_init; dai_link->ops = &simple_ops; - ret = simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(priv, dai_link, name); end: return simple_ret(priv, ret); } @@ -544,7 +544,7 @@ static int simple_parse_of(struct simple_util_priv *priv, struct link_info *li) if (ret < 0) goto end; - ret = simple_util_parse_card_name(card, PREFIX); + ret = simple_util_parse_card_name(priv, PREFIX); if (ret < 0) goto end; From 74a0ca4c7f19f1b273d665b3b53f7ae8af879658 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:31 +0000 Subject: [PATCH 0064/1090] ASoC: audio-graph-card: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qql2qlc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 93 +++++++++++++++------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index bd7ebbec0fc9..a8a3bad3df00 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -20,6 +20,13 @@ #define DPCM_SELECTABLE 1 +#define graph_ret(priv, ret) _graph_ret(priv, __func__, ret) +static inline int _graph_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + #define ep_to_port(ep) of_get_parent(ep) static struct device_node *port_to_ports(struct device_node *port) { @@ -113,17 +120,15 @@ static int graph_parse_node(struct simple_util_priv *priv, ret = graph_util_parse_dai(priv, ep, dlc, cpu); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm(ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_clk(dev, ep, dai, dlc); - if (ret < 0) - return ret; - - return 0; +end: + return graph_ret(priv, ret); } static int graph_link_init(struct simple_util_priv *priv, @@ -148,7 +153,7 @@ static int graph_link_init(struct simple_util_priv *priv, ret = simple_util_parse_daifmt(dev, ep_cpu, ep_codec, NULL, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto end; graph_util_parse_link_direction(top, &playback_only, &capture_only); graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); @@ -183,7 +188,9 @@ static int graph_link_init(struct simple_util_priv *priv, if (priv->ops) dai_link->ops = priv->ops; - return simple_util_set_dailink_name(priv, dai_link, name); + ret = simple_util_set_dailink_name(priv, dai_link, name); +end: + return graph_ret(priv, ret); } static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -215,7 +222,7 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, &is_single_links); if (ret) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); @@ -248,7 +255,7 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_parse_node(priv, codec_ep, li, NULL); if (ret < 0) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "be.%pOFP.%s", codecs->of_node, codecs->dai_name); @@ -267,8 +274,8 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); li->link++; - - return ret; +end: + return graph_ret(priv, ret); } static int graph_dai_link_of(struct simple_util_priv *priv, @@ -288,11 +295,11 @@ static int graph_dai_link_of(struct simple_util_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, &is_single_links); if (ret < 0) - return ret; + goto end; ret = graph_parse_node(priv, codec_ep, li, NULL); if (ret < 0) - return ret; + goto end; snprintf(dai_name, sizeof(dai_name), "%s-%s", cpus->dai_name, codecs->dai_name); @@ -302,11 +309,11 @@ static int graph_dai_link_of(struct simple_util_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); if (ret < 0) - return ret; + goto end; li->link++; - - return 0; +end: + return graph_ret(priv, ret); } static inline bool parse_as_dpcm_link(struct simple_util_priv *priv, @@ -383,13 +390,13 @@ static int __graph_for_each_link(struct simple_util_priv *priv, } if (ret < 0) - return ret; + goto end; codec_port_old = codec_port; } } - - return 0; +end: + return graph_ret(priv, ret); } static int graph_for_each_link(struct simple_util_priv *priv, @@ -422,7 +429,7 @@ static int graph_for_each_link(struct simple_util_priv *priv, break; } - return ret; + return graph_ret(priv, ret); } static int graph_count_noml(struct simple_util_priv *priv, @@ -431,11 +438,10 @@ static int graph_count_noml(struct simple_util_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - if (li->link >= SNDRV_MAX_LINKS) { - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; /* * DON'T REMOVE platforms @@ -450,8 +456,9 @@ static int graph_count_noml(struct simple_util_priv *priv, li->link += 1; /* 1xCPU-Codec */ dev_dbg(dev, "Count As Normal\n"); - - return 0; + ret = 0; +end: + return graph_ret(priv, ret); } static int graph_count_dpcm(struct simple_util_priv *priv, @@ -460,11 +467,10 @@ static int graph_count_dpcm(struct simple_util_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); + int ret = -EINVAL; - if (li->link >= SNDRV_MAX_LINKS) { - dev_err(dev, "too many links\n"); - return -EINVAL; - } + if (li->link >= SNDRV_MAX_LINKS) + goto end; if (li->cpu) { /* @@ -483,8 +489,9 @@ static int graph_count_dpcm(struct simple_util_priv *priv, } dev_dbg(dev, "Count As DPCM\n"); - - return 0; + ret = 0; +end: + return graph_ret(priv, ret); } static int graph_get_dais_count(struct simple_util_priv *priv, @@ -544,40 +551,41 @@ static int graph_get_dais_count(struct simple_util_priv *priv, int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) { struct snd_soc_card *card = simple_priv_to_card(priv); - int ret; + int ret = -ENOMEM; struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); if (!li) - return -ENOMEM; + goto end; card->owner = THIS_MODULE; card->dev = dev; ret = graph_get_dais_count(priv, li); if (ret < 0) - return ret; + goto end; + ret = -EINVAL; if (!li->link) - return -EINVAL; + goto end; ret = simple_util_init_priv(priv, li); if (ret < 0) - return ret; + goto end; priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); if (IS_ERR(priv->pa_gpio)) { ret = PTR_ERR(priv->pa_gpio); dev_err(dev, "failed to get amplifier gpio: %d\n", ret); - return ret; + goto end; } ret = simple_util_parse_widgets(card, NULL); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_routing(card, NULL); if (ret < 0) - return ret; + goto end; memset(li, 0, sizeof(*li)); ret = graph_for_each_link(priv, li, @@ -599,10 +607,9 @@ int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) goto err; return 0; - err: simple_util_clean_reference(card); - +end: return dev_err_probe(dev, ret, "parse error\n"); } EXPORT_SYMBOL_GPL(audio_graph_parse_of); From 8d83282e53185ec257a4ce08812e8fabee2c7212 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Feb 2025 00:16:36 +0000 Subject: [PATCH 0065/1090] ASoC: audio-graph-card2: use snd_soc_ret() We can use snd_soc_ret() to indicate error message when return. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c652ql8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 81 ++++++++++++++++----------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 945a16e6d691..5dcc78c551a2 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -234,6 +234,13 @@ enum graph_type { #define GRAPH_NODENAME_DPCM "dpcm" #define GRAPH_NODENAME_C2C "codec2codec" +#define graph_ret(priv, ret) _graph_ret(priv, __func__, ret) +static inline int _graph_ret(struct simple_util_priv *priv, + const char *func, int ret) +{ + return snd_soc_ret(simple_priv_to_dev(priv), ret, "at %s()\n", func); +} + #define ep_to_port(ep) of_get_parent(ep) static struct device_node *port_to_ports(struct device_node *port) { @@ -411,19 +418,19 @@ static int __graph_parse_node(struct simple_util_priv *priv, ret = graph_util_parse_dai(priv, ep, dlc, &is_single_links); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm(ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_tdm_width_map(priv, ep, dai); if (ret < 0) - return ret; + goto end; ret = simple_util_parse_clk(dev, ep, dai, dlc); if (ret < 0) - return ret; + goto end; /* * set DAI Name @@ -488,11 +495,12 @@ static int __graph_parse_node(struct simple_util_priv *priv, simple_util_canonicalize_cpu(cpus, is_single_links); simple_util_canonicalize_platform(platforms, cpus); } - - return 0; +end: + return graph_ret(priv, ret); } -static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, +static int graph_parse_node_multi_nm(struct simple_util_priv *priv, + struct snd_soc_dai_link *dai_link, int *nm_idx, int cpu_idx, struct device_node *mcpu_port) { @@ -534,10 +542,10 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, struct device_node *mcodec_port_top __free(device_node) = ep_to_port(mcodec_ep_top); struct device_node *mcodec_ports __free(device_node) = port_to_ports(mcodec_port_top); int nm_max = max(dai_link->num_cpus, dai_link->num_codecs); - int ret = 0; + int ret = -EINVAL; if (cpu_idx > dai_link->num_cpus) - return -EINVAL; + goto end; for_each_of_graph_port_endpoint(mcpu_port, mcpu_ep_n) { int codec_idx = 0; @@ -578,8 +586,8 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, if (ret < 0) break; } - - return ret; +end: + return graph_ret(priv, ret); } static int graph_parse_node_multi(struct simple_util_priv *priv, @@ -633,7 +641,7 @@ static int graph_parse_node_multi(struct simple_util_priv *priv, /* CPU:Codec = N:M */ if (is_cpu && dai_link->ch_maps) { - ret = graph_parse_node_multi_nm(dai_link, &nm_idx, idx, port); + ret = graph_parse_node_multi_nm(priv, dai_link, &nm_idx, idx, port); if (ret < 0) goto multi_err; } @@ -643,7 +651,7 @@ static int graph_parse_node_multi(struct simple_util_priv *priv, ret = -EINVAL; multi_err: - return ret; + return graph_ret(priv, ret); } static int graph_parse_node_single(struct simple_util_priv *priv, @@ -651,7 +659,7 @@ static int graph_parse_node_single(struct simple_util_priv *priv, struct device_node *ep, struct link_info *li, int is_cpu) { - return __graph_parse_node(priv, gtype, ep, li, is_cpu, 0); + return graph_ret(priv, __graph_parse_node(priv, gtype, ep, li, is_cpu, 0)); } static int graph_parse_node(struct simple_util_priv *priv, @@ -660,11 +668,14 @@ static int graph_parse_node(struct simple_util_priv *priv, struct link_info *li, int is_cpu) { struct device_node *port __free(device_node) = ep_to_port(ep); + int ret; if (graph_lnk_is_multi(port)) - return graph_parse_node_multi(priv, gtype, port, li, is_cpu); + ret = graph_parse_node_multi(priv, gtype, port, li, is_cpu); else - return graph_parse_node_single(priv, gtype, ep, li, is_cpu); + ret = graph_parse_node_single(priv, gtype, ep, li, is_cpu); + + return graph_ret(priv, ret); } static void graph_parse_daifmt(struct device_node *node, unsigned int *daifmt) @@ -842,18 +853,19 @@ int audio_graph2_link_normal(struct simple_util_priv *priv, */ ret = graph_parse_node(priv, GRAPH_NORMAL, codec_ep, li, 0); if (ret < 0) - return ret; + goto end; /* * call CPU, and set DAI Name */ ret = graph_parse_node(priv, GRAPH_NORMAL, cpu_ep, li, 1); if (ret < 0) - return ret; + goto end; graph_link_init(priv, lnk, cpu_ep, codec_ep, li, 1); - return ret; +end: + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_normal); @@ -946,7 +958,7 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, graph_link_init(priv, lnk, cpu_ep, codec_ep, li, is_cpu); - return ret; + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); @@ -992,8 +1004,13 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, struct snd_soc_pcm_stream *c2c_conf; c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL); - if (!c2c_conf) - return ret; + if (!c2c_conf) { + /* + * Clang doesn't allow to use "goto end" before calling __free(), + * because it bypasses the initialization. Use graph_ret() directly. + */ + return graph_ret(priv, -ENOMEM); + } c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */ c2c_conf->rates = SNDRV_PCM_RATE_8000_384000; @@ -1019,18 +1036,18 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, */ ret = graph_parse_node(priv, GRAPH_C2C, codec1_ep, li, 0); if (ret < 0) - return ret; + goto end; /* * call CPU, and set DAI Name */ ret = graph_parse_node(priv, GRAPH_C2C, codec0_ep, li, 1); if (ret < 0) - return ret; + goto end; graph_link_init(priv, lnk, codec0_ep, codec1_ep, li, 1); - - return ret; +end: + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_link_c2c); @@ -1078,7 +1095,7 @@ static int graph_link(struct simple_util_priv *priv, li->link++; err: - return ret; + return graph_ret(priv, ret); } static int graph_counter(struct device_node *lnk) @@ -1249,7 +1266,7 @@ static int graph_count(struct simple_util_priv *priv, li->link++; err: - return ret; + return graph_ret(priv, ret); } static int graph_for_each_link(struct simple_util_priv *priv, @@ -1266,7 +1283,7 @@ static int graph_for_each_link(struct simple_util_priv *priv, struct device_node *node = dev->of_node; struct device_node *lnk; enum graph_type gtype; - int rc, ret; + int rc, ret = 0; /* loop for all listed CPU port */ of_for_each_phandle(&it, rc, node, "links", NULL, 0) { @@ -1276,10 +1293,10 @@ static int graph_for_each_link(struct simple_util_priv *priv, ret = func(priv, hooks, gtype, lnk, li); if (ret < 0) - return ret; + break; } - return 0; + return graph_ret(priv, ret); } int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev, @@ -1355,7 +1372,7 @@ err: if (ret < 0) dev_err_probe(dev, ret, "parse error\n"); - return ret; + return graph_ret(priv, ret); } EXPORT_SYMBOL_GPL(audio_graph2_parse_of); From cb161c333927142818d6bf22a4da2b023fb2b8c9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Feb 2025 21:25:15 +0200 Subject: [PATCH 0066/1090] ASoC: tas2781: Switch to use %ptTsr Use %ptTsr instead of open-coded variant to print contents of time64_t type in human readable form. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20250206192537.1133763-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/sound/tas2781.h | 1 - sound/pci/hda/tas2781-spi.h | 1 - sound/pci/hda/tas2781_hda_i2c.c | 8 +++----- sound/pci/hda/tas2781_hda_spi.c | 3 --- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 72d2060904f6..0f1e585635bb 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -161,7 +161,6 @@ struct tasdevice_priv { struct mutex codec_lock; struct regmap *regmap; struct device *dev; - struct tm tm; enum device_catlog_id catlog_id; unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64]; diff --git a/sound/pci/hda/tas2781-spi.h b/sound/pci/hda/tas2781-spi.h index ecfc3c8bb821..7a0faceeb675 100644 --- a/sound/pci/hda/tas2781-spi.h +++ b/sound/pci/hda/tas2781-spi.h @@ -88,7 +88,6 @@ struct tasdevice_priv { struct mutex codec_lock; struct regmap *regmap; struct device *dev; - struct tm tm; unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE]; unsigned char coef_binaryname[64]; diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index 0e42b87dadb8..be9a90f643eb 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -594,7 +594,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); static efi_char16_t efi_name[] = L"CALI_DATA"; - struct tm *tm = &tas_priv->tm; unsigned int attr, crc; unsigned int *tmp_val; efi_status_t status; @@ -629,10 +628,9 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) crc, tmp_val[21]); if (crc == tmp_val[21]) { - time64_to_tm(tmp_val[20], 0, tm); - dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + time64_t seconds = tmp_val[20]; + + dev_dbg(tas_priv->dev, "%ptTsr\n", &seconds); tasdevice_apply_calibration(tas_priv); } else tas_priv->cali_data.total_sz = 0; diff --git a/sound/pci/hda/tas2781_hda_spi.c b/sound/pci/hda/tas2781_hda_spi.c index a42fa990e7b9..d91b19602485 100644 --- a/sound/pci/hda/tas2781_hda_spi.c +++ b/sound/pci/hda/tas2781_hda_spi.c @@ -802,7 +802,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME; unsigned char data[TASDEVICE_CALIBRATION_DATA_SIZE], *buf; unsigned int attr, crc, offset, *tmp_val; - struct tm *tm = &tas_priv->tm; unsigned long total_sz = 0; efi_status_t status; @@ -849,7 +848,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) if (crc != tmp_val[3 + tmp_val[1] * 6]) return 0; - time64_to_tm(tmp_val[2], 0, tm); for (int j = 0; j < tmp_val[1]; j++) { offset = j * 6 + 3; if (tmp_val[offset] == tas_priv->index) { @@ -882,7 +880,6 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) */ crc = crc32(~0, data, 84) ^ ~0; if (crc == tmp_val[21]) { - time64_to_tm(tmp_val[20], 0, tm); for (int i = 0; i < CALIB_MAX; i++) tas_priv->cali_data[i] = tmp_val[tas_priv->index * 5 + i]; From e2ceac2f323625632f12dd5333092976298a0cde Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:55 +0530 Subject: [PATCH 0067/1090] ASoC: amd: ps: rename structure names, variable and other macros Rename macros and structure names, variable with ACP63 tag which are specific to ACP6.3 platform. Rename 'stream_index' and 'sdw_dma_data' variable names to avoid check patch warnings. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-2-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 66 ++++++++++++++++---------------- sound/soc/amd/ps/pci-ps.c | 64 +++++++++++++++---------------- sound/soc/amd/ps/ps-sdw-dma.c | 72 +++++++++++++++++------------------ 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index e54eabaa4d3e..01910273624b 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -13,13 +13,13 @@ #define ACP63_REG_END 0x125C000 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 -#define ACP_PGFSM_CNTL_POWER_ON_MASK 1 -#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0 -#define ACP_PGFSM_STATUS_MASK 3 -#define ACP_POWERED_ON 0 -#define ACP_POWER_ON_IN_PROGRESS 1 -#define ACP_POWERED_OFF 2 -#define ACP_POWER_OFF_IN_PROGRESS 3 +#define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 +#define ACP63_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP63_PGFSM_STATUS_MASK 3 +#define ACP63_POWERED_ON 0 +#define ACP63_POWER_ON_IN_PROGRESS 1 +#define ACP63_POWERED_OFF 2 +#define ACP63_POWER_OFF_IN_PROGRESS 3 #define ACP_ERROR_MASK 0x20000000 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF @@ -60,7 +60,7 @@ #define AMD_SDW_MAX_MANAGERS 2 /* time in ms for acp timeout */ -#define ACP_TIMEOUT 500 +#define ACP63_TIMEOUT 500 #define ACP_SDW0_STAT BIT(21) #define ACP_SDW1_STAT BIT(2) @@ -72,13 +72,13 @@ #define ACP_AUDIO0_RX_THRESHOLD 0x1b #define ACP_AUDIO1_RX_THRESHOLD 0x19 #define ACP_AUDIO2_RX_THRESHOLD 0x17 -#define ACP_P1_AUDIO1_TX_THRESHOLD BIT(6) -#define ACP_P1_AUDIO1_RX_THRESHOLD BIT(5) -#define ACP_SDW_DMA_IRQ_MASK 0x1F800000 -#define ACP_P1_SDW_DMA_IRQ_MASK 0x60 +#define ACP63_P1_AUDIO1_TX_THRESHOLD BIT(6) +#define ACP63_P1_AUDIO1_RX_THRESHOLD BIT(5) +#define ACP63_SDW_DMA_IRQ_MASK 0x1F800000 +#define ACP63_P1_SDW_DMA_IRQ_MASK 0x60 #define ACP63_SDW0_DMA_MAX_STREAMS 6 #define ACP63_SDW1_DMA_MAX_STREAMS 2 -#define ACP_P1_AUDIO_TX_THRESHOLD 6 +#define ACP63_P1_AUDIO_TX_THRESHOLD 6 /* * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping @@ -91,8 +91,8 @@ * 4 (SDW0_AUDIO1_RX) 25 * 5 (SDW0_AUDIO2_RX) 23 */ -#define SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) -#define SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) +#define ACP63_SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP63_SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) /* * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping @@ -101,7 +101,7 @@ * 0 (SDW1_AUDIO1_TX) 6 * 1 (SDW1_AUDIO1_RX) 5 */ -#define SDW1_DMA_IRQ_MASK(i) (ACP_P1_AUDIO_TX_THRESHOLD - (i)) +#define ACP63_SDW1_DMA_IRQ_MASK(i) (ACP63_P1_AUDIO_TX_THRESHOLD - (i)) #define ACP_DELAY_US 5 #define ACP_SDW_RING_BUFF_ADDR_OFFSET (128 * 1024) @@ -148,18 +148,18 @@ enum acp_config { ACP_CONFIG_15, }; -enum amd_sdw0_channel { - ACP_SDW0_AUDIO0_TX = 0, - ACP_SDW0_AUDIO1_TX, - ACP_SDW0_AUDIO2_TX, - ACP_SDW0_AUDIO0_RX, - ACP_SDW0_AUDIO1_RX, - ACP_SDW0_AUDIO2_RX, +enum amd_acp63_sdw0_channel { + ACP63_SDW0_AUDIO0_TX = 0, + ACP63_SDW0_AUDIO1_TX, + ACP63_SDW0_AUDIO2_TX, + ACP63_SDW0_AUDIO0_RX, + ACP63_SDW0_AUDIO1_RX, + ACP63_SDW0_AUDIO2_RX, }; -enum amd_sdw1_channel { - ACP_SDW1_AUDIO1_TX, - ACP_SDW1_AUDIO1_RX, +enum amd_acp63_sdw1_channel { + ACP63_SDW1_AUDIO1_TX, + ACP63_SDW1_AUDIO1_RX, }; struct pdm_stream_instance { @@ -180,8 +180,8 @@ struct pdm_dev_data { struct sdw_dma_dev_data { void __iomem *acp_base; struct mutex *acp_lock; /* used to protect acp common register access */ - struct snd_pcm_substream *sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; - struct snd_pcm_substream *sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; }; struct acp_sdw_dma_stream { @@ -232,8 +232,10 @@ struct sdw_dma_ring_buf_reg { * @addr: pci ioremap address * @reg_range: ACP reigister range * @acp_rev: ACP PCI revision id - * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance - * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance + * @acp63_sdw0-dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW0 instance + * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire + * manager-SW1 instance */ struct acp63_dev_data { @@ -256,8 +258,8 @@ struct acp63_dev_data { u32 addr; u32 reg_range; u32 acp_rev; - u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; - u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; + u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; + u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; }; int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 8b556950b855..f5beb7f14913 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -30,10 +30,10 @@ static int acp63_power_on(void __iomem *acp_base) if (!val) return val; - if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) - writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) + writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); - return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP_TIMEOUT); + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); } static int acp63_reset(void __iomem *acp_base) @@ -45,13 +45,13 @@ static int acp63_reset(void __iomem *acp_base) ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, - DELAY_US, ACP_TIMEOUT); + DELAY_US, ACP63_TIMEOUT); if (ret) return ret; writel(0, acp_base + ACP_SOFT_RESET); - return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); } static void acp63_enable_interrupts(void __iomem *acp_base) @@ -104,24 +104,24 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) static irqreturn_t acp63_irq_thread(int irq, void *context) { - struct sdw_dma_dev_data *sdw_dma_data; + struct sdw_dma_dev_data *sdw_data; struct acp63_dev_data *adata = context; - u32 stream_index; + u32 stream_id; - sdw_dma_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); - for (stream_index = 0; stream_index < ACP63_SDW0_DMA_MAX_STREAMS; stream_index++) { - if (adata->sdw0_dma_intr_stat[stream_index]) { - if (sdw_dma_data->sdw0_dma_stream[stream_index]) - snd_pcm_period_elapsed(sdw_dma_data->sdw0_dma_stream[stream_index]); - adata->sdw0_dma_intr_stat[stream_index] = 0; + for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); + adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; } } - for (stream_index = 0; stream_index < ACP63_SDW1_DMA_MAX_STREAMS; stream_index++) { - if (adata->sdw1_dma_intr_stat[stream_index]) { - if (sdw_dma_data->sdw1_dma_stream[stream_index]) - snd_pcm_period_elapsed(sdw_dma_data->sdw1_dma_stream[stream_index]); - adata->sdw1_dma_intr_stat[stream_index] = 0; + for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); + adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; } } return IRQ_HANDLED; @@ -180,48 +180,48 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) snd_pcm_period_elapsed(ps_pdm_data->capture_stream); irq_flag = 1; } - if (ext_intr_stat & ACP_SDW_DMA_IRQ_MASK) { + if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { if (ext_intr_stat & BIT(index)) { writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); switch (index) { case ACP_AUDIO0_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO0_TX; + stream_id = ACP63_SDW0_AUDIO0_TX; break; case ACP_AUDIO1_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO1_TX; + stream_id = ACP63_SDW0_AUDIO1_TX; break; case ACP_AUDIO2_TX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO2_TX; + stream_id = ACP63_SDW0_AUDIO2_TX; break; case ACP_AUDIO0_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO0_RX; + stream_id = ACP63_SDW0_AUDIO0_RX; break; case ACP_AUDIO1_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO1_RX; + stream_id = ACP63_SDW0_AUDIO1_RX; break; case ACP_AUDIO2_RX_THRESHOLD: - stream_id = ACP_SDW0_AUDIO2_RX; + stream_id = ACP63_SDW0_AUDIO2_RX; break; } - adata->sdw0_dma_intr_stat[stream_id] = 1; + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; sdw_dma_irq_flag = 1; } } } - if (ext_intr_stat1 & ACP_P1_AUDIO1_RX_THRESHOLD) { - writel(ACP_P1_AUDIO1_RX_THRESHOLD, + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_RX] = 1; + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; sdw_dma_irq_flag = 1; } - if (ext_intr_stat1 & ACP_P1_AUDIO1_TX_THRESHOLD) { - writel(ACP_P1_AUDIO1_TX_THRESHOLD, + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_TX] = 1; + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; sdw_dma_irq_flag = 1; } diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index b602cca92b8b..878683619a05 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -18,7 +18,7 @@ #define DRV_NAME "amd_ps_sdw_dma" -static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { +static struct sdw_dma_ring_buf_reg acp63_sdw0_dma_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, @@ -44,7 +44,7 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register * set as per hardware register documentation */ -static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { +static struct sdw_dma_ring_buf_reg acp63_sdw1_dma_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, @@ -55,7 +55,7 @@ static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STRE ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, }; -static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { +static u32 acp63_sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { ACP_SW0_AUDIO0_TX_EN, ACP_SW0_AUDIO1_TX_EN, ACP_SW0_AUDIO2_TX_EN, @@ -70,7 +70,7 @@ static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers * as per hardware register documentation. */ -static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { +static u32 acp63_sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { ACP_SW1_AUDIO1_TX_EN, ACP_SW1_AUDIO1_RX_EN, }; @@ -117,8 +117,8 @@ static const struct snd_pcm_hardware acp63_sdw_hardware_capture = { static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable) { u32 ext_intr_cntl, ext_intr_cntl1; - u32 irq_mask = ACP_SDW_DMA_IRQ_MASK; - u32 irq_mask1 = ACP_P1_SDW_DMA_IRQ_MASK; + u32 irq_mask = ACP63_SDW_DMA_IRQ_MASK; + u32 irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK; if (enable) { ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); @@ -182,18 +182,18 @@ static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, switch (manager_instance) { case ACP_SDW0: - reg_dma_size = sdw0_dma_ring_buf_reg[stream_id].reg_dma_size; - reg_fifo_addr = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_addr; - reg_fifo_size = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; + reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr; break; case ACP_SDW1: - reg_dma_size = sdw1_dma_ring_buf_reg[stream_id].reg_dma_size; - reg_fifo_addr = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_addr; - reg_fifo_size = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; + reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr; break; default: return -EINVAL; @@ -267,19 +267,19 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, stream_id = stream->stream_id; switch (stream->instance) { case ACP_SDW0: - sdw_data->sdw0_dma_stream[stream_id] = substream; - water_mark_size_reg = sdw0_dma_ring_buf_reg[stream_id].water_mark_size_reg; + sdw_data->acp63_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg; acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - irq_mask = BIT(SDW0_DMA_TX_IRQ_MASK(stream_id)); + irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id)); else - irq_mask = BIT(SDW0_DMA_RX_IRQ_MASK(stream_id)); + irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id)); break; case ACP_SDW1: - sdw_data->sdw1_dma_stream[stream_id] = substream; + sdw_data->acp63_sdw1_dma_stream[stream_id] = substream; acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; - water_mark_size_reg = sdw1_dma_ring_buf_reg[stream_id].water_mark_size_reg; - irq_mask = BIT(SDW1_DMA_IRQ_MASK(stream_id)); + water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg; + irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id)); break; default: return -EINVAL; @@ -310,12 +310,12 @@ static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __io byte_count.bytescount = 0; switch (stream->instance) { case ACP_SDW0: - pos_low_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_low_reg; - pos_high_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_high_reg; + pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg; break; case ACP_SDW1: - pos_low_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_low_reg; - pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg; + pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg; break; default: goto POINTER_RETURN_BYTES; @@ -369,10 +369,10 @@ static int acp63_sdw_dma_close(struct snd_soc_component *component, return -EINVAL; switch (stream->instance) { case ACP_SDW0: - sdw_data->sdw0_dma_stream[stream->stream_id] = NULL; + sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL; break; case ACP_SDW1: - sdw_data->sdw1_dma_stream[stream->stream_id] = NULL; + sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL; break; default: return -EINVAL; @@ -395,10 +395,10 @@ static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, stream_id = stream->stream_id; switch (stream->instance) { case ACP_SDW0: - sdw_dma_en_reg = sdw0_dma_enable_reg[stream_id]; + sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id]; break; case ACP_SDW1: - sdw_dma_en_reg = sdw1_dma_enable_reg[stream_id]; + sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id]; break; default: return -EINVAL; @@ -512,13 +512,11 @@ static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) for (index = 0; index < stream_count; index++) { if (instance == ACP_SDW0) { - substream = sdw_data->sdw0_dma_stream[index]; - water_mark_size_reg = - sdw0_dma_ring_buf_reg[index].water_mark_size_reg; + substream = sdw_data->acp63_sdw0_dma_stream[index]; + water_mark_size_reg = acp63_sdw0_dma_reg[index].water_mark_size_reg; } else { - substream = sdw_data->sdw1_dma_stream[index]; - water_mark_size_reg = - sdw1_dma_ring_buf_reg[index].water_mark_size_reg; + substream = sdw_data->acp63_sdw1_dma_stream[index]; + water_mark_size_reg = acp63_sdw1_dma_reg[index].water_mark_size_reg; } if (substream && substream->runtime) { From 4b36a47e2d989b98953dbfb1e97da0f0169f5086 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:56 +0530 Subject: [PATCH 0068/1090] ASoC: amd: ps: use macro for ACP6.3 pci revision id Use macro for ACP6.3 PCI revision id instead of hard coded value. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-3-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 1 + sound/soc/amd/ps/pci-ps.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 01910273624b..8f3a597f658b 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -11,6 +11,7 @@ #define ACP_DEVICE_ID 0x15E2 #define ACP63_REG_START 0x1240000 #define ACP63_REG_END 0x125C000 +#define ACP63_PCI_REV 0x63 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 #define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index f5beb7f14913..9cc66a807ad9 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -562,7 +562,7 @@ static int snd_acp63_probe(struct pci_dev *pci, /* Pink Sardine device check */ switch (pci->revision) { - case 0x63: + case ACP63_PCI_REV: break; default: dev_dbg(&pci->dev, "acp63 pci device not found\n"); From db746fff89a14419379226ce0df8b94f472cf38c Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:57 +0530 Subject: [PATCH 0069/1090] ASoC: amd: ps: add acp pci driver hw_ops for acp6.3 platform Add ACP6.3 platform specific PCI driver hw_ops for acp init/de-init sequence. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-4-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/Makefile | 2 +- sound/soc/amd/ps/acp63.h | 32 ++++++++++ sound/soc/amd/ps/pci-ps.c | 118 +++++++++-------------------------- sound/soc/amd/ps/ps-common.c | 104 ++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 89 deletions(-) create mode 100644 sound/soc/amd/ps/ps-common.c diff --git a/sound/soc/amd/ps/Makefile b/sound/soc/amd/ps/Makefile index b5efb1c5382c..778ee4726389 100644 --- a/sound/soc/amd/ps/Makefile +++ b/sound/soc/amd/ps/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only # Pink Sardine platform Support -snd-pci-ps-y := pci-ps.o +snd-pci-ps-y := pci-ps.o ps-common.o snd-ps-pdm-dma-y := ps-pdm-dma.o snd-soc-ps-mach-y := ps-mach.o snd-ps-sdw-dma-y := ps-sdw-dma.o diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 8f3a597f658b..ec22a7dad6ac 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -130,6 +130,8 @@ #define SDW_MAX_BUFFER (SDW_PLAYBACK_MAX_PERIOD_SIZE * SDW_PLAYBACK_MAX_NUM_PERIODS) #define SDW_MIN_BUFFER SDW_MAX_BUFFER +#define ACP_HW_OPS(acp_data, cb) ((acp_data)->hw_ops->cb) + enum acp_config { ACP_CONFIG_0 = 0, ACP_CONFIG_1, @@ -213,10 +215,23 @@ struct sdw_dma_ring_buf_reg { u32 pos_high_reg; }; +struct acp63_dev_data; + +/** + * struct acp_hw_ops - ACP PCI driver platform specific ops + * @acp_init: ACP initialization + * @acp_deinit: ACP de-initialization + */ +struct acp_hw_ops { + int (*acp_init)(void __iomem *acp_base, struct device *dev); + int (*acp_deinit)(void __iomem *acp_base, struct device *dev); +}; + /** * struct acp63_dev_data - acp pci driver context * @acp63_base: acp mmio base * @res: resource + * @hw_ops: ACP pci driver platform-specific ops * @pdm_dev: ACP PDM controller platform device * @dmic_codec: platform device for DMIC Codec * sdw_dma_dev: platform device for SoundWire DMA controller @@ -242,6 +257,7 @@ struct sdw_dma_ring_buf_reg { struct acp63_dev_data { void __iomem *acp63_base; struct resource *res; + struct acp_hw_ops *hw_ops; struct platform_device *pdm_dev; struct platform_device *dmic_codec_dev; struct platform_device *sdw_dma_dev; @@ -263,4 +279,20 @@ struct acp63_dev_data { u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; }; +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops); + +static inline int acp_hw_init(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_init) + return ACP_HW_OPS(adata, acp_init)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_deinit) + return ACP_HW_OPS(adata, acp_deinit)(adata->acp63_base, dev); + return -EOPNOTSUPP; +} + int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 9cc66a807ad9..120bab1844bb 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -21,87 +21,6 @@ #include "acp63.h" -static int acp63_power_on(void __iomem *acp_base) -{ - u32 val; - - val = readl(acp_base + ACP_PGFSM_STATUS); - - if (!val) - return val; - - if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) - writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); - - return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); -} - -static int acp63_reset(void __iomem *acp_base) -{ - u32 val; - int ret; - - writel(1, acp_base + ACP_SOFT_RESET); - - ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, - val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, - DELAY_US, ACP63_TIMEOUT); - if (ret) - return ret; - - writel(0, acp_base + ACP_SOFT_RESET); - - return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); -} - -static void acp63_enable_interrupts(void __iomem *acp_base) -{ - writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); - writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); -} - -static void acp63_disable_interrupts(void __iomem *acp_base) -{ - writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); - writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); - writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); -} - -static int acp63_init(void __iomem *acp_base, struct device *dev) -{ - int ret; - - ret = acp63_power_on(acp_base); - if (ret) { - dev_err(dev, "ACP power on failed\n"); - return ret; - } - writel(0x01, acp_base + ACP_CONTROL); - ret = acp63_reset(acp_base); - if (ret) { - dev_err(dev, "ACP reset failed\n"); - return ret; - } - acp63_enable_interrupts(acp_base); - writel(0, acp_base + ACP_ZSC_DSP_CTRL); - return 0; -} - -static int acp63_deinit(void __iomem *acp_base, struct device *dev) -{ - int ret; - - acp63_disable_interrupts(acp_base); - ret = acp63_reset(acp_base); - if (ret) { - dev_err(dev, "ACP reset failed\n"); - return ret; - } - writel(0, acp_base + ACP_CONTROL); - writel(1, acp_base + ACP_ZSC_DSP_CTRL); - return 0; -} - static irqreturn_t acp63_irq_thread(int irq, void *context) { struct sdw_dma_dev_data *sdw_data; @@ -540,11 +459,29 @@ unregister_dmic_codec_dev: unregister_pdm_dev: platform_device_unregister(adata->pdm_dev); de_init: - if (acp63_deinit(adata->acp63_base, &pci->dev)) + if (acp_hw_deinit(adata, &pci->dev)) dev_err(&pci->dev, "ACP de-init failed\n"); return ret; } +static int acp_hw_init_ops(struct acp63_dev_data *adata, struct pci_dev *pci) +{ + adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops), + GFP_KERNEL); + if (!adata->hw_ops) + return -ENOMEM; + + switch (adata->acp_rev) { + case ACP63_PCI_REV: + acp63_hw_init_ops(adata->hw_ops); + break; + default: + dev_err(&pci->dev, "ACP device not found\n"); + return -ENODEV; + } + return 0; +} + static int snd_acp63_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -598,7 +535,12 @@ static int snd_acp63_probe(struct pci_dev *pci, pci_set_master(pci); pci_set_drvdata(pci, adata); mutex_init(&adata->acp_lock); - ret = acp63_init(adata->acp63_base, &pci->dev); + ret = acp_hw_init_ops(adata, pci); + if (ret) { + dev_err(&pci->dev, "ACP hw ops init failed\n"); + goto release_regions; + } + ret = acp_hw_init(adata, &pci->dev); if (ret) goto release_regions; ret = devm_request_threaded_irq(&pci->dev, pci->irq, acp63_irq_handler, @@ -632,7 +574,7 @@ skip_pdev_creation: pm_runtime_allow(&pci->dev); return 0; de_init: - if (acp63_deinit(adata->acp63_base, &pci->dev)) + if (acp_hw_deinit(adata, &pci->dev)) dev_err(&pci->dev, "ACP de-init failed\n"); release_regions: pci_release_regions(pci); @@ -677,7 +619,7 @@ static int __maybe_unused snd_acp63_suspend(struct device *dev) return 0; } } - ret = acp63_deinit(adata->acp63_base, dev); + ret = acp_hw_deinit(adata, dev); if (ret) dev_err(dev, "ACP de-init failed\n"); @@ -694,7 +636,7 @@ static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); return 0; } - ret = acp63_init(adata->acp63_base, dev); + ret = acp_hw_init(adata, dev); if (ret) { dev_err(dev, "ACP init failed\n"); return ret; @@ -716,7 +658,7 @@ static int __maybe_unused snd_acp63_resume(struct device *dev) return 0; } - ret = acp63_init(adata->acp63_base, dev); + ret = acp_hw_deinit(adata, dev); if (ret) dev_err(dev, "ACP init failed\n"); @@ -744,7 +686,7 @@ static void snd_acp63_remove(struct pci_dev *pci) } if (adata->mach_dev) platform_device_unregister(adata->mach_dev); - ret = acp63_deinit(adata->acp63_base, &pci->dev); + ret = acp_hw_deinit(adata, &pci->dev); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); pm_runtime_forbid(&pci->dev); diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c new file mode 100644 index 000000000000..771249a76537 --- /dev/null +++ b/sound/soc/amd/ps/ps-common.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1 + * platforms. + * + * Copyright 2025 Advanced Micro Devices, Inc. + * Authors: Vijendar Mukunda + */ + +#include +#include +#include +#include +#include +#include + +#include "acp63.h" + +static int acp63_power_on(void __iomem *acp_base) +{ + u32 val; + + val = readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return val; + + if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS) + writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static int acp63_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP63_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT); +} + +static void acp63_enable_interrupts(void __iomem *acp_base) +{ + writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); +} + +static void acp63_disable_interrupts(void __iomem *acp_base) +{ + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); + writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); + writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp63_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp63_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + acp63_enable_interrupts(acp_base); + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int acp63_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + acp63_disable_interrupts(acp_base); + ret = acp63_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_CONTROL); + writel(1, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp63_init; + hw_ops->acp_deinit = acp63_deinit; +} From 491628388005a26c02d6827e649284357daec213 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:58 +0530 Subject: [PATCH 0070/1090] ASoC: amd: ps: add callback functions for acp pci driver pm ops Add acp pci driver pm ops related callback functions for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-5-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 44 ++++++++++++++++++ sound/soc/amd/ps/pci-ps.c | 82 ++++------------------------------ sound/soc/amd/ps/ps-common.c | 86 ++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 74 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index ec22a7dad6ac..4e3f7eaac040 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -221,10 +221,18 @@ struct acp63_dev_data; * struct acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization + * acp_suspend: ACP system level suspend callback + * acp_resume: ACP system level resume callback + * acp_suspend_runtime: ACP runtime suspend callback + * acp_resume_runtime: ACP runtime resume callback */ struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + int (*acp_suspend)(struct device *dev); + int (*acp_resume)(struct device *dev); + int (*acp_suspend_runtime)(struct device *dev); + int (*acp_resume_runtime)(struct device *dev); }; /** @@ -295,4 +303,40 @@ static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev return -EOPNOTSUPP; } +static inline int acp_hw_suspend(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend) + return ACP_HW_OPS(adata, acp_suspend)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume) + return ACP_HW_OPS(adata, acp_resume)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend_runtime(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime) + return ACP_HW_OPS(adata, acp_suspend_runtime)(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime) + return ACP_HW_OPS(adata, acp_resume_runtime)(dev); + return -EOPNOTSUPP; +} + int snd_amd_acp_find_config(struct pci_dev *pci); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 120bab1844bb..a37fb6172958 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -584,90 +584,24 @@ disable_pci: return ret; } -static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) +static int __maybe_unused snd_acp_suspend(struct device *dev) { - u32 sdw0_en, sdw1_en; - - sdw0_en = readl(adata->acp63_base + ACP_SW0_EN); - sdw1_en = readl(adata->acp63_base + ACP_SW1_EN); - return (sdw0_en || sdw1_en); + return acp_hw_suspend(dev); } -static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata) +static int __maybe_unused snd_acp_runtime_resume(struct device *dev) { - u32 val; - - val = readl(adata->acp63_base + ACP_SW0_WAKE_EN); - if (val && adata->sdw->pdev[0]) - pm_request_resume(&adata->sdw->pdev[0]->dev); - - val = readl(adata->acp63_base + ACP_SW1_WAKE_EN); - if (val && adata->sdw->pdev[1]) - pm_request_resume(&adata->sdw->pdev[1]->dev); + return acp_hw_runtime_resume(dev); } -static int __maybe_unused snd_acp63_suspend(struct device *dev) +static int __maybe_unused snd_acp_resume(struct device *dev) { - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->is_sdw_dev) { - adata->sdw_en_stat = check_acp_sdw_enable_status(adata); - if (adata->sdw_en_stat) { - writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - } - ret = acp_hw_deinit(adata, dev); - if (ret) - dev_err(dev, "ACP de-init failed\n"); - - return ret; -} - -static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) -{ - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->sdw_en_stat) { - writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - ret = acp_hw_init(adata, dev); - if (ret) { - dev_err(dev, "ACP init failed\n"); - return ret; - } - - if (!adata->sdw_en_stat) - handle_acp63_sdw_pme_event(adata); - return 0; -} - -static int __maybe_unused snd_acp63_resume(struct device *dev) -{ - struct acp63_dev_data *adata; - int ret; - - adata = dev_get_drvdata(dev); - if (adata->sdw_en_stat) { - writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); - return 0; - } - - ret = acp_hw_deinit(adata, dev); - if (ret) - dev_err(dev, "ACP init failed\n"); - - return ret; + return acp_hw_resume(dev); } static const struct dev_pm_ops acp63_pm_ops = { - SET_RUNTIME_PM_OPS(snd_acp63_suspend, snd_acp63_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_acp63_suspend, snd_acp63_resume) + SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) }; static void snd_acp63_remove(struct pci_dev *pci) diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 771249a76537..7643f321be37 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "acp63.h" @@ -97,8 +98,93 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) return 0; } +static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) +{ + u32 sdw0_en, sdw1_en; + + sdw0_en = readl(adata->acp63_base + ACP_SW0_EN); + sdw1_en = readl(adata->acp63_base + ACP_SW1_EN); + return (sdw0_en || sdw1_en); +} + +static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata) +{ + u32 val; + + val = readl(adata->acp63_base + ACP_SW0_WAKE_EN); + if (val && adata->sdw->pdev[0]) + pm_request_resume(&adata->sdw->pdev[0]->dev); + + val = readl(adata->acp63_base + ACP_SW1_WAKE_EN); + if (val && adata->sdw->pdev[1]) + pm_request_resume(&adata->sdw->pdev[1]->dev); +} + +static int __maybe_unused snd_acp63_suspend(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->is_sdw_dev) { + adata->sdw_en_stat = check_acp_sdw_enable_status(adata); + if (adata->sdw_en_stat) { + writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + } + ret = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + + return ret; +} + +static int __maybe_unused snd_acp63_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + + if (!adata->sdw_en_stat) + handle_acp63_sdw_pme_event(adata); + return 0; +} + +static int __maybe_unused snd_acp63_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + return ret; +} + void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; + hw_ops->acp_suspend = snd_acp63_suspend; + hw_ops->acp_resume = snd_acp63_resume; + hw_ops->acp_suspend_runtime = snd_acp63_suspend; + hw_ops->acp_resume_runtime = snd_acp63_runtime_resume; } From 6547577e94ae3d9f8ff30d3267fe7ec394e3b20d Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:57:59 +0530 Subject: [PATCH 0071/1090] ASoC: amd: ps: add callback to read acp pin configuration Add pci driver callback to read acp pin configuration for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-6-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 8 ++++++++ sound/soc/amd/ps/pci-ps.c | 26 +------------------------- sound/soc/amd/ps/ps-common.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 4e3f7eaac040..a918a988e4d8 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -221,6 +221,7 @@ struct acp63_dev_data; * struct acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization + * @acp_get_config: function to read the acp pin configuration * acp_suspend: ACP system level suspend callback * acp_resume: ACP system level resume callback * acp_suspend_runtime: ACP runtime suspend callback @@ -229,6 +230,7 @@ struct acp63_dev_data; struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + void (*acp_get_config)(struct pci_dev *pci, struct acp63_dev_data *acp_data); int (*acp_suspend)(struct device *dev); int (*acp_resume)(struct device *dev); int (*acp_suspend_runtime)(struct device *dev); @@ -303,6 +305,12 @@ static inline int acp_hw_deinit(struct acp63_dev_data *adata, struct device *dev return -EOPNOTSUPP; } +static inline void acp_hw_get_config(struct pci_dev *pci, struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_get_config) + ACP_HW_OPS(adata, acp_get_config)(pci, adata); +} + static inline int acp_hw_suspend(struct device *dev) { struct acp63_dev_data *adata = dev_get_drvdata(dev); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index a37fb6172958..96399acf906c 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -299,7 +299,6 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a const union acpi_object *obj; acpi_handle handle; acpi_integer dmic_status; - u32 config; bool is_dmic_dev = false; bool is_sdw_dev = false; bool wov_en, dmic_en; @@ -309,30 +308,7 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a wov_en = true; dmic_en = false; - config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); - switch (config) { - case ACP_CONFIG_4: - case ACP_CONFIG_5: - case ACP_CONFIG_10: - case ACP_CONFIG_11: - acp_data->is_pdm_config = true; - break; - case ACP_CONFIG_2: - case ACP_CONFIG_3: - acp_data->is_sdw_config = true; - break; - case ACP_CONFIG_6: - case ACP_CONFIG_7: - case ACP_CONFIG_12: - case ACP_CONFIG_8: - case ACP_CONFIG_13: - case ACP_CONFIG_14: - acp_data->is_pdm_config = true; - acp_data->is_sdw_config = true; - break; - default: - break; - } + acp_hw_get_config(pci, acp_data); if (acp_data->is_pdm_config) { pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0); diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 7643f321be37..30e9e5fe034b 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,37 @@ static int acp63_deinit(void __iomem *acp_base, struct device *dev) return 0; } +static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + u32 config; + + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); + dev_dbg(&pci->dev, "ACP config value: %d\n", config); + switch (config) { + case ACP_CONFIG_4: + case ACP_CONFIG_5: + case ACP_CONFIG_10: + case ACP_CONFIG_11: + acp_data->is_pdm_config = true; + break; + case ACP_CONFIG_2: + case ACP_CONFIG_3: + acp_data->is_sdw_config = true; + break; + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_12: + case ACP_CONFIG_8: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + acp_data->is_pdm_config = true; + acp_data->is_sdw_config = true; + break; + default: + break; + } +} + static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata) { u32 sdw0_en, sdw1_en; @@ -183,6 +215,7 @@ void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; + hw_ops->acp_get_config = acp63_get_config; hw_ops->acp_suspend = snd_acp63_suspend; hw_ops->acp_resume = snd_acp63_resume; hw_ops->acp_suspend_runtime = snd_acp63_suspend; From 0a27b2d7a224326fab543ca586d501fe1857b655 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:00 +0530 Subject: [PATCH 0072/1090] ASoC: amd: ps: add soundwire dma irq thread callback Add acp pci driver Soundwire DMA irq thread callaback for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-7-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 8 ++++++++ sound/soc/amd/ps/pci-ps.c | 19 +------------------ sound/soc/amd/ps/ps-common.c | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index a918a988e4d8..9a20846d30ff 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -222,6 +222,7 @@ struct acp63_dev_data; * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization * @acp_get_config: function to read the acp pin configuration + * @acp_sdw_dma_irq_thread: ACP SoundWire DMA interrupt thread * acp_suspend: ACP system level suspend callback * acp_resume: ACP system level resume callback * acp_suspend_runtime: ACP runtime suspend callback @@ -231,6 +232,7 @@ struct acp_hw_ops { int (*acp_init)(void __iomem *acp_base, struct device *dev); int (*acp_deinit)(void __iomem *acp_base, struct device *dev); void (*acp_get_config)(struct pci_dev *pci, struct acp63_dev_data *acp_data); + void (*acp_sdw_dma_irq_thread)(struct acp63_dev_data *acp_data); int (*acp_suspend)(struct device *dev); int (*acp_resume)(struct device *dev); int (*acp_suspend_runtime)(struct device *dev); @@ -311,6 +313,12 @@ static inline void acp_hw_get_config(struct pci_dev *pci, struct acp63_dev_data ACP_HW_OPS(adata, acp_get_config)(pci, adata); } +static inline void acp_hw_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_sdw_dma_irq_thread) + ACP_HW_OPS(adata, acp_sdw_dma_irq_thread)(adata); +} + static inline int acp_hw_suspend(struct device *dev) { struct acp63_dev_data *adata = dev_get_drvdata(dev); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 96399acf906c..5d9c230043a6 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -23,26 +23,9 @@ static irqreturn_t acp63_irq_thread(int irq, void *context) { - struct sdw_dma_dev_data *sdw_data; struct acp63_dev_data *adata = context; - u32 stream_id; - sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); - - for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { - if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { - if (sdw_data->acp63_sdw0_dma_stream[stream_id]) - snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); - adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; - } - } - for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { - if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { - if (sdw_data->acp63_sdw1_dma_stream[stream_id]) - snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); - adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; - } - } + acp_hw_sdw_dma_irq_thread(adata); return IRQ_HANDLED; } diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 30e9e5fe034b..9098974b3608 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "acp63.h" @@ -211,11 +212,35 @@ static int __maybe_unused snd_acp63_resume(struct device *dev) return ret; } +static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + struct sdw_dma_dev_data *sdw_data; + u32 stream_id; + + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + + for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]); + adata->acp63_sdw0_dma_intr_stat[stream_id] = 0; + } + } + for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp63_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp63_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]); + adata->acp63_sdw1_dma_intr_stat[stream_id] = 0; + } + } +} + void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp63_init; hw_ops->acp_deinit = acp63_deinit; hw_ops->acp_get_config = acp63_get_config; + hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread; hw_ops->acp_suspend = snd_acp63_suspend; hw_ops->acp_resume = snd_acp63_resume; hw_ops->acp_suspend_runtime = snd_acp63_suspend; From 4516be370ced14c4fb454fd6cc016e47bffe109e Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:01 +0530 Subject: [PATCH 0073/1090] ASoC: amd: ps: refactor soundwire dma interrupt handling Move the Soundwire DMA interrupt handling to separate function. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-8-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 96 ++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 5d9c230043a6..04b43b4128bc 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -21,6 +21,55 @@ #include "acp63.h" +static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat, + u32 ext_intr_stat1) +{ + u32 stream_id = 0; + u16 sdw_dma_irq_flag = 0; + u16 index; + + if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { + for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { + if (ext_intr_stat & BIT(index)) { + writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); + switch (index) { + case ACP_AUDIO0_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_TX; + break; + case ACP_AUDIO1_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_TX; + break; + case ACP_AUDIO2_TX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_TX; + break; + case ACP_AUDIO0_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO0_RX; + break; + case ACP_AUDIO1_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO1_RX; + break; + case ACP_AUDIO2_RX_THRESHOLD: + stream_id = ACP63_SDW0_AUDIO2_RX; + break; + } + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; + sdw_dma_irq_flag = 1; + } + } + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; + sdw_dma_irq_flag = 1; + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; + sdw_dma_irq_flag = 1; + } + return sdw_dma_irq_flag; +} + static irqreturn_t acp63_irq_thread(int irq, void *context) { struct acp63_dev_data *adata = context; @@ -35,10 +84,8 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) struct pdm_dev_data *ps_pdm_data; struct amd_sdw_manager *amd_manager; u32 ext_intr_stat, ext_intr_stat1; - u32 stream_id = 0; u16 irq_flag = 0; u16 sdw_dma_irq_flag = 0; - u16 index; adata = dev_id; if (!adata) @@ -82,51 +129,8 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) snd_pcm_period_elapsed(ps_pdm_data->capture_stream); irq_flag = 1; } - if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) { - for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { - if (ext_intr_stat & BIT(index)) { - writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); - switch (index) { - case ACP_AUDIO0_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO0_TX; - break; - case ACP_AUDIO1_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO1_TX; - break; - case ACP_AUDIO2_TX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO2_TX; - break; - case ACP_AUDIO0_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO0_RX; - break; - case ACP_AUDIO1_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO1_RX; - break; - case ACP_AUDIO2_RX_THRESHOLD: - stream_id = ACP63_SDW0_AUDIO2_RX; - break; - } - - adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; - sdw_dma_irq_flag = 1; - } - } - } - - if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_RX_THRESHOLD, - adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; - sdw_dma_irq_flag = 1; - } - - if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_TX_THRESHOLD, - adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; - sdw_dma_irq_flag = 1; - } + sdw_dma_irq_flag = check_and_handle_sdw_dma_irq(adata, ext_intr_stat, ext_intr_stat1); if (sdw_dma_irq_flag) return IRQ_WAKE_THREAD; From fcb754602724fa2a1d0db72f13ddc3ef0306f911 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:02 +0530 Subject: [PATCH 0074/1090] ASoC: amd: ps: store acp revision id in SoundWire dma driver private data Store acp pci revision id in SoundWire dma driver private data structure. It will be used to distinguish platform specific code. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-9-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 1 + sound/soc/amd/ps/ps-sdw-dma.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 9a20846d30ff..098597d92bf9 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -183,6 +183,7 @@ struct pdm_dev_data { struct sdw_dma_dev_data { void __iomem *acp_base; struct mutex *acp_lock; /* used to protect acp common register access */ + u32 acp_rev; struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; }; diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 878683619a05..b3c716371d15 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -474,6 +474,7 @@ static int acp63_sdw_platform_probe(struct platform_device *pdev) return -ENOMEM; sdw_data->acp_lock = &acp_data->acp_lock; + sdw_data->acp_rev = acp_data->acp_rev; dev_set_drvdata(&pdev->dev, sdw_data); status = devm_snd_soc_register_component(&pdev->dev, &acp63_sdw_component, From 0fa0843db17ccd427fc7a23d313aafa88fc89e04 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:03 +0530 Subject: [PATCH 0075/1090] ASoC: amd: ps: refactor soundwire dma driver code Refactor existing SoundWire dma driver code by adding acp_rev check for ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-10-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-sdw-dma.c | 146 +++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 57 deletions(-) diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index b3c716371d15..d10950e1cf73 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -167,7 +167,7 @@ static void acp63_config_dma(struct acp_sdw_dma_stream *stream, void __iomem *ac } static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 size, - u32 manager_instance) + u32 manager_instance, u32 acp_rev) { u32 reg_dma_size; u32 reg_fifo_addr; @@ -180,20 +180,26 @@ static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 sdw_ring_buf_size; u32 sdw_mem_window_offset; - switch (manager_instance) { - case ACP_SDW0: - reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size; - reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr; - reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr; - break; - case ACP_SDW1: - reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size; - reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr; - reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size; - reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size; - reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr; + switch (acp_rev) { + case ACP63_PCI_REV: + switch (manager_instance) { + case ACP_SDW0: + reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr; + break; + case ACP_SDW1: + reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -265,21 +271,27 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, if (!stream) return -EINVAL; stream_id = stream->stream_id; - switch (stream->instance) { - case ACP_SDW0: - sdw_data->acp63_sdw0_dma_stream[stream_id] = substream; - water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg; - acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id)); - else - irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id)); - break; - case ACP_SDW1: - sdw_data->acp63_sdw1_dma_stream[stream_id] = substream; - acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; - water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg; - irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id)); + switch (sdw_data->acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp63_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id)); + break; + case ACP_SDW1: + sdw_data->acp63_sdw1_dma_stream[stream_id] = substream; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; + water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg; + irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id)); + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -290,7 +302,7 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, stream->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); acp63_config_dma(stream, sdw_data->acp_base, stream_id); ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, stream_id, size, - stream->instance); + stream->instance, sdw_data->acp_rev); if (ret) { dev_err(component->dev, "Invalid DMA channel\n"); return -EINVAL; @@ -302,20 +314,27 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, return 0; } -static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base) +static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base, + u32 acp_rev) { union acp_sdw_dma_count byte_count; u32 pos_low_reg, pos_high_reg; byte_count.bytescount = 0; - switch (stream->instance) { - case ACP_SDW0: - pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg; - pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg; - break; - case ACP_SDW1: - pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg; - pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg; + switch (acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg; + break; + case ACP_SDW1: + pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg; + break; + default: + goto POINTER_RETURN_BYTES; + } break; default: goto POINTER_RETURN_BYTES; @@ -340,7 +359,7 @@ static snd_pcm_uframes_t acp63_sdw_dma_pointer(struct snd_soc_component *comp, stream = substream->runtime->private_data; buffersize = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); - bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base); + bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base, sdw_data->acp_rev); if (bytescount > stream->bytescount) bytescount -= stream->bytescount; pos = do_div(bytescount, buffersize); @@ -367,12 +386,18 @@ static int acp63_sdw_dma_close(struct snd_soc_component *component, stream = substream->runtime->private_data; if (!stream) return -EINVAL; - switch (stream->instance) { - case ACP_SDW0: - sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL; - break; - case ACP_SDW1: - sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL; + switch (sdw_data->acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL; + break; + case ACP_SDW1: + sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -382,7 +407,7 @@ static int acp63_sdw_dma_close(struct snd_soc_component *component, } static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, - void __iomem *acp_base, bool sdw_dma_enable) + void __iomem *acp_base, u32 acp_rev, bool sdw_dma_enable) { struct acp_sdw_dma_stream *stream; u32 stream_id; @@ -393,12 +418,18 @@ static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, stream = substream->runtime->private_data; stream_id = stream->stream_id; - switch (stream->instance) { - case ACP_SDW0: - sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id]; - break; - case ACP_SDW1: - sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id]; + switch (acp_rev) { + case ACP63_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id]; + break; + case ACP_SDW1: + sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id]; + break; + default: + return -EINVAL; + } break; default: return -EINVAL; @@ -422,12 +453,12 @@ static int acp63_sdw_dma_trigger(struct snd_soc_component *comp, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, true); + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, true); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, false); + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, false); break; default: ret = -EINVAL; @@ -527,7 +558,8 @@ static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) buf_size = frames_to_bytes(runtime, runtime->buffer_size); acp63_config_dma(stream, sdw_data->acp_base, index); ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index, - buf_size, instance); + buf_size, instance, + ACP63_PCI_REV); if (ret) return ret; writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); From 43d6140cedad9f031b47dfde6f85856e007b3f04 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:04 +0530 Subject: [PATCH 0076/1090] ASoC: amd: ps: refactor soundwire dma interrupts enable/disable sequence Refactor SoundWire dma interrupts enable/disable sequence by passing interrupt mask values as an arguments. This will allow to use same function for enabling/disabling SoundWire dma interrupts for different platforms. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-11-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-sdw-dma.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index d10950e1cf73..674203a20338 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -114,11 +114,10 @@ static const struct snd_pcm_hardware acp63_sdw_hardware_capture = { .periods_max = SDW_CAPTURE_MAX_NUM_PERIODS, }; -static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable) +static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, u32 irq_mask, + u32 irq_mask1, bool enable) { u32 ext_intr_cntl, ext_intr_cntl1; - u32 irq_mask = ACP63_SDW_DMA_IRQ_MASK; - u32 irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK; if (enable) { ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); @@ -533,9 +532,11 @@ static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; u32 period_bytes, buf_size, water_mark_size_reg; - u32 stream_count; + u32 stream_count, irq_mask, irq_mask1; int index, instance, ret; + irq_mask = ACP63_SDW_DMA_IRQ_MASK; + irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK; for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) { if (instance == ACP_SDW0) stream_count = ACP63_SDW0_DMA_MAX_STREAMS; @@ -566,7 +567,7 @@ static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) } } } - acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, true); + acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true); return 0; } From 605aab3b3ca83f58681841b2dd16d4a7baefde6c Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:05 +0530 Subject: [PATCH 0077/1090] ASoC: amd: ps: rename acp_restore_sdw_dma_config() function Rename acp_restore_sdw_dma_config() as acp63_restore_sdw_dma_config() which is specific to ACP6.3 platform. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-12-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-sdw-dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 674203a20338..7cd153a4edc9 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -526,7 +526,7 @@ static void acp63_sdw_platform_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) +static int acp63_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) { struct acp_sdw_dma_stream *stream; struct snd_pcm_substream *substream; @@ -576,7 +576,7 @@ static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev) struct sdw_dma_dev_data *sdw_data; sdw_data = dev_get_drvdata(dev); - return acp_restore_sdw_dma_config(sdw_data); + return acp63_restore_sdw_dma_config(sdw_data); } static const struct dev_pm_ops acp63_pm_ops = { From 7c0ea26c57b0bb72d503fe27d6533f5addc5e3a3 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:06 +0530 Subject: [PATCH 0078/1090] ASoC: amd: ps: add pci driver hw_ops for ACP7.0 & ACP7.1 variants Add below ACP pci driver hw_ops for ACP7.0 & ACP7.1 variants. - acp_init() - acp_deinit() - acp_get_config() Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-13-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 14 ++++ sound/soc/amd/ps/pci-ps.c | 10 ++- sound/soc/amd/ps/ps-common.c | 138 +++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 098597d92bf9..f65f242211e9 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -12,6 +12,8 @@ #define ACP63_REG_START 0x1240000 #define ACP63_REG_END 0x125C000 #define ACP63_PCI_REV 0x63 +#define ACP70_PCI_REV 0x70 +#define ACP71_PCI_REV 0x71 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 #define ACP63_PGFSM_CNTL_POWER_ON_MASK 1 @@ -132,6 +134,12 @@ #define ACP_HW_OPS(acp_data, cb) ((acp_data)->hw_ops->cb) +#define ACP70_PGFSM_CNTL_POWER_ON_MASK 0x1F +#define ACP70_PGFSM_CNTL_POWER_OFF_MASK 0 +#define ACP70_PGFSM_STATUS_MASK 0xFF +#define ACP70_TIMEOUT 2000 +#define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 + enum acp_config { ACP_CONFIG_0 = 0, ACP_CONFIG_1, @@ -149,6 +157,11 @@ enum acp_config { ACP_CONFIG_13, ACP_CONFIG_14, ACP_CONFIG_15, + ACP_CONFIG_16, + ACP_CONFIG_17, + ACP_CONFIG_18, + ACP_CONFIG_19, + ACP_CONFIG_20, }; enum amd_acp63_sdw0_channel { @@ -293,6 +306,7 @@ struct acp63_dev_data { }; void acp63_hw_init_ops(struct acp_hw_ops *hw_ops); +void acp70_hw_init_ops(struct acp_hw_ops *hw_ops); static inline int acp_hw_init(struct acp63_dev_data *adata, struct device *dev) { diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 04b43b4128bc..8f73d2ce2197 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -438,6 +438,10 @@ static int acp_hw_init_ops(struct acp63_dev_data *adata, struct pci_dev *pci) case ACP63_PCI_REV: acp63_hw_init_ops(adata->hw_ops); break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + acp70_hw_init_ops(adata->hw_ops); + break; default: dev_err(&pci->dev, "ACP device not found\n"); return -ENODEV; @@ -460,12 +464,14 @@ static int snd_acp63_probe(struct pci_dev *pci, if (flag) return -ENODEV; - /* Pink Sardine device check */ + /* ACP PCI revision id check for ACP6.3, ACP7.0 & ACP7.1 platforms */ switch (pci->revision) { case ACP63_PCI_REV: + case ACP70_PCI_REV: + case ACP71_PCI_REV: break; default: - dev_dbg(&pci->dev, "acp63 pci device not found\n"); + dev_dbg(&pci->dev, "acp63/acp70/acp71 pci device not found\n"); return -ENODEV; } if (pci_enable_device(pci)) { diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 9098974b3608..a15284bde48d 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -246,3 +246,141 @@ void acp63_hw_init_ops(struct acp_hw_ops *hw_ops) hw_ops->acp_suspend_runtime = snd_acp63_suspend; hw_ops->acp_resume_runtime = snd_acp63_runtime_resume; } + +static int acp70_power_on(void __iomem *acp_base) +{ + u32 val = 0; + + val = readl(acp_base + ACP_PGFSM_STATUS); + + if (!val) + return 0; + if (val & ACP70_PGFSM_STATUS_MASK) + writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT); +} + +static int acp70_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP70_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT); +} + +static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base) +{ + u32 ext_intr_cntl1; + + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK; + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); +} + +static void acp70_enable_interrupts(void __iomem *acp_base) +{ + u32 sdw0_wake_en, sdw1_wake_en; + + writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); + sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN); + sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN); + if (sdw0_wake_en || sdw1_wake_en) + acp70_enable_sdw_host_wake_interrupts(acp_base); +} + +static void acp70_disable_interrupts(void __iomem *acp_base) +{ + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT); + writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); + writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp70_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp70_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp70_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + acp70_enable_interrupts(acp_base); + writel(0x1, acp_base + ACP_PME_EN); + return 0; +} + +static int acp70_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + acp70_disable_interrupts(acp_base); + ret = acp70_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data) +{ + u32 config; + + config = readl(acp_data->acp63_base + ACP_PIN_CONFIG); + dev_dbg(&pci->dev, "ACP config value: %d\n", config); + switch (config) { + case ACP_CONFIG_4: + case ACP_CONFIG_5: + case ACP_CONFIG_10: + case ACP_CONFIG_11: + case ACP_CONFIG_20: + acp_data->is_pdm_config = true; + break; + case ACP_CONFIG_2: + case ACP_CONFIG_3: + case ACP_CONFIG_16: + acp_data->is_sdw_config = true; + break; + case ACP_CONFIG_6: + case ACP_CONFIG_7: + case ACP_CONFIG_12: + case ACP_CONFIG_8: + case ACP_CONFIG_13: + case ACP_CONFIG_14: + case ACP_CONFIG_17: + case ACP_CONFIG_18: + case ACP_CONFIG_19: + acp_data->is_pdm_config = true; + acp_data->is_sdw_config = true; + break; + default: + break; + } +} + +void acp70_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp70_init; + hw_ops->acp_deinit = acp70_deinit; + hw_ops->acp_get_config = acp70_get_config; +} From fde277dbcf53be685d0b9976d636366c80a74da8 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:07 +0530 Subject: [PATCH 0079/1090] ASoC: amd: ps: add pm ops related hw_ops for ACP7.0 & ACP7.1 platforms Add ACP7.0 & ACP7.1 platform specific PM ops related hw_ops. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-14-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/ps-common.c | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index a15284bde48d..6639dac0a415 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -378,9 +378,74 @@ static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_dat } } +static int __maybe_unused snd_acp70_suspend(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + if (adata->is_sdw_dev) { + adata->sdw_en_stat = check_acp_sdw_enable_status(adata); + if (adata->sdw_en_stat) { + writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); + return 0; + } + } + ret = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + + return ret; +} + +static int __maybe_unused snd_acp70_runtime_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + writel(1, adata->acp63_base + ACP_PME_EN); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static int __maybe_unused snd_acp70_resume(struct device *dev) +{ + struct acp63_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + + if (adata->sdw_en_stat) { + writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL); + writel(1, adata->acp63_base + ACP_PME_EN); + return 0; + } + + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + return ret; +} + void acp70_hw_init_ops(struct acp_hw_ops *hw_ops) { hw_ops->acp_init = acp70_init; hw_ops->acp_deinit = acp70_deinit; hw_ops->acp_get_config = acp70_get_config; + hw_ops->acp_suspend = snd_acp70_suspend; + hw_ops->acp_resume = snd_acp70_resume; + hw_ops->acp_suspend_runtime = snd_acp70_suspend; + hw_ops->acp_resume_runtime = snd_acp70_runtime_resume; } From c878d5c1a525b88807d9d79888fe8340bcbf1aa3 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:08 +0530 Subject: [PATCH 0080/1090] ASoC: amd: ps: add ACP7.0 & ACP7.1 specific soundwire dma driver changes Add SoundWire dma driver changes specific to ACP7.0 & ACP7.1 platforms. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-15-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 52 ++++++++++++ sound/soc/amd/ps/ps-sdw-dma.c | 154 ++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index f65f242211e9..4d197bb8271a 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -140,6 +140,47 @@ #define ACP70_TIMEOUT 2000 #define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 +#define ACP70_SDW0_DMA_MAX_STREAMS 6 +#define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS + +#define ACP70_P1_AUDIO0_TX_THRESHOLD 0x8 +#define ACP70_P1_AUDIO1_TX_THRESHOLD 0x6 +#define ACP70_P1_AUDIO2_TX_THRESHOLD 0x4 +#define ACP70_P1_AUDIO0_RX_THRESHOLD 0x7 +#define ACP70_P1_AUDIO1_RX_THRESHOLD 0x5 +#define ACP70_P1_AUDIO2_RX_THRESHOLD 0x3 + +#define ACP70_SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP70_SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) + +/* + * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping + * in ACP_EXTENAL_INTR_CNTL1 register for ACP70/ACP71 platforms + * Stream id IRQ Bit + * 0 (SDW1_AUDIO0_TX) 8 + * 1 (SDW1_AUDIO1_TX) 6 + * 2 (SDW1_AUDIO2_TX) 4 + * 3 (SDW1_AUDIO0_RX) 7 + * 4 (SDW1_AUDIO1_RX) 5 + * 5 (SDW1_AUDIO2_RX) 3 + */ +#define ACP70_SDW1_DMA_TX_IRQ_MASK(i) (ACP70_P1_AUDIO0_TX_THRESHOLD - (2 * (i))) +#define ACP70_SDW1_DMA_RX_IRQ_MASK(i) (ACP70_P1_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) + +#define ACP70_SW0_AUDIO0_TX_EN ACP_SW0_AUDIO0_TX_EN +#define ACP70_SW0_AUDIO1_TX_EN ACP_SW0_AUDIO1_TX_EN +#define ACP70_SW0_AUDIO2_TX_EN ACP_SW0_AUDIO2_TX_EN +#define ACP70_SW0_AUDIO0_RX_EN ACP_SW0_AUDIO0_RX_EN +#define ACP70_SW0_AUDIO1_RX_EN ACP_SW0_AUDIO1_RX_EN +#define ACP70_SW0_AUDIO2_RX_EN ACP_SW0_AUDIO2_RX_EN + +#define ACP70_SW1_AUDIO0_TX_EN 0x0003C10 +#define ACP70_SW1_AUDIO1_TX_EN 0x0003C50 +#define ACP70_SW1_AUDIO2_TX_EN 0x0003C6C +#define ACP70_SW1_AUDIO0_RX_EN 0x0003C88 +#define ACP70_SW1_AUDIO1_RX_EN 0x0003D28 +#define ACP70_SW1_AUDIO2_RX_EN 0x0003D44 + enum acp_config { ACP_CONFIG_0 = 0, ACP_CONFIG_1, @@ -178,6 +219,15 @@ enum amd_acp63_sdw1_channel { ACP63_SDW1_AUDIO1_RX, }; +enum amd_acp70_sdw_channel { + ACP70_SDW_AUDIO0_TX = 0, + ACP70_SDW_AUDIO1_TX, + ACP70_SDW_AUDIO2_TX, + ACP70_SDW_AUDIO0_RX, + ACP70_SDW_AUDIO1_RX, + ACP70_SDW_AUDIO2_RX, +}; + struct pdm_stream_instance { u16 num_pages; u16 channels; @@ -199,6 +249,8 @@ struct sdw_dma_dev_data { u32 acp_rev; struct snd_pcm_substream *acp63_sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; struct snd_pcm_substream *acp63_sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp70_sdw0_dma_stream[ACP70_SDW0_DMA_MAX_STREAMS]; + struct snd_pcm_substream *acp70_sdw1_dma_stream[ACP70_SDW1_DMA_MAX_STREAMS]; }; struct acp_sdw_dma_stream { diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 7cd153a4edc9..2966244eb25e 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -75,6 +75,72 @@ static u32 acp63_sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { ACP_SW1_AUDIO1_RX_EN, }; +static struct sdw_dma_ring_buf_reg acp70_sdw0_dma_reg[ACP70_SDW0_DMA_MAX_STREAMS] = { + {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, + ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE, + ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE, + ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE, + ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE, + ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE, + ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE, + ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} +}; + +static struct sdw_dma_ring_buf_reg acp70_sdw1_dma_reg[ACP70_SDW1_DMA_MAX_STREAMS] = { + {ACP_P1_AUDIO0_TX_DMA_SIZE, ACP_P1_AUDIO0_TX_FIFOADDR, ACP_P1_AUDIO0_TX_FIFOSIZE, + ACP_P1_AUDIO0_TX_RINGBUFSIZE, ACP_P1_AUDIO0_TX_RINGBUFADDR, + ACP_P1_AUDIO0_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, + ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, + ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO2_TX_DMA_SIZE, ACP_P1_AUDIO2_TX_FIFOADDR, ACP_P1_AUDIO2_TX_FIFOSIZE, + ACP_P1_AUDIO2_TX_RINGBUFSIZE, ACP_P1_AUDIO2_TX_RINGBUFADDR, + ACP_P1_AUDIO2_TX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO0_RX_DMA_SIZE, ACP_P1_AUDIO0_RX_FIFOADDR, ACP_P1_AUDIO0_RX_FIFOSIZE, + ACP_P1_AUDIO0_RX_RINGBUFSIZE, ACP_P1_AUDIO0_RX_RINGBUFADDR, + ACP_P1_AUDIO0_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE, + ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR, + ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, + {ACP_P1_AUDIO2_RX_DMA_SIZE, ACP_P1_AUDIO2_RX_FIFOADDR, ACP_P1_AUDIO2_RX_FIFOSIZE, + ACP_P1_AUDIO2_RX_RINGBUFSIZE, ACP_P1_AUDIO2_RX_RINGBUFADDR, + ACP_P1_AUDIO2_RX_INTR_WATERMARK_SIZE, + ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} +}; + +static u32 acp70_sdw0_dma_enable_reg[ACP70_SDW0_DMA_MAX_STREAMS] = { + ACP70_SW0_AUDIO0_TX_EN, + ACP70_SW0_AUDIO1_TX_EN, + ACP70_SW0_AUDIO2_TX_EN, + ACP70_SW0_AUDIO0_RX_EN, + ACP70_SW0_AUDIO1_RX_EN, + ACP70_SW0_AUDIO2_RX_EN, +}; + +static u32 acp70_sdw1_dma_enable_reg[ACP70_SDW1_DMA_MAX_STREAMS] = { + ACP70_SW1_AUDIO0_TX_EN, + ACP70_SW1_AUDIO1_TX_EN, + ACP70_SW1_AUDIO2_TX_EN, + ACP70_SW1_AUDIO0_RX_EN, + ACP70_SW1_AUDIO1_RX_EN, + ACP70_SW1_AUDIO2_RX_EN, +}; + static const struct snd_pcm_hardware acp63_sdw_hardware_playback = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -200,6 +266,27 @@ static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, return -EINVAL; } break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + switch (manager_instance) { + case ACP_SDW0: + reg_dma_size = acp70_sdw0_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp70_sdw0_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp70_sdw0_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_addr; + break; + case ACP_SDW1: + reg_dma_size = acp70_sdw1_dma_reg[stream_id].reg_dma_size; + reg_fifo_addr = acp70_sdw1_dma_reg[stream_id].reg_fifo_addr; + reg_fifo_size = acp70_sdw1_dma_reg[stream_id].reg_fifo_size; + reg_ring_buf_size = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_size; + reg_ring_buf_addr = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_addr; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -292,6 +379,32 @@ static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, return -EINVAL; } break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp70_sdw0_dma_stream[stream_id] = substream; + water_mark_size_reg = acp70_sdw0_dma_reg[stream_id].water_mark_size_reg; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP70_SDW0_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP70_SDW0_DMA_RX_IRQ_MASK(stream_id)); + break; + case ACP_SDW1: + sdw_data->acp70_sdw1_dma_stream[stream_id] = substream; + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; + water_mark_size_reg = acp70_sdw1_dma_reg[stream_id].water_mark_size_reg; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + irq_mask = BIT(ACP70_SDW1_DMA_TX_IRQ_MASK(stream_id)); + else + irq_mask = BIT(ACP70_SDW1_DMA_RX_IRQ_MASK(stream_id)); + + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -335,6 +448,21 @@ static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __io goto POINTER_RETURN_BYTES; } break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + pos_low_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_high_reg; + break; + case ACP_SDW1: + pos_low_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_low_reg; + pos_high_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_high_reg; + break; + default: + goto POINTER_RETURN_BYTES; + } + break; default: goto POINTER_RETURN_BYTES; } @@ -398,6 +526,19 @@ static int acp63_sdw_dma_close(struct snd_soc_component *component, return -EINVAL; } break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_data->acp70_sdw0_dma_stream[stream->stream_id] = NULL; + break; + case ACP_SDW1: + sdw_data->acp70_sdw1_dma_stream[stream->stream_id] = NULL; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -430,6 +571,19 @@ static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, return -EINVAL; } break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + switch (stream->instance) { + case ACP_SDW0: + sdw_dma_en_reg = acp70_sdw0_dma_enable_reg[stream_id]; + break; + case ACP_SDW1: + sdw_dma_en_reg = acp70_sdw1_dma_enable_reg[stream_id]; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } From 1c35755f46423150e19ff57448786b4bb48fdb46 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:09 +0530 Subject: [PATCH 0081/1090] ASoC: amd: ps: implement function to restore dma config for ACP7.0 platform Implement function to restore the dma configuration during system level resume for ACP7.0 & ACP7.1 platforms. Add a conditional check to invoke restore dma configuration function based on acp pci revision id. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-16-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 2 ++ sound/soc/amd/ps/ps-sdw-dma.c | 46 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 4d197bb8271a..0aef3a852ff1 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -142,6 +142,8 @@ #define ACP70_SDW0_DMA_MAX_STREAMS 6 #define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS +#define ACP70_SDW_DMA_IRQ_MASK 0x1F800000 +#define ACP70_P1_SDW_DMA_IRQ_MASK 0x1F8 #define ACP70_P1_AUDIO0_TX_THRESHOLD 0x8 #define ACP70_P1_AUDIO1_TX_THRESHOLD 0x6 diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 2966244eb25e..557d312a23b2 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -725,12 +725,56 @@ static int acp63_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) return 0; } +static int acp70_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) +{ + struct acp_sdw_dma_stream *stream; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + u32 period_bytes, buf_size, water_mark_size_reg; + u32 stream_count, irq_mask, irq_mask1; + int index, instance, ret; + + irq_mask = ACP70_SDW_DMA_IRQ_MASK; + irq_mask1 = ACP70_P1_SDW_DMA_IRQ_MASK; + stream_count = ACP70_SDW0_DMA_MAX_STREAMS; + for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) { + for (index = 0; index < stream_count; index++) { + if (instance == ACP_SDW0) { + substream = sdw_data->acp70_sdw0_dma_stream[index]; + water_mark_size_reg = acp70_sdw0_dma_reg[index].water_mark_size_reg; + } else { + substream = sdw_data->acp70_sdw1_dma_stream[index]; + water_mark_size_reg = acp70_sdw1_dma_reg[index].water_mark_size_reg; + } + + if (substream && substream->runtime) { + runtime = substream->runtime; + stream = runtime->private_data; + period_bytes = frames_to_bytes(runtime, runtime->period_size); + buf_size = frames_to_bytes(runtime, runtime->buffer_size); + acp63_config_dma(stream, sdw_data->acp_base, index); + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index, + buf_size, instance, + sdw_data->acp_rev); + if (ret) + return ret; + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); + } + } + } + acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true); + return 0; +} + static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev) { struct sdw_dma_dev_data *sdw_data; sdw_data = dev_get_drvdata(dev); - return acp63_restore_sdw_dma_config(sdw_data); + if (sdw_data->acp_rev == ACP63_PCI_REV) + return acp63_restore_sdw_dma_config(sdw_data); + else + return acp70_restore_sdw_dma_config(sdw_data); } static const struct dev_pm_ops acp63_pm_ops = { From 0b6914a0121b4c9fc8f575b60a5dd43b74612908 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:10 +0530 Subject: [PATCH 0082/1090] ASoC: amd: ps: add soundwire dma interrupts handling for ACP7.0 platform Add Soundwie dma interrupts handling for ACP7.0 & ACP7.1 platforms. Add acp pci revision id conditional checks for handling platform specific implementation. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-17-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 6 ++++ sound/soc/amd/ps/pci-ps.c | 61 ++++++++++++++++++++++++++++++------ sound/soc/amd/ps/ps-common.c | 24 ++++++++++++++ 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 0aef3a852ff1..48dac2a044c2 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -332,6 +332,10 @@ struct acp_hw_ops { * manager-SW0 instance * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire * manager-SW1 instance + * @acp70_sdw0-dma_intr_stat: DMA interrupt status array for ACP7.0 platform SoundWire + * manager-SW0 instance + * @acp70_sdw_dma_intr_stat: DMA interrupt status array for ACP7.0 platform SoundWire + * manager-SW1 instance */ struct acp63_dev_data { @@ -357,6 +361,8 @@ struct acp63_dev_data { u32 acp_rev; u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; + u16 acp70_sdw0_dma_intr_stat[ACP70_SDW0_DMA_MAX_STREAMS]; + u16 acp70_sdw1_dma_intr_stat[ACP70_SDW1_DMA_MAX_STREAMS]; }; void acp63_hw_init_ops(struct acp_hw_ops *hw_ops); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 8f73d2ce2197..a9e140ca1296 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -52,20 +52,61 @@ static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 stream_id = ACP63_SDW0_AUDIO2_RX; break; } - adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; + if (adata->acp_rev >= ACP70_PCI_REV) + adata->acp70_sdw0_dma_intr_stat[stream_id] = 1; + else + adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; + sdw_dma_irq_flag = 1; } } } - if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; - sdw_dma_irq_flag = 1; - } - if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { - writel(ACP63_P1_AUDIO1_TX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; - sdw_dma_irq_flag = 1; + if (adata->acp_rev == ACP63_PCI_REV) { + if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_RX_THRESHOLD, + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; + sdw_dma_irq_flag = 1; + } + if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { + writel(ACP63_P1_AUDIO1_TX_THRESHOLD, + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; + sdw_dma_irq_flag = 1; + } + } else { + if (ext_intr_stat1 & ACP70_P1_SDW_DMA_IRQ_MASK) { + for (index = ACP70_P1_AUDIO2_RX_THRESHOLD; + index <= ACP70_P1_AUDIO0_TX_THRESHOLD; index++) { + if (ext_intr_stat1 & BIT(index)) { + writel(BIT(index), + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + switch (index) { + case ACP70_P1_AUDIO0_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO0_TX; + break; + case ACP70_P1_AUDIO1_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO1_TX; + break; + case ACP70_P1_AUDIO2_TX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO2_TX; + break; + case ACP70_P1_AUDIO0_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO0_RX; + break; + case ACP70_P1_AUDIO1_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO1_RX; + break; + case ACP70_P1_AUDIO2_RX_THRESHOLD: + stream_id = ACP70_SDW_AUDIO2_RX; + break; + } + + adata->acp70_sdw1_dma_intr_stat[stream_id] = 1; + sdw_dma_irq_flag = 1; + } + } + } } return sdw_dma_irq_flag; } diff --git a/sound/soc/amd/ps/ps-common.c b/sound/soc/amd/ps/ps-common.c index 6639dac0a415..1c89fb5fe1da 100644 --- a/sound/soc/amd/ps/ps-common.c +++ b/sound/soc/amd/ps/ps-common.c @@ -378,6 +378,29 @@ static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_dat } } +static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata) +{ + struct sdw_dma_dev_data *sdw_data; + u32 stream_id; + + sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev); + + for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp70_sdw0_dma_intr_stat[stream_id]) { + if (sdw_data->acp70_sdw0_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]); + adata->acp70_sdw0_dma_intr_stat[stream_id] = 0; + } + } + for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) { + if (adata->acp70_sdw1_dma_intr_stat[stream_id]) { + if (sdw_data->acp70_sdw1_dma_stream[stream_id]) + snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]); + adata->acp70_sdw1_dma_intr_stat[stream_id] = 0; + } + } +} + static int __maybe_unused snd_acp70_suspend(struct device *dev) { struct acp63_dev_data *adata; @@ -444,6 +467,7 @@ void acp70_hw_init_ops(struct acp_hw_ops *hw_ops) hw_ops->acp_init = acp70_init; hw_ops->acp_deinit = acp70_deinit; hw_ops->acp_get_config = acp70_get_config; + hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread; hw_ops->acp_suspend = snd_acp70_suspend; hw_ops->acp_resume = snd_acp70_resume; hw_ops->acp_suspend_runtime = snd_acp70_suspend; From 3898b189079c85735f57759b0d407518c01c745e Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:11 +0530 Subject: [PATCH 0083/1090] ASoC: amd: ps: add soundwire wake interrupt handling Add SoundWire wake interrupt handling for ACP7.0 & ACP7.1 platforms. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-18-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 8 +++++ sound/soc/amd/ps/pci-ps.c | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 48dac2a044c2..9940151b0675 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -139,6 +139,10 @@ #define ACP70_PGFSM_STATUS_MASK 0xFF #define ACP70_TIMEOUT 2000 #define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 +#define ACP70_SDW0_HOST_WAKE_STAT BIT(24) +#define ACP70_SDW1_HOST_WAKE_STAT BIT(25) +#define ACP70_SDW0_PME_STAT BIT(26) +#define ACP70_SDW1_PME_STAT BIT(27) #define ACP70_SDW0_DMA_MAX_STREAMS 6 #define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS @@ -325,6 +329,8 @@ struct acp_hw_ops { * @is_pdm_config: flat set to true when PDM configuration is selected from BIOS * @is_sdw_config: flag set to true when SDW configuration is selected from BIOS * @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled + * @acp70_sdw0_wake_event: flag set to true when wake irq asserted for SW0 instance + * @acp70_sdw1_wake_event: flag set to true when wake irq asserted for SW1 instance * @addr: pci ioremap address * @reg_range: ACP reigister range * @acp_rev: ACP PCI revision id @@ -356,6 +362,8 @@ struct acp63_dev_data { bool is_pdm_config; bool is_sdw_config; bool sdw_en_stat; + bool acp70_sdw0_wake_event; + bool acp70_sdw1_wake_event; u32 addr; u32 reg_range; u32 acp_rev; diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index a9e140ca1296..6a725cf36345 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -21,6 +21,65 @@ #include "acp63.h" +static void handle_acp70_sdw_wake_event(struct acp63_dev_data *adata) +{ + struct amd_sdw_manager *amd_manager; + + if (adata->acp70_sdw0_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw0_wake_event = 0; + } + + if (adata->acp70_sdw1_wake_event) { + amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev); + if (amd_manager) + pm_request_resume(amd_manager->dev); + adata->acp70_sdw1_wake_event = 0; + } +} + +static short int check_and_handle_acp70_sdw_wake_irq(struct acp63_dev_data *adata) +{ + u32 ext_intr_stat1; + int irq_flag = 0; + bool sdw_wake_irq = false; + + ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) { + writel(ACP70_SDW0_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) { + writel(ACP70_SDW1_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) { + writel(0, adata->acp63_base + ACP_SW0_WAKE_EN); + writel(ACP70_SDW0_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw0_wake_event = true; + sdw_wake_irq = true; + } + + if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) { + writel(0, adata->acp63_base + ACP_SW1_WAKE_EN); + writel(ACP70_SDW1_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); + adata->acp70_sdw1_wake_event = true; + sdw_wake_irq = true; + } + + if (sdw_wake_irq) { + handle_acp70_sdw_wake_event(adata); + irq_flag = 1; + } + return irq_flag; +} + static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat, u32 ext_intr_stat1) { @@ -163,6 +222,9 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) irq_flag = 1; } + if (adata->acp_rev >= ACP70_PCI_REV) + irq_flag = check_and_handle_acp70_sdw_wake_irq(adata); + if (ext_intr_stat & BIT(PDM_DMA_STAT)) { ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev); writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); From 0eb8f83c055cb3461734710d1b1ce2dd4f01806e Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:12 +0530 Subject: [PATCH 0084/1090] ASoC: amd: ps: update module description Update module description for Pink Sardine platform acp pci driver, SoundWire dma driver and PDM driver modules. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-19-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 2 +- sound/soc/amd/ps/ps-pdm-dma.c | 2 +- sound/soc/amd/ps/ps-sdw-dma.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 6a725cf36345..3a6034e074f5 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -723,7 +723,7 @@ module_pci_driver(ps_acp63_driver); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); MODULE_AUTHOR("Syed.SabaKareem@amd.com"); -MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver"); +MODULE_DESCRIPTION("AMD common ACP PCI driver for ACP6.3, ACP7.0 & ACP7.1 platforms"); MODULE_IMPORT_NS("SOUNDWIRE_AMD_INIT"); MODULE_IMPORT_NS("SND_AMD_SOUNDWIRE_ACPI"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index 318fc260f293..e726186fe8c6 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -458,6 +458,6 @@ static struct platform_driver acp63_pdm_dma_driver = { module_platform_driver(acp63_pdm_dma_driver); MODULE_AUTHOR("Syed.SabaKareem@amd.com"); -MODULE_DESCRIPTION("AMD PINK SARDINE PDM Driver"); +MODULE_DESCRIPTION("AMD common PDM Driver for ACP6.3, ACP7,0 & ACP7.1 platforms"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 557d312a23b2..2461c6421ae9 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -793,6 +793,6 @@ static struct platform_driver acp63_sdw_dma_driver = { module_platform_driver(acp63_sdw_dma_driver); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); -MODULE_DESCRIPTION("AMD ACP6.3 PS SDW DMA Driver"); +MODULE_DESCRIPTION("AMD common SDW DMA Driver for ACP6.3, ACP7.0 & ACP7.1 platforms"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); From f1e91acacf86fb2cd7478af490326cb9aa63e8ae Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:13 +0530 Subject: [PATCH 0085/1090] ASoC: amd: ps: update file description and copyright year Update files description for acp pci driver, SoundWire DMA driver, PDM driver and acp header file as new support is added for ACP7.0 & ACP7.1 platforms. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-20-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/acp63.h | 4 ++-- sound/soc/amd/ps/pci-ps.c | 4 ++-- sound/soc/amd/ps/ps-pdm-dma.c | 4 ++-- sound/soc/amd/ps/ps-sdw-dma.c | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h index 9940151b0675..85feae45c44c 100644 --- a/sound/soc/amd/ps/acp63.h +++ b/sound/soc/amd/ps/acp63.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * AMD ALSA SoC PDM Driver + * AMD Common ACP header file for ACP6.3, ACP7.0 & ACP7.1 platforms * - * Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (C) 2022, 2023, 2025 Advanced Micro Devices, Inc. All rights reserved. */ #include diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 3a6034e074f5..2cbfeb07d5c4 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AMD Pink Sardine ACP PCI Driver + * AMD common ACP PCI driver for ACP6.3, ACP7.0 & ACP7.1 platforms. * - * Copyright 2022 Advanced Micro Devices, Inc. + * Copyright 2022, 2025 Advanced Micro Devices, Inc. */ #include diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index e726186fe8c6..7cdeb34e8f73 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AMD ALSA SoC Pink Sardine PDM Driver + * AMD ALSA SoC common PDM Driver for ACP6.3, ACP7.0 & ACP7.1 platforms. * - * Copyright 2022 Advanced Micro Devices, Inc. + * Copyright 2022, 2025 Advanced Micro Devices, Inc. */ #include diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 2461c6421ae9..21b336109c99 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AMD ALSA SoC Pink Sardine SoundWire DMA Driver + * AMD ALSA SoC common SoundWire DMA Driver for ACP6.3, ACP7.0 and ACP7.1 + * platforms. * - * Copyright 2023 Advanced Micro Devices, Inc. + * Copyright 2023, 2025 Advanced Micro Devices, Inc. */ #include From 552f66c40134542f15d4302837e7d581a0b8e217 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:14 +0530 Subject: [PATCH 0086/1090] ASoC: amd: update Pink Sardine platform Kconfig description Update Pink Sardine platform Kconfig option description. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-21-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 803521178279..c7daae392d74 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -161,15 +161,15 @@ config SND_SOC_AMD_SOUNDWIRE If unsure select "N". config SND_SOC_AMD_PS - tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" + tristate "AMD Audio Coprocessor-v6.3/v7.0/v7.1 support" select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE select SND_SOC_ACPI_AMD_MATCH depends on X86 && PCI && ACPI help - This option enables Audio Coprocessor i.e ACP v6.3 support on - AMD Pink sardine platform. By enabling this flag build will be - triggered for ACP PCI driver, ACP PDM DMA driver, ACP SoundWire - DMA driver. + This option enables Audio Coprocessor i.e ACP6.3/ACP7.0/ACP7.1 + variants support. By enabling this flag build will be triggered + for ACP PCI driver, ACP PDM DMA driver, ACP SoundWire DMA + driver. Say m if you have such a device. If unsure select "N". From 638ad2bdb2f994c8bd99cc40e0c4796a8617ccf3 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:15 +0530 Subject: [PATCH 0087/1090] ASoC: amd: acp: add machine driver changes for ACP7.0 and ACP7.1 platforms Add SoundWire generic machine driver changes for legacy stack(No DSP) for ACP7.0 and ACP7.1 platforms. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-22-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 11 ++++++++ sound/soc/amd/acp/acp-sdw-mach-common.c | 34 +++++++++++++++++++++++++ sound/soc/amd/acp/soc_amd_sdw_common.h | 11 ++++++++ 3 files changed, 56 insertions(+) diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c index 9280cd30d19c..00aeea70f04e 100644 --- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -122,6 +122,13 @@ static int create_sdw_dailink(struct snd_soc_card *card, if (ret) return ret; break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + ret = get_acp70_cpu_pin_id(ffs(soc_end->link_mask - 1), + *be_id, &cpu_pin_id, dev); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -221,6 +228,8 @@ static int create_sdw_dailinks(struct snd_soc_card *card, switch (amd_ctx->acp_rev) { case ACP63_PCI_REV: + case ACP70_PCI_REV: + case ACP71_PCI_REV: sdw_platform_component->name = "amd_ps_sdw_dma.0"; break; default: @@ -266,6 +275,8 @@ static int create_dmic_dailinks(struct snd_soc_card *card, switch (amd_ctx->acp_rev) { case ACP63_PCI_REV: + case ACP70_PCI_REV: + case ACP71_PCI_REV: pdm_cpu->name = "acp_ps_pdm_dma.0"; pdm_platform->name = "acp_ps_pdm_dma.0"; break; diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c index 6f5c39ed1a18..e5f394dc2f4c 100644 --- a/sound/soc/amd/acp/acp-sdw-mach-common.c +++ b/sound/soc/amd/acp/acp-sdw-mach-common.c @@ -59,6 +59,40 @@ int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct dev } EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, "SND_SOC_AMD_SDW_MACH"); +int get_acp70_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP70_SW_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + default: + return -EINVAL; + } + dev_dbg(dev, "sdw_link_id:%d, be_id:%d, cpu_pin_id:%d\n", sdw_link_id, be_id, *cpu_pin_id); + return 0; +} +EXPORT_SYMBOL_NS_GPL(get_acp70_cpu_pin_id, "SND_SOC_AMD_SDW_MACH"); + MODULE_DESCRIPTION("AMD SoundWire Common Machine driver"); MODULE_AUTHOR("Vijendar Mukunda "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h index b7bae107c13e..9bedccfe25a9 100644 --- a/sound/soc/amd/acp/soc_amd_sdw_common.h +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -19,6 +19,8 @@ #define AMD_SDW_MAX_GROUPS 9 #define ACP63_PCI_REV 0x63 +#define ACP70_PCI_REV 0x70 +#define ACP71_PCI_REV 0x71 #define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) #define ASOC_SDW_FOUR_SPK BIT(4) #define ASOC_SDW_ACP_DMIC BIT(5) @@ -38,11 +40,20 @@ #define ACP_DMIC_BE_ID 4 +#define ACP70_SW_AUDIO0_TX 0 +#define ACP70_SW_AUDIO1_TX 1 +#define ACP70_SW_AUDIO2_TX 2 + +#define ACP70_SW_AUDIO0_RX 3 +#define ACP70_SW_AUDIO1_RX 4 +#define ACP70_SW_AUDIO2_RX 5 + struct amd_mc_ctx { unsigned int acp_rev; unsigned int max_sdw_links; }; int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev); +int get_acp70_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev); #endif From 187150671d83324f1ca56f7ab5e00f16a3b9f2a9 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:16 +0530 Subject: [PATCH 0088/1090] ASoC: amd: acp: add RT711, RT714 & RT1316 support for ACP7.0 platform Add support for corresponding codecs on ACP7.0 platform hardware configuration. SDW0: RT711 Jack SDW0: RT1316 Left Speaker SDW0: RT1316 Right Speaker SDW1: RT714 DMIC Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-23-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/Makefile | 2 +- sound/soc/amd/acp/amd-acp70-acpi-match.c | 88 ++++++++++++++++++++++++ sound/soc/amd/mach-config.h | 1 + sound/soc/amd/ps/pci-ps.c | 6 +- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 sound/soc/amd/acp/amd-acp70-acpi-match.c diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index bb2702036338..7c75892e678b 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -22,7 +22,7 @@ snd-acp70-y := acp70.o snd-acp-mach-y := acp-mach-common.o snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o snd-acp-sof-mach-y := acp-sof-mach.o -snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o +snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o amd-acp70-acpi-match.o snd-acp-sdw-mach-y := acp-sdw-mach-common.o snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c new file mode 100644 index 000000000000..fa59b462f227 --- /dev/null +++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acp70-acpi-match.c - tables and support for ACP 7.0 & ACP7.1 + * ACPI enumeration. + * + * Copyright 2025 Advanced Micro Devices, Inc. + */ + +#include +#include "../mach-config.h" + +static const struct snd_soc_acpi_endpoint single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0 +}; + +static const struct snd_soc_acpi_endpoint spk_l_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 0, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint spk_r_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1 +}; + +static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + }, + { + .adr = 0x000030025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1316-1" + }, + { + .adr = 0x000032025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + }, +}; + +static const struct snd_soc_acpi_adr_device rt714_adr[] = { + { + .adr = 0x130025d071401ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + +static const struct snd_soc_acpi_link_adr acp70_4_in_1_sdca[] = { + { .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_rt1316_group_adr), + .adr_d = rt711_rt1316_group_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt714_adr), + .adr_d = rt714_adr, + }, + {} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = { + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_4_in_1_sdca, + .drv_name = "amd_sdw", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sdw_machines); + +MODULE_DESCRIPTION("AMD ACP7.0 & ACP7.1 tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index a86c76f781f9..fdf016a64bbf 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -26,6 +26,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[]; struct config_entry { u32 flags; diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 2cbfeb07d5c4..220dca8cba85 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -632,7 +632,11 @@ static int snd_acp63_probe(struct pci_dev *pci, dev_err(&pci->dev, "ACP platform devices creation failed\n"); goto de_init; } - adata->machines = snd_soc_acpi_amd_acp63_sdw_machines; + if (adata->acp_rev >= ACP70_PCI_REV) + adata->machines = snd_soc_acpi_amd_acp70_sdw_machines; + else + adata->machines = snd_soc_acpi_amd_acp63_sdw_machines; + ret = acp63_machine_register(&pci->dev); if (ret) { dev_err(&pci->dev, "ACP machine register failed\n"); From d0252b0b945ec67fd09fc764dcadf445fb7757ee Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:17 +0530 Subject: [PATCH 0089/1090] ASoC: amd: acp: amd-acp70-acpi-match: Add rt722 support Patch adds driver data and match table for rt722 multi-function codec on acp7.0 and acp7.1 platforms at sdw link0 for legacy(NO DSP) stack. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-24-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/amd-acp70-acpi-match.c | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c index fa59b462f227..fe166015dc29 100644 --- a/sound/soc/amd/acp/amd-acp70-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c @@ -73,7 +73,51 @@ static const struct snd_soc_acpi_link_adr acp70_4_in_1_sdca[] = { {} }; +static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { + { + .adr = 0x000030025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_link_adr acp70_rt722_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = { + { + .link_mask = BIT(0), + .links = acp70_rt722_only, + .drv_name = "amd_sdw", + }, { .link_mask = BIT(0) | BIT(1), .links = acp70_4_in_1_sdca, From 31e3100d5e1fe69f944f84867be0cbfa5fd380c8 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:18 +0530 Subject: [PATCH 0090/1090] ASoC: amd: acp: amd-acp70-acpi-match: Add RT1320 & RT722 combination soundwire machine This patch adds below machine configuration for the ACP7.0 & ACP7.1 platforms. Link 0: RT722 codec with three endpoints: Headset, Speaker, and DMIC. Link 1: RT1320 amplifier. Note: The Speaker endpoint on the RT722 codec is not used. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-25-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/Kconfig | 1 + sound/soc/amd/acp/amd-acp70-acpi-match.c | 28 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 03f3fcbba5af..53793ec7c7b4 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -156,6 +156,7 @@ config SND_SOC_AMD_LEGACY_SDW_MACH select SND_SOC_RT712_SDCA_SDW select SND_SOC_RT712_SDCA_DMIC_SDW select SND_SOC_RT1316_SDW + select SND_SOC_RT1320_SDW select SND_SOC_RT715_SDW select SND_SOC_RT715_SDCA_SDW select SND_SOC_RT722_SDCA_SDW diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c index fe166015dc29..e87ccfeee5bd 100644 --- a/sound/soc/amd/acp/amd-acp70-acpi-match.c +++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c @@ -103,6 +103,15 @@ static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1320_1_single_adr[] = { + { + .adr = 0x000130025D132001ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1320-1" + } +}; + static const struct snd_soc_acpi_link_adr acp70_rt722_only[] = { { .mask = BIT(0), @@ -112,7 +121,26 @@ static const struct snd_soc_acpi_link_adr acp70_rt722_only[] = { {} }; +static const struct snd_soc_acpi_link_adr acp70_rt722_l0_rt1320_l1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1320_1_single_adr), + .adr_d = rt1320_1_single_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = { + { + .link_mask = BIT(0) | BIT(1), + .links = acp70_rt722_l0_rt1320_l1, + .drv_name = "amd_sdw", + }, { .link_mask = BIT(0), .links = acp70_rt722_only, From 4bb5b6f13fd83b32c8a93fbd399e7558415d1ce0 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 11:58:19 +0530 Subject: [PATCH 0091/1090] ASoC: amd: amd_sdw: Add quirks for Dell SKU's This patch adds a quirk to include the codec amplifier function for Dell SKU's listed in quirk table. Note: In these SKU's, the RT722 codec amplifier is excluded, and an external amplifier is used instead. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250207062819.1527184-26-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 34 +++++++++++++++++++++++++ sound/soc/amd/acp/soc_amd_sdw_common.h | 1 + 2 files changed, 35 insertions(+) diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c index 00aeea70f04e..2020c5cfb3d5 100644 --- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -28,6 +28,8 @@ static void log_quirks(struct device *dev) SOC_JACK_JDSRC(soc_sdw_quirk)); if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC) dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); + if (soc_sdw_quirk & ASOC_SDW_CODEC_SPKR) + dev_dbg(dev, "quirk ASOC_SDW_CODEC_SPKR enabled\n"); } static int soc_sdw_quirk_cb(const struct dmi_system_id *id) @@ -45,6 +47,38 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = { }, .driver_data = (void *)RT711_JD2, }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D80"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D81"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D82"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D83"), + }, + .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + }, {} }; diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h index 9bedccfe25a9..1f24e0e06487 100644 --- a/sound/soc/amd/acp/soc_amd_sdw_common.h +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -24,6 +24,7 @@ #define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) #define ASOC_SDW_FOUR_SPK BIT(4) #define ASOC_SDW_ACP_DMIC BIT(5) +#define ASOC_SDW_CODEC_SPKR BIT(15) #define AMD_SDW0 0 #define AMD_SDW1 1 From 91f505dc3a94c04421a2a51e8c40acf7ea67ecbc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Feb 2025 20:36:36 +0800 Subject: [PATCH 0092/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add rt712_vb + rt1320 support s/lnl/ptl Fixes: bd40d912728f ("ASoC: Intel: soc-acpi-intel-ptl-match: add rt712_vb + rt1320 support") Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://patch.msgid.link/20250207123637.215320-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-ptl-match.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 9eb4a43e3e7a..e487c4e1c034 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -270,7 +270,7 @@ static const struct snd_soc_acpi_link_adr lnl_sdw_rt713_vb_l2_rt1320_l13[] = { {} }; -static const struct snd_soc_acpi_link_adr lnl_sdw_rt712_vb_l2_rt1320_l1[] = { +static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l2_rt1320_l1[] = { { .mask = BIT(2), .num_adr = ARRAY_SIZE(rt712_vb_2_group1_adr), @@ -337,10 +337,10 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { }, { .link_mask = BIT(1) | BIT(2), - .links = lnl_sdw_rt712_vb_l2_rt1320_l1, + .links = ptl_sdw_rt712_vb_l2_rt1320_l1, .drv_name = "sof_sdw", .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, - .sof_tplg_filename = "sof-lnl-rt712-l2-rt1320-l1.tplg" + .sof_tplg_filename = "sof-ptl-rt712-l2-rt1320-l1.tplg" }, { .link_mask = BIT(1) | BIT(2) | BIT(3), From 852c0b7204ded184924c41ab99b2ac7a70ad4dab Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Feb 2025 20:36:37 +0800 Subject: [PATCH 0093/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add rt713_vb_l2_rt1320_l13 s/lnl/ptl Fixes: a7ebb0255188 ("ASoC: Intel: soc-acpi-intel-ptl-match: add rt713_vb_l2_rt1320_l13 support") Signed-off-by: Peter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://patch.msgid.link/20250207123637.215320-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-ptl-match.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index e487c4e1c034..dd7993b76dee 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -251,7 +251,7 @@ static const struct snd_soc_acpi_link_adr ptl_rvp[] = { {} }; -static const struct snd_soc_acpi_link_adr lnl_sdw_rt713_vb_l2_rt1320_l13[] = { +static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l2_rt1320_l13[] = { { .mask = BIT(2), .num_adr = ARRAY_SIZE(rt713_vb_2_adr), @@ -344,10 +344,10 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { }, { .link_mask = BIT(1) | BIT(2) | BIT(3), - .links = lnl_sdw_rt713_vb_l2_rt1320_l13, + .links = ptl_sdw_rt713_vb_l2_rt1320_l13, .drv_name = "sof_sdw", .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, - .sof_tplg_filename = "sof-lnl-rt713-l2-rt1320-l13.tplg" + .sof_tplg_filename = "sof-ptl-rt713-l2-rt1320-l13.tplg" }, {}, }; From 651e0ed391b148f83afba0bfbd8a56e38e58c34d Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:40 -0500 Subject: [PATCH 0094/1090] ASoC: SOF: imx: introduce more common structures and functions The SOF drivers for imx chips have a lot of duplicate code and routines/code snippets that could certainly be reused among drivers. As such, introduce a new set of structures and functions that will help eliminate the redundancy and code size of the drivers. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-2-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx-common.c | 431 ++++++++++++++++++++++++++++++++- sound/soc/sof/imx/imx-common.h | 151 ++++++++++++ 2 files changed, 581 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index fce6d9cf6a6b..82057af1436c 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -1,11 +1,16 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright 2020 NXP +// Copyright 2020-2025 NXP // // Common helpers for the audio DSP on i.MX8 +#include #include +#include +#include +#include #include + #include "../ops.h" #include "imx-common.h" @@ -74,5 +79,429 @@ void imx8_dump(struct snd_sof_dev *sdev, u32 flags) } EXPORT_SYMBOL(imx8_dump); +static void imx_handle_reply(struct imx_dsp_ipc *ipc) +{ + struct snd_sof_dev *sdev; + unsigned long flags; + + sdev = imx_dsp_get_data(ipc); + + spin_lock_irqsave(&sdev->ipc_lock, flags); + snd_sof_ipc_process_reply(sdev, 0); + spin_unlock_irqrestore(&sdev->ipc_lock, flags); +} + +static void imx_handle_request(struct imx_dsp_ipc *ipc) +{ + struct snd_sof_dev *sdev; + u32 panic_code; + + sdev = imx_dsp_get_data(ipc); + + if (get_chip_info(sdev)->ipc_info.has_panic_code) { + sof_mailbox_read(sdev, sdev->debug_box.offset + 0x4, + &panic_code, + sizeof(panic_code)); + + if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { + snd_sof_dsp_panic(sdev, panic_code, true); + return; + } + } + + snd_sof_ipc_msgs_rx(sdev); +} + +static struct imx_dsp_ops imx_ipc_ops = { + .handle_reply = imx_handle_reply, + .handle_request = imx_handle_request, +}; + +static int imx_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +{ + struct imx_common_data *common = sdev->pdata->hw_pdata; + + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); + imx_dsp_ring_doorbell(common->ipc_handle, 0x0); + + return 0; +} + +static int imx_get_bar_index(struct snd_sof_dev *sdev, u32 type) +{ + switch (type) { + case SOF_FW_BLK_TYPE_IRAM: + case SOF_FW_BLK_TYPE_SRAM: + return type; + default: + return -EINVAL; + } +} + +static int imx_get_mailbox_offset(struct snd_sof_dev *sdev) +{ + return get_chip_info(sdev)->ipc_info.boot_mbox_offset; +} + +static int imx_get_window_offset(struct snd_sof_dev *sdev, u32 id) +{ + return get_chip_info(sdev)->ipc_info.window_offset; +} + +static int imx_set_power_state(struct snd_sof_dev *sdev, + const struct sof_dsp_power_state *target) +{ + sdev->dsp_power_state = *target; + + return 0; +} + +static int imx_common_resume(struct snd_sof_dev *sdev) +{ + struct imx_common_data *common; + int ret, i; + + common = sdev->pdata->hw_pdata; + + ret = clk_bulk_prepare_enable(common->clk_num, common->clks); + if (ret) + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); + + for (i = 0; i < DSP_MU_CHAN_NUM; i++) + imx_dsp_request_channel(common->ipc_handle, i); + + /* done. If need be, core will be started by SOF core immediately after */ + return 0; +} + +static int imx_common_suspend(struct snd_sof_dev *sdev) +{ + struct imx_common_data *common; + int i, ret; + + common = sdev->pdata->hw_pdata; + + ret = imx_chip_core_shutdown(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to shutdown core: %d\n", ret); + return ret; + } + + for (i = 0; i < DSP_MU_CHAN_NUM; i++) + imx_dsp_free_channel(common->ipc_handle, i); + + clk_bulk_disable_unprepare(common->clk_num, common->clks); + + return 0; +} + +static int imx_runtime_resume(struct snd_sof_dev *sdev) +{ + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; + int ret; + + ret = imx_common_resume(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to runtime common resume: %d\n", ret); + return ret; + } + + return snd_sof_dsp_set_power_state(sdev, &target_state); +} + +static int imx_resume(struct snd_sof_dev *sdev) +{ + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D0, + }; + int ret; + + ret = imx_common_resume(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to common resume: %d\n", ret); + return ret; + } + + if (pm_runtime_suspended(sdev->dev)) { + pm_runtime_disable(sdev->dev); + pm_runtime_set_active(sdev->dev); + pm_runtime_mark_last_busy(sdev->dev); + pm_runtime_enable(sdev->dev); + pm_runtime_idle(sdev->dev); + } + + return snd_sof_dsp_set_power_state(sdev, &target_state); +} + +static int imx_runtime_suspend(struct snd_sof_dev *sdev) +{ + const struct sof_dsp_power_state target_state = { + .state = SOF_DSP_PM_D3, + }; + int ret; + + ret = imx_common_suspend(sdev); + if (ret < 0) + dev_err(sdev->dev, "failed to runtime common suspend: %d\n", ret); + + return snd_sof_dsp_set_power_state(sdev, &target_state); +} + +static int imx_suspend(struct snd_sof_dev *sdev, unsigned int target_state) +{ + const struct sof_dsp_power_state target_power_state = { + .state = target_state, + }; + int ret; + + if (!pm_runtime_suspended(sdev->dev)) { + ret = imx_common_suspend(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to common suspend: %d\n", ret); + return ret; + } + } + + return snd_sof_dsp_set_power_state(sdev, &target_power_state); +} + +static int imx_region_name_to_blk_type(const char *region_name) +{ + if (!strcmp(region_name, "iram")) + return SOF_FW_BLK_TYPE_IRAM; + else if (!strcmp(region_name, "dram")) + return SOF_FW_BLK_TYPE_DRAM; + else if (!strcmp(region_name, "sram")) + return SOF_FW_BLK_TYPE_SRAM; + else + return -EINVAL; +} + +static int imx_parse_ioremap_memory(struct snd_sof_dev *sdev) +{ + const struct imx_chip_info *chip_info; + struct reserved_mem *reserved; + struct platform_device *pdev; + struct device_node *res_np; + phys_addr_t base, size; + struct resource *res; + int i, blk_type, ret; + + pdev = to_platform_device(sdev->dev); + chip_info = get_chip_info(sdev); + + for (i = 0; chip_info->memory[i].name; i++) { + blk_type = imx_region_name_to_blk_type(chip_info->memory[i].name); + if (blk_type < 0) + return dev_err_probe(sdev->dev, blk_type, + "no blk type for region %s\n", + chip_info->memory[i].name); + + if (!chip_info->memory[i].reserved) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + chip_info->memory[i].name); + if (!res) + return dev_err_probe(sdev->dev, -ENODEV, + "failed to fetch %s resource\n", + chip_info->memory[i].name); + + base = res->start; + size = resource_size(res); + } else { + ret = of_property_match_string(pdev->dev.of_node, + "memory-region-names", + chip_info->memory[i].name); + if (ret < 0) + return dev_err_probe(sdev->dev, ret, + "no valid index for %s\n", + chip_info->memory[i].name); + + res_np = of_parse_phandle(pdev->dev.of_node, + "memory-region", + ret); + if (!res_np) + return dev_err_probe(sdev->dev, -ENODEV, + "failed to parse phandle %s\n", + chip_info->memory[i].name); + + reserved = of_reserved_mem_lookup(res_np); + of_node_put(res_np); + if (!reserved) + return dev_err_probe(sdev->dev, -ENODEV, + "failed to get %s reserved\n", + chip_info->memory[i].name); + + base = reserved->base; + size = reserved->size; + } + + sdev->bar[blk_type] = devm_ioremap(sdev->dev, base, size); + if (IS_ERR(sdev->bar[blk_type])) + return dev_err_probe(sdev->dev, + PTR_ERR(sdev->bar[blk_type]), + "failed to ioremap %s region\n", + chip_info->memory[i].name); + } + + return 0; +} + +static void imx_unregister_action(void *data) +{ + struct imx_common_data *common; + struct snd_sof_dev *sdev; + + sdev = data; + common = sdev->pdata->hw_pdata; + + if (get_chip_info(sdev)->has_dma_reserved) + of_reserved_mem_device_release(sdev->dev); + + platform_device_unregister(common->ipc_dev); +} + +static int imx_probe(struct snd_sof_dev *sdev) +{ + struct dev_pm_domain_attach_data domain_data = { + .pd_names = NULL, /* no filtering */ + .pd_flags = PD_FLAG_DEV_LINK_ON, + }; + struct imx_common_data *common; + struct platform_device *pdev; + int ret; + + pdev = to_platform_device(sdev->dev); + + common = devm_kzalloc(sdev->dev, sizeof(*common), GFP_KERNEL); + if (!common) + return dev_err_probe(sdev->dev, -ENOMEM, + "failed to allocate common data\n"); + + common->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", + PLATFORM_DEVID_NONE, + pdev, sizeof(*pdev)); + if (IS_ERR(common->ipc_dev)) + return dev_err_probe(sdev->dev, PTR_ERR(common->ipc_dev), + "failed to create IPC device\n"); + + if (get_chip_info(sdev)->has_dma_reserved) { + ret = of_reserved_mem_device_init_by_name(sdev->dev, + pdev->dev.of_node, + "dma"); + if (ret) { + platform_device_unregister(common->ipc_dev); + + return dev_err_probe(sdev->dev, ret, + "failed to bind DMA region\n"); + } + } + + /* let the devres API take care of the cleanup */ + ret = devm_add_action_or_reset(sdev->dev, + imx_unregister_action, + sdev); + if (ret) + return dev_err_probe(sdev->dev, ret, "failed to add devm action\n"); + + common->ipc_handle = dev_get_drvdata(&common->ipc_dev->dev); + if (!common->ipc_handle) + return dev_err_probe(sdev->dev, -EPROBE_DEFER, + "failed to fetch IPC handle\n"); + + ret = imx_parse_ioremap_memory(sdev); + if (ret < 0) + return dev_err_probe(sdev->dev, ret, + "failed to parse/ioremap memory regions\n"); + + if (!sdev->dev->pm_domain) { + ret = devm_pm_domain_attach_list(sdev->dev, + &domain_data, &common->pd_list); + if (ret < 0) + return dev_err_probe(sdev->dev, ret, "failed to attach PDs\n"); + } + + ret = devm_clk_bulk_get_all(sdev->dev, &common->clks); + if (ret < 0) + return dev_err_probe(sdev->dev, common->clk_num, + "failed to fetch clocks\n"); + common->clk_num = ret; + + ret = clk_bulk_prepare_enable(common->clk_num, common->clks); + if (ret < 0) + return dev_err_probe(sdev->dev, ret, "failed to enable clocks\n"); + + common->ipc_handle->ops = &imx_ipc_ops; + imx_dsp_set_data(common->ipc_handle, sdev); + + sdev->num_cores = 1; + sdev->pdata->hw_pdata = common; + sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; + sdev->dsp_box.offset = get_chip_info(sdev)->ipc_info.boot_mbox_offset; + + return imx_chip_probe(sdev); +} + +static void imx_remove(struct snd_sof_dev *sdev) +{ + struct imx_common_data *common; + int ret; + + common = sdev->pdata->hw_pdata; + + if (!pm_runtime_suspended(sdev->dev)) { + ret = imx_chip_core_shutdown(sdev); + if (ret < 0) + dev_err(sdev->dev, "failed to shutdown core: %d\n", ret); + + clk_bulk_disable_unprepare(common->clk_num, common->clks); + } +} + +const struct snd_sof_dsp_ops sof_imx_ops = { + .probe = imx_probe, + .remove = imx_remove, + + .run = imx_chip_core_kick, + .reset = imx_chip_core_reset, + + .block_read = sof_block_read, + .block_write = sof_block_write, + + .mailbox_read = sof_mailbox_read, + .mailbox_write = sof_mailbox_write, + + .send_msg = imx_send_msg, + .get_mailbox_offset = imx_get_mailbox_offset, + .get_window_offset = imx_get_window_offset, + + .ipc_msg_data = sof_ipc_msg_data, + .set_stream_data_offset = sof_set_stream_data_offset, + + .get_bar_index = imx_get_bar_index, + .load_firmware = snd_sof_load_firmware_memcpy, + + .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem, + + .pcm_open = sof_stream_pcm_open, + .pcm_close = sof_stream_pcm_close, + + .runtime_suspend = imx_runtime_suspend, + .runtime_resume = imx_runtime_resume, + .suspend = imx_suspend, + .resume = imx_resume, + + .set_power_state = imx_set_power_state, + + .hw_info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, +}; +EXPORT_SYMBOL(sof_imx_ops); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF helpers for IMX platforms"); diff --git a/sound/soc/sof/imx/imx-common.h b/sound/soc/sof/imx/imx-common.h index 13d7f3ef675e..9bd711dbb5d0 100644 --- a/sound/soc/sof/imx/imx-common.h +++ b/sound/soc/sof/imx/imx-common.h @@ -4,10 +4,159 @@ #define __IMX_COMMON_H__ #include +#include +#include + +#include "../sof-of-dev.h" +#include "../ops.h" #define EXCEPT_MAX_HDR_SIZE 0x400 #define IMX8_STACK_DUMP_SIZE 32 +/* chip_info refers to the data stored in struct sof_dev_desc's chip_info */ +#define get_chip_info(sdev)\ + ((const struct imx_chip_info *)((sdev)->pdata->desc->chip_info)) + +/* chip_pdata refers to the data stored in struct imx_common_data's chip_pdata */ +#define get_chip_pdata(sdev)\ + (((struct imx_common_data *)((sdev)->pdata->hw_pdata))->chip_pdata) + +/* can be used if: + * 1) The only supported IPC version is IPC3. + * 2) The default paths/FW name match values below. + * + * otherwise, just explicitly declare the structure + */ +#define IMX_SOF_DEV_DESC(mach_name, of_machs, \ + mach_chip_info, mach_ops, mach_ops_init) \ +static struct sof_dev_desc sof_of_##mach_name##_desc = { \ + .of_machines = of_machs, \ + .chip_info = mach_chip_info, \ + .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), \ + .ipc_default = SOF_IPC_TYPE_3, \ + .default_fw_path = { \ + [SOF_IPC_TYPE_3] = "imx/sof", \ + }, \ + .default_tplg_path = { \ + [SOF_IPC_TYPE_3] = "imx/sof-tplg", \ + }, \ + .default_fw_filename = { \ + [SOF_IPC_TYPE_3] = "sof-" #mach_name ".ri", \ + }, \ + .ops = mach_ops, \ + .ops_init = mach_ops_init, \ +} + +/* to be used alongside IMX_SOF_DEV_DESC() */ +#define IMX_SOF_DEV_DESC_NAME(mach_name) sof_of_##mach_name##_desc + +/* dai driver entry w/ playback and capture caps. If one direction is missing + * then set the channels to 0. + */ +#define IMX_SOF_DAI_DRV_ENTRY(dai_name, pb_cmin, pb_cmax, cap_cmin, cap_cmax) \ +{ \ + .name = dai_name, \ + .playback = { \ + .channels_min = pb_cmin, \ + .channels_max = pb_cmax, \ + }, \ + .capture = { \ + .channels_min = cap_cmin, \ + .channels_max = cap_cmax, \ + }, \ +} + +/* use if playback and capture have the same min/max channel count */ +#define IMX_SOF_DAI_DRV_ENTRY_BIDIR(dai_name, cmin, cmax)\ + IMX_SOF_DAI_DRV_ENTRY(dai_name, cmin, cmax, cmin, cmax) + +struct imx_ipc_info { + /* true if core is able to write a panic code to the debug box */ + bool has_panic_code; + /* offset to mailbox in which firmware initially writes FW_READY */ + int boot_mbox_offset; + /* offset to region at which the mailboxes start */ + int window_offset; +}; + +struct imx_chip_ops { + /* called after clocks and PDs are enabled */ + int (*probe)(struct snd_sof_dev *sdev); + /* used directly by the SOF core */ + int (*core_kick)(struct snd_sof_dev *sdev); + /* called during suspend()/remove() before clocks are disabled */ + int (*core_shutdown)(struct snd_sof_dev *sdev); + /* used directly by the SOF core */ + int (*core_reset)(struct snd_sof_dev *sdev); +}; + +struct imx_memory_info { + const char *name; + bool reserved; +}; + +struct imx_chip_info { + struct imx_ipc_info ipc_info; + /* does the chip have a reserved memory region for DMA? */ + bool has_dma_reserved; + struct imx_memory_info *memory; + struct snd_soc_dai_driver *drv; + int num_drv; + /* optional */ + const struct imx_chip_ops *ops; +}; + +struct imx_common_data { + struct platform_device *ipc_dev; + struct imx_dsp_ipc *ipc_handle; + /* core may have no clocks */ + struct clk_bulk_data *clks; + int clk_num; + /* core may have no PDs */ + struct dev_pm_domain_list *pd_list; + void *chip_pdata; +}; + +static inline int imx_chip_core_kick(struct snd_sof_dev *sdev) +{ + const struct imx_chip_ops *ops = get_chip_info(sdev)->ops; + + if (ops && ops->core_kick) + return ops->core_kick(sdev); + + return 0; +} + +static inline int imx_chip_core_shutdown(struct snd_sof_dev *sdev) +{ + const struct imx_chip_ops *ops = get_chip_info(sdev)->ops; + + if (ops && ops->core_shutdown) + return ops->core_shutdown(sdev); + + return 0; +} + +static inline int imx_chip_core_reset(struct snd_sof_dev *sdev) +{ + const struct imx_chip_ops *ops = get_chip_info(sdev)->ops; + + if (ops && ops->core_reset) + return ops->core_reset(sdev); + + return 0; +} + +static inline int imx_chip_probe(struct snd_sof_dev *sdev) +{ + const struct imx_chip_ops *ops = get_chip_info(sdev)->ops; + + if (ops && ops->probe) + return ops->probe(sdev); + + return 0; +} + void imx8_get_registers(struct snd_sof_dev *sdev, struct sof_ipc_dsp_oops_xtensa *xoops, struct sof_ipc_panic_info *panic_info, @@ -15,4 +164,6 @@ void imx8_get_registers(struct snd_sof_dev *sdev, void imx8_dump(struct snd_sof_dev *sdev, u32 flags); +extern const struct snd_sof_dsp_ops sof_imx_ops; + #endif From 645753d01356ff1a756812f1c69c53eb5c9081cd Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:41 -0500 Subject: [PATCH 0095/1090] ASoC: SOF: imx8: use common imx chip interface The common interface for imx chips (defined in imx-common.c) contains the definitions for a lot of functions required by the SOF core. As such, the platform driver can just use the common definitions instead of duplicating code by re-defining aforementioned functions. Make the transition to the new common interface. This consists of: 1) Removing unneeded functions, which are already defined in the common interface. 2) Defining some chip-specific operations/structures required by the interface to work. 3) Dropping structure definitions that are no longer needed. 4) Adapting some existing functions to the new interface. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-3-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 528 +++++---------------------------------- 1 file changed, 68 insertions(+), 460 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 1e7bf00d7c46..25e3296a1e5e 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright 2019 NXP +// Copyright 2019-2025 NXP // // Author: Daniel Baluta // @@ -41,100 +41,28 @@ #define MBOX_OFFSET 0x800000 #define MBOX_SIZE 0x1000 -struct imx8_priv { - struct device *dev; - struct snd_sof_dev *sdev; - - /* DSP IPC handler */ - struct imx_dsp_ipc *dsp_ipc; - struct platform_device *ipc_dev; - - /* System Controller IPC handler */ - struct imx_sc_ipc *sc_ipc; - - /* Power domain handling */ - int num_domains; - struct device **pd_dev; - struct device_link **link; - - struct clk_bulk_data *clks; - int clk_num; -}; - -static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev) -{ - return MBOX_OFFSET; -} - -static int imx8_get_window_offset(struct snd_sof_dev *sdev, u32 id) -{ - return MBOX_OFFSET; -} - -static void imx8_dsp_handle_reply(struct imx_dsp_ipc *ipc) -{ - struct imx8_priv *priv = imx_dsp_get_data(ipc); - unsigned long flags; - - spin_lock_irqsave(&priv->sdev->ipc_lock, flags); - snd_sof_ipc_process_reply(priv->sdev, 0); - spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); -} - -static void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc) -{ - struct imx8_priv *priv = imx_dsp_get_data(ipc); - u32 p; /* panic code */ - - /* Read the message from the debug box. */ - sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, &p, sizeof(p)); - - /* Check to see if the message is a panic code (0x0dead***) */ - if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) - snd_sof_dsp_panic(priv->sdev, p, true); - else - snd_sof_ipc_msgs_rx(priv->sdev); -} - -static struct imx_dsp_ops dsp_ops = { - .handle_reply = imx8_dsp_handle_reply, - .handle_request = imx8_dsp_handle_request, -}; - -static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) -{ - struct imx8_priv *priv = sdev->pdata->hw_pdata; - - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - imx_dsp_ring_doorbell(priv->dsp_ipc, 0); - - return 0; -} - /* * DSP control. */ static int imx8x_run(struct snd_sof_dev *sdev) { - struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata; int ret; - ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + ret = imx_sc_misc_set_control(get_chip_pdata(sdev), IMX_SC_R_DSP, IMX_SC_C_OFS_SEL, 1); if (ret < 0) { dev_err(sdev->dev, "Error system address offset source select\n"); return ret; } - ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + ret = imx_sc_misc_set_control(get_chip_pdata(sdev), IMX_SC_R_DSP, IMX_SC_C_OFS_AUDIO, 0x80); if (ret < 0) { dev_err(sdev->dev, "Error system address offset of AUDIO\n"); return ret; } - ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + ret = imx_sc_misc_set_control(get_chip_pdata(sdev), IMX_SC_R_DSP, IMX_SC_C_OFS_PERIPH, 0x5A); if (ret < 0) { dev_err(sdev->dev, "Error system address offset of PERIPH %d\n", @@ -142,14 +70,14 @@ static int imx8x_run(struct snd_sof_dev *sdev) return ret; } - ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + ret = imx_sc_misc_set_control(get_chip_pdata(sdev), IMX_SC_R_DSP, IMX_SC_C_OFS_IRQ, 0x51); if (ret < 0) { dev_err(sdev->dev, "Error system address offset of IRQ\n"); return ret; } - imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true, + imx_sc_pm_cpu_start(get_chip_pdata(sdev), IMX_SC_R_DSP, true, RESET_VECTOR_VADDR); return 0; @@ -157,17 +85,16 @@ static int imx8x_run(struct snd_sof_dev *sdev) static int imx8_run(struct snd_sof_dev *sdev) { - struct imx8_priv *dsp_priv = sdev->pdata->hw_pdata; int ret; - ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP, + ret = imx_sc_misc_set_control(get_chip_pdata(sdev), IMX_SC_R_DSP, IMX_SC_C_OFS_SEL, 0); if (ret < 0) { dev_err(sdev->dev, "Error system address offset source select\n"); return ret; } - imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true, + imx_sc_pm_cpu_start(get_chip_pdata(sdev), IMX_SC_R_DSP, true, RESET_VECTOR_VADDR); return 0; @@ -175,272 +102,20 @@ static int imx8_run(struct snd_sof_dev *sdev) static int imx8_probe(struct snd_sof_dev *sdev) { - struct platform_device *pdev = to_platform_device(sdev->dev); - struct device_node *np = pdev->dev.of_node; - struct device_node *res_node; - struct resource *mmio; - struct imx8_priv *priv; - struct resource res; - u32 base, size; - int ret = 0; - int i; + struct imx_sc_ipc *sc_ipc_handle; + struct imx_common_data *common; + int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + common = sdev->pdata->hw_pdata; - sdev->num_cores = 1; - sdev->pdata->hw_pdata = priv; - priv->dev = sdev->dev; - priv->sdev = sdev; + ret = imx_scu_get_handle(&sc_ipc_handle); + if (ret < 0) + return dev_err_probe(sdev->dev, ret, + "failed to fetch SC IPC handle\n"); - /* power up device associated power domains */ - priv->num_domains = of_count_phandle_with_args(np, "power-domains", - "#power-domain-cells"); - if (priv->num_domains < 0) { - dev_err(sdev->dev, "no power-domains property in %pOF\n", np); - return priv->num_domains; - } - - priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains, - sizeof(*priv->pd_dev), GFP_KERNEL); - if (!priv->pd_dev) - return -ENOMEM; - - priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains, - sizeof(*priv->link), GFP_KERNEL); - if (!priv->link) - return -ENOMEM; - - for (i = 0; i < priv->num_domains; i++) { - priv->pd_dev[i] = dev_pm_domain_attach_by_id(&pdev->dev, i); - if (IS_ERR(priv->pd_dev[i])) { - ret = PTR_ERR(priv->pd_dev[i]); - goto exit_unroll_pm; - } - priv->link[i] = device_link_add(&pdev->dev, priv->pd_dev[i], - DL_FLAG_STATELESS | - DL_FLAG_PM_RUNTIME | - DL_FLAG_RPM_ACTIVE); - if (!priv->link[i]) { - ret = -ENOMEM; - dev_pm_domain_detach(priv->pd_dev[i], false); - goto exit_unroll_pm; - } - } - - ret = imx_scu_get_handle(&priv->sc_ipc); - if (ret) { - dev_err(sdev->dev, "Cannot obtain SCU handle (err = %d)\n", - ret); - goto exit_unroll_pm; - } - - priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", - PLATFORM_DEVID_NONE, - pdev, sizeof(*pdev)); - if (IS_ERR(priv->ipc_dev)) { - ret = PTR_ERR(priv->ipc_dev); - goto exit_unroll_pm; - } - - priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); - if (!priv->dsp_ipc) { - /* DSP IPC driver not probed yet, try later */ - ret = -EPROBE_DEFER; - dev_err(sdev->dev, "Failed to get drvdata\n"); - goto exit_pdev_unregister; - } - - imx_dsp_set_data(priv->dsp_ipc, priv); - priv->dsp_ipc->ops = &dsp_ops; - - /* DSP base */ - mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mmio) { - base = mmio->start; - size = resource_size(mmio); - } else { - dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); - ret = -EINVAL; - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); - if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { - dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", - base, size); - ret = -ENODEV; - goto exit_pdev_unregister; - } - sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; - - res_node = of_parse_phandle(np, "memory-region", 0); - if (!res_node) { - dev_err(&pdev->dev, "failed to get memory region node\n"); - ret = -ENODEV; - goto exit_pdev_unregister; - } - - ret = of_address_to_resource(res_node, 0, &res); - of_node_put(res_node); - if (ret) { - dev_err(&pdev->dev, "failed to get reserved region address\n"); - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - resource_size(&res)); - if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { - dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", - base, size); - ret = -ENOMEM; - goto exit_pdev_unregister; - } - sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; - - /* set default mailbox offset for FW ready message */ - sdev->dsp_box.offset = MBOX_OFFSET; - - ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); - goto exit_pdev_unregister; - } - priv->clk_num = ret; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - goto exit_pdev_unregister; - } + common->chip_pdata = sc_ipc_handle; return 0; - -exit_pdev_unregister: - platform_device_unregister(priv->ipc_dev); -exit_unroll_pm: - while (--i >= 0) { - device_link_del(priv->link[i]); - dev_pm_domain_detach(priv->pd_dev[i], false); - } - - return ret; -} - -static void imx8_remove(struct snd_sof_dev *sdev) -{ - struct imx8_priv *priv = sdev->pdata->hw_pdata; - int i; - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); - platform_device_unregister(priv->ipc_dev); - - for (i = 0; i < priv->num_domains; i++) { - device_link_del(priv->link[i]); - dev_pm_domain_detach(priv->pd_dev[i], false); - } -} - -/* on i.MX8 there is 1 to 1 match between type and BAR idx */ -static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type) -{ - /* Only IRAM and SRAM bars are valid */ - switch (type) { - case SOF_FW_BLK_TYPE_IRAM: - case SOF_FW_BLK_TYPE_SRAM: - return type; - default: - return -EINVAL; - } -} - -static void imx8_suspend(struct snd_sof_dev *sdev) -{ - int i; - struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata; - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_free_channel(priv->dsp_ipc, i); - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); -} - -static int imx8_resume(struct snd_sof_dev *sdev) -{ - struct imx8_priv *priv = (struct imx8_priv *)sdev->pdata->hw_pdata; - int ret; - int i; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - return ret; - } - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_request_channel(priv->dsp_ipc, i); - - return 0; -} - -static int imx8_dsp_runtime_resume(struct snd_sof_dev *sdev) -{ - int ret; - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - }; - - ret = imx8_resume(sdev); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8_dsp_runtime_suspend(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D3, - }; - - imx8_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = target_state, - }; - - if (!pm_runtime_suspended(sdev->dev)) - imx8_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8_dsp_resume(struct snd_sof_dev *sdev) -{ - int ret; - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - }; - - ret = imx8_resume(sdev); - if (ret < 0) - return ret; - - if (pm_runtime_suspended(sdev->dev)) { - pm_runtime_disable(sdev->dev); - pm_runtime_set_active(sdev->dev); - pm_runtime_mark_last_busy(sdev->dev); - pm_runtime_enable(sdev->dev); - pm_runtime_idle(sdev->dev); - } - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); } static struct snd_soc_dai_driver imx8_dai[] = { @@ -468,135 +143,64 @@ static struct snd_soc_dai_driver imx8_dai[] = { }, }; -static int imx8_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) +static struct snd_sof_dsp_ops sof_imx8_ops; + +static int imx8_ops_init(struct snd_sof_dev *sdev) { - sdev->dsp_power_state = *target_state; + /* first copy from template */ + memcpy(&sof_imx8_ops, &sof_imx_ops, sizeof(sof_imx_ops)); + + /* then set common imx8 ops */ + sof_imx8_ops.dbg_dump = imx8_dump; + sof_imx8_ops.dsp_arch_ops = &sof_xtensa_arch_ops; + sof_imx8_ops.debugfs_add_region_item = + snd_sof_debugfs_add_region_item_iomem; + + /* ... and finally set DAI driver */ + sof_imx8_ops.drv = get_chip_info(sdev)->drv; + sof_imx8_ops.num_drv = get_chip_info(sdev)->num_drv; return 0; } -/* i.MX8 ops */ -static const struct snd_sof_dsp_ops sof_imx8_ops = { - /* probe and remove */ - .probe = imx8_probe, - .remove = imx8_remove, - /* DSP core boot */ - .run = imx8_run, - - /* Block IO */ - .block_read = sof_block_read, - .block_write = sof_block_write, - - /* Mailbox IO */ - .mailbox_read = sof_mailbox_read, - .mailbox_write = sof_mailbox_write, - - /* ipc */ - .send_msg = imx8_send_msg, - .get_mailbox_offset = imx8_get_mailbox_offset, - .get_window_offset = imx8_get_window_offset, - - .ipc_msg_data = sof_ipc_msg_data, - .set_stream_data_offset = sof_set_stream_data_offset, - - .get_bar_index = imx8_get_bar_index, - - /* firmware loading */ - .load_firmware = snd_sof_load_firmware_memcpy, - - /* Debug information */ - .dbg_dump = imx8_dump, - .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem, - - /* stream callbacks */ - .pcm_open = sof_stream_pcm_open, - .pcm_close = sof_stream_pcm_close, - - /* Firmware ops */ - .dsp_arch_ops = &sof_xtensa_arch_ops, - - /* DAI drivers */ - .drv = imx8_dai, - .num_drv = ARRAY_SIZE(imx8_dai), - - /* ALSA HW info flags */ - .hw_info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - - /* PM */ - .runtime_suspend = imx8_dsp_runtime_suspend, - .runtime_resume = imx8_dsp_runtime_resume, - - .suspend = imx8_dsp_suspend, - .resume = imx8_dsp_resume, - - .set_power_state = imx8_dsp_set_power_state, +static const struct imx_chip_ops imx8_chip_ops = { + .probe = imx8_probe, + .core_kick = imx8_run, }; -/* i.MX8X ops */ -static const struct snd_sof_dsp_ops sof_imx8x_ops = { - /* probe and remove */ - .probe = imx8_probe, - .remove = imx8_remove, - /* DSP core boot */ - .run = imx8x_run, +static const struct imx_chip_ops imx8x_chip_ops = { + .probe = imx8_probe, + .core_kick = imx8x_run, +}; - /* Block IO */ - .block_read = sof_block_read, - .block_write = sof_block_write, +static struct imx_memory_info imx8_memory_regions[] = { + { .name = "iram", .reserved = false }, + { .name = "sram", .reserved = true }, + { } +}; - /* Mailbox IO */ - .mailbox_read = sof_mailbox_read, - .mailbox_write = sof_mailbox_write, - - /* ipc */ - .send_msg = imx8_send_msg, - .get_mailbox_offset = imx8_get_mailbox_offset, - .get_window_offset = imx8_get_window_offset, - - .ipc_msg_data = sof_ipc_msg_data, - .set_stream_data_offset = sof_set_stream_data_offset, - - .get_bar_index = imx8_get_bar_index, - - /* firmware loading */ - .load_firmware = snd_sof_load_firmware_memcpy, - - /* Debug information */ - .dbg_dump = imx8_dump, - .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem, - - /* stream callbacks */ - .pcm_open = sof_stream_pcm_open, - .pcm_close = sof_stream_pcm_close, - - /* Firmware ops */ - .dsp_arch_ops = &sof_xtensa_arch_ops, - - /* DAI drivers */ +static const struct imx_chip_info imx8_chip_info = { + .ipc_info = { + .has_panic_code = true, + .boot_mbox_offset = 0x800000, + .window_offset = 0x800000, + }, + .memory = imx8_memory_regions, .drv = imx8_dai, .num_drv = ARRAY_SIZE(imx8_dai), + .ops = &imx8_chip_ops, +}; - /* PM */ - .runtime_suspend = imx8_dsp_runtime_suspend, - .runtime_resume = imx8_dsp_runtime_resume, - - .suspend = imx8_dsp_suspend, - .resume = imx8_dsp_resume, - - .set_power_state = imx8_dsp_set_power_state, - - /* ALSA HW info flags */ - .hw_info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP +static const struct imx_chip_info imx8x_chip_info = { + .ipc_info = { + .has_panic_code = true, + .boot_mbox_offset = 0x800000, + .window_offset = 0x800000, + }, + .memory = imx8_memory_regions, + .drv = imx8_dai, + .num_drv = ARRAY_SIZE(imx8_dai), + .ops = &imx8x_chip_ops, }; static struct snd_sof_of_mach sof_imx8_machs[] = { @@ -636,6 +240,7 @@ static struct snd_sof_of_mach sof_imx8_machs[] = { static struct sof_dev_desc sof_of_imx8qxp_desc = { .of_machines = sof_imx8_machs, + .chip_info = &imx8x_chip_info, .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), .ipc_default = SOF_IPC_TYPE_3, .default_fw_path = { @@ -648,11 +253,13 @@ static struct sof_dev_desc sof_of_imx8qxp_desc = { [SOF_IPC_TYPE_3] = "sof-imx8x.ri", }, .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", - .ops = &sof_imx8x_ops, + .ops = &sof_imx8_ops, + .ops_init = imx8_ops_init, }; static struct sof_dev_desc sof_of_imx8qm_desc = { .of_machines = sof_imx8_machs, + .chip_info = &imx8_chip_info, .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), .ipc_default = SOF_IPC_TYPE_3, .default_fw_path = { @@ -666,6 +273,7 @@ static struct sof_dev_desc sof_of_imx8qm_desc = { }, .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", .ops = &sof_imx8_ops, + .ops_init = imx8_ops_init, }; static const struct of_device_id sof_of_imx8_ids[] = { From 563e40153a56cbfae8721f9591022df5d930f939 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:42 -0500 Subject: [PATCH 0096/1090] ASoC: SOF: imx8: use IMX_SOF_* macros The definition of 'struct sof_dev_desc' has the following properties for imx chips: 1) FW path is the same for all chips. 2) Topology path is the same for all chips. 3) FW name can be written as: "sof-${machine_name}.ri" 4) IPC3 is the only supported protocol The structure takes quite a few lines of code. Since the intention is to add support for more imx8 chips in the same driver, we need to try and reduce the number of lines taken by information that's not particularly useful. As such, we can use 'IMX_SOF_DEV_DESC()' to reduce the declaration of the structure to just one line. The only information that's particularly useful can be seen from the parameters of the macro. Of course, if any of the assumptions don't apply anymore, driver writers can simply declare the 'struct sof_dev_desc' the "old fashioned way". No reason to make the macro suit multiple needs. The same logic applies to the array of 'struct snd_soc_dai_driver'. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Daniel Baluta Reviewed-by: Iuliana Prodan Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-4-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 73 +++++++--------------------------------- 1 file changed, 12 insertions(+), 61 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 25e3296a1e5e..52dff369d9cf 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -119,28 +119,8 @@ static int imx8_probe(struct snd_sof_dev *sdev) } static struct snd_soc_dai_driver imx8_dai[] = { -{ - .name = "esai0", - .playback = { - .channels_min = 1, - .channels_max = 8, - }, - .capture = { - .channels_min = 1, - .channels_max = 8, - }, -}, -{ - .name = "sai1", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, + IMX_SOF_DAI_DRV_ENTRY_BIDIR("esai0", 1, 8), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai1", 1, 32), }; static struct snd_sof_dsp_ops sof_imx8_ops; @@ -238,47 +218,18 @@ static struct snd_sof_of_mach sof_imx8_machs[] = { {} }; -static struct sof_dev_desc sof_of_imx8qxp_desc = { - .of_machines = sof_imx8_machs, - .chip_info = &imx8x_chip_info, - .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), - .ipc_default = SOF_IPC_TYPE_3, - .default_fw_path = { - [SOF_IPC_TYPE_3] = "imx/sof", - }, - .default_tplg_path = { - [SOF_IPC_TYPE_3] = "imx/sof-tplg", - }, - .default_fw_filename = { - [SOF_IPC_TYPE_3] = "sof-imx8x.ri", - }, - .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", - .ops = &sof_imx8_ops, - .ops_init = imx8_ops_init, -}; - -static struct sof_dev_desc sof_of_imx8qm_desc = { - .of_machines = sof_imx8_machs, - .chip_info = &imx8_chip_info, - .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), - .ipc_default = SOF_IPC_TYPE_3, - .default_fw_path = { - [SOF_IPC_TYPE_3] = "imx/sof", - }, - .default_tplg_path = { - [SOF_IPC_TYPE_3] = "imx/sof-tplg", - }, - .default_fw_filename = { - [SOF_IPC_TYPE_3] = "sof-imx8.ri", - }, - .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", - .ops = &sof_imx8_ops, - .ops_init = imx8_ops_init, -}; +IMX_SOF_DEV_DESC(imx8, sof_imx8_machs, &imx8_chip_info, &sof_imx8_ops, imx8_ops_init); +IMX_SOF_DEV_DESC(imx8x, sof_imx8_machs, &imx8x_chip_info, &sof_imx8_ops, imx8_ops_init); static const struct of_device_id sof_of_imx8_ids[] = { - { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc}, - { .compatible = "fsl,imx8qm-dsp", .data = &sof_of_imx8qm_desc}, + { + .compatible = "fsl,imx8qxp-dsp", + .data = &IMX_SOF_DEV_DESC_NAME(imx8x), + }, + { + .compatible = "fsl,imx8qm-dsp", + .data = &IMX_SOF_DEV_DESC_NAME(imx8), + }, { } }; MODULE_DEVICE_TABLE(of, sof_of_imx8_ids); From 45e02edd8422b6c4a511f38403dbd805cd139733 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:43 -0500 Subject: [PATCH 0097/1090] ASoC: SOF: imx8: drop unneeded/unused macros/header includes Drop some unneeded/unused macro definitions and header includes. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Daniel Baluta Reviewed-by: Iuliana Prodan Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-5-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 52dff369d9cf..9a32ebe3eabc 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -6,41 +6,12 @@ // // Hardware interface for audio DSP on i.MX8 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - #include #include -#include "../ops.h" -#include "../sof-of-dev.h" #include "imx-common.h" -/* DSP memories */ -#define IRAM_OFFSET 0x10000 -#define IRAM_SIZE (2 * 1024) -#define DRAM0_OFFSET 0x0 -#define DRAM0_SIZE (32 * 1024) -#define DRAM1_OFFSET 0x8000 -#define DRAM1_SIZE (32 * 1024) -#define SYSRAM_OFFSET 0x18000 -#define SYSRAM_SIZE (256 * 1024) -#define SYSROM_OFFSET 0x58000 -#define SYSROM_SIZE (192 * 1024) - #define RESET_VECTOR_VADDR 0x596f8000 -#define MBOX_OFFSET 0x800000 -#define MBOX_SIZE 0x1000 - /* * DSP control. */ From 896530b7b0c08ee8b3296d5f012bfe1b0a979b86 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:44 -0500 Subject: [PATCH 0098/1090] ASoC: SOF: imx: merge imx8 and imx8m drivers Now that the common interface for imx chip has been introduced, there's no longer a need to have a separate platform driver for imx8m. As such, merge the driver with the imx8 driver. Furthermore, delete the old driver as it's no longer useful. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-6-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 9 - sound/soc/sof/imx/Makefile | 2 - sound/soc/sof/imx/imx8.c | 136 ++++++++- sound/soc/sof/imx/imx8m.c | 567 ------------------------------------- 4 files changed, 134 insertions(+), 580 deletions(-) delete mode 100644 sound/soc/sof/imx/imx8m.c diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 4751b04d5e6f..92fdf80d6e51 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -32,15 +32,6 @@ config SND_SOC_SOF_IMX8 Say Y if you have such a device. If unsure select "N". -config SND_SOC_SOF_IMX8M - tristate "SOF support for i.MX8M" - depends on IMX_DSP - select SND_SOC_SOF_IMX_COMMON - help - This adds support for Sound Open Firmware for NXP i.MX8M platforms. - Say Y if you have such a device. - If unsure select "N". - config SND_SOC_SOF_IMX8ULP tristate "SOF support for i.MX8ULP" depends on IMX_DSP diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index be0bf0736dfa..852140bb8104 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,11 +1,9 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-imx8-y := imx8.o -snd-sof-imx8m-y := imx8m.o snd-sof-imx8ulp-y := imx8ulp.o snd-sof-imx-common-y := imx-common.o obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o -obj-$(CONFIG_SND_SOC_SOF_IMX8M) += snd-sof-imx8m.o obj-$(CONFIG_SND_SOC_SOF_IMX8ULP) += snd-sof-imx8ulp.o obj-$(CONFIG_SND_SOC_SOF_IMX_COMMON) += imx-common.o diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 9a32ebe3eabc..7e08b239aac0 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -6,12 +6,34 @@ // // Hardware interface for audio DSP on i.MX8 -#include #include + +#include +#include + #include "imx-common.h" +/* imx8/imx8x macros */ #define RESET_VECTOR_VADDR 0x596f8000 +/* imx8m macros */ +#define IMX8M_DAP_DEBUG 0x28800000 +#define IMX8M_DAP_DEBUG_SIZE (64 * 1024) +#define IMX8M_DAP_PWRCTL (0x4000 + 0x3020) +#define IMX8M_PWRCTL_CORERESET BIT(16) + +#define AudioDSP_REG0 0x100 +#define AudioDSP_REG1 0x104 +#define AudioDSP_REG2 0x108 +#define AudioDSP_REG3 0x10c + +#define AudioDSP_REG2_RUNSTALL BIT(5) + +struct imx8m_chip_data { + void __iomem *dap; + struct regmap *regmap; +}; + /* * DSP control. */ @@ -89,11 +111,83 @@ static int imx8_probe(struct snd_sof_dev *sdev) return 0; } +static int imx8m_reset(struct snd_sof_dev *sdev) +{ + struct imx8m_chip_data *chip; + u32 pwrctl; + + chip = get_chip_pdata(sdev); + + /* put DSP into reset and stall */ + pwrctl = readl(chip->dap + IMX8M_DAP_PWRCTL); + pwrctl |= IMX8M_PWRCTL_CORERESET; + writel(pwrctl, chip->dap + IMX8M_DAP_PWRCTL); + + /* keep reset asserted for 10 cycles */ + usleep_range(1, 2); + + regmap_update_bits(chip->regmap, AudioDSP_REG2, + AudioDSP_REG2_RUNSTALL, AudioDSP_REG2_RUNSTALL); + + /* take the DSP out of reset and keep stalled for FW loading */ + pwrctl = readl(chip->dap + IMX8M_DAP_PWRCTL); + pwrctl &= ~IMX8M_PWRCTL_CORERESET; + writel(pwrctl, chip->dap + IMX8M_DAP_PWRCTL); + + return 0; +} + +static int imx8m_run(struct snd_sof_dev *sdev) +{ + struct imx8m_chip_data *chip = get_chip_pdata(sdev); + + regmap_update_bits(chip->regmap, AudioDSP_REG2, AudioDSP_REG2_RUNSTALL, 0); + + return 0; +} + +static int imx8m_probe(struct snd_sof_dev *sdev) +{ + struct imx_common_data *common; + struct imx8m_chip_data *chip; + + common = sdev->pdata->hw_pdata; + + chip = devm_kzalloc(sdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return dev_err_probe(sdev->dev, -ENOMEM, + "failed to allocate chip data\n"); + + chip->dap = devm_ioremap(sdev->dev, IMX8M_DAP_DEBUG, IMX8M_DAP_DEBUG_SIZE); + if (!chip->dap) + return dev_err_probe(sdev->dev, -ENODEV, + "failed to ioremap DAP\n"); + + chip->regmap = syscon_regmap_lookup_by_phandle(sdev->dev->of_node, "fsl,dsp-ctrl"); + if (IS_ERR(chip->regmap)) + return dev_err_probe(sdev->dev, PTR_ERR(chip->regmap), + "failed to fetch dsp ctrl regmap\n"); + + common->chip_pdata = chip; + + return 0; +} + static struct snd_soc_dai_driver imx8_dai[] = { IMX_SOF_DAI_DRV_ENTRY_BIDIR("esai0", 1, 8), IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai1", 1, 32), }; +static struct snd_soc_dai_driver imx8m_dai[] = { + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai1", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai2", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai3", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai5", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai6", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai7", 1, 32), + IMX_SOF_DAI_DRV_ENTRY("micfil", 0, 0, 1, 8), +}; + static struct snd_sof_dsp_ops sof_imx8_ops; static int imx8_ops_init(struct snd_sof_dev *sdev) @@ -124,12 +218,24 @@ static const struct imx_chip_ops imx8x_chip_ops = { .core_kick = imx8x_run, }; +static const struct imx_chip_ops imx8m_chip_ops = { + .probe = imx8m_probe, + .core_kick = imx8m_run, + .core_reset = imx8m_reset, +}; + static struct imx_memory_info imx8_memory_regions[] = { { .name = "iram", .reserved = false }, { .name = "sram", .reserved = true }, { } }; +static struct imx_memory_info imx8m_memory_regions[] = { + { .name = "iram", .reserved = false }, + { .name = "sram", .reserved = true }, + { } +}; + static const struct imx_chip_info imx8_chip_info = { .ipc_info = { .has_panic_code = true, @@ -154,6 +260,18 @@ static const struct imx_chip_info imx8x_chip_info = { .ops = &imx8x_chip_ops, }; +static const struct imx_chip_info imx8m_chip_info = { + .ipc_info = { + .has_panic_code = true, + .boot_mbox_offset = 0x800000, + .window_offset = 0x800000, + }, + .memory = imx8m_memory_regions, + .drv = imx8m_dai, + .num_drv = ARRAY_SIZE(imx8m_dai), + .ops = &imx8m_chip_ops, +}; + static struct snd_sof_of_mach sof_imx8_machs[] = { { .compatible = "fsl,imx8qxp-mek", @@ -185,12 +303,22 @@ static struct snd_sof_of_mach sof_imx8_machs[] = { .sof_tplg_filename = "sof-imx8-cs42888.tplg", .drv_name = "asoc-audio-graph-card2", }, - + { + .compatible = "fsl,imx8mp-evk", + .sof_tplg_filename = "sof-imx8mp-wm8960.tplg", + .drv_name = "asoc-audio-graph-card2", + }, + { + .compatible = "fsl,imx8mp-evk-revb4", + .sof_tplg_filename = "sof-imx8mp-wm8962.tplg", + .drv_name = "asoc-audio-graph-card2", + }, {} }; IMX_SOF_DEV_DESC(imx8, sof_imx8_machs, &imx8_chip_info, &sof_imx8_ops, imx8_ops_init); IMX_SOF_DEV_DESC(imx8x, sof_imx8_machs, &imx8x_chip_info, &sof_imx8_ops, imx8_ops_init); +IMX_SOF_DEV_DESC(imx8m, sof_imx8_machs, &imx8m_chip_info, &sof_imx8_ops, imx8_ops_init); static const struct of_device_id sof_of_imx8_ids[] = { { @@ -201,6 +329,10 @@ static const struct of_device_id sof_of_imx8_ids[] = { .compatible = "fsl,imx8qm-dsp", .data = &IMX_SOF_DEV_DESC_NAME(imx8), }, + { + .compatible = "fsl,imx8mp-dsp", + .data = &IMX_SOF_DEV_DESC_NAME(imx8m), + }, { } }; MODULE_DEVICE_TABLE(of, sof_of_imx8_ids); diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c deleted file mode 100644 index 3cabdebac558..000000000000 --- a/sound/soc/sof/imx/imx8m.c +++ /dev/null @@ -1,567 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -// -// Copyright 2020 NXP -// -// Author: Daniel Baluta -// -// Hardware interface for audio DSP on i.MX8M - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../ops.h" -#include "../sof-of-dev.h" -#include "imx-common.h" - -#define MBOX_OFFSET 0x800000 -#define MBOX_SIZE 0x1000 - -/* DAP registers */ -#define IMX8M_DAP_DEBUG 0x28800000 -#define IMX8M_DAP_DEBUG_SIZE (64 * 1024) -#define IMX8M_DAP_PWRCTL (0x4000 + 0x3020) -#define IMX8M_PWRCTL_CORERESET BIT(16) - -/* DSP audio mix registers */ -#define AudioDSP_REG0 0x100 -#define AudioDSP_REG1 0x104 -#define AudioDSP_REG2 0x108 -#define AudioDSP_REG3 0x10c - -#define AudioDSP_REG2_RUNSTALL BIT(5) - -struct imx8m_priv { - struct device *dev; - struct snd_sof_dev *sdev; - - /* DSP IPC handler */ - struct imx_dsp_ipc *dsp_ipc; - struct platform_device *ipc_dev; - - struct clk_bulk_data *clks; - int clk_num; - - void __iomem *dap; - struct regmap *regmap; -}; - -static int imx8m_get_mailbox_offset(struct snd_sof_dev *sdev) -{ - return MBOX_OFFSET; -} - -static int imx8m_get_window_offset(struct snd_sof_dev *sdev, u32 id) -{ - return MBOX_OFFSET; -} - -static void imx8m_dsp_handle_reply(struct imx_dsp_ipc *ipc) -{ - struct imx8m_priv *priv = imx_dsp_get_data(ipc); - unsigned long flags; - - spin_lock_irqsave(&priv->sdev->ipc_lock, flags); - snd_sof_ipc_process_reply(priv->sdev, 0); - spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); -} - -static void imx8m_dsp_handle_request(struct imx_dsp_ipc *ipc) -{ - struct imx8m_priv *priv = imx_dsp_get_data(ipc); - u32 p; /* Panic code */ - - /* Read the message from the debug box. */ - sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, &p, sizeof(p)); - - /* Check to see if the message is a panic code (0x0dead***) */ - if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) - snd_sof_dsp_panic(priv->sdev, p, true); - else - snd_sof_ipc_msgs_rx(priv->sdev); -} - -static struct imx_dsp_ops imx8m_dsp_ops = { - .handle_reply = imx8m_dsp_handle_reply, - .handle_request = imx8m_dsp_handle_request, -}; - -static int imx8m_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) -{ - struct imx8m_priv *priv = sdev->pdata->hw_pdata; - - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - imx_dsp_ring_doorbell(priv->dsp_ipc, 0); - - return 0; -} - -/* - * DSP control. - */ -static int imx8m_run(struct snd_sof_dev *sdev) -{ - struct imx8m_priv *priv = (struct imx8m_priv *)sdev->pdata->hw_pdata; - - regmap_update_bits(priv->regmap, AudioDSP_REG2, AudioDSP_REG2_RUNSTALL, 0); - - return 0; -} - -static int imx8m_reset(struct snd_sof_dev *sdev) -{ - struct imx8m_priv *priv = (struct imx8m_priv *)sdev->pdata->hw_pdata; - u32 pwrctl; - - /* put DSP into reset and stall */ - pwrctl = readl(priv->dap + IMX8M_DAP_PWRCTL); - pwrctl |= IMX8M_PWRCTL_CORERESET; - writel(pwrctl, priv->dap + IMX8M_DAP_PWRCTL); - - /* keep reset asserted for 10 cycles */ - usleep_range(1, 2); - - regmap_update_bits(priv->regmap, AudioDSP_REG2, - AudioDSP_REG2_RUNSTALL, AudioDSP_REG2_RUNSTALL); - - /* take the DSP out of reset and keep stalled for FW loading */ - pwrctl = readl(priv->dap + IMX8M_DAP_PWRCTL); - pwrctl &= ~IMX8M_PWRCTL_CORERESET; - writel(pwrctl, priv->dap + IMX8M_DAP_PWRCTL); - - return 0; -} - -static int imx8m_probe(struct snd_sof_dev *sdev) -{ - struct platform_device *pdev = to_platform_device(sdev->dev); - struct device_node *np = pdev->dev.of_node; - struct device_node *res_node; - struct resource *mmio; - struct imx8m_priv *priv; - struct resource res; - u32 base, size; - int ret = 0; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - sdev->num_cores = 1; - sdev->pdata->hw_pdata = priv; - priv->dev = sdev->dev; - priv->sdev = sdev; - - priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", - PLATFORM_DEVID_NONE, - pdev, sizeof(*pdev)); - if (IS_ERR(priv->ipc_dev)) - return PTR_ERR(priv->ipc_dev); - - priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); - if (!priv->dsp_ipc) { - /* DSP IPC driver not probed yet, try later */ - ret = -EPROBE_DEFER; - dev_err(sdev->dev, "Failed to get drvdata\n"); - goto exit_pdev_unregister; - } - - imx_dsp_set_data(priv->dsp_ipc, priv); - priv->dsp_ipc->ops = &imx8m_dsp_ops; - - /* DSP base */ - mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mmio) { - base = mmio->start; - size = resource_size(mmio); - } else { - dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); - ret = -EINVAL; - goto exit_pdev_unregister; - } - - priv->dap = devm_ioremap(sdev->dev, IMX8M_DAP_DEBUG, IMX8M_DAP_DEBUG_SIZE); - if (!priv->dap) { - dev_err(sdev->dev, "error: failed to map DAP debug memory area"); - ret = -ENODEV; - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); - if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { - dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", - base, size); - ret = -ENODEV; - goto exit_pdev_unregister; - } - sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; - - res_node = of_parse_phandle(np, "memory-region", 0); - if (!res_node) { - dev_err(&pdev->dev, "failed to get memory region node\n"); - ret = -ENODEV; - goto exit_pdev_unregister; - } - - ret = of_address_to_resource(res_node, 0, &res); - of_node_put(res_node); - if (ret) { - dev_err(&pdev->dev, "failed to get reserved region address\n"); - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - resource_size(&res)); - if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { - dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", - base, size); - ret = -ENOMEM; - goto exit_pdev_unregister; - } - sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; - - /* set default mailbox offset for FW ready message */ - sdev->dsp_box.offset = MBOX_OFFSET; - - priv->regmap = syscon_regmap_lookup_by_phandle(np, "fsl,dsp-ctrl"); - if (IS_ERR(priv->regmap)) { - dev_err(sdev->dev, "cannot find dsp-ctrl registers"); - ret = PTR_ERR(priv->regmap); - goto exit_pdev_unregister; - } - - ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); - goto exit_pdev_unregister; - } - priv->clk_num = ret; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - goto exit_pdev_unregister; - } - - return 0; - -exit_pdev_unregister: - platform_device_unregister(priv->ipc_dev); - return ret; -} - -static void imx8m_remove(struct snd_sof_dev *sdev) -{ - struct imx8m_priv *priv = sdev->pdata->hw_pdata; - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); - platform_device_unregister(priv->ipc_dev); -} - -/* on i.MX8 there is 1 to 1 match between type and BAR idx */ -static int imx8m_get_bar_index(struct snd_sof_dev *sdev, u32 type) -{ - /* Only IRAM and SRAM bars are valid */ - switch (type) { - case SOF_FW_BLK_TYPE_IRAM: - case SOF_FW_BLK_TYPE_SRAM: - return type; - default: - return -EINVAL; - } -} - -static struct snd_soc_dai_driver imx8m_dai[] = { -{ - .name = "sai1", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "sai2", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "sai3", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "sai5", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "sai6", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "sai7", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, -}, -{ - .name = "micfil", - .capture = { - .channels_min = 1, - .channels_max = 8, - }, -}, -}; - -static int imx8m_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) -{ - sdev->dsp_power_state = *target_state; - - return 0; -} - -static int imx8m_resume(struct snd_sof_dev *sdev) -{ - struct imx8m_priv *priv = (struct imx8m_priv *)sdev->pdata->hw_pdata; - int ret; - int i; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - return ret; - } - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_request_channel(priv->dsp_ipc, i); - - return 0; -} - -static void imx8m_suspend(struct snd_sof_dev *sdev) -{ - struct imx8m_priv *priv = (struct imx8m_priv *)sdev->pdata->hw_pdata; - int i; - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_free_channel(priv->dsp_ipc, i); - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); -} - -static int imx8m_dsp_runtime_resume(struct snd_sof_dev *sdev) -{ - int ret; - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - }; - - ret = imx8m_resume(sdev); - if (ret < 0) - return ret; - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8m_dsp_runtime_suspend(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D3, - }; - - imx8m_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8m_dsp_resume(struct snd_sof_dev *sdev) -{ - int ret; - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - }; - - ret = imx8m_resume(sdev); - if (ret < 0) - return ret; - - if (pm_runtime_suspended(sdev->dev)) { - pm_runtime_disable(sdev->dev); - pm_runtime_set_active(sdev->dev); - pm_runtime_mark_last_busy(sdev->dev); - pm_runtime_enable(sdev->dev); - pm_runtime_idle(sdev->dev); - } - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8m_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = target_state, - }; - - if (!pm_runtime_suspended(sdev->dev)) - imx8m_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -/* i.MX8 ops */ -static const struct snd_sof_dsp_ops sof_imx8m_ops = { - /* probe and remove */ - .probe = imx8m_probe, - .remove = imx8m_remove, - /* DSP core boot */ - .run = imx8m_run, - .reset = imx8m_reset, - - /* Block IO */ - .block_read = sof_block_read, - .block_write = sof_block_write, - - /* Mailbox IO */ - .mailbox_read = sof_mailbox_read, - .mailbox_write = sof_mailbox_write, - - /* ipc */ - .send_msg = imx8m_send_msg, - .get_mailbox_offset = imx8m_get_mailbox_offset, - .get_window_offset = imx8m_get_window_offset, - - .ipc_msg_data = sof_ipc_msg_data, - .set_stream_data_offset = sof_set_stream_data_offset, - - .get_bar_index = imx8m_get_bar_index, - - /* firmware loading */ - .load_firmware = snd_sof_load_firmware_memcpy, - - /* Debug information */ - .dbg_dump = imx8_dump, - .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem, - - /* stream callbacks */ - .pcm_open = sof_stream_pcm_open, - .pcm_close = sof_stream_pcm_close, - /* Firmware ops */ - .dsp_arch_ops = &sof_xtensa_arch_ops, - - /* DAI drivers */ - .drv = imx8m_dai, - .num_drv = ARRAY_SIZE(imx8m_dai), - - .suspend = imx8m_dsp_suspend, - .resume = imx8m_dsp_resume, - - .runtime_suspend = imx8m_dsp_runtime_suspend, - .runtime_resume = imx8m_dsp_runtime_resume, - - .set_power_state = imx8m_dsp_set_power_state, - - .hw_info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, -}; - -static struct snd_sof_of_mach sof_imx8mp_machs[] = { - { - .compatible = "fsl,imx8mp-evk-revb4", - .sof_tplg_filename = "sof-imx8mp-wm8962.tplg", - .drv_name = "asoc-audio-graph-card2", - }, - { - .compatible = "fsl,imx8mp-evk", - .sof_tplg_filename = "sof-imx8mp-wm8960.tplg", - .drv_name = "asoc-audio-graph-card2", - }, - {} -}; - -static struct sof_dev_desc sof_of_imx8mp_desc = { - .of_machines = sof_imx8mp_machs, - .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), - .ipc_default = SOF_IPC_TYPE_3, - .default_fw_path = { - [SOF_IPC_TYPE_3] = "imx/sof", - }, - .default_tplg_path = { - [SOF_IPC_TYPE_3] = "imx/sof-tplg", - }, - .default_fw_filename = { - [SOF_IPC_TYPE_3] = "sof-imx8m.ri", - }, - .nocodec_tplg_filename = "sof-imx8-nocodec.tplg", - .ops = &sof_imx8m_ops, -}; - -static const struct of_device_id sof_of_imx8m_ids[] = { - { .compatible = "fsl,imx8mp-dsp", .data = &sof_of_imx8mp_desc}, - { } -}; -MODULE_DEVICE_TABLE(of, sof_of_imx8m_ids); - -/* DT driver definition */ -static struct platform_driver snd_sof_of_imx8m_driver = { - .probe = sof_of_probe, - .remove = sof_of_remove, - .driver = { - .name = "sof-audio-of-imx8m", - .pm = &sof_of_pm, - .of_match_table = sof_of_imx8m_ids, - }, -}; -module_platform_driver(snd_sof_of_imx8m_driver); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("SOF support for IMX8M platforms"); -MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); From 07e3e514dd385300bd08da4a8df09240d272821e Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:45 -0500 Subject: [PATCH 0099/1090] ASoC: SOF: imx: merge imx8 and imx8ulp drivers Now that the common interface for imx chip has been introduced, there's no longer a need to have a separate platform driver for imx8ulp. As such, merge the driver with the imx8 driver. Furthermore, delete the old driver as it's no longer useful. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-7-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 9 - sound/soc/sof/imx/Makefile | 2 - sound/soc/sof/imx/imx8.c | 113 ++++++++ sound/soc/sof/imx/imx8ulp.c | 520 ------------------------------------ 4 files changed, 113 insertions(+), 531 deletions(-) delete mode 100644 sound/soc/sof/imx/imx8ulp.c diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 92fdf80d6e51..2edf9de2c886 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -32,13 +32,4 @@ config SND_SOC_SOF_IMX8 Say Y if you have such a device. If unsure select "N". -config SND_SOC_SOF_IMX8ULP - tristate "SOF support for i.MX8ULP" - depends on IMX_DSP - select SND_SOC_SOF_IMX_COMMON - help - This adds support for Sound Open Firmware for NXP i.MX8ULP platforms. - Say Y if you have such a device. - If unsure select "N". - endif ## SND_SOC_SOF_IMX_TOPLEVEL diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index 852140bb8104..36a3a67c6efb 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,9 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-imx8-y := imx8.o -snd-sof-imx8ulp-y := imx8ulp.o snd-sof-imx-common-y := imx-common.o obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o -obj-$(CONFIG_SND_SOC_SOF_IMX8ULP) += snd-sof-imx8ulp.o obj-$(CONFIG_SND_SOC_SOF_IMX_COMMON) += imx-common.o diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 7e08b239aac0..4be4c569b583 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -8,6 +8,7 @@ #include +#include #include #include @@ -29,6 +30,16 @@ #define AudioDSP_REG2_RUNSTALL BIT(5) +/* imx8ulp macros */ +#define FSL_SIP_HIFI_XRDC 0xc200000e +#define SYSCTRL0 0x8 +#define EXECUTE_BIT BIT(13) +#define RESET_BIT BIT(16) +#define HIFI4_CLK_BIT BIT(17) +#define PB_CLK_BIT BIT(18) +#define PLAT_CLK_BIT BIT(19) +#define DEBUG_LOGIC_BIT BIT(25) + struct imx8m_chip_data { void __iomem *dap; struct regmap *regmap; @@ -173,6 +184,68 @@ static int imx8m_probe(struct snd_sof_dev *sdev) return 0; } +static int imx8ulp_run(struct snd_sof_dev *sdev) +{ + struct regmap *regmap = get_chip_pdata(sdev); + + /* Controls the HiFi4 DSP Reset: 1 in reset, 0 out of reset */ + regmap_update_bits(regmap, SYSCTRL0, RESET_BIT, 0); + + /* Reset HiFi4 DSP Debug logic: 1 debug reset, 0 out of reset*/ + regmap_update_bits(regmap, SYSCTRL0, DEBUG_LOGIC_BIT, 0); + + /* Stall HIFI4 DSP Execution: 1 stall, 0 run */ + regmap_update_bits(regmap, SYSCTRL0, EXECUTE_BIT, 0); + + return 0; +} + +static int imx8ulp_reset(struct snd_sof_dev *sdev) +{ + struct arm_smccc_res smc_res; + struct regmap *regmap; + + regmap = get_chip_pdata(sdev); + + /* HiFi4 Platform Clock Enable: 1 enabled, 0 disabled */ + regmap_update_bits(regmap, SYSCTRL0, PLAT_CLK_BIT, PLAT_CLK_BIT); + + /* HiFi4 PBCLK clock enable: 1 enabled, 0 disabled */ + regmap_update_bits(regmap, SYSCTRL0, PB_CLK_BIT, PB_CLK_BIT); + + /* HiFi4 Clock Enable: 1 enabled, 0 disabled */ + regmap_update_bits(regmap, SYSCTRL0, HIFI4_CLK_BIT, HIFI4_CLK_BIT); + + regmap_update_bits(regmap, SYSCTRL0, RESET_BIT, RESET_BIT); + + usleep_range(1, 2); + + /* Stall HIFI4 DSP Execution: 1 stall, 0 not stall */ + regmap_update_bits(regmap, SYSCTRL0, EXECUTE_BIT, EXECUTE_BIT); + usleep_range(1, 2); + + arm_smccc_smc(FSL_SIP_HIFI_XRDC, 0, 0, 0, 0, 0, 0, 0, &smc_res); + + return smc_res.a0; +} + +static int imx8ulp_probe(struct snd_sof_dev *sdev) +{ + struct imx_common_data *common; + struct regmap *regmap; + + common = sdev->pdata->hw_pdata; + + regmap = syscon_regmap_lookup_by_phandle(sdev->dev->of_node, "fsl,dsp-ctrl"); + if (IS_ERR(regmap)) + return dev_err_probe(sdev->dev, PTR_ERR(regmap), + "failed to fetch dsp ctrl regmap\n"); + + common->chip_pdata = regmap; + + return 0; +} + static struct snd_soc_dai_driver imx8_dai[] = { IMX_SOF_DAI_DRV_ENTRY_BIDIR("esai0", 1, 8), IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai1", 1, 32), @@ -188,6 +261,11 @@ static struct snd_soc_dai_driver imx8m_dai[] = { IMX_SOF_DAI_DRV_ENTRY("micfil", 0, 0, 1, 8), }; +static struct snd_soc_dai_driver imx8ulp_dai[] = { + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai5", 1, 32), + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai6", 1, 32), +}; + static struct snd_sof_dsp_ops sof_imx8_ops; static int imx8_ops_init(struct snd_sof_dev *sdev) @@ -224,6 +302,12 @@ static const struct imx_chip_ops imx8m_chip_ops = { .core_reset = imx8m_reset, }; +static const struct imx_chip_ops imx8ulp_chip_ops = { + .probe = imx8ulp_probe, + .core_kick = imx8ulp_run, + .core_reset = imx8ulp_reset, +}; + static struct imx_memory_info imx8_memory_regions[] = { { .name = "iram", .reserved = false }, { .name = "sram", .reserved = true }, @@ -236,6 +320,12 @@ static struct imx_memory_info imx8m_memory_regions[] = { { } }; +static struct imx_memory_info imx8ulp_memory_regions[] = { + { .name = "iram", .reserved = false }, + { .name = "sram", .reserved = true }, + { } +}; + static const struct imx_chip_info imx8_chip_info = { .ipc_info = { .has_panic_code = true, @@ -272,6 +362,19 @@ static const struct imx_chip_info imx8m_chip_info = { .ops = &imx8m_chip_ops, }; +static const struct imx_chip_info imx8ulp_chip_info = { + .ipc_info = { + .has_panic_code = true, + .boot_mbox_offset = 0x800000, + .window_offset = 0x800000, + }, + .has_dma_reserved = true, + .memory = imx8ulp_memory_regions, + .drv = imx8ulp_dai, + .num_drv = ARRAY_SIZE(imx8ulp_dai), + .ops = &imx8ulp_chip_ops, +}; + static struct snd_sof_of_mach sof_imx8_machs[] = { { .compatible = "fsl,imx8qxp-mek", @@ -313,12 +416,18 @@ static struct snd_sof_of_mach sof_imx8_machs[] = { .sof_tplg_filename = "sof-imx8mp-wm8962.tplg", .drv_name = "asoc-audio-graph-card2", }, + { + .compatible = "fsl,imx8ulp-evk", + .sof_tplg_filename = "sof-imx8ulp-btsco.tplg", + .drv_name = "asoc-audio-graph-card2", + }, {} }; IMX_SOF_DEV_DESC(imx8, sof_imx8_machs, &imx8_chip_info, &sof_imx8_ops, imx8_ops_init); IMX_SOF_DEV_DESC(imx8x, sof_imx8_machs, &imx8x_chip_info, &sof_imx8_ops, imx8_ops_init); IMX_SOF_DEV_DESC(imx8m, sof_imx8_machs, &imx8m_chip_info, &sof_imx8_ops, imx8_ops_init); +IMX_SOF_DEV_DESC(imx8ulp, sof_imx8_machs, &imx8ulp_chip_info, &sof_imx8_ops, imx8_ops_init); static const struct of_device_id sof_of_imx8_ids[] = { { @@ -333,6 +442,10 @@ static const struct of_device_id sof_of_imx8_ids[] = { .compatible = "fsl,imx8mp-dsp", .data = &IMX_SOF_DEV_DESC_NAME(imx8m), }, + { + .compatible = "fsl,imx8ulp-dsp", + .data = &IMX_SOF_DEV_DESC_NAME(imx8ulp), + }, { } }; MODULE_DEVICE_TABLE(of, sof_of_imx8_ids); diff --git a/sound/soc/sof/imx/imx8ulp.c b/sound/soc/sof/imx/imx8ulp.c deleted file mode 100644 index 0704da27e69d..000000000000 --- a/sound/soc/sof/imx/imx8ulp.c +++ /dev/null @@ -1,520 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -// -// Copyright 2021-2022 NXP -// -// Author: Peng Zhang -// -// Hardware interface for audio DSP on i.MX8ULP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "../ops.h" -#include "../sof-of-dev.h" -#include "imx-common.h" - -#define FSL_SIP_HIFI_XRDC 0xc200000e - -/* SIM Domain register */ -#define SYSCTRL0 0x8 -#define EXECUTE_BIT BIT(13) -#define RESET_BIT BIT(16) -#define HIFI4_CLK_BIT BIT(17) -#define PB_CLK_BIT BIT(18) -#define PLAT_CLK_BIT BIT(19) -#define DEBUG_LOGIC_BIT BIT(25) - -#define MBOX_OFFSET 0x800000 -#define MBOX_SIZE 0x1000 - -struct imx8ulp_priv { - struct device *dev; - struct snd_sof_dev *sdev; - - /* DSP IPC handler */ - struct imx_dsp_ipc *dsp_ipc; - struct platform_device *ipc_dev; - - struct regmap *regmap; - struct clk_bulk_data *clks; - int clk_num; -}; - -static void imx8ulp_sim_lpav_start(struct imx8ulp_priv *priv) -{ - /* Controls the HiFi4 DSP Reset: 1 in reset, 0 out of reset */ - regmap_update_bits(priv->regmap, SYSCTRL0, RESET_BIT, 0); - - /* Reset HiFi4 DSP Debug logic: 1 debug reset, 0 out of reset*/ - regmap_update_bits(priv->regmap, SYSCTRL0, DEBUG_LOGIC_BIT, 0); - - /* Stall HIFI4 DSP Execution: 1 stall, 0 run */ - regmap_update_bits(priv->regmap, SYSCTRL0, EXECUTE_BIT, 0); -} - -static int imx8ulp_get_mailbox_offset(struct snd_sof_dev *sdev) -{ - return MBOX_OFFSET; -} - -static int imx8ulp_get_window_offset(struct snd_sof_dev *sdev, u32 id) -{ - return MBOX_OFFSET; -} - -static void imx8ulp_dsp_handle_reply(struct imx_dsp_ipc *ipc) -{ - struct imx8ulp_priv *priv = imx_dsp_get_data(ipc); - unsigned long flags; - - spin_lock_irqsave(&priv->sdev->ipc_lock, flags); - - snd_sof_ipc_process_reply(priv->sdev, 0); - - spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); -} - -static void imx8ulp_dsp_handle_request(struct imx_dsp_ipc *ipc) -{ - struct imx8ulp_priv *priv = imx_dsp_get_data(ipc); - u32 p; /* panic code */ - - /* Read the message from the debug box. */ - sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, &p, sizeof(p)); - - /* Check to see if the message is a panic code (0x0dead***) */ - if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) - snd_sof_dsp_panic(priv->sdev, p, true); - else - snd_sof_ipc_msgs_rx(priv->sdev); -} - -static struct imx_dsp_ops dsp_ops = { - .handle_reply = imx8ulp_dsp_handle_reply, - .handle_request = imx8ulp_dsp_handle_request, -}; - -static int imx8ulp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) -{ - struct imx8ulp_priv *priv = sdev->pdata->hw_pdata; - - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - imx_dsp_ring_doorbell(priv->dsp_ipc, 0); - - return 0; -} - -static int imx8ulp_run(struct snd_sof_dev *sdev) -{ - struct imx8ulp_priv *priv = sdev->pdata->hw_pdata; - - imx8ulp_sim_lpav_start(priv); - - return 0; -} - -static int imx8ulp_reset(struct snd_sof_dev *sdev) -{ - struct imx8ulp_priv *priv = sdev->pdata->hw_pdata; - struct arm_smccc_res smc_resource; - - /* HiFi4 Platform Clock Enable: 1 enabled, 0 disabled */ - regmap_update_bits(priv->regmap, SYSCTRL0, PLAT_CLK_BIT, PLAT_CLK_BIT); - - /* HiFi4 PBCLK clock enable: 1 enabled, 0 disabled */ - regmap_update_bits(priv->regmap, SYSCTRL0, PB_CLK_BIT, PB_CLK_BIT); - - /* HiFi4 Clock Enable: 1 enabled, 0 disabled */ - regmap_update_bits(priv->regmap, SYSCTRL0, HIFI4_CLK_BIT, HIFI4_CLK_BIT); - - regmap_update_bits(priv->regmap, SYSCTRL0, RESET_BIT, RESET_BIT); - usleep_range(1, 2); - - /* Stall HIFI4 DSP Execution: 1 stall, 0 not stall */ - regmap_update_bits(priv->regmap, SYSCTRL0, EXECUTE_BIT, EXECUTE_BIT); - usleep_range(1, 2); - - arm_smccc_smc(FSL_SIP_HIFI_XRDC, 0, 0, 0, 0, 0, 0, 0, &smc_resource); - - return 0; -} - -static int imx8ulp_probe(struct snd_sof_dev *sdev) -{ - struct platform_device *pdev = to_platform_device(sdev->dev); - struct device_node *np = pdev->dev.of_node; - struct device_node *res_node; - struct resource *mmio; - struct imx8ulp_priv *priv; - struct resource res; - u32 base, size; - int ret = 0; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - sdev->num_cores = 1; - sdev->pdata->hw_pdata = priv; - priv->dev = sdev->dev; - priv->sdev = sdev; - - /* System integration module(SIM) control dsp configuration */ - priv->regmap = syscon_regmap_lookup_by_phandle(np, "fsl,dsp-ctrl"); - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - - priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", - PLATFORM_DEVID_NONE, - pdev, sizeof(*pdev)); - if (IS_ERR(priv->ipc_dev)) - return PTR_ERR(priv->ipc_dev); - - priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev); - if (!priv->dsp_ipc) { - /* DSP IPC driver not probed yet, try later */ - ret = -EPROBE_DEFER; - dev_err(sdev->dev, "Failed to get drvdata\n"); - goto exit_pdev_unregister; - } - - imx_dsp_set_data(priv->dsp_ipc, priv); - priv->dsp_ipc->ops = &dsp_ops; - - /* DSP base */ - mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mmio) { - base = mmio->start; - size = resource_size(mmio); - } else { - dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n"); - ret = -EINVAL; - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size); - if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) { - dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n", - base, size); - ret = -ENODEV; - goto exit_pdev_unregister; - } - sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM; - - res_node = of_parse_phandle(np, "memory-reserved", 0); - if (!res_node) { - dev_err(&pdev->dev, "failed to get memory region node\n"); - ret = -ENODEV; - goto exit_pdev_unregister; - } - - ret = of_address_to_resource(res_node, 0, &res); - of_node_put(res_node); - if (ret) { - dev_err(&pdev->dev, "failed to get reserved region address\n"); - goto exit_pdev_unregister; - } - - sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start, - resource_size(&res)); - if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { - dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n", - base, size); - ret = -ENOMEM; - goto exit_pdev_unregister; - } - sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; - - /* set default mailbox offset for FW ready message */ - sdev->dsp_box.offset = MBOX_OFFSET; - - ret = of_reserved_mem_device_init(sdev->dev); - if (ret) { - dev_err(&pdev->dev, "failed to init reserved memory region %d\n", ret); - goto exit_pdev_unregister; - } - - ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); - goto exit_pdev_unregister; - } - priv->clk_num = ret; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - goto exit_pdev_unregister; - } - - return 0; - -exit_pdev_unregister: - platform_device_unregister(priv->ipc_dev); - - return ret; -} - -static void imx8ulp_remove(struct snd_sof_dev *sdev) -{ - struct imx8ulp_priv *priv = sdev->pdata->hw_pdata; - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); - platform_device_unregister(priv->ipc_dev); -} - -/* on i.MX8 there is 1 to 1 match between type and BAR idx */ -static int imx8ulp_get_bar_index(struct snd_sof_dev *sdev, u32 type) -{ - return type; -} - -static int imx8ulp_suspend(struct snd_sof_dev *sdev) -{ - int i; - struct imx8ulp_priv *priv = (struct imx8ulp_priv *)sdev->pdata->hw_pdata; - - /*Stall DSP, release in .run() */ - regmap_update_bits(priv->regmap, SYSCTRL0, EXECUTE_BIT, EXECUTE_BIT); - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_free_channel(priv->dsp_ipc, i); - - clk_bulk_disable_unprepare(priv->clk_num, priv->clks); - - return 0; -} - -static int imx8ulp_resume(struct snd_sof_dev *sdev) -{ - struct imx8ulp_priv *priv = (struct imx8ulp_priv *)sdev->pdata->hw_pdata; - int i, ret; - - ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); - if (ret < 0) { - dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); - return ret; - } - - for (i = 0; i < DSP_MU_CHAN_NUM; i++) - imx_dsp_request_channel(priv->dsp_ipc, i); - - return 0; -} - -static int imx8ulp_dsp_runtime_resume(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - .substate = 0, - }; - - imx8ulp_resume(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8ulp_dsp_runtime_suspend(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D3, - .substate = 0, - }; - - imx8ulp_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8ulp_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = target_state, - .substate = 0, - }; - - if (!pm_runtime_suspended(sdev->dev)) - imx8ulp_suspend(sdev); - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static int imx8ulp_dsp_resume(struct snd_sof_dev *sdev) -{ - const struct sof_dsp_power_state target_dsp_state = { - .state = SOF_DSP_PM_D0, - .substate = 0, - }; - - imx8ulp_resume(sdev); - - if (pm_runtime_suspended(sdev->dev)) { - pm_runtime_disable(sdev->dev); - pm_runtime_set_active(sdev->dev); - pm_runtime_mark_last_busy(sdev->dev); - pm_runtime_enable(sdev->dev); - pm_runtime_idle(sdev->dev); - } - - return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); -} - -static struct snd_soc_dai_driver imx8ulp_dai[] = { - { - .name = "sai5", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, - }, - { - .name = "sai6", - .playback = { - .channels_min = 1, - .channels_max = 32, - }, - .capture = { - .channels_min = 1, - .channels_max = 32, - }, - }, -}; - -static int imx8ulp_dsp_set_power_state(struct snd_sof_dev *sdev, - const struct sof_dsp_power_state *target_state) -{ - sdev->dsp_power_state = *target_state; - - return 0; -} - -/* i.MX8 ops */ -static const struct snd_sof_dsp_ops sof_imx8ulp_ops = { - /* probe and remove */ - .probe = imx8ulp_probe, - .remove = imx8ulp_remove, - /* DSP core boot */ - .run = imx8ulp_run, - .reset = imx8ulp_reset, - - /* Block IO */ - .block_read = sof_block_read, - .block_write = sof_block_write, - - /* Module IO */ - .read64 = sof_io_read64, - - /* Mailbox IO */ - .mailbox_read = sof_mailbox_read, - .mailbox_write = sof_mailbox_write, - - /* ipc */ - .send_msg = imx8ulp_send_msg, - .get_mailbox_offset = imx8ulp_get_mailbox_offset, - .get_window_offset = imx8ulp_get_window_offset, - - .ipc_msg_data = sof_ipc_msg_data, - .set_stream_data_offset = sof_set_stream_data_offset, - - /* stream callbacks */ - .pcm_open = sof_stream_pcm_open, - .pcm_close = sof_stream_pcm_close, - - /* module loading */ - .get_bar_index = imx8ulp_get_bar_index, - /* firmware loading */ - .load_firmware = snd_sof_load_firmware_memcpy, - - /* Debug information */ - .dbg_dump = imx8_dump, - - /* Firmware ops */ - .dsp_arch_ops = &sof_xtensa_arch_ops, - - /* DAI drivers */ - .drv = imx8ulp_dai, - .num_drv = ARRAY_SIZE(imx8ulp_dai), - - /* ALSA HW info flags */ - .hw_info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - - /* PM */ - .runtime_suspend = imx8ulp_dsp_runtime_suspend, - .runtime_resume = imx8ulp_dsp_runtime_resume, - - .suspend = imx8ulp_dsp_suspend, - .resume = imx8ulp_dsp_resume, - - .set_power_state = imx8ulp_dsp_set_power_state, -}; - -static struct snd_sof_of_mach sof_imx8ulp_machs[] = { - { - .compatible = "fsl,imx8ulp-evk", - .sof_tplg_filename = "sof-imx8ulp-btsco.tplg", - .drv_name = "asoc-audio-graph-card2", - }, - {} -}; - -static struct sof_dev_desc sof_of_imx8ulp_desc = { - .of_machines = sof_imx8ulp_machs, - .ipc_supported_mask = BIT(SOF_IPC_TYPE_3), - .ipc_default = SOF_IPC_TYPE_3, - .default_fw_path = { - [SOF_IPC_TYPE_3] = "imx/sof", - }, - .default_tplg_path = { - [SOF_IPC_TYPE_3] = "imx/sof-tplg", - }, - .default_fw_filename = { - [SOF_IPC_TYPE_3] = "sof-imx8ulp.ri", - }, - .nocodec_tplg_filename = "sof-imx8ulp-nocodec.tplg", - .ops = &sof_imx8ulp_ops, -}; - -static const struct of_device_id sof_of_imx8ulp_ids[] = { - { .compatible = "fsl,imx8ulp-dsp", .data = &sof_of_imx8ulp_desc}, - { } -}; -MODULE_DEVICE_TABLE(of, sof_of_imx8ulp_ids); - -/* DT driver definition */ -static struct platform_driver snd_sof_of_imx8ulp_driver = { - .probe = sof_of_probe, - .remove = sof_of_remove, - .driver = { - .name = "sof-audio-of-imx8ulp", - .pm = &sof_of_pm, - .of_match_table = sof_of_imx8ulp_ids, - }, -}; -module_platform_driver(snd_sof_of_imx8ulp_driver); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("SOF support for IMX8ULP platforms"); -MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); From 6cf5df1040ba0694aea6a5edc6f31811a442ea36 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:22:46 -0500 Subject: [PATCH 0100/1090] ASoC: SOF: imx: add driver for the imx95 chip Add SOF support for the imx95 chip. Although the support is just for the imx95 chip, the driver is intended for all chips in the imx9 family. Note that the imx95 support could have just as easily been added to the imx8 platform driver but a new platform driver was created because the intention is to keep the families in separate drivers. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Link: https://patch.msgid.link/20250207162246.3104-8-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/Kconfig | 9 +++ sound/soc/sof/imx/Makefile | 2 + sound/soc/sof/imx/imx9.c | 137 +++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 sound/soc/sof/imx/imx9.c diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig index 2edf9de2c886..327e2df94a58 100644 --- a/sound/soc/sof/imx/Kconfig +++ b/sound/soc/sof/imx/Kconfig @@ -32,4 +32,13 @@ config SND_SOC_SOF_IMX8 Say Y if you have such a device. If unsure select "N". +config SND_SOC_SOF_IMX9 + tristate "SOF support for i.MX9" + depends on IMX_DSP + select SND_SOC_SOF_IMX_COMMON + help + This adds support for Sound Open Firmware for NXP i.MX9 platforms. + Say Y if you need such a device. + If unsure select "N". + endif ## SND_SOC_SOF_IMX_TOPLEVEL diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index 36a3a67c6efb..74b5ecad8fe8 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,7 +1,9 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) snd-sof-imx8-y := imx8.o +snd-sof-imx9-y := imx9.o snd-sof-imx-common-y := imx-common.o obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o +obj-$(CONFIG_SND_SOC_SOF_IMX9) += snd-sof-imx9.o obj-$(CONFIG_SND_SOC_SOF_IMX_COMMON) += imx-common.o diff --git a/sound/soc/sof/imx/imx9.c b/sound/soc/sof/imx/imx9.c new file mode 100644 index 000000000000..598675d4350a --- /dev/null +++ b/sound/soc/sof/imx/imx9.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +/* + * Copyright 2025 NXP + */ + +#include + +#include "imx-common.h" + +#define IMX_SIP_SRC 0xC2000005 +#define IMX_SIP_SRC_M_RESET_ADDR_SET 0x03 + +#define IMX95_CPU_VEC_FLAGS_BOOT BIT(29) + +#define IMX_SIP_LMM 0xC200000F +#define IMX_SIP_LMM_BOOT 0x0 +#define IMX_SIP_LMM_SHUTDOWN 0x1 + +#define IMX95_M7_LM_ID 0x1 + +static struct snd_soc_dai_driver imx95_dai[] = { + IMX_SOF_DAI_DRV_ENTRY_BIDIR("sai3", 1, 32), +}; + +static struct snd_sof_dsp_ops sof_imx9_ops; + +static int imx95_ops_init(struct snd_sof_dev *sdev) +{ + /* first copy from template */ + memcpy(&sof_imx9_ops, &sof_imx_ops, sizeof(sof_imx_ops)); + + /* ... and finally set DAI driver */ + sof_imx9_ops.drv = get_chip_info(sdev)->drv; + sof_imx9_ops.num_drv = get_chip_info(sdev)->num_drv; + + return 0; +} + +static int imx95_chip_probe(struct snd_sof_dev *sdev) +{ + struct arm_smccc_res smc_res; + struct platform_device *pdev; + struct resource *res; + + pdev = to_platform_device(sdev->dev); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram"); + if (!res) + return dev_err_probe(sdev->dev, -ENODEV, + "failed to fetch SRAM region\n"); + + /* set core boot reset address */ + arm_smccc_smc(IMX_SIP_SRC, IMX_SIP_SRC_M_RESET_ADDR_SET, res->start, + IMX95_CPU_VEC_FLAGS_BOOT, 0, 0, 0, 0, &smc_res); + + return smc_res.a0; +} + +static int imx95_core_kick(struct snd_sof_dev *sdev) +{ + struct arm_smccc_res smc_res; + + arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_BOOT, + IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); + + return smc_res.a0; +} + +static int imx95_core_shutdown(struct snd_sof_dev *sdev) +{ + struct arm_smccc_res smc_res; + + arm_smccc_smc(IMX_SIP_LMM, IMX_SIP_LMM_SHUTDOWN, + IMX95_M7_LM_ID, 0, 0, 0, 0, 0, &smc_res); + + return smc_res.a0; +} + +static const struct imx_chip_ops imx95_chip_ops = { + .probe = imx95_chip_probe, + .core_kick = imx95_core_kick, + .core_shutdown = imx95_core_shutdown, +}; + +static struct imx_memory_info imx95_memory_regions[] = { + { .name = "sram", .reserved = false }, + { } +}; + +static const struct imx_chip_info imx95_chip_info = { + .ipc_info = { + .boot_mbox_offset = 0x6001000, + .window_offset = 0x6000000, + }, + .has_dma_reserved = true, + .memory = imx95_memory_regions, + .drv = imx95_dai, + .num_drv = ARRAY_SIZE(imx95_dai), + .ops = &imx95_chip_ops, +}; + +static struct snd_sof_of_mach sof_imx9_machs[] = { + { + .compatible = "fsl,imx95-19x19-evk", + .sof_tplg_filename = "sof-imx95-wm8962.tplg", + .drv_name = "asoc-audio-graph-card2", + }, + { + } +}; + +IMX_SOF_DEV_DESC(imx95, sof_imx9_machs, &imx95_chip_info, &sof_imx9_ops, imx95_ops_init); + +static const struct of_device_id sof_of_imx9_ids[] = { + { + .compatible = "fsl,imx95-cm7-sof", + .data = &IMX_SOF_DEV_DESC_NAME(imx95), + }, + { + }, +}; +MODULE_DEVICE_TABLE(of, sof_of_imx9_ids); + +static struct platform_driver snd_sof_of_imx9_driver = { + .probe = sof_of_probe, + .remove = sof_of_remove, + .driver = { + .name = "sof-audio-of-imx9", + .pm = &sof_of_pm, + .of_match_table = sof_of_imx9_ids, + }, +}; +module_platform_driver(snd_sof_of_imx9_driver); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("SOF driver for imx9 platforms"); +MODULE_AUTHOR("Laurentiu Mihalcea "); From 629dd55cf77bd3a8f80049150d3c05fef6d3b468 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:52 +0000 Subject: [PATCH 0101/1090] ASoC: SDCA: Minor formatting and naming tweaks Fix up some variable/struct member naming, add some missing kerneldoc and fix some minor formatting/whitespace issues. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca.h | 20 +++++------ include/sound/sdca_function.h | 64 +++++++++++++++++++++------------ sound/soc/sdca/sdca_device.c | 3 +- sound/soc/sdca/sdca_functions.c | 26 ++++++++++---- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/include/sound/sdca.h b/include/sound/sdca.h index 973252d0adac..31b39f2297b9 100644 --- a/include/sound/sdca.h +++ b/include/sound/sdca.h @@ -17,10 +17,10 @@ struct sdw_slave; #define SDCA_MAX_FUNCTION_COUNT 8 /** - * sdca_device_desc - short descriptor for an SDCA Function - * @adr: ACPI address (used for SDCA register access) - * @type: Function topology type - * @name: human-readable string + * struct sdca_function_desc - short descriptor for an SDCA Function + * @name: Human-readable string. + * @type: Function topology type. + * @adr: ACPI address (used for SDCA register access). */ struct sdca_function_desc { const char *name; @@ -29,17 +29,17 @@ struct sdca_function_desc { }; /** - * sdca_device_data - structure containing all SDCA related information - * @sdca_interface_revision: value read from _DSD property, mainly to check - * for changes between silicon versions - * @num_functions: total number of supported SDCA functions. Invalid/unsupported + * struct sdca_device_data - structure containing all SDCA related information + * @interface_revision: Value read from _DSD property, mainly to check + * for changes between silicon versions. + * @num_functions: Total number of supported SDCA functions. Invalid/unsupported * functions will be skipped. - * @sdca_func: array of function descriptors + * @function: Array of function descriptors. */ struct sdca_device_data { u32 interface_revision; int num_functions; - struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT]; + struct sdca_function_desc function[SDCA_MAX_FUNCTION_COUNT]; }; enum sdca_quirk { diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index c051c17903e8..1d1d3a1da52d 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -11,39 +11,57 @@ #include -/* +/** + * enum sdca_function_type - SDCA Function Type codes + * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. + * @SDCA_FUNCTION_TYPE_SIMPLE_AMP: Subset of SmartAmp. + * @SDCA_FUNCTION_TYPE_SMART_MIC: Smart microphone with acoustic triggers. + * @SDCA_FUNCTION_TYPE_SIMPLE_MIC: Subset of SmartMic. + * @SDCA_FUNCTION_TYPE_SPEAKER_MIC: Combination of SmartMic and SmartAmp. + * @SDCA_FUNCTION_TYPE_UAJ: 3.5mm Universal Audio jack. + * @SDCA_FUNCTION_TYPE_RJ: Retaskable jack. + * @SDCA_FUNCTION_TYPE_SIMPLE_JACK: Subset of UAJ. + * @SDCA_FUNCTION_TYPE_HID: Human Interface Device, for e.g. buttons. + * @SDCA_FUNCTION_TYPE_IMP_DEF: Implementation-defined function. + * * SDCA Function Types from SDCA specification v1.0a Section 5.1.2 - * all Function types not described are reserved + * all Function types not described are reserved. + * * Note that SIMPLE_AMP, SIMPLE_MIC and SIMPLE_JACK Function Types * are NOT defined in SDCA 1.0a, but they were defined in earlier * drafts and are planned for 1.1. */ - enum sdca_function_type { - SDCA_FUNCTION_TYPE_SMART_AMP = 0x01, /* Amplifier with protection features */ - SDCA_FUNCTION_TYPE_SIMPLE_AMP = 0x02, /* subset of SmartAmp */ - SDCA_FUNCTION_TYPE_SMART_MIC = 0x03, /* Smart microphone with acoustic triggers */ - SDCA_FUNCTION_TYPE_SIMPLE_MIC = 0x04, /* subset of SmartMic */ - SDCA_FUNCTION_TYPE_SPEAKER_MIC = 0x05, /* Combination of SmartMic and SmartAmp */ - SDCA_FUNCTION_TYPE_UAJ = 0x06, /* 3.5mm Universal Audio jack */ - SDCA_FUNCTION_TYPE_RJ = 0x07, /* Retaskable jack */ - SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08, /* Subset of UAJ */ - SDCA_FUNCTION_TYPE_HID = 0x0A, /* Human Interface Device, for e.g. buttons */ - SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F, /* Implementation-defined function */ + SDCA_FUNCTION_TYPE_SMART_AMP = 0x01, + SDCA_FUNCTION_TYPE_SIMPLE_AMP = 0x02, + SDCA_FUNCTION_TYPE_SMART_MIC = 0x03, + SDCA_FUNCTION_TYPE_SIMPLE_MIC = 0x04, + SDCA_FUNCTION_TYPE_SPEAKER_MIC = 0x05, + SDCA_FUNCTION_TYPE_UAJ = 0x06, + SDCA_FUNCTION_TYPE_RJ = 0x07, + SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08, + SDCA_FUNCTION_TYPE_HID = 0x0A, + SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F, }; /* Human-readable names used for kernel logs and Function device registration/bind */ -#define SDCA_FUNCTION_TYPE_SMART_AMP_NAME "SmartAmp" -#define SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME "SimpleAmp" -#define SDCA_FUNCTION_TYPE_SMART_MIC_NAME "SmartMic" -#define SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME "SimpleMic" -#define SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME "SpeakerMic" -#define SDCA_FUNCTION_TYPE_UAJ_NAME "UAJ" -#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ" -#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack" -#define SDCA_FUNCTION_TYPE_HID_NAME "HID" -#define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined" +#define SDCA_FUNCTION_TYPE_SMART_AMP_NAME "SmartAmp" +#define SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME "SimpleAmp" +#define SDCA_FUNCTION_TYPE_SMART_MIC_NAME "SmartMic" +#define SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME "SimpleMic" +#define SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME "SpeakerMic" +#define SDCA_FUNCTION_TYPE_UAJ_NAME "UAJ" +#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ" +#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack" +#define SDCA_FUNCTION_TYPE_HID_NAME "HID" +#define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined" +/** + * enum sdca_entity0_controls - SDCA Controls for Entity 0 + * + * Control Selectors for Entity 0 from SDCA specification v1.0 Section + * 6.7.1.1. + */ enum sdca_entity0_controls { SDCA_CTL_ENTITY_0_COMMIT_GROUP_MASK = 0x01, SDCA_CTL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04, diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c index b6399b773986..0244cdcdd109 100644 --- a/sound/soc/sdca/sdca_device.c +++ b/sound/soc/sdca/sdca_device.c @@ -48,8 +48,7 @@ static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave) return false; for (i = 0; i < slave->sdca_data.num_functions; i++) { - if (slave->sdca_data.sdca_func[i].type == - SDCA_FUNCTION_TYPE_SMART_MIC) + if (slave->sdca_data.function[i].type == SDCA_FUNCTION_TYPE_SMART_MIC) return true; } diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 38071bc838b9..00d6d044c816 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -21,7 +22,7 @@ static int patch_sdca_function_type(u32 interface_revision, u32 *function_type) { /* * Unfortunately early SDCA specifications used different indices for Functions, - * for backwards compatibility we have to reorder the values found + * for backwards compatibility we have to reorder the values found. */ if (interface_revision < 0x0801) { switch (*function_type) { @@ -85,7 +86,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data) struct fwnode_handle *control5; /* used to identify function type */ const char *function_name; u32 function_type; - int func_index; + int function_index; u64 addr; int ret; @@ -145,24 +146,35 @@ static int find_sdca_function(struct acpi_device *adev, void *data) function_name, function_type, addr); /* store results */ - func_index = sdca_data->num_functions; - sdca_data->sdca_func[func_index].adr = addr; - sdca_data->sdca_func[func_index].type = function_type; - sdca_data->sdca_func[func_index].name = function_name; + function_index = sdca_data->num_functions; + sdca_data->function[function_index].adr = addr; + sdca_data->function[function_index].type = function_type; + sdca_data->function[function_index].name = function_name; sdca_data->num_functions++; return 0; } +/** + * sdca_lookup_functions - Parse sdca_device_desc for each Function + * @slave: SoundWire slave device to be processed. + * + * Iterate through the available SDCA Functions and fill in a short + * descriptor (struct sdca_function_desc) for each function, this + * information is stored along with the SoundWire slave device and + * used for adding drivers and quirks before the devices have fully + * probed. + */ void sdca_lookup_functions(struct sdw_slave *slave) { struct device *dev = &slave->dev; struct acpi_device *adev = to_acpi_device_node(dev->fwnode); if (!adev) { - dev_info(dev, "No matching ACPI device found, ignoring peripheral\n"); + dev_info(dev, "no matching ACPI device found, ignoring peripheral\n"); return; } + acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data); } EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA"); From 996bf834d0b61cb5a1389356c1ed7db1230139d7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 5 Feb 2025 11:37:53 +0000 Subject: [PATCH 0102/1090] ASoC: SDCA: Add code to parse Function information Add a helper function to parse all the Function and Entity information from ACPI. In SDCA each device may have several Functions and each corresponds to a specific audio capability such as say amplifier playback or microphone capture. Each Function then contains a number of Entities that represent individual parts of the audio signal chain and are linked together in a graph similar to DAPM. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca.h | 2 + include/sound/sdca_function.h | 95 +++++++++++ sound/soc/sdca/sdca_functions.c | 268 ++++++++++++++++++++++++++++++++ 3 files changed, 365 insertions(+) diff --git a/include/sound/sdca.h b/include/sound/sdca.h index 31b39f2297b9..5a5d6de78d72 100644 --- a/include/sound/sdca.h +++ b/include/sound/sdca.h @@ -18,11 +18,13 @@ struct sdw_slave; /** * struct sdca_function_desc - short descriptor for an SDCA Function + * @node: firmware node for the Function. * @name: Human-readable string. * @type: Function topology type. * @adr: ACPI address (used for SDCA register access). */ struct sdca_function_desc { + struct fwnode_handle *node; const char *name; u32 type; u8 adr; diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 1d1d3a1da52d..3f4031d285d6 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -11,6 +11,15 @@ #include +struct device; +struct sdca_function_desc; + +/* + * The addressing space for SDCA relies on 7 bits for Entities, so a + * maximum of 128 Entities per function can be represented. + */ +#define SDCA_MAX_ENTITY_COUNT 128 + /** * enum sdca_function_type - SDCA Function Type codes * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. @@ -90,4 +99,90 @@ enum sdca_entity0_controls { SDCA_CTL_ENTITY_0_FUNCTION_BUSY = BIT(7), }; +/** + * enum sdca_entity_type - SDCA Entity Type codes + * @SDCA_ENTITY_TYPE_IT: Input Terminal. + * @SDCA_ENTITY_TYPE_OT: Output Terminal. + * @SDCA_ENTITY_TYPE_MU: Mixer Unit. + * @SDCA_ENTITY_TYPE_SU: Selector Unit. + * @SDCA_ENTITY_TYPE_FU: Feature Unit. + * @SDCA_ENTITY_TYPE_XU: Extension Unit. + * @SDCA_ENTITY_TYPE_CS: Clock Source. + * @SDCA_ENTITY_TYPE_CX: Clock selector. + * @SDCA_ENTITY_TYPE_PDE: Power-Domain Entity. + * @SDCA_ENTITY_TYPE_GE: Group Entity. + * @SDCA_ENTITY_TYPE_SPE: Security & Privacy Entity. + * @SDCA_ENTITY_TYPE_CRU: Channel Remapping Unit. + * @SDCA_ENTITY_TYPE_UDMPU: Up-Down Mixer Processing Unit. + * @SDCA_ENTITY_TYPE_MFPU: Multi-Function Processing Unit. + * @SDCA_ENTITY_TYPE_SMPU: Smart Microphone Processing Unit. + * @SDCA_ENTITY_TYPE_SAPU: Smart Amp Processing Unit. + * @SDCA_ENTITY_TYPE_PPU: Posture Processing Unit. + * @SDCA_ENTITY_TYPE_TG: Tone Generator. + * @SDCA_ENTITY_TYPE_HIDE: Human Interface Device Entity. + * + * SDCA Entity Types from SDCA specification v1.0 Section 6.1.2 + * all Entity Types not described are reserved. + */ +enum sdca_entity_type { + SDCA_ENTITY_TYPE_IT = 0x02, + SDCA_ENTITY_TYPE_OT = 0x03, + SDCA_ENTITY_TYPE_MU = 0x05, + SDCA_ENTITY_TYPE_SU = 0x06, + SDCA_ENTITY_TYPE_FU = 0x07, + SDCA_ENTITY_TYPE_XU = 0x0A, + SDCA_ENTITY_TYPE_CS = 0x0B, + SDCA_ENTITY_TYPE_CX = 0x0C, + SDCA_ENTITY_TYPE_PDE = 0x11, + SDCA_ENTITY_TYPE_GE = 0x12, + SDCA_ENTITY_TYPE_SPE = 0x13, + SDCA_ENTITY_TYPE_CRU = 0x20, + SDCA_ENTITY_TYPE_UDMPU = 0x21, + SDCA_ENTITY_TYPE_MFPU = 0x22, + SDCA_ENTITY_TYPE_SMPU = 0x23, + SDCA_ENTITY_TYPE_SAPU = 0x24, + SDCA_ENTITY_TYPE_PPU = 0x25, + SDCA_ENTITY_TYPE_TG = 0x30, + SDCA_ENTITY_TYPE_HIDE = 0x31, +}; + +/** + * struct sdca_entity - information for one SDCA Entity + * @label: String such as "OT 12". + * @id: Identifier used for addressing. + * @type: Type code for the Entity. + * @sources: Dynamically allocated array pointing to each input Entity + * connected to this Entity. + * @num_sources: Number of sources for the Entity. + */ +struct sdca_entity { + const char *label; + int id; + enum sdca_entity_type type; + + struct sdca_entity **sources; + int num_sources; +}; + +/** + * struct sdca_function_data - top-level information for one SDCA function + * @desc: Pointer to short descriptor from initial parsing. + * @entities: Dynamically allocated array of Entities. + * @num_entities: Number of Entities reported in this Function. + * @busy_max_delay: Maximum Function busy delay in microseconds, before an + * error should be reported. + */ +struct sdca_function_data { + struct sdca_function_desc *desc; + + struct sdca_entity *entities; + int num_entities; + + unsigned int busy_max_delay; +}; + +int sdca_parse_function(struct device *dev, + struct sdca_function_desc *desc, + struct sdca_function_data *function); + #endif diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 00d6d044c816..72b82280918d 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -18,6 +18,11 @@ #include #include +/* + * Should be long enough to encompass all the MIPI DisCo properties. + */ +#define SDCA_PROPERTY_LENGTH 64 + static int patch_sdca_function_type(u32 interface_revision, u32 *function_type) { /* @@ -150,6 +155,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data) sdca_data->function[function_index].adr = addr; sdca_data->function[function_index].type = function_type; sdca_data->function[function_index].name = function_name; + sdca_data->function[function_index].node = function_node; sdca_data->num_functions++; return 0; @@ -179,5 +185,267 @@ void sdca_lookup_functions(struct sdw_slave *slave) } EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA"); +static int find_sdca_entity(struct device *dev, + struct fwnode_handle *function_node, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + u32 tmp; + int ret; + + ret = fwnode_property_read_string(entity_node, "mipi-sdca-entity-label", + &entity->label); + if (ret) { + dev_err(dev, "%pfwP: entity %#x: label missing: %d\n", + function_node, entity->id, ret); + return ret; + } + + ret = fwnode_property_read_u32(entity_node, "mipi-sdca-entity-type", &tmp); + if (ret) { + dev_err(dev, "%s: type missing: %d\n", entity->label, ret); + return ret; + } + + entity->type = tmp; + + dev_info(dev, "%s: entity %#x type %#x\n", + entity->label, entity->id, entity->type); + + return 0; +} + +static int find_sdca_entities(struct device *dev, + struct fwnode_handle *function_node, + struct sdca_function_data *function) +{ + struct sdca_entity *entities; + u32 *entity_list; + int num_entities; + int i, ret; + + num_entities = fwnode_property_count_u32(function_node, + "mipi-sdca-entity-id-list"); + if (num_entities <= 0) { + dev_err(dev, "%pfwP: entity id list missing: %d\n", + function_node, num_entities); + return -EINVAL; + } else if (num_entities > SDCA_MAX_ENTITY_COUNT) { + dev_err(dev, "%pfwP: maximum number of entities exceeded\n", + function_node); + return -EINVAL; + } + + entities = devm_kcalloc(dev, num_entities, sizeof(*entities), GFP_KERNEL); + if (!entities) + return -ENOMEM; + + entity_list = kcalloc(num_entities, sizeof(*entity_list), GFP_KERNEL); + if (!entity_list) + return -ENOMEM; + + fwnode_property_read_u32_array(function_node, "mipi-sdca-entity-id-list", + entity_list, num_entities); + + for (i = 0; i < num_entities; i++) + entities[i].id = entity_list[i]; + + kfree(entity_list); + + /* now read subproperties */ + for (i = 0; i < num_entities; i++) { + char entity_property[SDCA_PROPERTY_LENGTH]; + struct fwnode_handle *entity_node; + + /* DisCo uses upper-case for hex numbers */ + snprintf(entity_property, sizeof(entity_property), + "mipi-sdca-entity-id-0x%X-subproperties", entities[i].id); + + entity_node = fwnode_get_named_child_node(function_node, entity_property); + if (!entity_node) { + dev_err(dev, "%pfwP: entity node %s not found\n", + function_node, entity_property); + return -EINVAL; + } + + ret = find_sdca_entity(dev, function_node, entity_node, &entities[i]); + fwnode_handle_put(entity_node); + if (ret) + return ret; + } + + function->num_entities = num_entities; + function->entities = entities; + + return 0; +} + +static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data *function, + const char *entity_label) +{ + int i; + + for (i = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + + if (!strcmp(entity->label, entity_label)) + return entity; + } + + return NULL; +} + +static int find_sdca_entity_connection(struct device *dev, + struct sdca_function_data *function, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity **pins; + int num_pins, pin; + u64 pin_list; + int i, ret; + + ret = fwnode_property_read_u64(entity_node, "mipi-sdca-input-pin-list", &pin_list); + if (ret == -EINVAL) { + /* Allow missing pin lists, assume no pins. */ + dev_warn(dev, "%s: missing pin list\n", entity->label); + return 0; + } else if (ret) { + dev_err(dev, "%s: failed to read pin list: %d\n", entity->label, ret); + return ret; + } else if (pin_list & BIT(0)) { + /* + * Each bit set in the pin-list refers to an entity_id in this + * Function. Entity 0 is an illegal connection since it is used + * for Function-level configurations. + */ + dev_err(dev, "%s: pin 0 used as input\n", entity->label); + return -EINVAL; + } else if (!pin_list) { + return 0; + } + + num_pins = hweight64(pin_list); + pins = devm_kcalloc(dev, num_pins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + i = 0; + for_each_set_bit(pin, (unsigned long *)&pin_list, BITS_PER_TYPE(pin_list)) { + char pin_property[SDCA_PROPERTY_LENGTH]; + struct fwnode_handle *connected_node; + struct sdca_entity *connected_entity; + const char *connected_label; + + snprintf(pin_property, sizeof(pin_property), "mipi-sdca-input-pin-%d", pin); + + connected_node = fwnode_get_named_child_node(entity_node, pin_property); + if (!connected_node) { + dev_err(dev, "%s: pin node %s not found\n", + entity->label, pin_property); + return -EINVAL; + } + + ret = fwnode_property_read_string(connected_node, "mipi-sdca-entity-label", + &connected_label); + if (ret) { + dev_err(dev, "%s: pin %d label missing: %d\n", + entity->label, pin, ret); + fwnode_handle_put(connected_node); + return ret; + } + + connected_entity = find_sdca_entity_by_label(function, connected_label); + if (!connected_entity) { + dev_err(dev, "%s: failed to find entity with label %s\n", + entity->label, connected_label); + fwnode_handle_put(connected_node); + return -EINVAL; + } + + pins[i] = connected_entity; + + dev_info(dev, "%s -> %s\n", connected_entity->label, entity->label); + + i++; + fwnode_handle_put(connected_node); + } + + entity->num_sources = num_pins; + entity->sources = pins; + + return 0; +} + +static int find_sdca_connections(struct device *dev, + struct fwnode_handle *function_node, + struct sdca_function_data *function) +{ + int i; + + for (i = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + char entity_property[SDCA_PROPERTY_LENGTH]; + struct fwnode_handle *entity_node; + int ret; + + /* DisCo uses upper-case for hex numbers */ + snprintf(entity_property, sizeof(entity_property), + "mipi-sdca-entity-id-0x%X-subproperties", + entity->id); + + entity_node = fwnode_get_named_child_node(function_node, entity_property); + if (!entity_node) { + dev_err(dev, "%pfwP: entity node %s not found\n", + function_node, entity_property); + return -EINVAL; + } + + ret = find_sdca_entity_connection(dev, function, entity_node, entity); + fwnode_handle_put(entity_node); + if (ret) + return ret; + } + + return 0; +} + +/** + * sdca_parse_function - parse ACPI DisCo for a Function + * @dev: Pointer to device against which function data will be allocated. + * @function_desc: Pointer to the Function short descriptor. + * @function: Pointer to the Function information, to be populated. + * + * Return: Returns 0 for success. + */ +int sdca_parse_function(struct device *dev, + struct sdca_function_desc *function_desc, + struct sdca_function_data *function) +{ + u32 tmp; + int ret; + + function->desc = function_desc; + + ret = fwnode_property_read_u32(function_desc->node, + "mipi-sdca-function-busy-max-delay", &tmp); + if (!ret) + function->busy_max_delay = tmp; + + dev_info(dev, "%pfwP: name %s delay %dus\n", function->desc->node, + function->desc->name, function->busy_max_delay); + + ret = find_sdca_entities(dev, function_desc->node, function); + if (ret) + return ret; + + ret = find_sdca_connections(dev, function_desc->node, function); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL_NS(sdca_parse_function, "SND_SOC_SDCA"); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SDCA library"); From 19f6748abbab8523a7b32a5e371e39d4d8d4aba5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 5 Feb 2025 11:37:54 +0000 Subject: [PATCH 0103/1090] ASoC: SDCA: Parse initialization write table Each SDCA Function may contain a table of register writes that should be written out before the Function is used. Add code to parse this table from the DisCo tables in ACPI. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 20 +++++++++++ sound/soc/sdca/sdca_functions.c | 61 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 3f4031d285d6..47fc1da8e4f3 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -10,6 +10,7 @@ #define __SDCA_FUNCTION_H__ #include +#include struct device; struct sdca_function_desc; @@ -20,6 +21,11 @@ struct sdca_function_desc; */ #define SDCA_MAX_ENTITY_COUNT 128 +/* + * Sanity check on number of initialization writes, can be expanded if needed. + */ +#define SDCA_MAX_INIT_COUNT 2048 + /** * enum sdca_function_type - SDCA Function Type codes * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. @@ -65,6 +71,16 @@ enum sdca_function_type { #define SDCA_FUNCTION_TYPE_HID_NAME "HID" #define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined" +/** + * struct sdca_init_write - a single initialization write + * @addr: Register address to be written + * @val: Single byte value to be written + */ +struct sdca_init_write { + u32 addr; + u8 val; +}; + /** * enum sdca_entity0_controls - SDCA Controls for Entity 0 * @@ -167,7 +183,9 @@ struct sdca_entity { /** * struct sdca_function_data - top-level information for one SDCA function * @desc: Pointer to short descriptor from initial parsing. + * @init_table: Pointer to a table of initialization writes. * @entities: Dynamically allocated array of Entities. + * @num_init_table: Number of initialization writes. * @num_entities: Number of Entities reported in this Function. * @busy_max_delay: Maximum Function busy delay in microseconds, before an * error should be reported. @@ -175,7 +193,9 @@ struct sdca_entity { struct sdca_function_data { struct sdca_function_desc *desc; + struct sdca_init_write *init_table; struct sdca_entity *entities; + int num_init_table; int num_entities; unsigned int busy_max_delay; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 72b82280918d..f914ec3f86c9 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -9,6 +9,7 @@ #define dev_fmt(fmt) "%s: " fmt, __func__ #include +#include #include #include #include @@ -185,6 +186,62 @@ void sdca_lookup_functions(struct sdw_slave *slave) } EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA"); +static int find_sdca_init_table(struct device *dev, + struct fwnode_handle *function_node, + struct sdca_function_data *function) +{ + struct sdca_init_write *init_write; + int write_size = sizeof(init_write->addr) + sizeof(init_write->val); + u8 *init_list, *init_iter; + int num_init_writes; + + num_init_writes = fwnode_property_count_u8(function_node, + "mipi-sdca-function-initialization-table"); + if (!num_init_writes || num_init_writes == -EINVAL) { + return 0; + } else if (num_init_writes < 0) { + dev_err(dev, "%pfwP: failed to read initialization table: %d\n", + function_node, num_init_writes); + return num_init_writes; + } else if (num_init_writes % write_size != 0) { + dev_err(dev, "%pfwP: init table size invalid\n", function_node); + return -EINVAL; + } else if (num_init_writes > SDCA_MAX_INIT_COUNT) { + dev_err(dev, "%pfwP: maximum init table size exceeded\n", function_node); + return -EINVAL; + } + + init_write = devm_kcalloc(dev, num_init_writes / write_size, + sizeof(*init_write), GFP_KERNEL); + if (!init_write) + return -ENOMEM; + + init_list = kcalloc(num_init_writes, sizeof(*init_list), GFP_KERNEL); + if (!init_list) + return -ENOMEM; + + fwnode_property_read_u8_array(function_node, + "mipi-sdca-function-initialization-table", + init_list, num_init_writes); + + function->num_init_table = num_init_writes; + function->init_table = init_write; + + for (init_iter = init_list; init_iter < init_list + num_init_writes;) { + u32 *addr = (u32 *)init_iter; + + init_write->addr = le32_to_cpu(*addr); + init_iter += sizeof(init_write->addr); + + init_write->val = *init_iter; + init_iter += sizeof(init_write->val); + } + + kfree(init_list); + + return 0; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -435,6 +492,10 @@ int sdca_parse_function(struct device *dev, dev_info(dev, "%pfwP: name %s delay %dus\n", function->desc->node, function->desc->name, function->busy_max_delay); + ret = find_sdca_init_table(dev, function_desc->node, function); + if (ret) + return ret; + ret = find_sdca_entities(dev, function_desc->node, function); if (ret) return ret; From 9ee6d50ae4b0fe14ed70a5265a05874d41e10848 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:55 +0000 Subject: [PATCH 0104/1090] ASoC: SDCA: Add support for Entity 0 Within SDCA there is a special Entity called Entity 0 which is used to hold Function level controls. Whilst Entity 0 isn't a full SDCA Entity, it is helpful to add an sdca_entity structure for it. This will allow it to be treated identically in the code that handles SDCA Controls. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 4 ++++ sound/soc/sdca/sdca_functions.c | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 47fc1da8e4f3..a51e3a459e36 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -117,6 +117,9 @@ enum sdca_entity0_controls { /** * enum sdca_entity_type - SDCA Entity Type codes + * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the + * specification but useful internally as an Entity structure + * is allocated for Entity 0, to hold Entity 0 controls. * @SDCA_ENTITY_TYPE_IT: Input Terminal. * @SDCA_ENTITY_TYPE_OT: Output Terminal. * @SDCA_ENTITY_TYPE_MU: Mixer Unit. @@ -141,6 +144,7 @@ enum sdca_entity0_controls { * all Entity Types not described are reserved. */ enum sdca_entity_type { + SDCA_ENTITY_TYPE_ENTITY_0 = 0x00, SDCA_ENTITY_TYPE_IT = 0x02, SDCA_ENTITY_TYPE_OT = 0x03, SDCA_ENTITY_TYPE_MU = 0x05, diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index f914ec3f86c9..b0ca92f1bc57 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -293,7 +293,8 @@ static int find_sdca_entities(struct device *dev, return -EINVAL; } - entities = devm_kcalloc(dev, num_entities, sizeof(*entities), GFP_KERNEL); + /* Add 1 to make space for Entity 0 */ + entities = devm_kcalloc(dev, num_entities + 1, sizeof(*entities), GFP_KERNEL); if (!entities) return -ENOMEM; @@ -331,7 +332,13 @@ static int find_sdca_entities(struct device *dev, return ret; } - function->num_entities = num_entities; + /* + * Add Entity 0 at end of the array, makes it easy to skip during + * all the Entity searches involved in creating connections. + */ + entities[num_entities].label = "entity0"; + + function->num_entities = num_entities + 1; function->entities = entities; return 0; @@ -440,7 +447,8 @@ static int find_sdca_connections(struct device *dev, { int i; - for (i = 0; i < function->num_entities; i++) { + /* Entity 0 cannot have connections */ + for (i = 0; i < function->num_entities - 1; i++) { struct sdca_entity *entity = &function->entities[i]; char entity_property[SDCA_PROPERTY_LENGTH]; struct fwnode_handle *entity_node; From 42b144cb6a2d87385fa0b124c975d6cf1e3ec630 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:56 +0000 Subject: [PATCH 0105/1090] ASoC: SDCA: Add SDCA Control parsing Each SDCA Entity will contain a number of Controls, these are basically equivalent to registers. Although a single Control will only ever contain a single field. Some of these would map directly to ALSA controls once more of the SDCA class driver is implemented. These controls are parsed out of the DisCo ACPI tables. One small todo here is that each Control can have multiple sub-entries (Control Numbers), these are typically used to represent channels. Whilst support is present for these, currently the ACPI properties that would allow differing defaults for each channel are not parsed. But there is nothing here that should prevent that being added in the future. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 534 +++++++++++++++++++++++++++++++ sound/soc/sdca/sdca_functions.c | 539 ++++++++++++++++++++++++++++++++ 2 files changed, 1073 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index a51e3a459e36..64043090fe76 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -81,6 +81,342 @@ struct sdca_init_write { u8 val; }; +/** + * define SDCA_CTL_TYPE - create a unique identifier for an SDCA Control + * @ent: Entity Type code. + * @sel: Control Selector code. + * + * Sometimes there is a need to identify a type of Control, for example to + * determine what name the control should have. SDCA Selectors are reused + * across Entity types, as such it is necessary to combine both the Entity + * Type and the Control Selector to obtain a unique identifier. + */ +#define SDCA_CTL_TYPE(ent, sel) ((ent) << 8 | (sel)) + +/** + * define SDCA_CTL_TYPE_S - static version of SDCA_CTL_TYPE + * @ent: Entity name, for example IT, MFPU, etc. this string can be read + * from the last characters of the SDCA_ENTITY_TYPE_* macros. + * @sel: Control Selector name, for example MIC_BIAS, MUTE, etc. this + * string can be read from the last characters of the SDCA_CTL_*_* + * macros. + * + * Short hand to specific a Control type statically for example: + * SDAC_CTL_TYPE_S(IT, MIC_BIAS). + */ +#define SDCA_CTL_TYPE_S(ent, sel) SDCA_CTL_TYPE(SDCA_ENTITY_TYPE_##ent, \ + SDCA_CTL_##ent##_##sel) + +/** + * enum sdca_it_controls - SDCA Controls for Input Terminal + * + * Control Selectors for Input Terminal from SDCA specification v1.0 + * section 6.2.1.3. + */ +enum sdca_it_controls { + SDCA_CTL_IT_MIC_BIAS = 0x03, + SDCA_CTL_IT_USAGE = 0x04, + SDCA_CTL_IT_LATENCY = 0x08, + SDCA_CTL_IT_CLUSTERINDEX = 0x10, + SDCA_CTL_IT_DATAPORT_SELECTOR = 0x11, + SDCA_CTL_IT_MATCHING_GUID = 0x12, + SDCA_CTL_IT_KEEP_ALIVE = 0x13, + SDCA_CTL_IT_NDAI_STREAM = 0x14, + SDCA_CTL_IT_NDAI_CATEGORY = 0x15, + SDCA_CTL_IT_NDAI_CODINGTYPE = 0x16, + SDCA_CTL_IT_NDAI_PACKETTYPE = 0x17, +}; + +/** + * enum sdca_ot_controls - SDCA Controls for Output Terminal + * + * Control Selectors for Output Terminal from SDCA specification v1.0 + * section 6.2.2.3. + */ +enum sdca_ot_controls { + SDCA_CTL_OT_USAGE = 0x04, + SDCA_CTL_OT_LATENCY = 0x08, + SDCA_CTL_OT_DATAPORT_SELECTOR = 0x11, + SDCA_CTL_OT_MATCHING_GUID = 0x12, + SDCA_CTL_OT_KEEP_ALIVE = 0x13, + SDCA_CTL_OT_NDAI_STREAM = 0x14, + SDCA_CTL_OT_NDAI_CATEGORY = 0x15, + SDCA_CTL_OT_NDAI_CODINGTYPE = 0x16, + SDCA_CTL_OT_NDAI_PACKETTYPE = 0x17, +}; + +/** + * enum sdca_mu_controls - SDCA Controls for Mixer Unit + * + * Control Selectors for Mixer Unit from SDCA specification v1.0 + * section 6.3.4.2. + */ +enum sdca_mu_controls { + SDCA_CTL_MU_MIXER = 0x01, + SDCA_CTL_MU_LATENCY = 0x06, +}; + +/** + * enum sdca_su_controls - SDCA Controls for Selector Unit + * + * Control Selectors for Selector Unit from SDCA specification v1.0 + * section 6.3.8.3. + */ +enum sdca_su_controls { + SDCA_CTL_SU_SELECTOR = 0x01, + SDCA_CTL_SU_LATENCY = 0x02, +}; + +/** + * enum sdca_fu_controls - SDCA Controls for Feature Unit + * + * Control Selectors for Feature Unit from SDCA specification v1.0 + * section 6.3.2.3. + */ +enum sdca_fu_controls { + SDCA_CTL_FU_MUTE = 0x01, + SDCA_CTL_FU_CHANNEL_VOLUME = 0x02, + SDCA_CTL_FU_AGC = 0x07, + SDCA_CTL_FU_BASS_BOOST = 0x09, + SDCA_CTL_FU_LOUDNESS = 0x0A, + SDCA_CTL_FU_GAIN = 0x0B, + SDCA_CTL_FU_LATENCY = 0x10, +}; + +/** + * enum sdca_xu_controls - SDCA Controls for Extension Unit + * + * Control Selectors for Extension Unit from SDCA specification v1.0 + * section 6.3.10.3. + */ +enum sdca_xu_controls { + SDCA_CTL_XU_BYPASS = 0x01, + SDCA_CTL_XU_LATENCY = 0x06, + SDCA_CTL_XU_XU_ID = 0x07, + SDCA_CTL_XU_XU_VERSION = 0x08, + SDCA_CTL_XU_FDL_CURRENTOWNER = 0x10, + SDCA_CTL_XU_FDL_MESSAGEOFFSET = 0x12, + SDCA_CTL_XU_FDL_MESSAGELENGTH = 0x13, + SDCA_CTL_XU_FDL_STATUS = 0x14, + SDCA_CTL_XU_FDL_SET_INDEX = 0x15, + SDCA_CTL_XU_FDL_HOST_REQUEST = 0x16, +}; + +/** + * enum sdca_cs_controls - SDCA Controls for Clock Source + * + * Control Selectors for Clock Source from SDCA specification v1.0 + * section 6.4.1.3. + */ +enum sdca_cs_controls { + SDCA_CTL_CS_CLOCK_VALID = 0x02, + SDCA_CTL_CS_SAMPLERATEINDEX = 0x10, +}; + +/** + * enum sdca_cx_controls - SDCA Controls for Clock Selector + * + * Control Selectors for Clock Selector from SDCA specification v1.0 + * section 6.4.2.3. + */ +enum sdca_cx_controls { + SDCA_CTL_CX_CLOCK_SELECT = 0x01, +}; + +/** + * enum sdca_pde_controls - SDCA Controls for Power Domain Entity + * + * Control Selectors for Power Domain Entity from SDCA specification + * v1.0 section 6.5.2.2. + */ +enum sdca_pde_controls { + SDCA_CTL_PDE_REQUESTED_PS = 0x01, + SDCA_CTL_PDE_ACTUAL_PS = 0x10, +}; + +/** + * enum sdca_ge_controls - SDCA Controls for Group Unit + * + * Control Selectors for Group Unit from SDCA specification v1.0 + * section 6.5.1.4. + */ +enum sdca_ge_controls { + SDCA_CTL_GE_SELECTED_MODE = 0x01, + SDCA_CTL_GE_DETECTED_MODE = 0x02, +}; + +/** + * enum sdca_spe_controls - SDCA Controls for Security & Privacy Unit + * + * Control Selectors for Security & Privacy Unit from SDCA + * specification v1.0 Section 6.5.3.2. + */ +enum sdca_spe_controls { + SDCA_CTL_SPE_PRIVATE = 0x01, + SDCA_CTL_SPE_PRIVACY_POLICY = 0x02, + SDCA_CTL_SPE_PRIVACY_LOCKSTATE = 0x03, + SDCA_CTL_SPE_PRIVACY_OWNER = 0x04, + SDCA_CTL_SPE_AUTHTX_CURRENTOWNER = 0x10, + SDCA_CTL_SPE_AUTHTX_MESSAGEOFFSET = 0x12, + SDCA_CTL_SPE_AUTHTX_MESSAGELENGTH = 0x13, + SDCA_CTL_SPE_AUTHRX_CURRENTOWNER = 0x14, + SDCA_CTL_SPE_AUTHRX_MESSAGEOFFSET = 0x16, + SDCA_CTL_SPE_AUTHRX_MESSAGELENGTH = 0x17, +}; + +/** + * enum sdca_cru_controls - SDCA Controls for Channel Remapping Unit + * + * Control Selectors for Channel Remapping Unit from SDCA + * specification v1.0 Section 6.3.1.3. + */ +enum sdca_cru_controls { + SDCA_CTL_CRU_LATENCY = 0x06, + SDCA_CTL_CRU_CLUSTERINDEX = 0x10, +}; + +/** + * enum sdca_udmpu_controls - SDCA Controls for Up-Down Mixer Processing Unit + * + * Control Selectors for Up-Down Mixer Processing Unit from SDCA + * specification v1.0 Section 6.3.9.3. + */ +enum sdca_udmpu_controls { + SDCA_CTL_UDMPU_LATENCY = 0x06, + SDCA_CTL_UDMPU_CLUSTERINDEX = 0x10, + SDCA_CTL_UDMPU_ACOUSTIC_ENERGY_LEVEL_MONITOR = 0x11, + SDCA_CTL_UDMPU_ULTRASOUND_LOOP_GAIN = 0x12, + SDCA_CTL_UDMPU_OPAQUESET_0 = 0x18, + SDCA_CTL_UDMPU_OPAQUESET_1 = 0x19, + SDCA_CTL_UDMPU_OPAQUESET_2 = 0x1A, + SDCA_CTL_UDMPU_OPAQUESET_3 = 0x1B, + SDCA_CTL_UDMPU_OPAQUESET_4 = 0x1C, + SDCA_CTL_UDMPU_OPAQUESET_5 = 0x1D, + SDCA_CTL_UDMPU_OPAQUESET_6 = 0x1E, + SDCA_CTL_UDMPU_OPAQUESET_7 = 0x1F, + SDCA_CTL_UDMPU_OPAQUESET_8 = 0x20, + SDCA_CTL_UDMPU_OPAQUESET_9 = 0x21, + SDCA_CTL_UDMPU_OPAQUESET_10 = 0x22, + SDCA_CTL_UDMPU_OPAQUESET_11 = 0x23, + SDCA_CTL_UDMPU_OPAQUESET_12 = 0x24, + SDCA_CTL_UDMPU_OPAQUESET_13 = 0x25, + SDCA_CTL_UDMPU_OPAQUESET_14 = 0x26, + SDCA_CTL_UDMPU_OPAQUESET_15 = 0x27, + SDCA_CTL_UDMPU_OPAQUESET_16 = 0x28, + SDCA_CTL_UDMPU_OPAQUESET_17 = 0x29, + SDCA_CTL_UDMPU_OPAQUESET_18 = 0x2A, + SDCA_CTL_UDMPU_OPAQUESET_19 = 0x2B, + SDCA_CTL_UDMPU_OPAQUESET_20 = 0x2C, + SDCA_CTL_UDMPU_OPAQUESET_21 = 0x2D, + SDCA_CTL_UDMPU_OPAQUESET_22 = 0x2E, + SDCA_CTL_UDMPU_OPAQUESET_23 = 0x2F, +}; + +/** + * enum sdca_mfpu_controls - SDCA Controls for Multi-Function Processing Unit + * + * Control Selectors for Multi-Function Processing Unit from SDCA + * specification v1.0 Section 6.3.3.4. + */ +enum sdca_mfpu_controls { + SDCA_CTL_MFPU_BYPASS = 0x01, + SDCA_CTL_MFPU_ALGORITHM_READY = 0x04, + SDCA_CTL_MFPU_ALGORITHM_ENABLE = 0x05, + SDCA_CTL_MFPU_LATENCY = 0x08, + SDCA_CTL_MFPU_ALGORITHM_PREPARE = 0x09, + SDCA_CTL_MFPU_CLUSTERINDEX = 0x10, + SDCA_CTL_MFPU_CENTER_FREQUENCY_INDEX = 0x11, + SDCA_CTL_MFPU_ULTRASOUND_LEVEL = 0x12, + SDCA_CTL_MFPU_AE_NUMBER = 0x13, + SDCA_CTL_MFPU_AE_CURRENTOWNER = 0x14, + SDCA_CTL_MFPU_AE_MESSAGEOFFSET = 0x16, + SDCA_CTL_MFPU_AE_MESSAGELENGTH = 0x17, +}; + +/** + * enum sdca_smpu_controls - SDCA Controls for Smart Mic Processing Unit + * + * Control Selectors for Smart Mic Processing Unit from SDCA + * specification v1.0 Section 6.3.7.3. + */ +enum sdca_smpu_controls { + SDCA_CTL_SMPU_LATENCY = 0x06, + SDCA_CTL_SMPU_TRIGGER_ENABLE = 0x10, + SDCA_CTL_SMPU_TRIGGER_STATUS = 0x11, + SDCA_CTL_SMPU_HIST_BUFFER_MODE = 0x12, + SDCA_CTL_SMPU_HIST_BUFFER_PREAMBLE = 0x13, + SDCA_CTL_SMPU_HIST_ERROR = 0x14, + SDCA_CTL_SMPU_TRIGGER_EXTENSION = 0x15, + SDCA_CTL_SMPU_TRIGGER_READY = 0x16, + SDCA_CTL_SMPU_HIST_CURRENTOWNER = 0x18, + SDCA_CTL_SMPU_HIST_MESSAGEOFFSET = 0x1A, + SDCA_CTL_SMPU_HIST_MESSAGELENGTH = 0x1B, + SDCA_CTL_SMPU_DTODTX_CURRENTOWNER = 0x1C, + SDCA_CTL_SMPU_DTODTX_MESSAGEOFFSET = 0x1E, + SDCA_CTL_SMPU_DTODTX_MESSAGELENGTH = 0x1F, + SDCA_CTL_SMPU_DTODRX_CURRENTOWNER = 0x20, + SDCA_CTL_SMPU_DTODRX_MESSAGEOFFSET = 0x22, + SDCA_CTL_SMPU_DTODRX_MESSAGELENGTH = 0x23, +}; + +/** + * enum sdca_sapu_controls - SDCA Controls for Smart Amp Processing Unit + * + * Control Selectors for Smart Amp Processing Unit from SDCA + * specification v1.0 Section 6.3.6.3. + */ +enum sdca_sapu_controls { + SDCA_CTL_SAPU_LATENCY = 0x05, + SDCA_CTL_SAPU_PROTECTION_MODE = 0x10, + SDCA_CTL_SAPU_PROTECTION_STATUS = 0x11, + SDCA_CTL_SAPU_OPAQUESETREQ_INDEX = 0x12, + SDCA_CTL_SAPU_DTODTX_CURRENTOWNER = 0x14, + SDCA_CTL_SAPU_DTODTX_MESSAGEOFFSET = 0x16, + SDCA_CTL_SAPU_DTODTX_MESSAGELENGTH = 0x17, + SDCA_CTL_SAPU_DTODRX_CURRENTOWNER = 0x18, + SDCA_CTL_SAPU_DTODRX_MESSAGEOFFSET = 0x1A, + SDCA_CTL_SAPU_DTODRX_MESSAGELENGTH = 0x1B, +}; + +/** + * enum sdca_ppu_controls - SDCA Controls for Post Processing Unit + * + * Control Selectors for Post Processing Unit from SDCA specification + * v1.0 Section 6.3.5.3. + */ +enum sdca_ppu_controls { + SDCA_CTL_PPU_LATENCY = 0x06, + SDCA_CTL_PPU_POSTURENUMBER = 0x10, + SDCA_CTL_PPU_POSTUREEXTENSION = 0x11, + SDCA_CTL_PPU_HORIZONTALBALANCE = 0x12, + SDCA_CTL_PPU_VERTICALBALANCE = 0x13, +}; + +/** + * enum sdca_tg_controls - SDCA Controls for Tone Generator Entity + * + * Control Selectors for Tone Generator from SDCA specification v1.0 + * Section 6.5.4.4. + */ +enum sdca_tg_controls { + SDCA_CTL_TG_TONE_DIVIDER = 0x10, +}; + +/** + * enum sdca_hide_controls - SDCA Controls for HIDE Entity + * + * Control Selectors for HIDE from SDCA specification v1.0 Section + * 6.6.1.2. + */ +enum sdca_hide_controls { + SDCA_CTL_HIDE_HIDTX_CURRENTOWNER = 0x10, + SDCA_CTL_HIDE_HIDTX_MESSAGEOFFSET = 0x12, + SDCA_CTL_HIDE_HIDTX_MESSAGELENGTH = 0x13, + SDCA_CTL_HIDE_HIDRX_CURRENTOWNER = 0x14, + SDCA_CTL_HIDE_HIDRX_MESSAGEOFFSET = 0x16, + SDCA_CTL_HIDE_HIDRX_MESSAGELENGTH = 0x17, +}; + /** * enum sdca_entity0_controls - SDCA Controls for Entity 0 * @@ -115,6 +451,200 @@ enum sdca_entity0_controls { SDCA_CTL_ENTITY_0_FUNCTION_BUSY = BIT(7), }; +#define SDCA_CTL_MIC_BIAS_NAME "Mic Bias" +#define SDCA_CTL_USAGE_NAME "Usage" +#define SDCA_CTL_LATENCY_NAME "Latency" +#define SDCA_CTL_CLUSTERINDEX_NAME "Cluster Index" +#define SDCA_CTL_DATAPORT_SELECTOR_NAME "Dataport Selector" +#define SDCA_CTL_MATCHING_GUID_NAME "Matching GUID" +#define SDCA_CTL_KEEP_ALIVE_NAME "Keep Alive" +#define SDCA_CTL_NDAI_STREAM_NAME "NDAI Stream" +#define SDCA_CTL_NDAI_CATEGORY_NAME "NDAI Category" +#define SDCA_CTL_NDAI_CODINGTYPE_NAME "NDAI Coding Type" +#define SDCA_CTL_NDAI_PACKETTYPE_NAME "NDAI Packet Type" +#define SDCA_CTL_MIXER_NAME "Mixer" +#define SDCA_CTL_SELECTOR_NAME "Selector" +#define SDCA_CTL_MUTE_NAME "Mute" +#define SDCA_CTL_CHANNEL_VOLUME_NAME "Channel Volume" +#define SDCA_CTL_AGC_NAME "AGC" +#define SDCA_CTL_BASS_BOOST_NAME "Bass Boost" +#define SDCA_CTL_LOUDNESS_NAME "Loudness" +#define SDCA_CTL_GAIN_NAME "Gain" +#define SDCA_CTL_BYPASS_NAME "Bypass" +#define SDCA_CTL_XU_ID_NAME "XU ID" +#define SDCA_CTL_XU_VERSION_NAME "XU Version" +#define SDCA_CTL_FDL_CURRENTOWNER_NAME "FDL Current Owner" +#define SDCA_CTL_FDL_MESSAGEOFFSET_NAME "FDL Message Offset" +#define SDCA_CTL_FDL_MESSAGELENGTH_NAME "FDL Message Length" +#define SDCA_CTL_FDL_STATUS_NAME "FDL Status" +#define SDCA_CTL_FDL_SET_INDEX_NAME "FDL Set Index" +#define SDCA_CTL_FDL_HOST_REQUEST_NAME "FDL Host Request" +#define SDCA_CTL_CLOCK_VALID_NAME "Clock Valid" +#define SDCA_CTL_SAMPLERATEINDEX_NAME "Sample Rate Index" +#define SDCA_CTL_CLOCK_SELECT_NAME "Clock Select" +#define SDCA_CTL_REQUESTED_PS_NAME "Requested PS" +#define SDCA_CTL_ACTUAL_PS_NAME "Actual PS" +#define SDCA_CTL_SELECTED_MODE_NAME "Selected Mode" +#define SDCA_CTL_DETECTED_MODE_NAME "Detected Mode" +#define SDCA_CTL_PRIVATE_NAME "Private" +#define SDCA_CTL_PRIVACY_POLICY_NAME "Privacy Policy" +#define SDCA_CTL_PRIVACY_LOCKSTATE_NAME "Privacy Lockstate" +#define SDCA_CTL_PRIVACY_OWNER_NAME "Privacy Owner" +#define SDCA_CTL_AUTHTX_CURRENTOWNER_NAME "AuthTX Current Owner" +#define SDCA_CTL_AUTHTX_MESSAGEOFFSET_NAME "AuthTX Message Offset" +#define SDCA_CTL_AUTHTX_MESSAGELENGTH_NAME "AuthTX Message Length" +#define SDCA_CTL_AUTHRX_CURRENTOWNER_NAME "AuthRX Current Owner" +#define SDCA_CTL_AUTHRX_MESSAGEOFFSET_NAME "AuthRX Message Offset" +#define SDCA_CTL_AUTHRX_MESSAGELENGTH_NAME "AuthRX Message Length" +#define SDCA_CTL_ACOUSTIC_ENERGY_LEVEL_MONITOR_NAME "Acoustic Energy Level Monitor" +#define SDCA_CTL_ULTRASOUND_LOOP_GAIN_NAME "Ultrasound Loop Gain" +#define SDCA_CTL_OPAQUESET_0_NAME "Opaqueset 0" +#define SDCA_CTL_OPAQUESET_1_NAME "Opaqueset 1" +#define SDCA_CTL_OPAQUESET_2_NAME "Opaqueset 2" +#define SDCA_CTL_OPAQUESET_3_NAME "Opaqueset 3" +#define SDCA_CTL_OPAQUESET_4_NAME "Opaqueset 4" +#define SDCA_CTL_OPAQUESET_5_NAME "Opaqueset 5" +#define SDCA_CTL_OPAQUESET_6_NAME "Opaqueset 6" +#define SDCA_CTL_OPAQUESET_7_NAME "Opaqueset 7" +#define SDCA_CTL_OPAQUESET_8_NAME "Opaqueset 8" +#define SDCA_CTL_OPAQUESET_9_NAME "Opaqueset 9" +#define SDCA_CTL_OPAQUESET_10_NAME "Opaqueset 10" +#define SDCA_CTL_OPAQUESET_11_NAME "Opaqueset 11" +#define SDCA_CTL_OPAQUESET_12_NAME "Opaqueset 12" +#define SDCA_CTL_OPAQUESET_13_NAME "Opaqueset 13" +#define SDCA_CTL_OPAQUESET_14_NAME "Opaqueset 14" +#define SDCA_CTL_OPAQUESET_15_NAME "Opaqueset 15" +#define SDCA_CTL_OPAQUESET_16_NAME "Opaqueset 16" +#define SDCA_CTL_OPAQUESET_17_NAME "Opaqueset 17" +#define SDCA_CTL_OPAQUESET_18_NAME "Opaqueset 18" +#define SDCA_CTL_OPAQUESET_19_NAME "Opaqueset 19" +#define SDCA_CTL_OPAQUESET_20_NAME "Opaqueset 20" +#define SDCA_CTL_OPAQUESET_21_NAME "Opaqueset 21" +#define SDCA_CTL_OPAQUESET_22_NAME "Opaqueset 22" +#define SDCA_CTL_OPAQUESET_23_NAME "Opaqueset 23" +#define SDCA_CTL_ALGORITHM_READY_NAME "Algorithm Ready" +#define SDCA_CTL_ALGORITHM_ENABLE_NAME "Algorithm Enable" +#define SDCA_CTL_ALGORITHM_PREPARE_NAME "Algorithm Prepare" +#define SDCA_CTL_CENTER_FREQUENCY_INDEX_NAME "Center Frequency Index" +#define SDCA_CTL_ULTRASOUND_LEVEL_NAME "Ultrasound Level" +#define SDCA_CTL_AE_NUMBER_NAME "AE Number" +#define SDCA_CTL_AE_CURRENTOWNER_NAME "AE Current Owner" +#define SDCA_CTL_AE_MESSAGEOFFSET_NAME "AE Message Offset" +#define SDCA_CTL_AE_MESSAGELENGTH_NAME "AE Message Length" +#define SDCA_CTL_TRIGGER_ENABLE_NAME "Trigger Enable" +#define SDCA_CTL_TRIGGER_STATUS_NAME "Trigger Status" +#define SDCA_CTL_HIST_BUFFER_MODE_NAME "Hist Buffer Mode" +#define SDCA_CTL_HIST_BUFFER_PREAMBLE_NAME "Hist Buffer Preamble" +#define SDCA_CTL_HIST_ERROR_NAME "Hist Error" +#define SDCA_CTL_TRIGGER_EXTENSION_NAME "Trigger Extension" +#define SDCA_CTL_TRIGGER_READY_NAME "Trigger Ready" +#define SDCA_CTL_HIST_CURRENTOWNER_NAME "Hist Current Owner" +#define SDCA_CTL_HIST_MESSAGEOFFSET_NAME "Hist Message Offset" +#define SDCA_CTL_HIST_MESSAGELENGTH_NAME "Hist Message Length" +#define SDCA_CTL_DTODTX_CURRENTOWNER_NAME "DTODTX Current Owner" +#define SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME "DTODTX Message Offset" +#define SDCA_CTL_DTODTX_MESSAGELENGTH_NAME "DTODTX Message Length" +#define SDCA_CTL_DTODRX_CURRENTOWNER_NAME "DTODRX Current Owner" +#define SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME "DTODRX Message Offset" +#define SDCA_CTL_DTODRX_MESSAGELENGTH_NAME "DTODRX Message Length" +#define SDCA_CTL_PROTECTION_MODE_NAME "Protection Mode" +#define SDCA_CTL_PROTECTION_STATUS_NAME "Protection Status" +#define SDCA_CTL_OPAQUESETREQ_INDEX_NAME "Opaqueset Req Index" +#define SDCA_CTL_DTODTX_CURRENTOWNER_NAME "DTODTX Current Owner" +#define SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME "DTODTX Message Offset" +#define SDCA_CTL_DTODTX_MESSAGELENGTH_NAME "DTODTX Message Length" +#define SDCA_CTL_DTODRX_CURRENTOWNER_NAME "DTODRX Current Owner" +#define SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME "DTODRX Message Offset" +#define SDCA_CTL_DTODRX_MESSAGELENGTH_NAME "DTODRX Message Length" +#define SDCA_CTL_POSTURENUMBER_NAME "Posture Number" +#define SDCA_CTL_POSTUREEXTENSION_NAME "Posture Extension" +#define SDCA_CTL_HORIZONTALBALANCE_NAME "Horizontal Balance" +#define SDCA_CTL_VERTICALBALANCE_NAME "Vertical Balance" +#define SDCA_CTL_TONE_DIVIDER_NAME "Tone Divider" +#define SDCA_CTL_HIDTX_CURRENTOWNER_NAME "HIDTX Current Owner" +#define SDCA_CTL_HIDTX_MESSAGEOFFSET_NAME "HIDTX Message Offset" +#define SDCA_CTL_HIDTX_MESSAGELENGTH_NAME "HIDTX Message Length" +#define SDCA_CTL_HIDRX_CURRENTOWNER_NAME "HIDRX Current Owner" +#define SDCA_CTL_HIDRX_MESSAGEOFFSET_NAME "HIDRX Message Offset" +#define SDCA_CTL_HIDRX_MESSAGELENGTH_NAME "HIDRX Message Length" +#define SDCA_CTL_COMMIT_GROUP_MASK_NAME "Commit Group Mask" +#define SDCA_CTL_FUNCTION_SDCA_VERSION_NAME "Function SDCA Version" +#define SDCA_CTL_FUNCTION_TYPE_NAME "Function Type" +#define SDCA_CTL_FUNCTION_MANUFACTURER_ID_NAME "Function Manufacturer ID" +#define SDCA_CTL_FUNCTION_ID_NAME "Function ID" +#define SDCA_CTL_FUNCTION_VERSION_NAME "Function Version" +#define SDCA_CTL_FUNCTION_EXTENSION_ID_NAME "Function Extension ID" +#define SDCA_CTL_FUNCTION_EXTENSION_VERSION_NAME "Function Extension Version" +#define SDCA_CTL_FUNCTION_STATUS_NAME "Function Status" +#define SDCA_CTL_FUNCTION_ACTION_NAME "Function Action" +#define SDCA_CTL_DEVICE_MANUFACTURER_ID_NAME "Device Manufacturer ID" +#define SDCA_CTL_DEVICE_PART_ID_NAME "Device Part ID" +#define SDCA_CTL_DEVICE_VERSION_NAME "Device Version" +#define SDCA_CTL_DEVICE_SDCA_VERSION_NAME "Device SDCA Version" + +/** + * enum sdca_access_mode - SDCA Control access mode + * + * Access modes as described in the SDCA specification v1.0 section + * 7.1.8.2. + */ +enum sdca_access_mode { + SDCA_ACCESS_MODE_RW = 0x0, + SDCA_ACCESS_MODE_DUAL = 0x1, + SDCA_ACCESS_MODE_RW1C = 0x2, + SDCA_ACCESS_MODE_RO = 0x3, + SDCA_ACCESS_MODE_RW1S = 0x4, + SDCA_ACCESS_MODE_DC = 0x5, +}; + +/** + * enum sdca_access_layer - SDCA Control access layer + * + * Access layers as described in the SDCA specification v1.0 section + * 7.1.9. + */ +enum sdca_access_layer { + SDCA_ACCESS_LAYER_USER = 1 << 0, + SDCA_ACCESS_LAYER_APPLICATION = 1 << 1, + SDCA_ACCESS_LAYER_CLASS = 1 << 2, + SDCA_ACCESS_LAYER_PLATFORM = 1 << 3, + SDCA_ACCESS_LAYER_DEVICE = 1 << 4, + SDCA_ACCESS_LAYER_EXTENSION = 1 << 5, +}; + +/** + * struct sdca_control - information for one SDCA Control + * @label: Name for the Control, from SDCA Specification v1.0, section 7.1.7. + * @sel: Identifier used for addressing. + * @value: Holds the Control value for constants and defaults. + * @nbits: Number of bits used in the Control. + * @interrupt_position: SCDA interrupt line that will alert to changes on this + * Control. + * @cn_list: A bitmask showing the valid Control Numbers within this Control, + * Control Numbers typically represent channels. + * @mode: Access mode of the Control. + * @layers: Bitmask of access layers of the Control. + * @deferrable: Indicates if the access to the Control can be deferred. + * @has_default: Indicates the Control has a default value to be written. + * @has_fixed: Indicates the Control only supports a single value. + */ +struct sdca_control { + const char *label; + int sel; + + int value; + int nbits; + int interrupt_position; + u64 cn_list; + + enum sdca_access_mode mode; + u8 layers; + + bool deferrable; + bool has_default; + bool has_fixed; +}; + /** * enum sdca_entity_type - SDCA Entity Type codes * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the @@ -173,7 +703,9 @@ enum sdca_entity_type { * @type: Type code for the Entity. * @sources: Dynamically allocated array pointing to each input Entity * connected to this Entity. + * @controls: Dynamically allocated array of Controls. * @num_sources: Number of sources for the Entity. + * @num_controls: Number of Controls for the Entity. */ struct sdca_entity { const char *label; @@ -181,7 +713,9 @@ struct sdca_entity { enum sdca_entity_type type; struct sdca_entity **sources; + struct sdca_control *controls; int num_sources; + int num_controls; }; /** diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index b0ca92f1bc57..e495ccc5b4b6 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -242,6 +242,537 @@ static int find_sdca_init_table(struct device *dev, return 0; } +static const char *find_sdca_control_label(const struct sdca_entity *entity, + const struct sdca_control *control) +{ + switch (SDCA_CTL_TYPE(entity->type, control->sel)) { + case SDCA_CTL_TYPE_S(IT, MIC_BIAS): + return SDCA_CTL_MIC_BIAS_NAME; + case SDCA_CTL_TYPE_S(IT, USAGE): + case SDCA_CTL_TYPE_S(OT, USAGE): + return SDCA_CTL_USAGE_NAME; + case SDCA_CTL_TYPE_S(IT, LATENCY): + case SDCA_CTL_TYPE_S(OT, LATENCY): + case SDCA_CTL_TYPE_S(MU, LATENCY): + case SDCA_CTL_TYPE_S(SU, LATENCY): + case SDCA_CTL_TYPE_S(FU, LATENCY): + case SDCA_CTL_TYPE_S(XU, LATENCY): + case SDCA_CTL_TYPE_S(CRU, LATENCY): + case SDCA_CTL_TYPE_S(UDMPU, LATENCY): + case SDCA_CTL_TYPE_S(MFPU, LATENCY): + case SDCA_CTL_TYPE_S(SMPU, LATENCY): + case SDCA_CTL_TYPE_S(SAPU, LATENCY): + case SDCA_CTL_TYPE_S(PPU, LATENCY): + return SDCA_CTL_LATENCY_NAME; + case SDCA_CTL_TYPE_S(IT, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(CRU, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(UDMPU, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(MFPU, CLUSTERINDEX): + return SDCA_CTL_CLUSTERINDEX_NAME; + case SDCA_CTL_TYPE_S(IT, DATAPORT_SELECTOR): + case SDCA_CTL_TYPE_S(OT, DATAPORT_SELECTOR): + return SDCA_CTL_DATAPORT_SELECTOR_NAME; + case SDCA_CTL_TYPE_S(IT, MATCHING_GUID): + case SDCA_CTL_TYPE_S(OT, MATCHING_GUID): + case SDCA_CTL_TYPE_S(ENTITY_0, MATCHING_GUID): + return SDCA_CTL_MATCHING_GUID_NAME; + case SDCA_CTL_TYPE_S(IT, KEEP_ALIVE): + case SDCA_CTL_TYPE_S(OT, KEEP_ALIVE): + return SDCA_CTL_KEEP_ALIVE_NAME; + case SDCA_CTL_TYPE_S(IT, NDAI_STREAM): + case SDCA_CTL_TYPE_S(OT, NDAI_STREAM): + return SDCA_CTL_NDAI_STREAM_NAME; + case SDCA_CTL_TYPE_S(IT, NDAI_CATEGORY): + case SDCA_CTL_TYPE_S(OT, NDAI_CATEGORY): + return SDCA_CTL_NDAI_CATEGORY_NAME; + case SDCA_CTL_TYPE_S(IT, NDAI_CODINGTYPE): + case SDCA_CTL_TYPE_S(OT, NDAI_CODINGTYPE): + return SDCA_CTL_NDAI_CODINGTYPE_NAME; + case SDCA_CTL_TYPE_S(IT, NDAI_PACKETTYPE): + case SDCA_CTL_TYPE_S(OT, NDAI_PACKETTYPE): + return SDCA_CTL_NDAI_PACKETTYPE_NAME; + case SDCA_CTL_TYPE_S(MU, MIXER): + return SDCA_CTL_MIXER_NAME; + case SDCA_CTL_TYPE_S(SU, SELECTOR): + return SDCA_CTL_SELECTOR_NAME; + case SDCA_CTL_TYPE_S(FU, MUTE): + return SDCA_CTL_MUTE_NAME; + case SDCA_CTL_TYPE_S(FU, CHANNEL_VOLUME): + return SDCA_CTL_CHANNEL_VOLUME_NAME; + case SDCA_CTL_TYPE_S(FU, AGC): + return SDCA_CTL_AGC_NAME; + case SDCA_CTL_TYPE_S(FU, BASS_BOOST): + return SDCA_CTL_BASS_BOOST_NAME; + case SDCA_CTL_TYPE_S(FU, LOUDNESS): + return SDCA_CTL_LOUDNESS_NAME; + case SDCA_CTL_TYPE_S(FU, GAIN): + return SDCA_CTL_GAIN_NAME; + case SDCA_CTL_TYPE_S(XU, BYPASS): + case SDCA_CTL_TYPE_S(MFPU, BYPASS): + return SDCA_CTL_BYPASS_NAME; + case SDCA_CTL_TYPE_S(XU, XU_ID): + return SDCA_CTL_XU_ID_NAME; + case SDCA_CTL_TYPE_S(XU, XU_VERSION): + return SDCA_CTL_XU_VERSION_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): + return SDCA_CTL_FDL_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGEOFFSET): + return SDCA_CTL_FDL_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGELENGTH): + return SDCA_CTL_FDL_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_STATUS): + return SDCA_CTL_FDL_STATUS_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_SET_INDEX): + return SDCA_CTL_FDL_SET_INDEX_NAME; + case SDCA_CTL_TYPE_S(XU, FDL_HOST_REQUEST): + return SDCA_CTL_FDL_HOST_REQUEST_NAME; + case SDCA_CTL_TYPE_S(CS, CLOCK_VALID): + return SDCA_CTL_CLOCK_VALID_NAME; + case SDCA_CTL_TYPE_S(CS, SAMPLERATEINDEX): + return SDCA_CTL_SAMPLERATEINDEX_NAME; + case SDCA_CTL_TYPE_S(CX, CLOCK_SELECT): + return SDCA_CTL_CLOCK_SELECT_NAME; + case SDCA_CTL_TYPE_S(PDE, REQUESTED_PS): + return SDCA_CTL_REQUESTED_PS_NAME; + case SDCA_CTL_TYPE_S(PDE, ACTUAL_PS): + return SDCA_CTL_ACTUAL_PS_NAME; + case SDCA_CTL_TYPE_S(GE, SELECTED_MODE): + return SDCA_CTL_SELECTED_MODE_NAME; + case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): + return SDCA_CTL_DETECTED_MODE_NAME; + case SDCA_CTL_TYPE_S(SPE, PRIVATE): + return SDCA_CTL_PRIVATE_NAME; + case SDCA_CTL_TYPE_S(SPE, PRIVACY_POLICY): + return SDCA_CTL_PRIVACY_POLICY_NAME; + case SDCA_CTL_TYPE_S(SPE, PRIVACY_LOCKSTATE): + return SDCA_CTL_PRIVACY_LOCKSTATE_NAME; + case SDCA_CTL_TYPE_S(SPE, PRIVACY_OWNER): + return SDCA_CTL_PRIVACY_OWNER_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHTX_CURRENTOWNER): + return SDCA_CTL_AUTHTX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGEOFFSET): + return SDCA_CTL_AUTHTX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGELENGTH): + return SDCA_CTL_AUTHTX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHRX_CURRENTOWNER): + return SDCA_CTL_AUTHRX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGEOFFSET): + return SDCA_CTL_AUTHRX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGELENGTH): + return SDCA_CTL_AUTHRX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(UDMPU, ACOUSTIC_ENERGY_LEVEL_MONITOR): + return SDCA_CTL_ACOUSTIC_ENERGY_LEVEL_MONITOR_NAME; + case SDCA_CTL_TYPE_S(UDMPU, ULTRASOUND_LOOP_GAIN): + return SDCA_CTL_ULTRASOUND_LOOP_GAIN_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_0): + return SDCA_CTL_OPAQUESET_0_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_1): + return SDCA_CTL_OPAQUESET_1_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_2): + return SDCA_CTL_OPAQUESET_2_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_3): + return SDCA_CTL_OPAQUESET_3_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_4): + return SDCA_CTL_OPAQUESET_4_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_5): + return SDCA_CTL_OPAQUESET_5_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_6): + return SDCA_CTL_OPAQUESET_6_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_7): + return SDCA_CTL_OPAQUESET_7_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_8): + return SDCA_CTL_OPAQUESET_8_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_9): + return SDCA_CTL_OPAQUESET_9_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_10): + return SDCA_CTL_OPAQUESET_10_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_11): + return SDCA_CTL_OPAQUESET_11_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_12): + return SDCA_CTL_OPAQUESET_12_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_13): + return SDCA_CTL_OPAQUESET_13_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_14): + return SDCA_CTL_OPAQUESET_14_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_15): + return SDCA_CTL_OPAQUESET_15_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_16): + return SDCA_CTL_OPAQUESET_16_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_17): + return SDCA_CTL_OPAQUESET_17_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_18): + return SDCA_CTL_OPAQUESET_18_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_19): + return SDCA_CTL_OPAQUESET_19_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_20): + return SDCA_CTL_OPAQUESET_20_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_21): + return SDCA_CTL_OPAQUESET_21_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_22): + return SDCA_CTL_OPAQUESET_22_NAME; + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_23): + return SDCA_CTL_OPAQUESET_23_NAME; + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_READY): + return SDCA_CTL_ALGORITHM_READY_NAME; + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_ENABLE): + return SDCA_CTL_ALGORITHM_ENABLE_NAME; + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_PREPARE): + return SDCA_CTL_ALGORITHM_PREPARE_NAME; + case SDCA_CTL_TYPE_S(MFPU, CENTER_FREQUENCY_INDEX): + return SDCA_CTL_CENTER_FREQUENCY_INDEX_NAME; + case SDCA_CTL_TYPE_S(MFPU, ULTRASOUND_LEVEL): + return SDCA_CTL_ULTRASOUND_LEVEL_NAME; + case SDCA_CTL_TYPE_S(MFPU, AE_NUMBER): + return SDCA_CTL_AE_NUMBER_NAME; + case SDCA_CTL_TYPE_S(MFPU, AE_CURRENTOWNER): + return SDCA_CTL_AE_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGEOFFSET): + return SDCA_CTL_AE_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGELENGTH): + return SDCA_CTL_AE_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_ENABLE): + return SDCA_CTL_TRIGGER_ENABLE_NAME; + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_STATUS): + return SDCA_CTL_TRIGGER_STATUS_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_BUFFER_MODE): + return SDCA_CTL_HIST_BUFFER_MODE_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_BUFFER_PREAMBLE): + return SDCA_CTL_HIST_BUFFER_PREAMBLE_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_ERROR): + return SDCA_CTL_HIST_ERROR_NAME; + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_EXTENSION): + return SDCA_CTL_TRIGGER_EXTENSION_NAME; + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_READY): + return SDCA_CTL_TRIGGER_READY_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_CURRENTOWNER): + return SDCA_CTL_HIST_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGEOFFSET): + return SDCA_CTL_HIST_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGELENGTH): + return SDCA_CTL_HIST_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODTX_CURRENTOWNER): + return SDCA_CTL_DTODTX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGEOFFSET): + return SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGELENGTH): + return SDCA_CTL_DTODTX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODRX_CURRENTOWNER): + return SDCA_CTL_DTODRX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGEOFFSET): + return SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGELENGTH): + return SDCA_CTL_DTODRX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SAPU, PROTECTION_MODE): + return SDCA_CTL_PROTECTION_MODE_NAME; + case SDCA_CTL_TYPE_S(SAPU, PROTECTION_STATUS): + return SDCA_CTL_PROTECTION_STATUS_NAME; + case SDCA_CTL_TYPE_S(SAPU, OPAQUESETREQ_INDEX): + return SDCA_CTL_OPAQUESETREQ_INDEX_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODTX_CURRENTOWNER): + return SDCA_CTL_DTODTX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGEOFFSET): + return SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGELENGTH): + return SDCA_CTL_DTODTX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODRX_CURRENTOWNER): + return SDCA_CTL_DTODRX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGEOFFSET): + return SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGELENGTH): + return SDCA_CTL_DTODRX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(PPU, POSTURENUMBER): + return SDCA_CTL_POSTURENUMBER_NAME; + case SDCA_CTL_TYPE_S(PPU, POSTUREEXTENSION): + return SDCA_CTL_POSTUREEXTENSION_NAME; + case SDCA_CTL_TYPE_S(PPU, HORIZONTALBALANCE): + return SDCA_CTL_HORIZONTALBALANCE_NAME; + case SDCA_CTL_TYPE_S(PPU, VERTICALBALANCE): + return SDCA_CTL_VERTICALBALANCE_NAME; + case SDCA_CTL_TYPE_S(TG, TONE_DIVIDER): + return SDCA_CTL_TONE_DIVIDER_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER): + return SDCA_CTL_HIDTX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGEOFFSET): + return SDCA_CTL_HIDTX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGELENGTH): + return SDCA_CTL_HIDTX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDRX_CURRENTOWNER): + return SDCA_CTL_HIDRX_CURRENTOWNER_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGEOFFSET): + return SDCA_CTL_HIDRX_MESSAGEOFFSET_NAME; + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGELENGTH): + return SDCA_CTL_HIDRX_MESSAGELENGTH_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, COMMIT_GROUP_MASK): + return SDCA_CTL_COMMIT_GROUP_MASK_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_SDCA_VERSION): + return SDCA_CTL_FUNCTION_SDCA_VERSION_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_TYPE): + return SDCA_CTL_FUNCTION_TYPE_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_MANUFACTURER_ID): + return SDCA_CTL_FUNCTION_MANUFACTURER_ID_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_ID): + return SDCA_CTL_FUNCTION_ID_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_VERSION): + return SDCA_CTL_FUNCTION_VERSION_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_EXTENSION_ID): + return SDCA_CTL_FUNCTION_EXTENSION_ID_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_EXTENSION_VERSION): + return SDCA_CTL_FUNCTION_EXTENSION_VERSION_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS): + return SDCA_CTL_FUNCTION_STATUS_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_ACTION): + return SDCA_CTL_FUNCTION_ACTION_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_MANUFACTURER_ID): + return SDCA_CTL_DEVICE_MANUFACTURER_ID_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_PART_ID): + return SDCA_CTL_DEVICE_PART_ID_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_VERSION): + return SDCA_CTL_DEVICE_VERSION_NAME; + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_SDCA_VERSION): + return SDCA_CTL_DEVICE_SDCA_VERSION_NAME; + default: + return NULL; + } +} + +static unsigned int find_sdca_control_bits(const struct sdca_entity *entity, + const struct sdca_control *control) +{ + switch (SDCA_CTL_TYPE(entity->type, control->sel)) { + case SDCA_CTL_TYPE_S(IT, LATENCY): + case SDCA_CTL_TYPE_S(OT, LATENCY): + case SDCA_CTL_TYPE_S(MU, LATENCY): + case SDCA_CTL_TYPE_S(SU, LATENCY): + case SDCA_CTL_TYPE_S(FU, LATENCY): + case SDCA_CTL_TYPE_S(XU, LATENCY): + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(CRU, LATENCY): + case SDCA_CTL_TYPE_S(UDMPU, LATENCY): + case SDCA_CTL_TYPE_S(MFPU, LATENCY): + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, LATENCY): + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SAPU, LATENCY): + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(PPU, LATENCY): + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGELENGTH): + return 32; + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_MANUFACTURER_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_EXTENSION_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_MANUFACTURER_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_PART_ID): + case SDCA_CTL_TYPE_S(IT, DATAPORT_SELECTOR): + case SDCA_CTL_TYPE_S(OT, DATAPORT_SELECTOR): + case SDCA_CTL_TYPE_S(MU, MIXER): + case SDCA_CTL_TYPE_S(FU, CHANNEL_VOLUME): + case SDCA_CTL_TYPE_S(FU, GAIN): + case SDCA_CTL_TYPE_S(XU, XU_ID): + case SDCA_CTL_TYPE_S(UDMPU, ACOUSTIC_ENERGY_LEVEL_MONITOR): + case SDCA_CTL_TYPE_S(UDMPU, ULTRASOUND_LOOP_GAIN): + case SDCA_CTL_TYPE_S(MFPU, ULTRASOUND_LEVEL): + case SDCA_CTL_TYPE_S(PPU, HORIZONTALBALANCE): + case SDCA_CTL_TYPE_S(PPU, VERTICALBALANCE): + return 16; + case SDCA_CTL_TYPE_S(FU, MUTE): + case SDCA_CTL_TYPE_S(FU, AGC): + case SDCA_CTL_TYPE_S(FU, BASS_BOOST): + case SDCA_CTL_TYPE_S(FU, LOUDNESS): + case SDCA_CTL_TYPE_S(XU, BYPASS): + case SDCA_CTL_TYPE_S(MFPU, BYPASS): + return 1; + default: + return 8; + } +} + +/* + * TODO: Add support for -cn- properties, allowing different channels to have + * different defaults etc. + */ +static int find_sdca_entity_control(struct device *dev, struct sdca_entity *entity, + struct fwnode_handle *control_node, + struct sdca_control *control) +{ + u32 tmp; + int ret; + + ret = fwnode_property_read_u32(control_node, "mipi-sdca-control-access-mode", &tmp); + if (ret) { + dev_err(dev, "%s: control %#x: access mode missing: %d\n", + entity->label, control->sel, ret); + return ret; + } + + control->mode = tmp; + + ret = fwnode_property_read_u32(control_node, "mipi-sdca-control-access-layer", &tmp); + if (ret) { + dev_err(dev, "%s: control %#x: access layer missing: %d\n", + entity->label, control->sel, ret); + return ret; + } + + control->layers = tmp; + + switch (control->mode) { + case SDCA_ACCESS_MODE_DC: + ret = fwnode_property_read_u32(control_node, + "mipi-sdca-control-dc-value", + &tmp); + if (ret) { + dev_err(dev, "%s: control %#x: dc value missing: %d\n", + entity->label, control->sel, ret); + return ret; + } + + control->value = tmp; + control->has_fixed = true; + break; + case SDCA_ACCESS_MODE_RW: + case SDCA_ACCESS_MODE_DUAL: + ret = fwnode_property_read_u32(control_node, + "mipi-sdca-control-default-value", + &tmp); + if (!ret) { + control->value = tmp; + control->has_default = true; + } + + ret = fwnode_property_read_u32(control_node, + "mipi-sdca-control-fixed-value", + &tmp); + if (!ret) { + if (control->has_default && control->value != tmp) { + dev_err(dev, + "%s: control %#x: default and fixed value don't match\n", + entity->label, control->sel); + return -EINVAL; + } + + control->value = tmp; + control->has_fixed = true; + } + + control->deferrable = fwnode_property_read_bool(control_node, + "mipi-sdca-control-deferrable"); + break; + default: + break; + } + + ret = fwnode_property_read_u64(control_node, "mipi-sdca-control-cn-list", + &control->cn_list); + if (ret == -EINVAL) { + /* Spec allows not specifying cn-list if only the first number is used */ + control->cn_list = 0x1; + } else if (ret || !control->cn_list) { + dev_err(dev, "%s: control %#x: cn list missing: %d\n", + entity->label, control->sel, ret); + return ret; + } + + ret = fwnode_property_read_u32(control_node, + "mipi-sdca-control-interrupt-position", + &tmp); + if (!ret) + control->interrupt_position = tmp; + + control->label = find_sdca_control_label(entity, control); + if (!control->label) { + dev_err(dev, "%s: control %#x: name not found\n", + entity->label, control->sel); + return -EINVAL; + } + + control->nbits = find_sdca_control_bits(entity, control); + + dev_info(dev, "%s: %s: control %#x mode %#x layers %#x cn %#llx int %d value %#x %s\n", + entity->label, control->label, control->sel, + control->mode, control->layers, control->cn_list, + control->interrupt_position, control->value, + control->deferrable ? "deferrable" : ""); + + return 0; +} + +static int find_sdca_entity_controls(struct device *dev, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_control *controls; + int num_controls; + u64 control_list; + int control_sel; + int i, ret; + + ret = fwnode_property_read_u64(entity_node, "mipi-sdca-control-list", &control_list); + if (ret == -EINVAL) { + /* Allow missing control lists, assume no controls. */ + dev_warn(dev, "%s: missing control list\n", entity->label); + return 0; + } else if (ret) { + dev_err(dev, "%s: failed to read control list: %d\n", entity->label, ret); + return ret; + } else if (!control_list) { + return 0; + } + + num_controls = hweight64(control_list); + controls = devm_kcalloc(dev, num_controls, sizeof(*controls), GFP_KERNEL); + if (!controls) + return -ENOMEM; + + i = 0; + for_each_set_bit(control_sel, (unsigned long *)&control_list, + BITS_PER_TYPE(control_list)) { + struct fwnode_handle *control_node; + char control_property[SDCA_PROPERTY_LENGTH]; + + /* DisCo uses upper-case for hex numbers */ + snprintf(control_property, sizeof(control_property), + "mipi-sdca-control-0x%X-subproperties", control_sel); + + control_node = fwnode_get_named_child_node(entity_node, control_property); + if (!control_node) { + dev_err(dev, "%s: control node %s not found\n", + entity->label, control_property); + return -EINVAL; + } + + controls[i].sel = control_sel; + + ret = find_sdca_entity_control(dev, entity, control_node, &controls[i]); + fwnode_handle_put(control_node); + if (ret) + return ret; + + i++; + } + + entity->num_controls = num_controls; + entity->controls = controls; + + return 0; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -269,6 +800,10 @@ static int find_sdca_entity(struct device *dev, dev_info(dev, "%s: entity %#x type %#x\n", entity->label, entity->id, entity->type); + ret = find_sdca_entity_controls(dev, entity_node, entity); + if (ret) + return ret; + return 0; } @@ -338,6 +873,10 @@ static int find_sdca_entities(struct device *dev, */ entities[num_entities].label = "entity0"; + ret = find_sdca_entity_controls(dev, function_node, &entities[num_entities]); + if (ret) + return ret; + function->num_entities = num_entities + 1; function->entities = entities; From 64fb5af1d1bbcf1b808e9bb092b22fa1b691ae63 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:57 +0000 Subject: [PATCH 0106/1090] ASoC: SDCA: Add parsing for Control range structures DisCo/SDCA contains small buffers of data that hold ranges of valid values for the various SDCA Controls. Add support for parsing these from ACPI. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 14 ++++++++++ sound/soc/sdca/sdca_functions.c | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 64043090fe76..769ae6841064 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -612,6 +612,18 @@ enum sdca_access_layer { SDCA_ACCESS_LAYER_EXTENSION = 1 << 5, }; +/** + * struct sdca_control_range - SDCA Control range table + * @cols: Number of columns in the range table. + * @rows: Number of rows in the range table. + * @data: Array of values contained in the range table. + */ +struct sdca_control_range { + unsigned int cols; + unsigned int rows; + u32 *data; +}; + /** * struct sdca_control - information for one SDCA Control * @label: Name for the Control, from SDCA Specification v1.0, section 7.1.7. @@ -622,6 +634,7 @@ enum sdca_access_layer { * Control. * @cn_list: A bitmask showing the valid Control Numbers within this Control, * Control Numbers typically represent channels. + * @range: Buffer describing valid range of values for the Control. * @mode: Access mode of the Control. * @layers: Bitmask of access layers of the Control. * @deferrable: Indicates if the access to the Control can be deferred. @@ -637,6 +650,7 @@ struct sdca_control { int interrupt_position; u64 cn_list; + struct sdca_control_range range; enum sdca_access_mode mode; u8 layers; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index e495ccc5b4b6..d65b413f6d2f 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -603,6 +603,44 @@ static unsigned int find_sdca_control_bits(const struct sdca_entity *entity, } } +static int find_sdca_control_range(struct device *dev, + struct fwnode_handle *control_node, + struct sdca_control_range *range) +{ + u8 *range_list; + int num_range; + u16 *limits; + int i; + + num_range = fwnode_property_count_u8(control_node, "mipi-sdca-control-range"); + if (!num_range || num_range == -EINVAL) + return 0; + else if (num_range < 0) + return num_range; + + range_list = devm_kcalloc(dev, num_range, sizeof(*range_list), GFP_KERNEL); + if (!range_list) + return -ENOMEM; + + fwnode_property_read_u8_array(control_node, "mipi-sdca-control-range", + range_list, num_range); + + limits = (u16 *)range_list; + + range->cols = le16_to_cpu(limits[0]); + range->rows = le16_to_cpu(limits[1]); + range->data = (u32 *)&limits[2]; + + num_range = (num_range - (2 * sizeof(*limits))) / sizeof(*range->data); + if (num_range != range->cols * range->rows) + return -EINVAL; + + for (i = 0; i < num_range; i++) + range->data[i] = le32_to_cpu(range->data[i]); + + return 0; +} + /* * TODO: Add support for -cn- properties, allowing different channels to have * different defaults etc. @@ -678,6 +716,13 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti break; } + ret = find_sdca_control_range(dev, control_node, &control->range); + if (ret) { + dev_err(dev, "%s: control %#x: range missing: %d\n", + entity->label, control->sel, ret); + return ret; + } + ret = fwnode_property_read_u64(control_node, "mipi-sdca-control-cn-list", &control->cn_list); if (ret == -EINVAL) { From f87c2a275033120e15213f3d65234d98e726c4b7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:58 +0000 Subject: [PATCH 0107/1090] ASoC: SDCA: Add Channel Cluster parsing Within SDCA collections of Channels are referred to as Clusters, each Channel within a Cluster can have various properties attached to it. For example a stereo audio stream, would have a Cluster with 2 Channels one marked as left and the other as right. Various Clusters are specified in DisCo/ACPI and controls then allow the class driver to select between these channel configurations. Add support for parsing these Cluster definitions. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-8-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 170 ++++++++++++++++++++++++++++++++ sound/soc/sdca/sdca_functions.c | 165 +++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 769ae6841064..bc6e12b2211d 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -26,6 +26,18 @@ struct sdca_function_desc; */ #define SDCA_MAX_INIT_COUNT 2048 +/* + * The Cluster IDs are 16-bit, so a maximum of 65535 Clusters per + * function can be represented, however limit this to a slightly + * more reasonable value. Can be expanded if needed. + */ +#define SDCA_MAX_CLUSTER_COUNT 256 + +/* + * Sanity check on number of channels per Cluster, can be expanded if needed. + */ +#define SDCA_MAX_CHANNEL_COUNT 32 + /** * enum sdca_function_type - SDCA Function Type codes * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. @@ -732,13 +744,169 @@ struct sdca_entity { int num_controls; }; +/** + * enum sdca_channel_purpose - SDCA Channel Purpose code + * + * Channel Purpose codes as described in the SDCA specification v1.0 + * section 11.4.3. + */ +enum sdca_channel_purpose { + /* Table 210 - Purpose */ + SDCA_CHAN_PURPOSE_GENERIC_AUDIO = 0x01, + SDCA_CHAN_PURPOSE_VOICE = 0x02, + SDCA_CHAN_PURPOSE_SPEECH = 0x03, + SDCA_CHAN_PURPOSE_AMBIENT = 0x04, + SDCA_CHAN_PURPOSE_REFERENCE = 0x05, + SDCA_CHAN_PURPOSE_ULTRASOUND = 0x06, + SDCA_CHAN_PURPOSE_SENSE = 0x08, + SDCA_CHAN_PURPOSE_SILENCE = 0xFE, + SDCA_CHAN_PURPOSE_NON_AUDIO = 0xFF, + /* Table 211 - Amp Sense */ + SDCA_CHAN_PURPOSE_SENSE_V1 = 0x09, + SDCA_CHAN_PURPOSE_SENSE_V2 = 0x0A, + SDCA_CHAN_PURPOSE_SENSE_V12_INTERLEAVED = 0x10, + SDCA_CHAN_PURPOSE_SENSE_V21_INTERLEAVED = 0x11, + SDCA_CHAN_PURPOSE_SENSE_V12_PACKED = 0x12, + SDCA_CHAN_PURPOSE_SENSE_V21_PACKED = 0x13, + SDCA_CHAN_PURPOSE_SENSE_V1212_INTERLEAVED = 0x14, + SDCA_CHAN_PURPOSE_SENSE_V2121_INTERLEAVED = 0x15, + SDCA_CHAN_PURPOSE_SENSE_V1122_INTERLEAVED = 0x16, + SDCA_CHAN_PURPOSE_SENSE_V2211_INTERLEAVED = 0x17, + SDCA_CHAN_PURPOSE_SENSE_V1212_PACKED = 0x18, + SDCA_CHAN_PURPOSE_SENSE_V2121_PACKED = 0x19, + SDCA_CHAN_PURPOSE_SENSE_V1122_PACKED = 0x1A, + SDCA_CHAN_PURPOSE_SENSE_V2211_PACKED = 0x1B, +}; + +/** + * enum sdca_channel_relationship - SDCA Channel Relationship code + * + * Channel Relationship codes as described in the SDCA specification + * v1.0 section 11.4.2. + */ +enum sdca_channel_relationship { + /* Table 206 - Streaming */ + SDCA_CHAN_REL_UNDEFINED = 0x00, + SDCA_CHAN_REL_GENERIC_MONO = 0x01, + SDCA_CHAN_REL_GENERIC_LEFT = 0x02, + SDCA_CHAN_REL_GENERIC_RIGHT = 0x03, + SDCA_CHAN_REL_GENERIC_TOP = 0x48, + SDCA_CHAN_REL_GENERIC_BOTTOM = 0x49, + SDCA_CHAN_REL_CAPTURE_DIRECT = 0x4E, + SDCA_CHAN_REL_RENDER_DIRECT = 0x4F, + SDCA_CHAN_REL_FRONT_LEFT = 0x0B, + SDCA_CHAN_REL_FRONT_RIGHT = 0x0C, + SDCA_CHAN_REL_FRONT_CENTER = 0x0D, + SDCA_CHAN_REL_SIDE_LEFT = 0x12, + SDCA_CHAN_REL_SIDE_RIGHT = 0x13, + SDCA_CHAN_REL_BACK_LEFT = 0x16, + SDCA_CHAN_REL_BACK_RIGHT = 0x17, + SDCA_CHAN_REL_LOW_FREQUENCY_EFFECTS = 0x43, + SDCA_CHAN_REL_SOUNDWIRE_MIC = 0x55, + SDCA_CHAN_REL_SENSE_TRANSDUCER_1 = 0x58, + SDCA_CHAN_REL_SENSE_TRANSDUCER_2 = 0x59, + SDCA_CHAN_REL_SENSE_TRANSDUCER_12 = 0x5A, + SDCA_CHAN_REL_SENSE_TRANSDUCER_21 = 0x5B, + SDCA_CHAN_REL_ECHOREF_NONE = 0x70, + SDCA_CHAN_REL_ECHOREF_1 = 0x71, + SDCA_CHAN_REL_ECHOREF_2 = 0x72, + SDCA_CHAN_REL_ECHOREF_3 = 0x73, + SDCA_CHAN_REL_ECHOREF_4 = 0x74, + SDCA_CHAN_REL_ECHOREF_ALL = 0x75, + SDCA_CHAN_REL_ECHOREF_LFE_ALL = 0x76, + /* Table 207 - Speaker */ + SDCA_CHAN_REL_PRIMARY_TRANSDUCER = 0x50, + SDCA_CHAN_REL_SECONDARY_TRANSDUCER = 0x51, + SDCA_CHAN_REL_TERTIARY_TRANSDUCER = 0x52, + SDCA_CHAN_REL_LOWER_LEFT_ALLTRANSDUCER = 0x60, + SDCA_CHAN_REL_LOWER_RIGHT_ALLTRANSDUCER = 0x61, + SDCA_CHAN_REL_UPPER_LEFT_ALLTRANSDUCER = 0x62, + SDCA_CHAN_REL_UPPER_RIGHT_ALLTRANSDUCER = 0x63, + SDCA_CHAN_REL_LOWER_LEFT_PRIMARY = 0x64, + SDCA_CHAN_REL_LOWER_RIGHT_PRIMARY = 0x65, + SDCA_CHAN_REL_UPPER_LEFT_PRIMARY = 0x66, + SDCA_CHAN_REL_UPPER_RIGHT_PRIMARY = 0x67, + SDCA_CHAN_REL_LOWER_LEFT_SECONDARY = 0x68, + SDCA_CHAN_REL_LOWER_RIGHT_SECONDARY = 0x69, + SDCA_CHAN_REL_UPPER_LEFT_SECONDARY = 0x6A, + SDCA_CHAN_REL_UPPER_RIGHT_SECONDARY = 0x6B, + SDCA_CHAN_REL_LOWER_LEFT_TERTIARY = 0x6C, + SDCA_CHAN_REL_LOWER_RIGHT_TERTIARY = 0x6D, + SDCA_CHAN_REL_UPPER_LEFT_TERTIARY = 0x6E, + SDCA_CHAN_REL_UPPER_RIGHT_TERTIARY = 0x6F, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_PRIMARY = 0x94, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_PRIMARY = 0x95, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_PRIMARY = 0x96, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_PRIMARY = 0x97, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_SECONDARY = 0x98, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_SECONDARY = 0x99, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_SECONDARY = 0x9A, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_SECONDARY = 0x9B, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_TERTIARY = 0x9C, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_TERTIARY = 0x9D, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_TERTIARY = 0x9E, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_TERTIARY = 0x9F, + SDCA_CHAN_REL_DERIVED_MONO_PRIMARY = 0xA0, + SDCA_CHAN_REL_DERIVED_MONO_SECONDARY = 0xAB, + SDCA_CHAN_REL_DERIVED_MONO_TERTIARY = 0xAC, + /* Table 208 - Equipment */ + SDCA_CHAN_REL_EQUIPMENT_LEFT = 0x02, + SDCA_CHAN_REL_EQUIPMENT_RIGHT = 0x03, + SDCA_CHAN_REL_EQUIPMENT_COMBINED = 0x47, + SDCA_CHAN_REL_EQUIPMENT_TOP = 0x48, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM = 0x49, + SDCA_CHAN_REL_EQUIPMENT_TOP_LEFT = 0x4A, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM_LEFT = 0x4B, + SDCA_CHAN_REL_EQUIPMENT_TOP_RIGHT = 0x4C, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM_RIGHT = 0x4D, + SDCA_CHAN_REL_EQUIPMENT_SILENCED_OUTPUT = 0x57, + /* Table 209 - Other */ + SDCA_CHAN_REL_ARRAY = 0x04, + SDCA_CHAN_REL_MIC = 0x53, + SDCA_CHAN_REL_RAW = 0x54, + SDCA_CHAN_REL_SILENCED_MIC = 0x56, + SDCA_CHAN_REL_MULTI_SOURCE_1 = 0x78, + SDCA_CHAN_REL_MULTI_SOURCE_2 = 0x79, + SDCA_CHAN_REL_MULTI_SOURCE_3 = 0x7A, + SDCA_CHAN_REL_MULTI_SOURCE_4 = 0x7B, +}; + +/** + * struct sdca_channel - a single Channel with a Cluster + * @id: Identifier used for addressing. + * @purpose: Indicates the purpose of the Channel, usually to give + * semantic meaning to the audio, eg. voice, ultrasound. + * @relationship: Indicates the relationship of this Channel to others + * in the Cluster, often used to identify the physical position of the + * Channel eg. left. + */ +struct sdca_channel { + int id; + enum sdca_channel_purpose purpose; + enum sdca_channel_relationship relationship; +}; + +/** + * struct sdca_cluster - information about an SDCA Channel Cluster + * @id: Identifier used for addressing. + * @num_channels: Number of Channels within this Cluster. + * @channels: Dynamically allocated array of Channels. + */ +struct sdca_cluster { + int id; + int num_channels; + struct sdca_channel *channels; +}; + /** * struct sdca_function_data - top-level information for one SDCA function * @desc: Pointer to short descriptor from initial parsing. * @init_table: Pointer to a table of initialization writes. * @entities: Dynamically allocated array of Entities. + * @clusters: Dynamically allocated array of Channel Clusters. * @num_init_table: Number of initialization writes. * @num_entities: Number of Entities reported in this Function. + * @num_clusters: Number of Channel Clusters reported in this Function. * @busy_max_delay: Maximum Function busy delay in microseconds, before an * error should be reported. */ @@ -747,8 +915,10 @@ struct sdca_function_data { struct sdca_init_write *init_table; struct sdca_entity *entities; + struct sdca_cluster *clusters; int num_init_table; int num_entities; + int num_clusters; unsigned int busy_max_delay; }; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index d65b413f6d2f..4de25f485755 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -1059,6 +1059,167 @@ static int find_sdca_connections(struct device *dev, return 0; } +static int find_sdca_cluster_channel(struct device *dev, + struct sdca_cluster *cluster, + struct fwnode_handle *channel_node, + struct sdca_channel *channel) +{ + u32 tmp; + int ret; + + ret = fwnode_property_read_u32(channel_node, "mipi-sdca-cluster-channel-id", &tmp); + if (ret) { + dev_err(dev, "cluster %#x: missing channel id: %d\n", + cluster->id, ret); + return ret; + } + + channel->id = tmp; + + ret = fwnode_property_read_u32(channel_node, + "mipi-sdca-cluster-channel-purpose", + &tmp); + if (ret) { + dev_err(dev, "cluster %#x: channel %#x: missing purpose: %d\n", + cluster->id, channel->id, ret); + return ret; + } + + channel->purpose = tmp; + + ret = fwnode_property_read_u32(channel_node, + "mipi-sdca-cluster-channel-relationship", + &tmp); + if (ret) { + dev_err(dev, "cluster %#x: channel %#x: missing relationship: %d\n", + cluster->id, channel->id, ret); + return ret; + } + + channel->relationship = tmp; + + dev_info(dev, "cluster %#x: channel id %#x purpose %#x relationship %#x\n", + cluster->id, channel->id, channel->purpose, channel->relationship); + + return 0; +} + +static int find_sdca_cluster_channels(struct device *dev, + struct fwnode_handle *cluster_node, + struct sdca_cluster *cluster) +{ + struct sdca_channel *channels; + u32 num_channels; + int i, ret; + + ret = fwnode_property_read_u32(cluster_node, "mipi-sdca-channel-count", + &num_channels); + if (ret < 0) { + dev_err(dev, "cluster %#x: failed to read channel list: %d\n", + cluster->id, ret); + return ret; + } else if (num_channels > SDCA_MAX_CHANNEL_COUNT) { + dev_err(dev, "cluster %#x: maximum number of channels exceeded\n", + cluster->id); + return -EINVAL; + } + + channels = devm_kcalloc(dev, num_channels, sizeof(*channels), GFP_KERNEL); + if (!channels) + return -ENOMEM; + + for (i = 0; i < num_channels; i++) { + char channel_property[SDCA_PROPERTY_LENGTH]; + struct fwnode_handle *channel_node; + + /* DisCo uses upper-case for hex numbers */ + snprintf(channel_property, sizeof(channel_property), + "mipi-sdca-channel-%d-subproperties", i + 1); + + channel_node = fwnode_get_named_child_node(cluster_node, channel_property); + if (!channel_node) { + dev_err(dev, "cluster %#x: channel node %s not found\n", + cluster->id, channel_property); + return -EINVAL; + } + + ret = find_sdca_cluster_channel(dev, cluster, channel_node, &channels[i]); + fwnode_handle_put(channel_node); + if (ret) + return ret; + } + + cluster->num_channels = num_channels; + cluster->channels = channels; + + return 0; +} + +static int find_sdca_clusters(struct device *dev, + struct fwnode_handle *function_node, + struct sdca_function_data *function) +{ + struct sdca_cluster *clusters; + int num_clusters; + u32 *cluster_list; + int i, ret; + + num_clusters = fwnode_property_count_u32(function_node, "mipi-sdca-cluster-id-list"); + if (!num_clusters || num_clusters == -EINVAL) { + return 0; + } else if (num_clusters < 0) { + dev_err(dev, "%pfwP: failed to read cluster id list: %d\n", + function_node, num_clusters); + return num_clusters; + } else if (num_clusters > SDCA_MAX_CLUSTER_COUNT) { + dev_err(dev, "%pfwP: maximum number of clusters exceeded\n", function_node); + return -EINVAL; + } + + clusters = devm_kcalloc(dev, num_clusters, sizeof(*clusters), GFP_KERNEL); + if (!clusters) + return -ENOMEM; + + cluster_list = kcalloc(num_clusters, sizeof(*cluster_list), GFP_KERNEL); + if (!cluster_list) + return -ENOMEM; + + fwnode_property_read_u32_array(function_node, "mipi-sdca-cluster-id-list", + cluster_list, num_clusters); + + for (i = 0; i < num_clusters; i++) + clusters[i].id = cluster_list[i]; + + kfree(cluster_list); + + /* now read subproperties */ + for (i = 0; i < num_clusters; i++) { + char cluster_property[SDCA_PROPERTY_LENGTH]; + struct fwnode_handle *cluster_node; + + /* DisCo uses upper-case for hex numbers */ + snprintf(cluster_property, sizeof(cluster_property), + "mipi-sdca-cluster-id-0x%X-subproperties", clusters[i].id); + + cluster_node = fwnode_get_named_child_node(function_node, cluster_property); + if (!cluster_node) { + dev_err(dev, "%pfwP: cluster node %s not found\n", + function_node, cluster_property); + return -EINVAL; + } + + ret = find_sdca_cluster_channels(dev, cluster_node, &clusters[i]); + fwnode_handle_put(cluster_node); + if (ret) + return ret; + } + + function->num_clusters = num_clusters; + function->clusters = clusters; + + return 0; +} + /** * sdca_parse_function - parse ACPI DisCo for a Function * @dev: Pointer to device against which function data will be allocated. @@ -1096,6 +1257,10 @@ int sdca_parse_function(struct device *dev, if (ret) return ret; + ret = find_sdca_clusters(dev, function_desc->node, function); + if (ret < 0) + return ret; + return 0; } EXPORT_SYMBOL_NS(sdca_parse_function, "SND_SOC_SDCA"); From 5c93b20f6de4478e1fbcfb38eb46738bca74180e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:37:59 +0000 Subject: [PATCH 0108/1090] ASoC: SDCA: Add support for IT/OT Entity properties Add support for parsing the Input/Output Terminal Entity properties from DisCo/ACPI. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-9-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 117 +++++++++++++++++++++++++++++ sound/soc/sdca/sdca_functions.c | 127 ++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index bc6e12b2211d..6cb5ab79ee54 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -13,6 +13,7 @@ #include struct device; +struct sdca_entity; struct sdca_function_desc; /* @@ -671,6 +672,118 @@ struct sdca_control { bool has_fixed; }; +/** + * enum sdca_terminal_type - SDCA Terminal Types + * + * Indicate what a Terminal Entity is used for, see in section 6.2.3 + * of the SDCA v1.0 specification. + */ +enum sdca_terminal_type { + /* Table 77 - Data Port*/ + SDCA_TERM_TYPE_GENERIC = 0x101, + SDCA_TERM_TYPE_ULTRASOUND = 0x180, + SDCA_TERM_TYPE_CAPTURE_DIRECT_PCM_MIC = 0x181, + SDCA_TERM_TYPE_RAW_PDM_MIC = 0x182, + SDCA_TERM_TYPE_SPEECH = 0x183, + SDCA_TERM_TYPE_VOICE = 0x184, + SDCA_TERM_TYPE_SECONDARY_PCM_MIC = 0x185, + SDCA_TERM_TYPE_ACOUSTIC_CONTEXT_AWARENESS = 0x186, + SDCA_TERM_TYPE_DTOD_STREAM = 0x187, + SDCA_TERM_TYPE_REFERENCE_STREAM = 0x188, + SDCA_TERM_TYPE_SENSE_CAPTURE = 0x189, + SDCA_TERM_TYPE_STREAMING_MIC = 0x18A, + SDCA_TERM_TYPE_OPTIMIZATION_STREAM = 0x190, + SDCA_TERM_TYPE_PDM_RENDER_STREAM = 0x191, + SDCA_TERM_TYPE_COMPANION_DATA = 0x192, + /* Table 78 - Transducer */ + SDCA_TERM_TYPE_MICROPHONE_TRANSDUCER = 0x201, + SDCA_TERM_TYPE_MICROPHONE_ARRAY_TRANSDUCER = 0x205, + SDCA_TERM_TYPE_PRIMARY_FULL_RANGE_SPEAKER = 0x380, + SDCA_TERM_TYPE_PRIMARY_LFE_SPEAKER = 0x381, + SDCA_TERM_TYPE_PRIMARY_TWEETER_SPEAKER = 0x382, + SDCA_TERM_TYPE_PRIMARY_ULTRASOUND_SPEAKER = 0x383, + SDCA_TERM_TYPE_SECONDARY_FULL_RANGE_SPEAKER = 0x390, + SDCA_TERM_TYPE_SECONDARY_LFE_SPEAKER = 0x391, + SDCA_TERM_TYPE_SECONDARY_TWEETER_SPEAKER = 0x392, + SDCA_TERM_TYPE_SECONDARY_ULTRASOUND_SPEAKER = 0x393, + SDCA_TERM_TYPE_TERTIARY_FULL_RANGE_SPEAKER = 0x3A0, + SDCA_TERM_TYPE_TERTIARY_LFE_SPEAKER = 0x3A1, + SDCA_TERM_TYPE_TERTIARY_TWEETER_SPEAKER = 0x3A2, + SDCA_TERM_TYPE_TERTIARY_ULTRASOUND_SPEAKER = 0x3A3, + SDCA_TERM_TYPE_SPDIF = 0x605, + SDCA_TERM_TYPE_NDAI_DISPLAY_AUDIO = 0x610, + SDCA_TERM_TYPE_NDAI_USB = 0x612, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_MAIN = 0x614, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_ALTERNATE = 0x615, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_BOTH = 0x616, + SDCA_TERM_TYPE_LINEIN_STEREO = 0x680, + SDCA_TERM_TYPE_LINEIN_FRONT_LR = 0x681, + SDCA_TERM_TYPE_LINEIN_CENTER_LFE = 0x682, + SDCA_TERM_TYPE_LINEIN_SURROUND_LR = 0x683, + SDCA_TERM_TYPE_LINEIN_REAR_LR = 0x684, + SDCA_TERM_TYPE_LINEOUT_STEREO = 0x690, + SDCA_TERM_TYPE_LINEOUT_FRONT_LR = 0x691, + SDCA_TERM_TYPE_LINEOUT_CENTER_LFE = 0x692, + SDCA_TERM_TYPE_LINEOUT_SURROUND_LR = 0x693, + SDCA_TERM_TYPE_LINEOUT_REAR_LR = 0x694, + SDCA_TERM_TYPE_MIC_JACK = 0x6A0, + SDCA_TERM_TYPE_STEREO_JACK = 0x6B0, + SDCA_TERM_TYPE_FRONT_LR_JACK = 0x6B1, + SDCA_TERM_TYPE_CENTER_LFE_JACK = 0x6B2, + SDCA_TERM_TYPE_SURROUND_LR_JACK = 0x6B3, + SDCA_TERM_TYPE_REAR_LR_JACK = 0x6B4, + SDCA_TERM_TYPE_HEADPHONE_JACK = 0x6C0, + SDCA_TERM_TYPE_HEADSET_JACK = 0x6D0, + /* Table 79 - System */ + SDCA_TERM_TYPE_SENSE_DATA = 0x280, + SDCA_TERM_TYPE_PRIVACY_SIGNALING = 0x741, + SDCA_TERM_TYPE_PRIVACY_INDICATORS = 0x747, +}; + +/** + * enum sdca_connector_type - SDCA Connector Types + * + * Indicate the type of Connector that a Terminal Entity represents, + * see section 6.2.4 of the SDCA v1.0 specification. + */ +enum sdca_connector_type { + SDCA_CONN_TYPE_UNKNOWN = 0x00, + SDCA_CONN_TYPE_2P5MM_JACK = 0x01, + SDCA_CONN_TYPE_3P5MM_JACK = 0x02, + SDCA_CONN_TYPE_QUARTER_INCH_JACK = 0x03, + SDCA_CONN_TYPE_XLR = 0x05, + SDCA_CONN_TYPE_SPDIF_OPTICAL = 0x06, + SDCA_CONN_TYPE_RCA = 0x07, + SDCA_CONN_TYPE_DIN = 0x0E, + SDCA_CONN_TYPE_MINI_DIN = 0x0F, + SDCA_CONN_TYPE_EIAJ_OPTICAL = 0x13, + SDCA_CONN_TYPE_HDMI = 0x14, + SDCA_CONN_TYPE_DISPLAYPORT = 0x17, + SDCA_CONN_TYPE_LIGHTNING = 0x1B, + SDCA_CONN_TYPE_USB_C = 0x1E, + SDCA_CONN_TYPE_OTHER = 0xFF, +}; + +/** + * struct sdca_entity_iot - information specific to Input/Output Entities + * @clock: Pointer to the Entity providing this Terminal's clock. + * @type: Usage of the Terminal Entity. + * @connector: Physical Connector of the Terminal Entity. + * @reference: Physical Jack number of the Terminal Entity. + * @num_transducer: Number of transducers attached to the Terminal Entity. + * @is_dataport: Boolean indicating if this Terminal represents a Dataport. + */ +struct sdca_entity_iot { + struct sdca_entity *clock; + + enum sdca_terminal_type type; + enum sdca_connector_type connector; + int reference; + int num_transducer; + + bool is_dataport; +}; + /** * enum sdca_entity_type - SDCA Entity Type codes * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the @@ -732,6 +845,7 @@ enum sdca_entity_type { * @controls: Dynamically allocated array of Controls. * @num_sources: Number of sources for the Entity. * @num_controls: Number of Controls for the Entity. + * @iot: Input/Output Terminal specific Entity properties. */ struct sdca_entity { const char *label; @@ -742,6 +856,9 @@ struct sdca_entity { struct sdca_control *controls; int num_sources; int num_controls; + union { + struct sdca_entity_iot iot; + }; }; /** diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 4de25f485755..8a143048a0ab 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -818,6 +818,69 @@ static int find_sdca_entity_controls(struct device *dev, return 0; } +static bool find_sdca_iot_dataport(struct sdca_entity_iot *terminal) +{ + switch (terminal->type) { + case SDCA_TERM_TYPE_GENERIC: + case SDCA_TERM_TYPE_ULTRASOUND: + case SDCA_TERM_TYPE_CAPTURE_DIRECT_PCM_MIC: + case SDCA_TERM_TYPE_RAW_PDM_MIC: + case SDCA_TERM_TYPE_SPEECH: + case SDCA_TERM_TYPE_VOICE: + case SDCA_TERM_TYPE_SECONDARY_PCM_MIC: + case SDCA_TERM_TYPE_ACOUSTIC_CONTEXT_AWARENESS: + case SDCA_TERM_TYPE_DTOD_STREAM: + case SDCA_TERM_TYPE_REFERENCE_STREAM: + case SDCA_TERM_TYPE_SENSE_CAPTURE: + case SDCA_TERM_TYPE_STREAMING_MIC: + case SDCA_TERM_TYPE_OPTIMIZATION_STREAM: + case SDCA_TERM_TYPE_PDM_RENDER_STREAM: + case SDCA_TERM_TYPE_COMPANION_DATA: + return true; + default: + return false; + } +} + +static int find_sdca_entity_iot(struct device *dev, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity_iot *terminal = &entity->iot; + u32 tmp; + int ret; + + ret = fwnode_property_read_u32(entity_node, "mipi-sdca-terminal-type", &tmp); + if (ret) { + dev_err(dev, "%s: terminal type missing: %d\n", entity->label, ret); + return ret; + } + + terminal->type = tmp; + terminal->is_dataport = find_sdca_iot_dataport(terminal); + + ret = fwnode_property_read_u32(entity_node, + "mipi-sdca-terminal-reference-number", &tmp); + if (!ret) + terminal->reference = tmp; + + ret = fwnode_property_read_u32(entity_node, + "mipi-sdca-terminal-connector-type", &tmp); + if (!ret) + terminal->connector = tmp; + + ret = fwnode_property_read_u32(entity_node, + "mipi-sdca-terminal-transducer-count", &tmp); + if (!ret) + terminal->num_transducer = tmp; + + dev_info(dev, "%s: terminal type %#x ref %#x conn %#x count %d\n", + entity->label, terminal->type, terminal->reference, + terminal->connector, terminal->num_transducer); + + return 0; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -845,6 +908,17 @@ static int find_sdca_entity(struct device *dev, dev_info(dev, "%s: entity %#x type %#x\n", entity->label, entity->id, entity->type); + switch (entity->type) { + case SDCA_ENTITY_TYPE_IT: + case SDCA_ENTITY_TYPE_OT: + ret = find_sdca_entity_iot(dev, entity_node, entity); + break; + default: + break; + } + if (ret) + return ret; + ret = find_sdca_entity_controls(dev, entity_node, entity); if (ret) return ret; @@ -943,6 +1017,46 @@ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data * return NULL; } +static int find_sdca_entity_connection_iot(struct device *dev, + struct sdca_function_data *function, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity_iot *terminal = &entity->iot; + struct fwnode_handle *clock_node; + struct sdca_entity *clock_entity; + const char *clock_label; + int ret; + + clock_node = fwnode_get_named_child_node(entity_node, + "mipi-sdca-terminal-clock-connection"); + if (!clock_node) + return 0; + + ret = fwnode_property_read_string(clock_node, "mipi-sdca-entity-label", + &clock_label); + if (ret) { + dev_err(dev, "%s: clock label missing: %d\n", entity->label, ret); + fwnode_handle_put(clock_node); + return ret; + } + + clock_entity = find_sdca_entity_by_label(function, clock_label); + if (!clock_entity) { + dev_err(dev, "%s: failed to find clock with label %s\n", + entity->label, clock_label); + fwnode_handle_put(clock_node); + return -EINVAL; + } + + terminal->clock = clock_entity; + + dev_info(dev, "%s -> %s\n", clock_entity->label, entity->label); + + fwnode_handle_put(clock_node); + return 0; +} + static int find_sdca_entity_connection(struct device *dev, struct sdca_function_data *function, struct fwnode_handle *entity_node, @@ -953,6 +1067,19 @@ static int find_sdca_entity_connection(struct device *dev, u64 pin_list; int i, ret; + switch (entity->type) { + case SDCA_ENTITY_TYPE_IT: + case SDCA_ENTITY_TYPE_OT: + ret = find_sdca_entity_connection_iot(dev, function, + entity_node, entity); + break; + default: + ret = 0; + break; + } + if (ret) + return ret; + ret = fwnode_property_read_u64(entity_node, "mipi-sdca-input-pin-list", &pin_list); if (ret == -EINVAL) { /* Allow missing pin lists, assume no pins. */ From e80b8e5c53c30df1cba45258d10b04872b7eea67 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:38:00 +0000 Subject: [PATCH 0109/1090] ASoC: SDCA: Add support for clock Entity properties Add support for parsing the Clock Source Entity properties from DisCo/ACPI. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-10-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 25 +++++++++++++++++++++++++ sound/soc/sdca/sdca_functions.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 6cb5ab79ee54..13edc976679a 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -784,6 +784,29 @@ struct sdca_entity_iot { bool is_dataport; }; +/** + * enum sdca_clock_type - SDCA Clock Types + * + * Indicate the synchronicity of an Clock Entity, see section 6.4.1.3 + * of the SDCA v1.0 specification. + */ +enum sdca_clock_type { + SDCA_CLOCK_TYPE_EXTERNAL = 0x00, + SDCA_CLOCK_TYPE_INTERNAL_ASYNC = 0x01, + SDCA_CLOCK_TYPE_INTERNAL_SYNC = 0x02, + SDCA_CLOCK_TYPE_INTERNAL_SOURCE_SYNC = 0x03, +}; + +/** + * struct sdca_entity_cs - information specific to Clock Source Entities + * @type: Synchronicity of the Clock Source. + * @max_delay: The maximum delay in microseconds before the clock is stable. + */ +struct sdca_entity_cs { + enum sdca_clock_type type; + unsigned int max_delay; +}; + /** * enum sdca_entity_type - SDCA Entity Type codes * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the @@ -846,6 +869,7 @@ enum sdca_entity_type { * @num_sources: Number of sources for the Entity. * @num_controls: Number of Controls for the Entity. * @iot: Input/Output Terminal specific Entity properties. + * @cs: Clock Source specific Entity properties. */ struct sdca_entity { const char *label; @@ -858,6 +882,7 @@ struct sdca_entity { int num_controls; union { struct sdca_entity_iot iot; + struct sdca_entity_cs cs; }; }; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 8a143048a0ab..dd9e2dce6e65 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -881,6 +881,33 @@ static int find_sdca_entity_iot(struct device *dev, return 0; } +static int find_sdca_entity_cs(struct device *dev, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity_cs *clock = &entity->cs; + u32 tmp; + int ret; + + ret = fwnode_property_read_u32(entity_node, "mipi-sdca-cs-type", &tmp); + if (ret) { + dev_err(dev, "%s: clock type missing: %d\n", entity->label, ret); + return ret; + } + + clock->type = tmp; + + ret = fwnode_property_read_u32(entity_node, + "mipi-sdca-clock-valid-max-delay", &tmp); + if (!ret) + clock->max_delay = tmp; + + dev_info(dev, "%s: clock type %#x delay %d\n", entity->label, + clock->type, clock->max_delay); + + return 0; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -913,6 +940,9 @@ static int find_sdca_entity(struct device *dev, case SDCA_ENTITY_TYPE_OT: ret = find_sdca_entity_iot(dev, entity_node, entity); break; + case SDCA_ENTITY_TYPE_CS: + ret = find_sdca_entity_cs(dev, entity_node, entity); + break; default: break; } From 9da195880f167ab7c2d595388decf783c9920121 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Feb 2025 11:38:01 +0000 Subject: [PATCH 0110/1090] ASoC: SDCA: Add support for PDE Entity properties Add support for parsing the Power Domain Entity properties from DisCo/ACPI. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250205113801.3699902-11-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 48 +++++++++++ sound/soc/sdca/sdca_functions.c | 138 ++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 13edc976679a..f001ab643fed 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -39,6 +39,11 @@ struct sdca_function_desc; */ #define SDCA_MAX_CHANNEL_COUNT 32 +/* + * Sanity check on number of PDE delays, can be expanded if needed. + */ +#define SDCA_MAX_DELAY_COUNT 256 + /** * enum sdca_function_type - SDCA Function Type codes * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. @@ -807,6 +812,47 @@ struct sdca_entity_cs { unsigned int max_delay; }; +/** + * enum sdca_pde_power_state - SDCA Power States + * + * SDCA Power State values from SDCA specification v1.0 Section 7.12.4. + */ +enum sdca_pde_power_state { + SDCA_PDE_PS0 = 0x0, + SDCA_PDE_PS1 = 0x1, + SDCA_PDE_PS2 = 0x2, + SDCA_PDE_PS3 = 0x3, + SDCA_PDE_PS4 = 0x4, +}; + +/** + * struct sdca_pde_delay - describes the delay changing between 2 power states + * @from_ps: The power state being exited. + * @to_ps: The power state being entered. + * @us: The delay in microseconds switching between the two states. + */ +struct sdca_pde_delay { + int from_ps; + int to_ps; + unsigned int us; +}; + +/** + * struct sdca_entity_pde - information specific to Power Domain Entities + * @managed: Dynamically allocated array pointing to each Entity + * controlled by this PDE. + * @max_delay: Dynamically allocated array of delays for switching + * between power states. + * @num_managed: Number of Entities controlled by this PDE. + * @num_max_delay: Number of delays specified for state changes. + */ +struct sdca_entity_pde { + struct sdca_entity **managed; + struct sdca_pde_delay *max_delay; + int num_managed; + int num_max_delay; +}; + /** * enum sdca_entity_type - SDCA Entity Type codes * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the @@ -870,6 +916,7 @@ enum sdca_entity_type { * @num_controls: Number of Controls for the Entity. * @iot: Input/Output Terminal specific Entity properties. * @cs: Clock Source specific Entity properties. + * @pde: Power Domain Entity specific Entity properties. */ struct sdca_entity { const char *label; @@ -883,6 +930,7 @@ struct sdca_entity { union { struct sdca_entity_iot iot; struct sdca_entity_cs cs; + struct sdca_entity_pde pde; }; }; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index dd9e2dce6e65..091d55abe109 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -908,6 +908,66 @@ static int find_sdca_entity_cs(struct device *dev, return 0; } +static int find_sdca_entity_pde(struct device *dev, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + static const int mult_delay = 3; + struct sdca_entity_pde *power = &entity->pde; + struct sdca_pde_delay *delays; + int num_delays; + u32 *delay_list; + int i, j; + + num_delays = fwnode_property_count_u32(entity_node, + "mipi-sdca-powerdomain-transition-max-delay"); + if (num_delays <= 0) { + dev_err(dev, "%s: max delay list missing: %d\n", + entity->label, num_delays); + return -EINVAL; + } else if (num_delays % mult_delay != 0) { + dev_err(dev, "%s: delays not multiple of %d\n", + entity->label, mult_delay); + return -EINVAL; + } else if (num_delays > SDCA_MAX_DELAY_COUNT) { + dev_err(dev, "%s: maximum number of transition delays exceeded\n", + entity->label); + return -EINVAL; + } + + /* There are 3 values per delay */ + delays = devm_kcalloc(dev, num_delays / mult_delay, + sizeof(*delays), GFP_KERNEL); + if (!delays) + return -ENOMEM; + + delay_list = kcalloc(num_delays, sizeof(*delay_list), GFP_KERNEL); + if (!delay_list) + return -ENOMEM; + + fwnode_property_read_u32_array(entity_node, + "mipi-sdca-powerdomain-transition-max-delay", + delay_list, num_delays); + + num_delays /= mult_delay; + + for (i = 0, j = 0; i < num_delays; i++) { + delays[i].from_ps = delay_list[j++]; + delays[i].to_ps = delay_list[j++]; + delays[i].us = delay_list[j++]; + + dev_info(dev, "%s: from %#x to %#x delay %dus\n", entity->label, + delays[i].from_ps, delays[i].to_ps, delays[i].us); + } + + power->num_max_delay = num_delays; + power->max_delay = delays; + + kfree(delay_list); + + return 0; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -943,6 +1003,9 @@ static int find_sdca_entity(struct device *dev, case SDCA_ENTITY_TYPE_CS: ret = find_sdca_entity_cs(dev, entity_node, entity); break; + case SDCA_ENTITY_TYPE_PDE: + ret = find_sdca_entity_pde(dev, entity_node, entity); + break; default: break; } @@ -1047,6 +1110,21 @@ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data * return NULL; } +static struct sdca_entity *find_sdca_entity_by_id(struct sdca_function_data *function, + const int id) +{ + int i; + + for (i = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + + if (entity->id == id) + return entity; + } + + return NULL; +} + static int find_sdca_entity_connection_iot(struct device *dev, struct sdca_function_data *function, struct fwnode_handle *entity_node, @@ -1087,6 +1165,62 @@ static int find_sdca_entity_connection_iot(struct device *dev, return 0; } +static int find_sdca_entity_connection_pde(struct device *dev, + struct sdca_function_data *function, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity_pde *power = &entity->pde; + struct sdca_entity **managed; + u32 *managed_list; + int num_managed; + int i; + + num_managed = fwnode_property_count_u32(entity_node, + "mipi-sdca-powerdomain-managed-list"); + if (!num_managed) { + return 0; + } else if (num_managed < 0) { + dev_err(dev, "%s: managed list missing: %d\n", entity->label, num_managed); + return num_managed; + } else if (num_managed > SDCA_MAX_ENTITY_COUNT) { + dev_err(dev, "%s: maximum number of managed entities exceeded\n", + entity->label); + return -EINVAL; + } + + managed = devm_kcalloc(dev, num_managed, sizeof(*managed), GFP_KERNEL); + if (!managed) + return -ENOMEM; + + managed_list = kcalloc(num_managed, sizeof(*managed_list), GFP_KERNEL); + if (!managed_list) + return -ENOMEM; + + fwnode_property_read_u32_array(entity_node, + "mipi-sdca-powerdomain-managed-list", + managed_list, num_managed); + + for (i = 0; i < num_managed; i++) { + managed[i] = find_sdca_entity_by_id(function, managed_list[i]); + if (!managed[i]) { + dev_err(dev, "%s: failed to find entity with id %#x\n", + entity->label, managed_list[i]); + kfree(managed_list); + return -EINVAL; + } + + dev_info(dev, "%s -> %s\n", managed[i]->label, entity->label); + } + + kfree(managed_list); + + power->num_managed = num_managed; + power->managed = managed; + + return 0; +} + static int find_sdca_entity_connection(struct device *dev, struct sdca_function_data *function, struct fwnode_handle *entity_node, @@ -1103,6 +1237,10 @@ static int find_sdca_entity_connection(struct device *dev, ret = find_sdca_entity_connection_iot(dev, function, entity_node, entity); break; + case SDCA_ENTITY_TYPE_PDE: + ret = find_sdca_entity_connection_pde(dev, function, + entity_node, entity); + break; default: ret = 0; break; From cc2c3540d9477a9931fb0fd851fcaeba524a5b35 Mon Sep 17 00:00:00 2001 From: Sam Winchenbach Date: Mon, 3 Feb 2025 13:34:34 +0000 Subject: [PATCH 0111/1090] iio: filter: admv8818: Force initialization of SDO When a weak pull-up is present on the SDO line, regmap_update_bits fails to write both the SOFTRESET and SDOACTIVE bits because it incorrectly reads them as already set. Since the soft reset disables the SDO line, performing a read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line doesn't make sense. This change directly writes to the register instead of using regmap_update_bits. Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818") Signed-off-by: Sam Winchenbach Link: https://patch.msgid.link/SA1P110MB106904C961B0F3FAFFED74C0BCF5A@SA1P110MB1069.NAMP110.PROD.OUTLOOK.COM Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/filter/admv8818.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c index 848baa6e3bbf..d85b7d3de866 100644 --- a/drivers/iio/filter/admv8818.c +++ b/drivers/iio/filter/admv8818.c @@ -574,21 +574,15 @@ static int admv8818_init(struct admv8818_state *st) struct spi_device *spi = st->spi; unsigned int chip_id; - ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A, - ADMV8818_SOFTRESET_N_MSK | - ADMV8818_SOFTRESET_MSK, - FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) | - FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1)); + ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A, + ADMV8818_SOFTRESET_N_MSK | ADMV8818_SOFTRESET_MSK); if (ret) { dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n"); return ret; } - ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A, - ADMV8818_SDOACTIVE_N_MSK | - ADMV8818_SDOACTIVE_MSK, - FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) | - FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1)); + ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A, + ADMV8818_SDOACTIVE_N_MSK | ADMV8818_SDOACTIVE_MSK); if (ret) { dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n"); return ret; From 330cbb40bb3664a18a19760bd6dc6003d6624041 Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Mon, 20 Jan 2025 13:01:27 +0400 Subject: [PATCH 0112/1090] dt-bindings: ASoC: rockchip: Add compatible for RK3588 SPDIF Add a compatible string for SPDIF on RK3588, which is similar to the one on RK3568. Signed-off-by: Alexey Charkov Acked-by: Conor Dooley Link: https://patch.msgid.link/20250120-rk3588-spdif-v1-1-1415f5871dc7@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rockchip-spdif.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml index c3c989ef2a2c..32dea7392e8d 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml @@ -31,6 +31,10 @@ properties: - rockchip,rk3288-spdif - rockchip,rk3308-spdif - const: rockchip,rk3066-spdif + - items: + - enum: + - rockchip,rk3588-spdif + - const: rockchip,rk3568-spdif reg: maxItems: 1 From e97d06cb4386af4e069a2dc713de70500538d0bd Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 10 Feb 2025 12:59:37 +0100 Subject: [PATCH 0113/1090] ASoC: tscs454: Use str_enable_disable() in pll_power_event() Remove hard-coded strings by using the str_enable_disable() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250210115937.53654-1-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/codecs/tscs454.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 850e5de9271e..da2f3cb1cd13 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -737,9 +738,7 @@ static int pll_power_event(struct snd_soc_dapm_widget *w, ret = snd_soc_component_update_bits(component, R_PLLCTL, msk, val); if (ret < 0) { dev_err(component->dev, "Failed to %s PLL %d (%d)\n", - enable ? "enable" : "disable", - pll1 ? 1 : 2, - ret); + str_enable_disable(enable), pll1 ? 1 : 2, ret); return ret; } From c5528214c7c0a753c908a7b353309ba665985fb4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 10 Feb 2025 14:21:28 +0100 Subject: [PATCH 0114/1090] ASoC: codecs: wcd93xx-sdw: fix of_property_read_bool() warnings Using of_property_read_bool() for non-boolean properties has been deprecated in favour of of_property_present() and since commit c141ecc3cecd ("of: Warn when of_property_read_bool() is used on non-boolean properties") this also generates a warning: OF: /soc@0/soundwire@3330000/wcd9380-tx@0,3: Read of boolean property 'qcom,tx-port-mapping' with a value. Switch to using of_property_present() to look for "qcom,tx-port-mapping" properties. Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20250210132128.7734-1-johan+linaro@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd937x-sdw.c | 2 +- sound/soc/codecs/wcd938x-sdw.c | 2 +- sound/soc/codecs/wcd939x-sdw.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c index 1fbff313b965..4891fa0c963f 100644 --- a/sound/soc/codecs/wcd937x-sdw.c +++ b/sound/soc/codecs/wcd937x-sdw.c @@ -1028,7 +1028,7 @@ static int wcd9370_probe(struct sdw_slave *pdev, return -ENOMEM; /* Port map index starts at 0, however the data port for this codec start at index 1 */ - if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) { + if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) { wcd->is_tx = true; ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", &pdev->m_port_map[1], diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c index 7da8a10bd0a9..4e2ae542cee3 100644 --- a/sound/soc/codecs/wcd938x-sdw.c +++ b/sound/soc/codecs/wcd938x-sdw.c @@ -1229,7 +1229,7 @@ static int wcd9380_probe(struct sdw_slave *pdev, * Port map index starts with 0, however the data port for this codec * are from index 1 */ - if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) { + if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) { wcd->is_tx = true; ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", &pdev->m_port_map[1], diff --git a/sound/soc/codecs/wcd939x-sdw.c b/sound/soc/codecs/wcd939x-sdw.c index fca95777a75a..36868fad3e8b 100644 --- a/sound/soc/codecs/wcd939x-sdw.c +++ b/sound/soc/codecs/wcd939x-sdw.c @@ -1429,7 +1429,7 @@ static int wcd9390_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) * Port map index starts with 0, however the data port for this codec * are from index 1 */ - if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) { + if (of_property_present(dev->of_node, "qcom,tx-port-mapping")) { wcd->is_tx = true; ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", From 49f27f29446a5bfe633dd2cc0cfebd48a1a5e77f Mon Sep 17 00:00:00 2001 From: Vitaliy Shevtsov Date: Fri, 31 Jan 2025 20:26:55 +0500 Subject: [PATCH 0115/1090] wifi: nl80211: reject cooked mode if it is set along with other flags It is possible to set both MONITOR_FLAG_COOK_FRAMES and MONITOR_FLAG_ACTIVE flags simultaneously on the same monitor interface from the userspace. This causes a sub-interface to be created with no IEEE80211_SDATA_IN_DRIVER bit set because the monitor interface is in the cooked state and it takes precedence over all other states. When the interface is then being deleted the kernel calls WARN_ONCE() from check_sdata_in_driver() because of missing that bit. Fix this by rejecting MONITOR_FLAG_COOK_FRAMES if it is set along with other flags. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: 66f7ac50ed7c ("nl80211: Add monitor interface configuration flags") Cc: stable@vger.kernel.org Reported-by: syzbot+2e5c1e55b9e5c28a3da7@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=2e5c1e55b9e5c28a3da7 Signed-off-by: Vitaliy Shevtsov Link: https://patch.msgid.link/20250131152657.5606-1-v.shevtsov@mt-integration.ru Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d7d3da0f6833..fdb2aac951d1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4220,6 +4220,11 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) if (flags[flag]) *mntrflags |= (1< Date: Tue, 4 Feb 2025 13:31:29 +0100 Subject: [PATCH 0116/1090] wifi: mac80211: Cleanup sta TXQs on flush Drop the sta TXQs on flush when the drivers is not supporting flush. ieee80211_set_disassoc() tries to clean up everything for the sta. But it ignored queued frames in the sta TX queues when the driver isn't supporting the flush driver ops. Signed-off-by: Alexander Wetzel Link: https://patch.msgid.link/20250204123129.9162-1-Alexander@wetzel-home.de Signed-off-by: Johannes Berg --- net/mac80211/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f6b631faf4f7..7f02bd5891eb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -687,7 +687,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, unsigned int queues, bool drop) { - if (!local->ops->flush) + if (!local->ops->flush && !drop) return; /* @@ -714,7 +714,8 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, } } - drv_flush(local, sdata, queues, drop); + if (local->ops->flush) + drv_flush(local, sdata, queues, drop); ieee80211_wake_queues_by_reason(&local->hw, queues, IEEE80211_QUEUE_STOP_REASON_FLUSH, From 646262c71aca87bb66945933abe4e620796d6c5a Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Tue, 4 Feb 2025 17:42:40 +0100 Subject: [PATCH 0117/1090] wifi: mac80211: remove debugfs dir for virtual monitor Don't call ieee80211_debugfs_recreate_netdev() for virtual monitor interface when deleting it. The virtual monitor interface shouldn't have debugfs entries and trying to update them will *create* them on deletion. And when the virtual monitor interface is created/destroyed multiple times we'll get warnings about debugfs name conflicts. Signed-off-by: Alexander Wetzel Link: https://patch.msgid.link/20250204164240.370153-1-Alexander@wetzel-home.de Signed-off-by: Johannes Berg --- net/mac80211/driver-ops.c | 10 ++++++++-- net/mac80211/iface.c | 11 ++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index 299d38e9e863..2fc60e1e77a5 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -116,8 +116,14 @@ void drv_remove_interface(struct ieee80211_local *local, sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; - /* Remove driver debugfs entries */ - ieee80211_debugfs_recreate_netdev(sdata, sdata->vif.valid_links); + /* + * Remove driver debugfs entries. + * The virtual monitor interface doesn't get a debugfs + * entry, so it's exempt here. + */ + if (sdata != local->monitor_sdata) + ieee80211_debugfs_recreate_netdev(sdata, + sdata->vif.valid_links); trace_drv_remove_interface(local, sdata); local->ops->remove_interface(&local->hw, &sdata->vif); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0ea7e77860b7..738de269e13f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1206,16 +1206,17 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) return; } - RCU_INIT_POINTER(local->monitor_sdata, NULL); - mutex_unlock(&local->iflist_mtx); - - synchronize_net(); - + clear_bit(SDATA_STATE_RUNNING, &sdata->state); ieee80211_link_release_channel(&sdata->deflink); if (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) drv_remove_interface(local, sdata); + RCU_INIT_POINTER(local->monitor_sdata, NULL); + mutex_unlock(&local->iflist_mtx); + + synchronize_net(); + kfree(sdata); } From 7774e3920029398ad49dc848b23840593f14d515 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 9 Feb 2025 14:34:45 +0200 Subject: [PATCH 0118/1090] wifi: iwlwifi: fw: allocate chained SG tables for dump The firmware dumps can be pretty big, and since we use single pages for each SG table entry, even the table itself may end up being an order-5 allocation. Build chained tables so that we need not allocate a higher-order table here. This could be improved and cleaned up, e.g. by using the SG pool code or simply kvmalloc(), but all of that would require also updating the devcoredump first since that frees it all, so we need to be more careful. SG pool might also run against the CONFIG_ARCH_NO_SG_CHAIN limitation, which is irrelevant here. Also use _devcd_free_sgtable() for the error paths now, much simpler especially since it's in two places now. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.697c7a465ac9.Iea982df46b5c075bfb77ade36f187d99a70c63db@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 86 ++++++++++++++------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index fb2ea38e89ac..6594216f873c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -558,41 +558,71 @@ static void iwl_dump_prph(struct iwl_fw_runtime *fwrt, } /* - * alloc_sgtable - allocates scallerlist table in the given size, - * fills it with pages and returns it + * alloc_sgtable - allocates (chained) scatterlist in the given size, + * fills it with pages and returns it * @size: the size (in bytes) of the table -*/ -static struct scatterlist *alloc_sgtable(int size) + */ +static struct scatterlist *alloc_sgtable(ssize_t size) { - int alloc_size, nents, i; - struct page *new_page; - struct scatterlist *iter; - struct scatterlist *table; + struct scatterlist *result = NULL, *prev; + int nents, i, n_prev; nents = DIV_ROUND_UP(size, PAGE_SIZE); - table = kcalloc(nents, sizeof(*table), GFP_KERNEL); - if (!table) - return NULL; - sg_init_table(table, nents); - iter = table; - for_each_sg(table, iter, sg_nents(table), i) { - new_page = alloc_page(GFP_KERNEL); - if (!new_page) { - /* release all previous allocated pages in the table */ - iter = table; - for_each_sg(table, iter, sg_nents(table), i) { - new_page = sg_page(iter); - if (new_page) - __free_page(new_page); - } - kfree(table); + +#define N_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(*result)) + /* + * We need an additional entry for table chaining, + * this ensures the loop can finish i.e. we can + * fit at least two entries per page (obviously, + * many more really fit.) + */ + BUILD_BUG_ON(N_ENTRIES_PER_PAGE < 2); + + while (nents > 0) { + struct scatterlist *new, *iter; + int n_fill, n_alloc; + + if (nents <= N_ENTRIES_PER_PAGE) { + /* last needed table */ + n_fill = nents; + n_alloc = nents; + nents = 0; + } else { + /* fill a page with entries */ + n_alloc = N_ENTRIES_PER_PAGE; + /* reserve one for chaining */ + n_fill = n_alloc - 1; + nents -= n_fill; + } + + new = kcalloc(n_alloc, sizeof(*new), GFP_KERNEL); + if (!new) { + if (result) + _devcd_free_sgtable(result); return NULL; } - alloc_size = min_t(int, size, PAGE_SIZE); - size -= PAGE_SIZE; - sg_set_page(iter, new_page, alloc_size, 0); + sg_init_table(new, n_alloc); + + if (!result) + result = new; + else + sg_chain(prev, n_prev, new); + prev = new; + n_prev = n_alloc; + + for_each_sg(new, iter, n_fill, i) { + struct page *new_page = alloc_page(GFP_KERNEL); + + if (!new_page) { + _devcd_free_sgtable(result); + return NULL; + } + + sg_set_page(iter, new_page, PAGE_SIZE, 0); + } } - return table; + + return result; } static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt, From 3f8aa0b8a53df2247a84eaf3b3aa38b6ef86cb1c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 9 Feb 2025 14:34:46 +0200 Subject: [PATCH 0119/1090] wifi: iwlwifi: fw: avoid using an uninitialized variable iwl_fwrt_read_err_table can return true also when it failed to read the memory. In this case, err_id argument is not initialized, but the callers are still using it. Simply initialize it to 0. If the error table was read successfully it'll be overridden. Fixes: 43e0b2ada519 ("wifi: iwlwifi: fw: add an error table status getter") Signed-off-by: Miri Korenblit Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20250209143303.37cdbba4eb56.I95fe9bd95303b8179f946766558a9f15f4fe254c@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 8e0c85a1240d..c7b261c8ec96 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -540,6 +540,9 @@ bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id) } err_info = {}; int ret; + if (err_id) + *err_id = 0; + if (!base) return false; From f9751163bffd3fe60794929829f810968c6de73d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 9 Feb 2025 14:34:47 +0200 Subject: [PATCH 0120/1090] wifi: iwlwifi: mvm: clean up ROC on failure If the firmware fails to start the session protection, then we do call iwl_mvm_roc_finished() here, but that won't do anything at all because IWL_MVM_STATUS_ROC_P2P_RUNNING was never set. Set IWL_MVM_STATUS_ROC_P2P_RUNNING in the failure/stop path. If it started successfully before, it's already set, so that doesn't matter, and if it didn't start it needs to be set to clean up. Not doing so will lead to a WARN_ON() later on a fresh remain- on-channel, since the link is already active when activated as it was never deactivated. Fixes: 35c1bbd93c4e ("wifi: iwlwifi: mvm: remove IWL_MVM_STATUS_NEED_FLUSH_P2P") Signed-off-by: Johannes Berg Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.0fe36c291068.I67f5dac742170dd937f11e4d4f937f45f71b7cb4@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 9216c43a35c4..ebfa88b38b71 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -1030,6 +1030,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, /* End TE, notify mac80211 */ mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID; mvmvif->time_event_data.link_id = -1; + /* set the bit so the ROC cleanup will actually clean up */ + set_bit(IWL_MVM_STATUS_ROC_P2P_RUNNING, &mvm->status); iwl_mvm_roc_finished(mvm); ieee80211_remain_on_channel_expired(mvm->hw); } else if (le32_to_cpu(notif->start)) { From d48ff3ce92259bae7e77732c7cfd7cbc7992c021 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Feb 2025 14:34:48 +0200 Subject: [PATCH 0121/1090] wifi: iwlwifi: mvm: don't dump the firmware state upon RFKILL while suspend This is not really a firmware error. We need to reload the firmware, but this doesn't mean that we should consider this as a firmware error. When the firmware was restarted upon resume, this wasn't felt by the driver. Now that we keep the firmware running during suspend even if we don't have wowlan, this started to pop-up. Fixes: e8bb19c1d590 ("wifi: iwlwifi: support fast resume") Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.a10463a40318.I14131781c3124b58e60e1f5e9d793a2bc88b464c@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 77 ++++++++++++++------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 129b6bdf9ef9..82ca7f8b1bb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -3092,8 +3092,14 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, ieee80211_resume_disconnect(vif); } -static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) +enum rt_status { + FW_ALIVE, + FW_NEEDS_RESET, + FW_ERROR, +}; + +static enum rt_status iwl_mvm_check_rt_status(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { u32 err_id; @@ -3101,29 +3107,35 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm, if (iwl_fwrt_read_err_table(mvm->trans, mvm->trans->dbg.lmac_error_event_table[0], &err_id)) { - if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) { - struct cfg80211_wowlan_wakeup wakeup = { - .rfkill_release = true, - }; - ieee80211_report_wowlan_wakeup(vif, &wakeup, - GFP_KERNEL); + if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN) { + IWL_WARN(mvm, "Rfkill was toggled during suspend\n"); + if (vif) { + struct cfg80211_wowlan_wakeup wakeup = { + .rfkill_release = true, + }; + + ieee80211_report_wowlan_wakeup(vif, &wakeup, + GFP_KERNEL); + } + + return FW_NEEDS_RESET; } - return true; + return FW_ERROR; } /* check if we have lmac2 set and check for error */ if (iwl_fwrt_read_err_table(mvm->trans, mvm->trans->dbg.lmac_error_event_table[1], NULL)) - return true; + return FW_ERROR; /* check for umac error */ if (iwl_fwrt_read_err_table(mvm->trans, mvm->trans->dbg.umac_error_event_table, NULL)) - return true; + return FW_ERROR; - return false; + return FW_ALIVE; } /* @@ -3492,6 +3504,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) bool d0i3_first = fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_D0I3_END_FIRST); bool resume_notif_based = iwl_mvm_d3_resume_notif_based(mvm); + enum rt_status rt_status; bool keep = false; mutex_lock(&mvm->mutex); @@ -3515,14 +3528,19 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt); - if (iwl_mvm_check_rt_status(mvm, vif)) { - IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n"); + rt_status = iwl_mvm_check_rt_status(mvm, vif); + if (rt_status != FW_ALIVE) { set_bit(STATUS_FW_ERROR, &mvm->trans->status); - iwl_mvm_dump_nic_error_log(mvm); - iwl_dbg_tlv_time_point(&mvm->fwrt, - IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL); - iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - false, 0); + if (rt_status == FW_ERROR) { + IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n"); + iwl_mvm_dump_nic_error_log(mvm); + iwl_dbg_tlv_time_point(&mvm->fwrt, + IWL_FW_INI_TIME_POINT_FW_ASSERT, + NULL); + iwl_fw_dbg_collect_desc(&mvm->fwrt, + &iwl_dump_desc_assert, + false, 0); + } ret = 1; goto err; } @@ -3679,6 +3697,7 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm) .notif_expected = IWL_D3_NOTIF_D3_END_NOTIF, }; + enum rt_status rt_status; int ret; lockdep_assert_held(&mvm->mutex); @@ -3688,14 +3707,20 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm) mvm->last_reset_or_resume_time_jiffies = jiffies; iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt); - if (iwl_mvm_check_rt_status(mvm, NULL)) { - IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n"); + rt_status = iwl_mvm_check_rt_status(mvm, NULL); + if (rt_status != FW_ALIVE) { set_bit(STATUS_FW_ERROR, &mvm->trans->status); - iwl_mvm_dump_nic_error_log(mvm); - iwl_dbg_tlv_time_point(&mvm->fwrt, - IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL); - iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - false, 0); + if (rt_status == FW_ERROR) { + IWL_ERR(mvm, + "iwl_mvm_check_rt_status failed, device is gone during suspend\n"); + iwl_mvm_dump_nic_error_log(mvm); + iwl_dbg_tlv_time_point(&mvm->fwrt, + IWL_FW_INI_TIME_POINT_FW_ASSERT, + NULL); + iwl_fw_dbg_collect_desc(&mvm->fwrt, + &iwl_dump_desc_assert, + false, 0); + } mvm->trans->state = IWL_TRANS_NO_FW; ret = -ENODEV; From d73d2c6e3313f0ba60711ab4f4b9044eddca9ca5 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Feb 2025 14:34:49 +0200 Subject: [PATCH 0122/1090] wifi: iwlwifi: mvm: don't try to talk to a dead firmware This fixes: bad state = 0 WARNING: CPU: 10 PID: 702 at drivers/net/wireless/inel/iwlwifi/iwl-trans.c:178 iwl_trans_send_cmd+0xba/0xe0 [iwlwifi] Call Trace: ? __warn+0xca/0x1c0 ? iwl_trans_send_cmd+0xba/0xe0 [iwlwifi 64fa9ad799a0e0d2ba53d4af93a53ad9a531f8d4] iwl_fw_dbg_clear_monitor_buf+0xd7/0x110 [iwlwifi 64fa9ad799a0e0d2ba53d4af93a53ad9a531f8d4] _iwl_dbgfs_fw_dbg_clear_write+0xe2/0x120 [iwlmvm 0e8adb18cea92d2c341766bcc10b18699290068a] Ask whether the firmware is alive before sending a command. Fixes: 268712dc3b34 ("wifi: iwlwifi: mvm: add a debugfs hook to clear the monitor data") Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.8e1597b62c70.I12ea71dd9b805b095c9fc12a10c9f34a4e801b61@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 83e3c1160362..55d035b896e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1479,6 +1479,13 @@ static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm, if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000) return -EOPNOTSUPP; + /* + * If the firmware is not running, silently succeed since there is + * no data to clear. + */ + if (!iwl_mvm_firmware_running(mvm)) + return count; + mutex_lock(&mvm->mutex); iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt); mutex_unlock(&mvm->mutex); From a03e2082e678ea10d0d8bdf3ed933eb05a8ddbb0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Feb 2025 14:34:50 +0200 Subject: [PATCH 0123/1090] wifi: iwlwifi: mvm: use the right version of the rate API The firmware uses the newer version of the API in recent devices. For older devices, we translate the rate to the new format. Don't parse the rate with old parsing macros. Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.13d70cdcbb4e.Ic92193bce4013b70a823cfef250ee79c16cf7c17@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 09fd8752046e..14ea89f931bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -995,7 +995,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, */ u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); u32 rate_n_flags = phy_data->rate_n_flags; - u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1; + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; u8 offs = 0; rx_status->bw = RATE_INFO_BW_HE_RU; @@ -1050,13 +1050,13 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, if (he_mu) he_mu->flags2 |= - le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1, + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags), IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); - else if (he_type == RATE_MCS_HE_TYPE_TRIG_V1) + else if (he_type == RATE_MCS_HE_TYPE_TRIG) he->data6 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) | - le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1, + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags), IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW); } From e0dc2c1bef722cbf16ae557690861e5f91208129 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 9 Feb 2025 14:34:51 +0200 Subject: [PATCH 0124/1090] wifi: iwlwifi: limit printed string from FW file There's no guarantee here that the file is always with a NUL-termination, so reading the string may read beyond the end of the TLV. If that's the last TLV in the file, it can perhaps even read beyond the end of the file buffer. Fix that by limiting the print format to the size of the buffer we have. Fixes: aee1b6385e29 ("iwlwifi: support fseq tlv and print fseq version") Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.cb5f9d0c2f5d.Idec695d53c6c2234aade306f7647b576c7e3d928@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index d3a65f33097c..352b6e73e08f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1181,7 +1181,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, if (tlv_len != sizeof(*fseq_ver)) goto invalid_tlv_len; - IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %s\n", + IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n", fseq_ver->version); } break; From 3b08e608d50c44ca1135beed179f266aa0461da7 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Sun, 9 Feb 2025 14:34:52 +0200 Subject: [PATCH 0125/1090] wifi: iwlwifi: Free pages allocated when failing to build A-MSDU When failing to prepare the data needed for A-MSDU transmission, the memory allocated for the TSO management was not freed. Fix it. Fixes: 7f5e3038f029 ("wifi: iwlwifi: map entire SKB when sending AMSDUs") Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.bc27fad9b3d5.Ibf43dd18fb652b1a59061204e081f11c9fa34a3f@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 1f483f15c238..dce5096db82b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -347,6 +347,7 @@ iwl_tfh_tfd *iwl_txq_gen2_build_tx_amsdu(struct iwl_trans *trans, return tfd; out_err: + iwl_pcie_free_tso_pages(trans, skb, out_meta); iwl_txq_gen2_tfd_unmap(trans, out_meta, tfd); return NULL; } From 3640dbc1f75ce15d128ea4af44226960d894f3fd Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Sun, 9 Feb 2025 14:34:53 +0200 Subject: [PATCH 0126/1090] wifi: iwlwifi: Fix A-MSDU TSO preparation The TSO preparation assumed that the skb head contained the headers while the rest of the data was in the fragments. Since this is not always true, e.g., it is possible that the data was linearised, modify the TSO preparation to start the data processing after the network headers. Fixes: 7f5e3038f029 ("wifi: iwlwifi: map entire SKB when sending AMSDUs") Signed-off-by: Ilan Peer Reviewed-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250209143303.75769a4769bf.Iaf79e8538093cdf8c446c292cc96164ad6498f61@changeid Signed-off-by: Johannes Berg --- .../wireless/intel/iwlwifi/pcie/internal.h | 5 +++-- .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 5 +++-- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 20 +++++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 856b7e9f717d..45460f93d24a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2003-2015, 2018-2024 Intel Corporation + * Copyright (C) 2003-2015, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -646,7 +646,8 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, unsigned int len); struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *cmd_meta, - u8 **hdr, unsigned int hdr_room); + u8 **hdr, unsigned int hdr_room, + unsigned int offset); void iwl_pcie_free_tso_pages(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *cmd_meta); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index dce5096db82b..401919f9fe88 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020, 2023-2024 Intel Corporation + * Copyright (C) 2018-2020, 2023-2025 Intel Corporation */ #include #include @@ -188,7 +188,8 @@ static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)); /* Our device supports 9 segments at most, it will fit in 1 page */ - sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room); + sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room, + snap_ip_tcp_hdrlen + hdr_len); if (!sgt) return -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 334ebd4c12fa..7b6071a59b69 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2021, 2023-2024 Intel Corporation + * Copyright (C) 2003-2014, 2018-2021, 2023-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1855,6 +1855,7 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, * @cmd_meta: command meta to store the scatter list information for unmapping * @hdr: output argument for TSO headers * @hdr_room: requested length for TSO headers + * @offset: offset into the data from which mapping should start * * Allocate space for a scatter gather list and TSO headers and map the SKB * using the scatter gather list. The SKB is unmapped again when the page is @@ -1864,18 +1865,20 @@ dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, */ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *cmd_meta, - u8 **hdr, unsigned int hdr_room) + u8 **hdr, unsigned int hdr_room, + unsigned int offset) { struct sg_table *sgt; + unsigned int n_segments; if (WARN_ON_ONCE(skb_has_frag_list(skb))) return NULL; + n_segments = DIV_ROUND_UP(skb->len - offset, skb_shinfo(skb)->gso_size); *hdr = iwl_pcie_get_page_hdr(trans, hdr_room + __alignof__(struct sg_table) + sizeof(struct sg_table) + - (skb_shinfo(skb)->nr_frags + 1) * - sizeof(struct scatterlist), + n_segments * sizeof(struct scatterlist), skb); if (!*hdr) return NULL; @@ -1883,11 +1886,11 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, sgt = (void *)PTR_ALIGN(*hdr + hdr_room, __alignof__(struct sg_table)); sgt->sgl = (void *)(sgt + 1); - sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1); + sg_init_table(sgt->sgl, n_segments); /* Only map the data, not the header (it is copied to the TSO page) */ - sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb), - skb->data_len); + sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, offset, + skb->len - offset); if (WARN_ON_ONCE(sgt->orig_nents <= 0)) return NULL; @@ -1939,7 +1942,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len; /* Our device supports 9 segments at most, it will fit in 1 page */ - sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room); + sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room, + snap_ip_tcp_hdrlen + hdr_len + iv_len); if (!sgt) return -ENOMEM; From 21aa330fec31bb530a4ef6c9555fb157d0711112 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 6 Feb 2025 11:03:06 +0800 Subject: [PATCH 0127/1090] ASoC: fsl_micfil: Add decimation filter bypass mode support When decimation filter bypass mode is enabled, PDM data can be written into FIFO directly without any processing. The interface of this mode is DSD big endian format, when user needs this format, then this mode is enabled. This mode is only for the i.MX943 platform currently. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20250206030306.2618620-1-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 49 ++++++++++++++++++++++++++++++++++---- sound/soc/fsl/fsl_micfil.h | 1 + 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index fa4136683392..73d8910a6188 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ struct fsl_micfil { struct fsl_micfil_verid verid; struct fsl_micfil_param param; bool mclk_flag; /* mclk enable flag */ + bool dec_bypass; }; struct fsl_micfil_soc_data { @@ -129,7 +131,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx943 = { .fifos = 8, .fifo_depth = 32, .dataline = 0xf, - .formats = SNDRV_PCM_FMTBIT_S32_LE, + .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_DSD_U32_BE, .use_edma = true, .use_verid = true, .volume_sx = false, @@ -724,14 +726,14 @@ static int fsl_micfil_trigger(struct snd_pcm_substream *substream, int cmd, if (ret) return ret; - if (micfil->vad_enabled) + if (micfil->vad_enabled && !micfil->dec_bypass) fsl_micfil_hwvad_enable(micfil); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (micfil->vad_enabled) + if (micfil->vad_enabled && !micfil->dec_bypass) fsl_micfil_hwvad_disable(micfil); /* Disable the module */ @@ -778,8 +780,9 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream, { struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai); unsigned int channels = params_channels(params); + snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); - int clk_div = 8; + int clk_div = 8, mclk_rate, div_multiply_k; int osr = MICFIL_OSR_DEFAULT; int ret; @@ -801,7 +804,39 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream, micfil->mclk_flag = true; - ret = clk_set_rate(micfil->mclk, rate * clk_div * osr * 8); + /* floor(K * CLKDIV) */ + switch (micfil->quality) { + case QUALITY_HIGH: + div_multiply_k = clk_div >> 1; + break; + case QUALITY_LOW: + case QUALITY_VLOW1: + div_multiply_k = clk_div << 1; + break; + case QUALITY_VLOW2: + div_multiply_k = clk_div << 2; + break; + case QUALITY_MEDIUM: + case QUALITY_VLOW0: + default: + div_multiply_k = clk_div; + break; + } + + if (format == SNDRV_PCM_FORMAT_DSD_U32_BE) { + micfil->dec_bypass = true; + /* + * According to equation 29 in RM: + * MCLK_CLK_ROOT = PDM CLK rate * 2 * floor(K * CLKDIV) + * PDM CLK rate = rate * physical bit width (32) + */ + mclk_rate = rate * div_multiply_k * 32 * 2; + } else { + micfil->dec_bypass = false; + mclk_rate = rate * clk_div * osr * 8; + } + + ret = clk_set_rate(micfil->mclk, mclk_rate); if (ret) return ret; @@ -809,6 +844,10 @@ static int fsl_micfil_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; + regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2, + MICFIL_CTRL2_DEC_BYPASS, + micfil->dec_bypass ? MICFIL_CTRL2_DEC_BYPASS : 0); + ret = regmap_update_bits(micfil->regmap, REG_MICFIL_CTRL2, MICFIL_CTRL2_CLKDIV | MICFIL_CTRL2_CICOSR, FIELD_PREP(MICFIL_CTRL2_CLKDIV, clk_div) | diff --git a/sound/soc/fsl/fsl_micfil.h b/sound/soc/fsl/fsl_micfil.h index aa3661ea4ffc..fdfe4e7125bc 100644 --- a/sound/soc/fsl/fsl_micfil.h +++ b/sound/soc/fsl/fsl_micfil.h @@ -53,6 +53,7 @@ #define MICFIL_CTRL1_CHEN(ch) BIT(ch) /* MICFIL Control Register 2 -- REG_MICFILL_CTRL2 0x04 */ +#define MICFIL_CTRL2_DEC_BYPASS BIT(31) #define MICFIL_CTRL2_QSEL_SHIFT 25 #define MICFIL_CTRL2_QSEL GENMASK(27, 25) #define MICFIL_QSEL_MEDIUM_QUALITY 0 From 59115e2e25f42924181055ed7cc1d123af7598b7 Mon Sep 17 00:00:00 2001 From: Naman Jain Date: Thu, 16 Jan 2025 06:12:24 +0000 Subject: [PATCH 0128/1090] x86/hyperv/vtl: Stop kernel from probing VTL0 low memory For Linux, running in Hyper-V VTL (Virtual Trust Level), kernel in VTL2 tries to access VTL0 low memory in probe_roms. This memory is not described in the e820 map. Initialize probe_roms call to no-ops during boot for VTL2 kernel to avoid this. The issue got identified in OpenVMM which detects invalid accesses initiated from kernel running in VTL2. Co-developed-by: Saurabh Sengar Signed-off-by: Saurabh Sengar Signed-off-by: Naman Jain Tested-by: Roman Kisel Reviewed-by: Roman Kisel Link: https://lore.kernel.org/r/20250116061224.1701-1-namjain@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <20250116061224.1701-1-namjain@linux.microsoft.com> --- arch/x86/hyperv/hv_vtl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 4e1b1e3b5658..3f4e20d7b724 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -30,6 +30,7 @@ void __init hv_vtl_init_platform(void) x86_platform.realmode_init = x86_init_noop; x86_init.irqs.pre_vector_init = x86_init_noop; x86_init.timers.timer_init = x86_init_noop; + x86_init.resources.probe_roms = x86_init_noop; /* Avoid searching for BIOS MP tables */ x86_init.mpparse.find_mptable = x86_init_noop; From 91931af18bd22437e08e2471f5484d6fbdd8ab93 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 10 Feb 2025 16:33:27 -0600 Subject: [PATCH 0129/1090] gpiolib: add gpiod_multi_set_value_cansleep() Add a new gpiod_multi_set_value_cansleep() helper function with fewer parameters than gpiod_set_array_value_cansleep(). Calling gpiod_set_array_value_cansleep() can get quite verbose. In many cases, the first arguments all come from the same struct gpio_descs, so having a separate function where we can just pass that cuts down on the boilerplate. Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20250210-gpio-set-array-helper-v3-1-d6a673674da8@baylibre.com Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/consumer.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index db2dfbae8edb..5cbd4afd7862 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -3,6 +3,7 @@ #define __LINUX_GPIO_CONSUMER_H #include +#include #include struct acpi_device; @@ -655,4 +656,14 @@ static inline void gpiod_unexport(struct gpio_desc *desc) #endif /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ +static inline int gpiod_multi_set_value_cansleep(struct gpio_descs *descs, + unsigned long *value_bitmap) +{ + if (IS_ERR_OR_NULL(descs)) + return PTR_ERR_OR_ZERO(descs); + + return gpiod_set_array_value_cansleep(descs->ndescs, descs->desc, + descs->info, value_bitmap); +} + #endif From f22ba3561daa792dd138ed543e0bf48efe0b999c Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 11 Feb 2025 17:50:18 -0500 Subject: [PATCH 0130/1090] ASoC: SOF: imx-common: set sdev->pdata->hw_pdata after common is alloc'd 'imx_unregister_action' uses 'sdev->pdata->hw_pdata' to fetch the pointer to the common data structure. As such, if 'sdev->pdata->hw_pdata' is not set before adding 'imx_unregister_action' to the devres list, we risk derefrencing a NULL pointer if any of the calls between 'devm_add_action_or_reset' and 'sdev->pdata->hw_pdata = common' fails. Set 'sdev->pdata->hw_pdata' to point to 'common' as soon as 'common' is allocated. Fixes: 651e0ed391b1 (" ASoC: SOF: imx: introduce more common structures and functions") Signed-off-by: Laurentiu Mihalcea Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Link: https://patch.msgid.link/20250211225018.2642-1-laurentiumihalcea111@gmail.com Reviewed-by: Frank Li Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index 82057af1436c..c3594815e60e 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -378,6 +378,7 @@ static int imx_probe(struct snd_sof_dev *sdev) if (!common) return dev_err_probe(sdev->dev, -ENOMEM, "failed to allocate common data\n"); + sdev->pdata->hw_pdata = common; common->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp", PLATFORM_DEVID_NONE, @@ -436,7 +437,6 @@ static int imx_probe(struct snd_sof_dev *sdev) imx_dsp_set_data(common->ipc_handle, sdev); sdev->num_cores = 1; - sdev->pdata->hw_pdata = common; sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; sdev->dsp_box.offset = get_chip_info(sdev)->ipc_info.boot_mbox_offset; From ad0fbcebb5f6e093d433a0873758a2778d747eb8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 10 Feb 2025 16:33:41 -0600 Subject: [PATCH 0131/1090] ASoC: adau1701: use gpiod_multi_set_value_cansleep Reduce verbosity by using gpiod_multi_set_value_cansleep() instead of gpiod_set_array_value_cansleep(). Acked-by: Mark Brown Reviewed-by: Linus Walleij Signed-off-by: David Lechner Acked-by: Jonathan Cameron Link: https://patch.msgid.link/20250210-gpio-set-array-helper-v3-15-d6a673674da8@baylibre.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau1701.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 291249e0a2a3..6876462d8bdb 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -325,9 +325,7 @@ static int adau1701_reset(struct snd_soc_component *component, unsigned int clkd __assign_bit(1, values, 1); break; } - gpiod_set_array_value_cansleep(adau1701->gpio_pll_mode->ndescs, - adau1701->gpio_pll_mode->desc, adau1701->gpio_pll_mode->info, - values); + gpiod_multi_set_value_cansleep(adau1701->gpio_pll_mode, values); } adau1701->pll_clkdiv = clkdiv; From 828c0aa63706410503526d0ee522b9ac3232c86b Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Thu, 13 Feb 2025 16:06:52 +0530 Subject: [PATCH 0132/1090] ASoC: amd: ps: use switch statements for acp pci revision id check Use switch statements for acp pci revision id check in SoundWire dma irq handling. Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250213103652.1082203-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 220dca8cba85..2ff8e67c19bd 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -111,16 +111,21 @@ static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 stream_id = ACP63_SDW0_AUDIO2_RX; break; } - if (adata->acp_rev >= ACP70_PCI_REV) - adata->acp70_sdw0_dma_intr_stat[stream_id] = 1; - else + switch (adata->acp_rev) { + case ACP63_PCI_REV: adata->acp63_sdw0_dma_intr_stat[stream_id] = 1; - + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: + adata->acp70_sdw0_dma_intr_stat[stream_id] = 1; + break; + } sdw_dma_irq_flag = 1; } } } - if (adata->acp_rev == ACP63_PCI_REV) { + switch (adata->acp_rev) { + case ACP63_PCI_REV: if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); @@ -133,7 +138,9 @@ static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_TX] = 1; sdw_dma_irq_flag = 1; } - } else { + break; + case ACP70_PCI_REV: + case ACP71_PCI_REV: if (ext_intr_stat1 & ACP70_P1_SDW_DMA_IRQ_MASK) { for (index = ACP70_P1_AUDIO2_RX_THRESHOLD; index <= ACP70_P1_AUDIO0_TX_THRESHOLD; index++) { @@ -166,6 +173,7 @@ static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 } } } + break; } return sdw_dma_irq_flag; } From ae575d2145d1a2c8bb5d2835d7d54751f3b0bace Mon Sep 17 00:00:00 2001 From: Sheetal Date: Thu, 13 Feb 2025 11:12:16 +0000 Subject: [PATCH 0133/1090] ASoC: tegra: Remove the isomgr_bw APIs export Commit 4a91fe4c0d683 ("ASoC: tegra: Add interconnect support") exported tegra_isomgr_adma_setbw, tegra_isomgr_adma_register and tegra_isomgr_adma_register APIs, but there are no users of these that required these symbols to be exported. Hence, remove the exporting of the symbols. Fixes: 4a91fe4c0d683 ("ASoC: tegra: Add interconnect support") Signed-off-by: Sheetal Link: https://patch.msgid.link/20250213111216.1238344-1-sheetal@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_isomgr_bw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c index 7789efe13873..18e802bca6a6 100644 --- a/sound/soc/tegra/tegra_isomgr_bw.c +++ b/sound/soc/tegra/tegra_isomgr_bw.c @@ -75,7 +75,6 @@ int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, return icc_set_bw(adma_isomgr->icc_path_handle, adma_isomgr->current_bandwidth, adma_isomgr->max_bw); } -EXPORT_SYMBOL(tegra_isomgr_adma_setbw); int tegra_isomgr_adma_register(struct device *dev) { @@ -114,7 +113,6 @@ int tegra_isomgr_adma_register(struct device *dev) return 0; } -EXPORT_SYMBOL(tegra_isomgr_adma_register); void tegra_isomgr_adma_unregister(struct device *dev) { @@ -125,7 +123,6 @@ void tegra_isomgr_adma_unregister(struct device *dev) mutex_destroy(&admaif->adma_isomgr->mutex); } -EXPORT_SYMBOL(tegra_isomgr_adma_unregister); MODULE_AUTHOR("Mohan Kumar "); MODULE_DESCRIPTION("Tegra ADMA Bandwidth Request driver"); From 994719ed6d81a6f4677875ab6730254c0bc484ea Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Wed, 12 Feb 2025 10:12:26 +0100 Subject: [PATCH 0134/1090] ASoC: Intel: avs: Use str_on_off() in avs_dsp_core_power() Remove hard-coded strings by using the str_on_off() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250212091227.1217-3-thorsten.blum@linux.dev Reviewed-by: Cezary Rojewski Signed-off-by: Mark Brown --- sound/soc/intel/avs/dsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index 7b47e52c2b39..b9de691e9b9b 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -6,6 +6,7 @@ // Amadeusz Slawinski // +#include #include #include "avs.h" #include "registers.h" @@ -39,7 +40,7 @@ int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power) AVS_ADSPCS_TIMEOUT_US); if (ret) dev_err(adev->dev, "core_mask %d power %s failed: %d\n", - core_mask, power ? "on" : "off", ret); + core_mask, str_on_off(power), ret); return ret; } From 11c1967f1a796bf2ff56a7118147f1d39d9f5ee0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:23:20 +0000 Subject: [PATCH 0135/1090] ASoC: soc-pcm: no need to check dpcm->fe on dpcm_be_connect() All dpcm from for_each_dpcm_be(fe, ...) loop has same fe (that is the reason to connected to this list). We don't need to check (dpcm->fe == fe) in this loop. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmdvyk87.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ebe99d369ca9..0d556d350560 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1304,10 +1304,9 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, snd_soc_dpcm_mutex_assert_held(fe); /* only add new dpcms */ - for_each_dpcm_be(fe, stream, dpcm) { - if (dpcm->be == be && dpcm->fe == fe) + for_each_dpcm_be(fe, stream, dpcm) + if (dpcm->be == be) return 0; - } fe_substream = snd_soc_dpcm_get_substream(fe, stream); be_substream = snd_soc_dpcm_get_substream(be, stream); From 238c863eb3d3c6ed58493bacfd1f4b36bdcfa92f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:23:52 +0000 Subject: [PATCH 0136/1090] ASoC: soc-core: makes snd_soc_set_dmi_name() local soc-core.c only calls snd_soc_set_dmi_name(), so we don't need to have EXPORT_SYMBOL_GPL() for it. Let's makes it local function. No one uses *flavour parameter, let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7tfyk7b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ---------- sound/soc/soc-core.c | 15 +++++++-------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 16e4e488521c..62c90ef40f1a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -522,16 +522,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt); -#ifdef CONFIG_DMI -int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour); -#else -static inline int snd_soc_set_dmi_name(struct snd_soc_card *card, - const char *flavour) -{ - return 0; -} -#endif - /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 26b34b688508..ae7b3e39d5ff 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1887,7 +1887,6 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str) /** * snd_soc_set_dmi_name() - Register DMI names to card * @card: The card to register DMI names - * @flavour: The flavour "differentiator" for the card amongst its peers. * * An Intel machine driver may be used by many different devices but are * difficult for userspace to differentiate, since machine drivers usually @@ -1915,7 +1914,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str) * * Returns 0 on success, otherwise a negative error code. */ -int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) +static int snd_soc_set_dmi_name(struct snd_soc_card *card) { const char *vendor, *product, *board; @@ -1959,16 +1958,16 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) return 0; } - /* Add flavour to dmi long name */ - if (flavour) - append_dmi_string(card, flavour); - /* set the card long name */ card->long_name = card->dmi_longname; return 0; } -EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name); +#else +static inline int snd_soc_set_dmi_name(struct snd_soc_card *card) +{ + return 0; +} #endif /* CONFIG_DMI */ static void soc_check_tplg_fes(struct snd_soc_card *card) @@ -2256,7 +2255,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card) goto probe_end; /* try to set some sane longname if DMI is available */ - snd_soc_set_dmi_name(card, NULL); + snd_soc_set_dmi_name(card); soc_setup_card_name(card, card->snd_card->shortname, card->name, NULL); From 1248d29464cc682c2a1793cfc5d4ebeb374c6738 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:24:06 +0000 Subject: [PATCH 0137/1090] ASoC: soc-ops: makes snd_soc_read_signed() void snd_soc_read_signed() never return error. Let's makes it void. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8zyk6x.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index c6601ef16f84..bb1fbffeef9f 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -122,10 +122,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); * This functions reads a codec register. The register value is shifted right * by 'shift' bits and masked with the given 'mask'. Afterwards it translates * the given registervalue into a signed integer if sign_bit is non-zero. - * - * Returns 0 on sucess, otherwise an error value */ -static int snd_soc_read_signed(struct snd_soc_component *component, +static void snd_soc_read_signed(struct snd_soc_component *component, unsigned int reg, unsigned int mask, unsigned int shift, unsigned int sign_bit, int *signed_val) { @@ -137,13 +135,13 @@ static int snd_soc_read_signed(struct snd_soc_component *component, if (!sign_bit) { *signed_val = val; - return 0; + return; } /* non-negative number */ if (!(val & BIT(sign_bit))) { *signed_val = val; - return 0; + return; } ret = val; @@ -157,8 +155,6 @@ static int snd_soc_read_signed(struct snd_soc_component *component, ret |= ~((int)(BIT(sign_bit) - 1)); *signed_val = ret; - - return 0; } /** @@ -266,14 +262,11 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1ULL << fls(max)) - 1; unsigned int invert = mc->invert; int val; - int ret; if (sign_bit) mask = BIT(sign_bit + 1) - 1; - ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); - if (ret) - return ret; + snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); ucontrol->value.integer.value[0] = val - min; if (invert) @@ -282,13 +275,9 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2) - ret = snd_soc_read_signed(component, reg, mask, rshift, - sign_bit, &val); + snd_soc_read_signed(component, reg, mask, rshift, sign_bit, &val); else - ret = snd_soc_read_signed(component, reg2, mask, shift, - sign_bit, &val); - if (ret) - return ret; + snd_soc_read_signed(component, reg2, mask, shift, sign_bit, &val); ucontrol->value.integer.value[1] = val - min; if (invert) From 7e1caa679686dde5c24d60b139f234568045758f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:24:17 +0000 Subject: [PATCH 0138/1090] ASoC: soc-pcm: makes dpcm_dapm_stream_event() void No one uses dpcm_dapm_stream_event() return value, and it always return 0. Let's makes it void. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seojyk6m.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 4 ++-- sound/soc/soc-pcm.c | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index c6fb350b4b06..c1b88c3b7835 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -143,8 +143,8 @@ void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream); int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd); int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, - int event); +void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event); + bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir); int widget_in_list(struct snd_soc_dapm_widget_list *list, struct snd_soc_dapm_widget *widget); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0d556d350560..a206a25451f7 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -400,8 +400,7 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) } /* DPCM stream event, send event to FE and all active BEs. */ -int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, - int event) +void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event) { struct snd_soc_dpcm *dpcm; @@ -422,8 +421,6 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, } snd_soc_dapm_stream_event(fe, dir, event); - - return 0; } static void soc_pcm_set_dai_params(struct snd_soc_dai *dai, From 7f1186a8d738661b941b298fd6d1d5725ed71428 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:24:38 +0000 Subject: [PATCH 0139/1090] ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot() snd_soc_dai_set_tdm_slot() calls .xlate_tdm_slot_mask() or snd_soc_xlate_tdm_slot_mask(), but didn't check its return value. Let's check it. This patch might break existing driver. In such case, let's makes each func to void instead of int. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6z7yk61.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 7c4c9127e5f3..8f2b5b840bb0 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -261,10 +261,11 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, if (dai->driver->ops && dai->driver->ops->xlate_tdm_slot_mask) - dai->driver->ops->xlate_tdm_slot_mask(slots, - &tx_mask, &rx_mask); + ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); else - snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (ret) + goto err; for_each_pcm_streams(stream) snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); @@ -273,6 +274,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, dai->driver->ops->set_tdm_slot) ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); +err: return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); From 0c4a06395156d16ea33e959fccea84e4cfec04c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:24:54 +0000 Subject: [PATCH 0140/1090] ASoC: soc-pcm: remove duplicate param from __soc_pcm_hw_params() We can get struct snd_soc_pcm_runtime from struct snd_pcm_substream, no need to have both as function parameter. Let's shrink it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mseryk5l.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a206a25451f7..062e2cc467cd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1062,10 +1062,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) * function can also be called multiple times and can allocate buffers * (using snd_pcm_lib_* ). It's non-atomic. */ -static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_substream *substream, +static int __soc_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; struct snd_pcm_hw_params tmp_params; @@ -1171,7 +1171,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, int ret; snd_soc_dpcm_mutex_lock(rtd); - ret = __soc_pcm_hw_params(rtd, substream, params); + ret = __soc_pcm_hw_params(substream, params); snd_soc_dpcm_mutex_unlock(rtd); return ret; } @@ -2123,7 +2123,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) dev_dbg(be->dev, "ASoC: hw_params BE %s\n", be->dai_link->name); - ret = __soc_pcm_hw_params(be, be_substream, &hw_params); + ret = __soc_pcm_hw_params(be_substream, &hw_params); if (ret < 0) goto unwind; @@ -2179,7 +2179,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, params_channels(params), params_format(params)); /* call hw_params on the frontend */ - ret = __soc_pcm_hw_params(fe, substream, params); + ret = __soc_pcm_hw_params(substream, params); if (ret < 0) dpcm_be_dai_hw_free(fe, stream); else From 257a060fe219bb0dcb98f12ce34f04eca6d08352 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:28:43 +0000 Subject: [PATCH 0141/1090] ASoC: remove update from snd_soc_card snd_soc_card :: update is used only for passing parameters to dapm_widget_update() like below. card->update = update; ret = soc_dapm_xxx(card, ...); card->update = NULL; Let's passing it via function parameter and remove update from snd_soc_card. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldubyjz9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 - sound/soc/soc-dapm.c | 48 +++++++++++++++++++------------------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 62c90ef40f1a..644cfe26022e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1106,7 +1106,6 @@ struct snd_soc_card { /* Generic DAPM context for the card */ struct snd_soc_dapm_context dapm; struct snd_soc_dapm_stats dapm_stats; - struct snd_soc_dapm_update *update; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_card_root; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 420fe7dea31e..b7818388984e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1743,9 +1743,8 @@ static void dapm_seq_run(struct snd_soc_card *card, soc_dapm_async_complete(d); } -static void dapm_widget_update(struct snd_soc_card *card) +static void dapm_widget_update(struct snd_soc_card *card, struct snd_soc_dapm_update *update) { - struct snd_soc_dapm_update *update = card->update; struct snd_soc_dapm_widget_list *wlist; struct snd_soc_dapm_widget *w = NULL; unsigned int wi; @@ -1951,7 +1950,8 @@ static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) * o Input pin to Output pin (bypass, sidetone) * o DAC to ADC (loopback). */ -static int dapm_power_widgets(struct snd_soc_card *card, int event) +static int dapm_power_widgets(struct snd_soc_card *card, int event, + struct snd_soc_dapm_update *update) { struct snd_soc_dapm_widget *w; struct snd_soc_dapm_context *d; @@ -2059,7 +2059,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) /* Power down widgets first; try to avoid amplifying pops. */ dapm_seq_run(card, &down_list, event, false); - dapm_widget_update(card); + dapm_widget_update(card, update); /* Now power up. */ dapm_seq_run(card, &up_list, event, true); @@ -2332,7 +2332,9 @@ static void soc_dapm_connect_path(struct snd_soc_dapm_path *path, /* test and update the power status of a mux widget */ static int soc_dapm_mux_update_power(struct snd_soc_card *card, - struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) + struct snd_kcontrol *kcontrol, + struct snd_soc_dapm_update *update, + int mux, struct soc_enum *e) { struct snd_soc_dapm_path *path; int found = 0; @@ -2353,7 +2355,7 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, } if (found) - dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP, update); return found; } @@ -2366,9 +2368,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, int ret; snd_soc_dapm_mutex_lock(card); - card->update = update; - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); - card->update = NULL; + ret = soc_dapm_mux_update_power(card, kcontrol, update, mux, e); snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -2379,6 +2379,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power); /* test and update the power status of a mixer or switch widget */ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_kcontrol *kcontrol, + struct snd_soc_dapm_update *update, int connect, int rconnect) { struct snd_soc_dapm_path *path; @@ -2418,7 +2419,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, } if (found) - dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP, update); return found; } @@ -2431,9 +2432,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, int ret; snd_soc_dapm_mutex_lock(card); - card->update = update; - ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1); - card->update = NULL; + ret = soc_dapm_mixer_update_power(card, kcontrol, update, connect, -1); snd_soc_dapm_mutex_unlock(card); if (ret > 0) snd_soc_dpcm_runtime_update(card); @@ -2689,7 +2688,7 @@ int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm) if (!snd_soc_card_is_instantiated(dapm->card)) return 0; - return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); + return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP, NULL); } EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked); @@ -3358,7 +3357,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) dapm_debugfs_add_widget(w); } - dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP); + dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP, NULL); snd_soc_dapm_mutex_unlock(card); return 0; } @@ -3447,6 +3446,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val, rval = 0; int connect, rconnect = -1, change, reg_change = 0; struct snd_soc_dapm_update update = {}; + struct snd_soc_dapm_update *pupdate = NULL; int ret = 0; val = (ucontrol->value.integer.value[0] & mask); @@ -3495,13 +3495,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, update.reg = reg; update.mask = mask << shift; update.val = val; - card->update = &update; + pupdate = &update; } - - ret = soc_dapm_mixer_update_power(card, kcontrol, connect, - rconnect); - - card->update = NULL; + ret = soc_dapm_mixer_update_power(card, kcontrol, pupdate, connect, rconnect); } snd_soc_dapm_mutex_unlock(card); @@ -3568,6 +3564,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, change, reg_change = 0; unsigned int mask; struct snd_soc_dapm_update update = {}; + struct snd_soc_dapm_update *pupdate = NULL; int ret = 0; if (item[0] >= e->items) @@ -3595,12 +3592,9 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, update.reg = e->reg; update.mask = mask; update.val = val; - card->update = &update; + pupdate = &update; } - - ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); - - card->update = NULL; + ret = soc_dapm_mux_update_power(card, kcontrol, pupdate, item[0], e); } snd_soc_dapm_mutex_unlock(card); @@ -4526,7 +4520,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, for_each_rtd_dais(rtd, i, dai) soc_dapm_dai_stream_event(dai, stream, event); - dapm_power_widgets(rtd->card, event); + dapm_power_widgets(rtd->card, event, NULL); } /** From 40b1f89a1691c4b7740bec2c868f1e4c60346353 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:28:57 +0000 Subject: [PATCH 0142/1090] ASoC: remove dpcm_process_paths() dpcm_process_paths() will call dpcm_add_paths() (A) or dpcm_prune_paths() (B) dpcm_process_paths(..., new) { if (new) (A) return dpcm_add_paths(...); else (B) return dpcm_prune_paths(...); } but the user who need to call dpcm_prune_paths() (B) is only soc_dpcm_fe_runtime_update(), all other user want to call is dpcm_add_paths() (A). We don't need to have confusing dpcm_process_paths(). Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9vyjyu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 4 ++-- sound/soc/soc-compress.c | 2 +- sound/soc/soc-pcm.c | 28 +++++++++++----------------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index c1b88c3b7835..af24665e37e8 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -132,8 +132,8 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_); void dpcm_path_put(struct snd_soc_dapm_widget_list **list); -int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, - int stream, struct snd_soc_dapm_widget_list **list, int new); +int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, + struct snd_soc_dapm_widget_list **list_); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int do_hw_free, struct snd_soc_dpcm *last); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 563dc0767c17..01d1d6bee28c 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -148,7 +148,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) snd_soc_dpcm_mutex_lock(fe); /* calculate valid and active FE <-> BE dpcms */ - dpcm_process_paths(fe, stream, &list, 1); + dpcm_add_paths(fe, stream, &list); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 062e2cc467cd..96776824d9da 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1550,8 +1550,8 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, return prune; } -static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, - struct snd_soc_dapm_widget_list **list_) +int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, + struct snd_soc_dapm_widget_list **list_) { struct snd_soc_card *card = fe->card; struct snd_soc_dapm_widget_list *list = *list_; @@ -1616,19 +1616,6 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, return new; } -/* - * Find the corresponding BE DAIs that source or sink audio to this - * FE substream. - */ -int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, - int stream, struct snd_soc_dapm_widget_list **list, int new) -{ - if (new) - return dpcm_add_paths(fe, stream, list); - else - return dpcm_prune_paths(fe, stream, list); -} - void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -2706,7 +2693,14 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) return paths; /* update any playback/capture paths */ - count = dpcm_process_paths(fe, stream, &list, new); + /* + * Find the corresponding BE DAIs that source or sink audio to this + * FE substream. + */ + if (new) + count = dpcm_add_paths(fe, stream, &list); + else + count = dpcm_prune_paths(fe, stream, &list); if (count) { dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); if (new) @@ -2798,7 +2792,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) goto open_end; /* calculate valid and active FE <-> BE dpcms */ - dpcm_process_paths(fe, stream, &list, 1); + dpcm_add_paths(fe, stream, &list); ret = dpcm_fe_dai_startup(fe_substream); if (ret < 0) From 3aebbcba4baaa81bc8c83f2229ed8e774cf40618 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:29:03 +0000 Subject: [PATCH 0143/1090] ASoC: soc-pcm: cleanup dpcm_dai_trigger_fe_be() DPCM is already difficult to read, but now dpcm_dai_trigger_fe_be() even difficult to read. static int dpcm_dai_trigger_fe_be(.., fe_first) { ^ if (fe_first) { (A) ... |(x) goto end; v } ^ (B) ... v end: return ... } It want to switch function call order by using "fe_first" for fe->be order part (A), or be->fe order part (B). But the code is using "goto" in last of (A) (=x). Just use "if..else" for (A) (B) is easy to read and understand what it want to do. static int dpcm_dai_trigger_fe_be(.., fe_first) { ^ if (fe_first) { (A) ... v } ^ else { (B) ... v } return ... } Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikpfyjyo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 96776824d9da..8a3073a506aa 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2365,18 +2365,18 @@ static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream, goto end; ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); - goto end; } - /* call trigger on the frontend after the backend. */ - ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); - if (ret < 0) - goto end; + else { + ret = dpcm_be_dai_trigger(fe, substream->stream, cmd); + if (ret < 0) + goto end; - dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", - fe->dai_link->name, cmd); + dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n", + fe->dai_link->name, cmd); - ret = soc_pcm_trigger(substream, cmd); + ret = soc_pcm_trigger(substream, cmd); + } end: return snd_soc_ret(fe->dev, ret, "trigger FE cmd: %d failed\n", cmd); } From 42da18e62652b58ba5ecd1524c146b202cda9bb7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:29:14 +0000 Subject: [PATCH 0144/1090] ASoC: soc-pcm: cleanup dpcm_fe_dai_do_trigger() dpcm_fe_dai_do_trigger() has big duplicate code. Let's makes code more simple. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64zyjyd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 52 +++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8a3073a506aa..2a53a2eb4acd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2386,46 +2386,17 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_soc_pcm_runtime *fe = snd_soc_substream_to_rtd(substream); int stream = substream->stream; int ret = 0; + int fe_first; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; switch (trigger) { case SND_SOC_DPCM_TRIGGER_PRE: - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_DRAIN: - ret = dpcm_dai_trigger_fe_be(substream, cmd, true); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = dpcm_dai_trigger_fe_be(substream, cmd, false); - break; - default: - ret = -EINVAL; - break; - } + fe_first = true; break; case SND_SOC_DPCM_TRIGGER_POST: - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_DRAIN: - ret = dpcm_dai_trigger_fe_be(substream, cmd, false); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = dpcm_dai_trigger_fe_be(substream, cmd, true); - break; - default: - ret = -EINVAL; - break; - } + fe_first = false; break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, @@ -2434,6 +2405,23 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) goto out; } + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_DRAIN: + ret = dpcm_dai_trigger_fe_be(substream, cmd, fe_first); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = dpcm_dai_trigger_fe_be(substream, cmd, !fe_first); + break; + default: + ret = -EINVAL; + break; + } + if (ret < 0) goto out; From 1c3b5f37409682184669457a5bdf761268eafbe5 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:24 +0000 Subject: [PATCH 0145/1090] ASoC: tas2764: Power up/down amp on mute ops The ASoC convention is that clocks are removed after codec mute, and power up/down is more about top level power management. For these chips, the "mute" state still expects a TDM clock, and yanking the clock in this state will trigger clock errors. So, do the full shutdown<->mute<->active transition on the mute operation, so the amp is in software shutdown by the time the clocks are removed. This fixes TDM clock errors when streams are stopped. Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-1-dbab892a69b5@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 51 ++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index d482cd194c08..60d660a88fab 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -180,33 +180,6 @@ static SOC_ENUM_SINGLE_DECL( static const struct snd_kcontrol_new tas2764_asi1_mux = SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum); -static int tas2764_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); - int ret; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - tas2764->dac_powered = true; - ret = tas2764_update_pwr_ctrl(tas2764); - break; - case SND_SOC_DAPM_PRE_PMD: - tas2764->dac_powered = false; - ret = tas2764_update_pwr_ctrl(tas2764); - break; - default: - dev_err(tas2764->dev, "Unsupported event\n"); - return -EINVAL; - } - - if (ret < 0) - return ret; - - return 0; -} - static const struct snd_kcontrol_new isense_switch = SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1); static const struct snd_kcontrol_new vsense_switch = @@ -219,8 +192,7 @@ static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = { 1, &isense_switch), SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 1, &vsense_switch), - SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_OUTPUT("OUT"), SND_SOC_DAPM_SIGGEN("VMON"), SND_SOC_DAPM_SIGGEN("IMON") @@ -241,9 +213,28 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) { struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(dai->component); + int ret; + + if (!mute) { + tas2764->dac_powered = true; + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + } tas2764->unmuted = !mute; - return tas2764_update_pwr_ctrl(tas2764); + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + + if (mute) { + tas2764->dac_powered = false; + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + } + + return 0; } static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) From 08a66f55f7246d477b19620a953476dfc02beefc Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:25 +0000 Subject: [PATCH 0146/1090] ASoC: tas2764: Wait for ramp-down after shutdown When we shut down the amp, we need to wait for the built-in ramp-down before we can remove the TDM clocks. There is no documented status regiter to poll, so the best we can do is a delay. Datasheet says 5.9ms for ramp-down and 1.5ms between shutdown and next startup, so let's do 6ms after mute and 2ms after shutdown. That gives us a cumulative 8ms for ramp-down and guaratees the required minimum shutdown time. Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-2-dbab892a69b5@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 60d660a88fab..0b033ab51f7f 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -142,6 +142,8 @@ static int tas2764_codec_suspend(struct snd_soc_component *component) regcache_cache_only(tas2764->regmap, true); regcache_mark_dirty(tas2764->regmap); + usleep_range(6000, 7000); + return 0; } @@ -228,10 +230,16 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) return ret; if (mute) { + /* Wait for ramp-down */ + usleep_range(6000, 7000); + tas2764->dac_powered = false; ret = tas2764_update_pwr_ctrl(tas2764); if (ret) return ret; + + /* Wait a bit after shutdown */ + usleep_range(2000, 3000); } return 0; From f37f1748564ac51d32f7588bd7bfc99913ccab8e Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:26 +0000 Subject: [PATCH 0147/1090] ASoC: tas2764: Mark SW_RESET as volatile Since the bit is self-clearing. Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-3-dbab892a69b5@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 0b033ab51f7f..d01333c7dd93 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -642,6 +642,7 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = { static bool tas2764_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case TAS2764_SW_RST: case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4: case TAS2764_INT_CLK_CFG: return true; From d64c4c3d1c578f98d70db1c5e2535b47adce9d07 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:27 +0000 Subject: [PATCH 0148/1090] ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-4-dbab892a69b5@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index d01333c7dd93..49d32e957789 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -625,6 +625,7 @@ static const struct reg_default tas2764_reg_defaults[] = { { TAS2764_TDM_CFG2, 0x0a }, { TAS2764_TDM_CFG3, 0x10 }, { TAS2764_TDM_CFG5, 0x42 }, + { TAS2764_INT_CLK_CFG, 0x19 }, }; static const struct regmap_range_cfg tas2764_regmap_ranges[] = { From 99e6ea912340d6a262a60d5dd0c87c5e7b2d6ff2 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 7 Feb 2025 13:21:45 +0100 Subject: [PATCH 0149/1090] spi: atmel-quadspi: remove references to runtime PM on error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to call runtime PM put APIs on error path of `atmel_qspi_sama7g5_transfer()` as the caller (`atmel_qspi_exec_op()`) of it will take care of this if needed. Fixes: 5af42209a4d2 ("spi: atmel-quadspi: Add support for sama7g5 QSPI") Signed-off-by: Claudiu Beznea Signed-off-by: Durai Manickam KR Reported-by: Alexander Dahl Closes: https://lore.kernel.org/linux-spi/20250109-carat-festivity-5f088e1add3c@thorsis.com/ [ csokas.bence: Rebase and clarify msg, fix/add tags ] Signed-off-by: Bence Csókás Link: https://patch.msgid.link/20250207122145.162183-2-csokas.bence@prolan.hu Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index d8c9be64d006..244ac0106862 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -930,11 +930,8 @@ static int atmel_qspi_sama7g5_transfer(struct spi_mem *mem, /* Release the chip-select. */ ret = atmel_qspi_reg_sync(aq); - if (ret) { - pm_runtime_mark_last_busy(&aq->pdev->dev); - pm_runtime_put_autosuspend(&aq->pdev->dev); + if (ret) return ret; - } atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR); return atmel_qspi_wait_for_completion(aq, QSPI_SR_CSRA); From 3d7a20f9ba7b09a35df4bdb5f0ddb2a0c8a4f39e Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 13 Feb 2025 08:03:41 +0000 Subject: [PATCH 0150/1090] MAINTAINERS: add tambarus as R for Samsung SPI I'm currently working on a Samsung SoC which includes SPI. I'd like to be Cc'ed to further contributions and help on reviewing them. Add me as reviewer. Signed-off-by: Tudor Ambarus Acked-by: Andi Shyti Reviewed-by: Sam Protsenko Link: https://patch.msgid.link/20250213-gs101-spi-r-v1-1-1e3ab8096873@linaro.org Signed-off-by: Mark Brown --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index efee40ea589f..3a5d1d5891e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21075,6 +21075,7 @@ F: include/linux/clk/samsung.h SAMSUNG SPI DRIVERS M: Andi Shyti +R: Tudor Ambarus L: linux-spi@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained From 7103f0589ac220eac3d2b1e8411494b31b883d06 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 13:14:34 +0100 Subject: [PATCH 0151/1090] x86/microcode/AMD: Remove ugly linebreak in __verify_patch_section() signature No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250211163648.30531-2-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index a5dac7f3c0a0..4a62625c311a 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -246,8 +246,7 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size) * On success, @sh_psize returns the patch size according to the section header, * to the caller. */ -static bool -__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize) +static bool __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize) { u32 p_type, p_size; const u32 *hdr; From 3ef0740d10b005a45e8ae5b4b7b5d37bfddf63c0 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 12:23:47 +0100 Subject: [PATCH 0152/1090] x86/microcode/AMD: Remove unused save_microcode_in_initrd_amd() declarations Commit a7939f016720 ("x86/microcode/amd: Cache builtin/initrd microcode early") renamed it to save_microcode_in_initrd() and made it static. Zap the forgotten declarations. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250211163648.30531-3-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 2 +- arch/x86/kernel/cpu/microcode/internal.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 4a62625c311a..f831c0602994 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -517,7 +517,7 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize) * patch container file in initrd, traverse equivalent cpu table, look for a * matching microcode patch, and update, all in initrd memory in place. * When vmalloc() is available for use later -- on 64-bit during first AP load, - * and on 32-bit during save_microcode_in_initrd_amd() -- we can call + * and on 32-bit during save_microcode_in_initrd() -- we can call * load_microcode_amd() to save equivalent cpu table and microcode patches in * kernel heap memory. * diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h index 21776c529fa9..5df621752fef 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -100,14 +100,12 @@ extern bool force_minrev; #ifdef CONFIG_CPU_SUP_AMD void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family); void load_ucode_amd_ap(unsigned int family); -int save_microcode_in_initrd_amd(unsigned int family); void reload_ucode_amd(unsigned int cpu); struct microcode_ops *init_amd_microcode(void); void exit_amd_microcode(void); #else /* CONFIG_CPU_SUP_AMD */ static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { } static inline void load_ucode_amd_ap(unsigned int family) { } -static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; } static inline void reload_ucode_amd(unsigned int cpu) { } static inline struct microcode_ops *init_amd_microcode(void) { return NULL; } static inline void exit_amd_microcode(void) { } From dc15675074dcfd79a2f10a6e39f96b0244961a01 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 12:46:45 +0100 Subject: [PATCH 0153/1090] x86/microcode/AMD: Merge early_apply_microcode() into its single callsite No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250211163648.30531-4-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 60 +++++++++++++---------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index f831c0602994..90f93b3ca9db 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -512,39 +512,6 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize) return true; } -/* - * Early load occurs before we can vmalloc(). So we look for the microcode - * patch container file in initrd, traverse equivalent cpu table, look for a - * matching microcode patch, and update, all in initrd memory in place. - * When vmalloc() is available for use later -- on 64-bit during first AP load, - * and on 32-bit during save_microcode_in_initrd() -- we can call - * load_microcode_amd() to save equivalent cpu table and microcode patches in - * kernel heap memory. - * - * Returns true if container found (sets @desc), false otherwise. - */ -static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size) -{ - struct cont_desc desc = { 0 }; - struct microcode_amd *mc; - - scan_containers(ucode, size, &desc); - - mc = desc.mc; - if (!mc) - return false; - - /* - * Allow application of the same revision to pick up SMT-specific - * changes even if the revision of the other SMT thread is already - * up-to-date. - */ - if (old_rev > mc->hdr.patch_id) - return false; - - return __apply_microcode_amd(mc, desc.psize); -} - static bool get_builtin_microcode(struct cpio_data *cp) { char fw_name[36] = "amd-ucode/microcode_amd.bin"; @@ -582,8 +549,19 @@ static bool __init find_blobs_in_containers(struct cpio_data *ret) return found; } +/* + * Early load occurs before we can vmalloc(). So we look for the microcode + * patch container file in initrd, traverse equivalent cpu table, look for a + * matching microcode patch, and update, all in initrd memory in place. + * When vmalloc() is available for use later -- on 64-bit during first AP load, + * and on 32-bit during save_microcode_in_initrd() -- we can call + * load_microcode_amd() to save equivalent cpu table and microcode patches in + * kernel heap memory. + */ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax) { + struct cont_desc desc = { }; + struct microcode_amd *mc; struct cpio_data cp = { }; u32 dummy; @@ -597,7 +575,21 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ if (!find_blobs_in_containers(&cp)) return; - if (early_apply_microcode(ed->old_rev, cp.data, cp.size)) + scan_containers(cp.data, cp.size, &desc); + + mc = desc.mc; + if (!mc) + return; + + /* + * Allow application of the same revision to pick up SMT-specific + * changes even if the revision of the other SMT thread is already + * up-to-date. + */ + if (ed->old_rev > mc->hdr.patch_id) + return; + + if (__apply_microcode_amd(mc, desc.psize)) native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); } From b39c387164879eef71886fc93cee5ca7dd7bf500 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 12:51:37 +0100 Subject: [PATCH 0154/1090] x86/microcode/AMD: Get rid of the _load_microcode_amd() forward declaration Simply move save_microcode_in_initrd() down. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250211163648.30531-5-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 54 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 90f93b3ca9db..adfea4d0d129 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -593,34 +593,6 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); } -static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size); - -static int __init save_microcode_in_initrd(void) -{ - unsigned int cpuid_1_eax = native_cpuid_eax(1); - struct cpuinfo_x86 *c = &boot_cpu_data; - struct cont_desc desc = { 0 }; - enum ucode_state ret; - struct cpio_data cp; - - if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) - return 0; - - if (!find_blobs_in_containers(&cp)) - return -EINVAL; - - scan_containers(cp.data, cp.size, &desc); - if (!desc.mc) - return -EINVAL; - - ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); - if (ret > UCODE_UPDATED) - return -EINVAL; - - return 0; -} -early_initcall(save_microcode_in_initrd); - static inline bool patch_cpus_equivalent(struct ucode_patch *p, struct ucode_patch *n, bool ignore_stepping) @@ -1004,6 +976,32 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz return ret; } +static int __init save_microcode_in_initrd(void) +{ + unsigned int cpuid_1_eax = native_cpuid_eax(1); + struct cpuinfo_x86 *c = &boot_cpu_data; + struct cont_desc desc = { 0 }; + enum ucode_state ret; + struct cpio_data cp; + + if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) + return 0; + + if (!find_blobs_in_containers(&cp)) + return -EINVAL; + + scan_containers(cp.data, cp.size, &desc); + if (!desc.mc) + return -EINVAL; + + ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); + if (ret > UCODE_UPDATED) + return -EINVAL; + + return 0; +} +early_initcall(save_microcode_in_initrd); + /* * AMD microcode firmware naming convention, up to family 15h they are in * the legacy file: From 037e81fb9d2dfe7b31fd97e5f578854e38f09887 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 13:02:32 +0100 Subject: [PATCH 0155/1090] x86/microcode/AMD: Add get_patch_level() Put the MSR_AMD64_PATCH_LEVEL reading of the current microcode revision the hw has, into a separate function. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250211163648.30531-6-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 46 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index adfea4d0d129..31f90e129b08 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -145,6 +145,15 @@ ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; */ static u32 bsp_cpuid_1_eax __ro_after_init; +static u32 get_patch_level(void) +{ + u32 rev, dummy __always_unused; + + native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); + + return rev; +} + static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val) { union zen_patch_rev p; @@ -483,10 +492,10 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc) } } -static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize) +static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev, + unsigned int psize) { unsigned long p_addr = (unsigned long)&mc->hdr.data_code; - u32 rev, dummy; native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr); @@ -504,9 +513,8 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize) } /* verify patch application was successful */ - native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); - - if (rev != mc->hdr.patch_id) + *cur_rev = get_patch_level(); + if (*cur_rev != mc->hdr.patch_id) return false; return true; @@ -563,11 +571,12 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ struct cont_desc desc = { }; struct microcode_amd *mc; struct cpio_data cp = { }; - u32 dummy; + u32 rev; bsp_cpuid_1_eax = cpuid_1_eax; - native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy); + rev = get_patch_level(); + ed->old_rev = rev; /* Needed in load_microcode_amd() */ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax; @@ -589,8 +598,8 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ if (ed->old_rev > mc->hdr.patch_id) return; - if (__apply_microcode_amd(mc, desc.psize)) - native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); + if (__apply_microcode_amd(mc, &rev, desc.psize)) + ed->new_rev = rev; } static inline bool patch_cpus_equivalent(struct ucode_patch *p, @@ -692,14 +701,9 @@ static void free_cache(void) static struct ucode_patch *find_patch(unsigned int cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - u32 rev, dummy __always_unused; u16 equiv_id = 0; - /* fetch rev if not populated yet: */ - if (!uci->cpu_sig.rev) { - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); - uci->cpu_sig.rev = rev; - } + uci->cpu_sig.rev = get_patch_level(); if (x86_family(bsp_cpuid_1_eax) < 0x17) { equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); @@ -722,22 +726,20 @@ void reload_ucode_amd(unsigned int cpu) mc = p->data; - rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); - + rev = get_patch_level(); if (rev < mc->hdr.patch_id) { - if (__apply_microcode_amd(mc, p->size)) - pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id); + if (__apply_microcode_amd(mc, &rev, p->size)) + pr_info_once("reload revision: 0x%08x\n", rev); } } static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { - struct cpuinfo_x86 *c = &cpu_data(cpu); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct ucode_patch *p; csig->sig = cpuid_eax(0x00000001); - csig->rev = c->microcode; + csig->rev = get_patch_level(); /* * a patch could have been loaded early, set uci->mc so that @@ -778,7 +780,7 @@ static enum ucode_state apply_microcode_amd(int cpu) goto out; } - if (!__apply_microcode_amd(mc_amd, p->size)) { + if (!__apply_microcode_amd(mc_amd, &rev, p->size)) { pr_err("CPU%d: update failed for patch_level=0x%08x\n", cpu, mc_amd->hdr.patch_id); return UCODE_ERROR; From 735049b801cf3d597752017385cfc8768ce44303 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Thu, 30 Jan 2025 19:48:55 +0000 Subject: [PATCH 0156/1090] x86/amd_node, platform/x86/amd/hsmp: Have HSMP use SMN through AMD_NODE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HSMP interface is just an SMN interface with different offsets. Define an HSMP wrapper in the SMN code and have the HSMP platform driver use that rather than a local solution. Also, remove the "root" member from AMD_NB, since there are no more users of it. Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Carlos Bilbao Acked-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20250130-wip-x86-amd-nb-cleanup-v4-1-b5cc997e471b@amd.com --- arch/x86/include/asm/amd_nb.h | 1 - arch/x86/include/asm/amd_node.h | 13 ++++++++++ arch/x86/kernel/amd_nb.c | 1 - arch/x86/kernel/amd_node.c | 9 +++++++ drivers/platform/x86/amd/hsmp/Kconfig | 2 +- drivers/platform/x86/amd/hsmp/acpi.c | 7 +++--- drivers/platform/x86/amd/hsmp/hsmp.c | 1 - drivers/platform/x86/amd/hsmp/hsmp.h | 3 --- drivers/platform/x86/amd/hsmp/plat.c | 36 +++++++++------------------ 9 files changed, 39 insertions(+), 34 deletions(-) diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 4c4efb93045e..adfa0854cf2d 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h @@ -27,7 +27,6 @@ struct amd_l3_cache { }; struct amd_northbridge { - struct pci_dev *root; struct pci_dev *misc; struct pci_dev *link; struct amd_l3_cache l3_cache; diff --git a/arch/x86/include/asm/amd_node.h b/arch/x86/include/asm/amd_node.h index 113ad3e8ee40..002c3afbd30f 100644 --- a/arch/x86/include/asm/amd_node.h +++ b/arch/x86/include/asm/amd_node.h @@ -30,7 +30,20 @@ static inline u16 amd_num_nodes(void) return topology_amd_nodes_per_pkg() * topology_max_packages(); } +#ifdef CONFIG_AMD_NODE int __must_check amd_smn_read(u16 node, u32 address, u32 *value); int __must_check amd_smn_write(u16 node, u32 address, u32 value); +/* Should only be used by the HSMP driver. */ +int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write); +#else +static inline int __must_check amd_smn_read(u16 node, u32 address, u32 *value) { return -ENODEV; } +static inline int __must_check amd_smn_write(u16 node, u32 address, u32 value) { return -ENODEV; } + +static inline int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write) +{ + return -ENODEV; +} +#endif /* CONFIG_AMD_NODE */ + #endif /*_ASM_X86_AMD_NODE_H_*/ diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 11fac09e3a8c..24d7a87edf9c 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -73,7 +73,6 @@ static int amd_cache_northbridges(void) amd_northbridges.nb = nb; for (i = 0; i < amd_northbridges.num; i++) { - node_to_amd_nb(i)->root = amd_node_get_root(i); node_to_amd_nb(i)->misc = amd_node_get_func(i, 3); /* diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c index d2ec7fd555c5..65045f223c10 100644 --- a/arch/x86/kernel/amd_node.c +++ b/arch/x86/kernel/amd_node.c @@ -97,6 +97,9 @@ static DEFINE_MUTEX(smn_mutex); #define SMN_INDEX_OFFSET 0x60 #define SMN_DATA_OFFSET 0x64 +#define HSMP_INDEX_OFFSET 0xc4 +#define HSMP_DATA_OFFSET 0xc8 + /* * SMN accesses may fail in ways that are difficult to detect here in the called * functions amd_smn_read() and amd_smn_write(). Therefore, callers must do @@ -179,6 +182,12 @@ int __must_check amd_smn_write(u16 node, u32 address, u32 value) } EXPORT_SYMBOL_GPL(amd_smn_write); +int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write) +{ + return __amd_smn_rw(HSMP_INDEX_OFFSET, HSMP_DATA_OFFSET, node, address, value, write); +} +EXPORT_SYMBOL_GPL(amd_smn_hsmp_rdwr); + static int amd_cache_roots(void) { u16 node, num_nodes = amd_num_nodes(); diff --git a/drivers/platform/x86/amd/hsmp/Kconfig b/drivers/platform/x86/amd/hsmp/Kconfig index 7d10d4462a45..d6f7a62d55b5 100644 --- a/drivers/platform/x86/amd/hsmp/Kconfig +++ b/drivers/platform/x86/amd/hsmp/Kconfig @@ -7,7 +7,7 @@ config AMD_HSMP tristate menu "AMD HSMP Driver" - depends on AMD_NB || COMPILE_TEST + depends on AMD_NODE || COMPILE_TEST config AMD_HSMP_ACPI tristate "AMD HSMP ACPI device driver" diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c index 444b43be35a2..c1eccb3c80c5 100644 --- a/drivers/platform/x86/amd/hsmp/acpi.c +++ b/drivers/platform/x86/amd/hsmp/acpi.c @@ -10,7 +10,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include @@ -24,6 +23,8 @@ #include +#include + #include "hsmp.h" #define DRIVER_NAME "amd_hsmp" @@ -321,8 +322,8 @@ static int hsmp_acpi_probe(struct platform_device *pdev) return -ENOMEM; if (!hsmp_pdev->is_probed) { - hsmp_pdev->num_sockets = amd_nb_num(); - if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) + hsmp_pdev->num_sockets = amd_num_nodes(); + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) return -ENODEV; hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c index 03164e30b3a5..a3ac09a90de4 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.c +++ b/drivers/platform/x86/amd/hsmp/hsmp.c @@ -8,7 +8,6 @@ */ #include -#include #include #include diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h index e852f0a947e4..af8b21f821d6 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.h +++ b/drivers/platform/x86/amd/hsmp/hsmp.h @@ -21,8 +21,6 @@ #define HSMP_ATTR_GRP_NAME_SIZE 10 -#define MAX_AMD_SOCKETS 8 - #define HSMP_CDEV_NAME "hsmp_cdev" #define HSMP_DEVNODE_NAME "hsmp" @@ -41,7 +39,6 @@ struct hsmp_socket { void __iomem *virt_base_addr; struct semaphore hsmp_sem; char name[HSMP_ATTR_GRP_NAME_SIZE]; - struct pci_dev *root; struct device *dev; u16 sock_ind; int (*amd_hsmp_rdwr)(struct hsmp_socket *sock, u32 off, u32 *val, bool rw); diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c index 02ca85762b68..b9782a078dbd 100644 --- a/drivers/platform/x86/amd/hsmp/plat.c +++ b/drivers/platform/x86/amd/hsmp/plat.c @@ -10,14 +10,16 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include +#include #include #include #include #include #include +#include + #include "hsmp.h" #define DRIVER_NAME "amd_hsmp" @@ -34,28 +36,12 @@ #define SMN_HSMP_MSG_RESP 0x0010980 #define SMN_HSMP_MSG_DATA 0x00109E0 -#define HSMP_INDEX_REG 0xc4 -#define HSMP_DATA_REG 0xc8 - static struct hsmp_plat_device *hsmp_pdev; static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset, u32 *value, bool write) { - int ret; - - if (!sock->root) - return -ENODEV; - - ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, - sock->mbinfo.base_addr + offset); - if (ret) - return ret; - - ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value) - : pci_read_config_dword(sock->root, HSMP_DATA_REG, value)); - - return ret; + return amd_smn_hsmp_rdwr(sock->sock_ind, sock->mbinfo.base_addr + offset, value, write); } static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj, @@ -95,7 +81,12 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, * Static array of 8 + 1(for NULL) elements is created below * to create sysfs groups for sockets. * is_bin_visible function is used to show / hide the necessary groups. + * + * Validate the maximum number against MAX_AMD_NUM_NODES. If this changes, + * then the attributes and groups below must be adjusted. */ +static_assert(MAX_AMD_NUM_NODES == 8); + #define HSMP_BIN_ATTR(index, _list) \ static const struct bin_attribute attr##index = { \ .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ @@ -159,10 +150,7 @@ static int init_platform_device(struct device *dev) int ret, i; for (i = 0; i < hsmp_pdev->num_sockets; i++) { - if (!node_to_amd_nb(i)) - return -ENODEV; sock = &hsmp_pdev->sock[i]; - sock->root = node_to_amd_nb(i)->root; sock->sock_ind = i; sock->dev = dev; sock->mbinfo.base_addr = SMN_HSMP_BASE; @@ -305,11 +293,11 @@ static int __init hsmp_plt_init(void) return -ENOMEM; /* - * amd_nb_num() returns number of SMN/DF interfaces present in the system + * amd_num_nodes() returns number of SMN/DF interfaces present in the system * if we have N SMN/DF interfaces that ideally means N sockets */ - hsmp_pdev->num_sockets = amd_nb_num(); - if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) + hsmp_pdev->num_sockets = amd_num_nodes(); + if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) return ret; ret = platform_driver_register(&amd_hsmp_driver); From bebe0afb74514ae51f4f348b28326c658b02209d Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 30 Jan 2025 19:48:56 +0000 Subject: [PATCH 0157/1090] x86/amd_node: Add SMN offsets to exclusive region access Offsets 0x60 and 0x64 are used internally by kernel drivers that call the amd_smn_read() and amd_smn_write() functions. If userspace accesses the regions at the same time as the kernel it may cause malfunctions in drivers using the offsets. Add these offsets to the exclusions so that the kernel is tainted if a non locked down userspace tries to access them. Signed-off-by: Mario Limonciello Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20250130-wip-x86-amd-nb-cleanup-v4-2-b5cc997e471b@amd.com --- arch/x86/kernel/amd_node.c | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c index 65045f223c10..ac571948cb35 100644 --- a/arch/x86/kernel/amd_node.c +++ b/arch/x86/kernel/amd_node.c @@ -93,6 +93,7 @@ static struct pci_dev **amd_roots; /* Protect the PCI config register pairs used for SMN. */ static DEFINE_MUTEX(smn_mutex); +static bool smn_exclusive; #define SMN_INDEX_OFFSET 0x60 #define SMN_DATA_OFFSET 0x64 @@ -149,6 +150,9 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b if (!root) return err; + if (!smn_exclusive) + return err; + guard(mutex)(&smn_mutex); err = pci_write_config_dword(root, i_off, address); @@ -202,6 +206,39 @@ static int amd_cache_roots(void) return 0; } +static int reserve_root_config_spaces(void) +{ + struct pci_dev *root = NULL; + struct pci_bus *bus = NULL; + + while ((bus = pci_find_next_bus(bus))) { + /* Root device is Device 0 Function 0 on each Primary Bus. */ + root = pci_get_slot(bus, 0); + if (!root) + continue; + + if (root->vendor != PCI_VENDOR_ID_AMD && + root->vendor != PCI_VENDOR_ID_HYGON) + continue; + + pci_dbg(root, "Reserving PCI config space\n"); + + /* + * There are a few SMN index/data pairs and other registers + * that shouldn't be accessed by user space. + * So reserve the entire PCI config space for simplicity rather + * than covering specific registers piecemeal. + */ + if (!pci_request_config_region_exclusive(root, 0, PCI_CFG_SPACE_SIZE, NULL)) { + pci_err(root, "Failed to reserve config space\n"); + return -EEXIST; + } + } + + smn_exclusive = true; + return 0; +} + static int __init amd_smn_init(void) { int err; @@ -218,6 +255,10 @@ static int __init amd_smn_init(void) if (err) return err; + err = reserve_root_config_spaces(); + if (err) + return err; + return 0; } From 6b06755af6679fd7c98ebc017ac31c8a74127538 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 30 Jan 2025 19:48:57 +0000 Subject: [PATCH 0158/1090] x86/amd_node: Add support for debugfs access to SMN registers There are certain registers on AMD Zen systems that can only be accessed through SMN. Introduce a new interface that provides debugfs files for accessing SMN. As this introduces the capability for userspace to manipulate the hardware in unpredictable ways, taint the kernel when writing. Signed-off-by: Mario Limonciello Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20250130-wip-x86-amd-nb-cleanup-v4-3-b5cc997e471b@amd.com --- arch/x86/kernel/amd_node.c | 99 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c index ac571948cb35..b670fa85c61b 100644 --- a/arch/x86/kernel/amd_node.c +++ b/arch/x86/kernel/amd_node.c @@ -8,6 +8,7 @@ * Author: Yazen Ghannam */ +#include #include /* @@ -192,6 +193,87 @@ int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *value, bool write } EXPORT_SYMBOL_GPL(amd_smn_hsmp_rdwr); +static struct dentry *debugfs_dir; +static u16 debug_node; +static u32 debug_address; + +static ssize_t smn_node_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + u16 node; + int ret; + + ret = kstrtou16_from_user(userbuf, count, 0, &node); + if (ret) + return ret; + + if (node >= amd_num_nodes()) + return -ENODEV; + + debug_node = node; + return count; +} + +static int smn_node_show(struct seq_file *m, void *v) +{ + seq_printf(m, "0x%08x\n", debug_node); + return 0; +} + +static ssize_t smn_address_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + int ret; + + ret = kstrtouint_from_user(userbuf, count, 0, &debug_address); + if (ret) + return ret; + + return count; +} + +static int smn_address_show(struct seq_file *m, void *v) +{ + seq_printf(m, "0x%08x\n", debug_address); + return 0; +} + +static int smn_value_show(struct seq_file *m, void *v) +{ + u32 val; + int ret; + + ret = amd_smn_read(debug_node, debug_address, &val); + if (ret) + return ret; + + seq_printf(m, "0x%08x\n", val); + return 0; +} + +static ssize_t smn_value_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + u32 val; + int ret; + + ret = kstrtouint_from_user(userbuf, count, 0, &val); + if (ret) + return ret; + + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + + ret = amd_smn_write(debug_node, debug_address, val); + if (ret) + return ret; + + return count; +} + +DEFINE_SHOW_STORE_ATTRIBUTE(smn_node); +DEFINE_SHOW_STORE_ATTRIBUTE(smn_address); +DEFINE_SHOW_STORE_ATTRIBUTE(smn_value); + static int amd_cache_roots(void) { u16 node, num_nodes = amd_num_nodes(); @@ -239,6 +321,15 @@ static int reserve_root_config_spaces(void) return 0; } +static bool enable_dfs; + +static int __init amd_smn_enable_dfs(char *str) +{ + enable_dfs = true; + return 1; +} +__setup("amd_smn_debugfs_enable", amd_smn_enable_dfs); + static int __init amd_smn_init(void) { int err; @@ -259,6 +350,14 @@ static int __init amd_smn_init(void) if (err) return err; + if (enable_dfs) { + debugfs_dir = debugfs_create_dir("amd_smn", arch_debugfs_dir); + + debugfs_create_file("node", 0600, debugfs_dir, NULL, &smn_node_fops); + debugfs_create_file("address", 0600, debugfs_dir, NULL, &smn_address_fops); + debugfs_create_file("value", 0600, debugfs_dir, NULL, &smn_value_fops); + } + return 0; } From 783db6851c1821d8b983ffb12b99c279ff64f2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Sat, 8 Feb 2025 00:57:22 +0000 Subject: [PATCH 0159/1090] ASoC: ops: Enforce platform maximum on initial value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lower the volume if it is violating the platform maximum at its initial value (i.e. at the time of the 'snd_soc_limit_volume' call). Signed-off-by: Martin PoviÅ¡er [Cherry picked from the Asahi kernel with fixups -- broonie] Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index c6601ef16f84..a7d0d4035d65 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); +static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + struct snd_ctl_elem_value uctl; + int ret; + + if (!mc->platform_max) + return 0; + + ret = kctl->get(kctl, &uctl); + if (ret < 0) + return ret; + + if (uctl.value.integer.value[0] > mc->platform_max) + uctl.value.integer.value[0] = mc->platform_max; + + if (snd_soc_volsw_is_stereo(mc) && + uctl.value.integer.value[1] > mc->platform_max) + uctl.value.integer.value[1] = mc->platform_max; + + ret = kctl->put(kctl, &uctl); + if (ret < 0) + return ret; + + return 0; +} + /** * snd_soc_limit_volume - Set new limit to an existing volume control. * @@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card, struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; if (max <= mc->max - mc->min) { mc->platform_max = max; - ret = 0; + ret = snd_soc_clip_to_platform_max(kctl); } } return ret; From 9dc016eaba3a70febcd1db5f1a0beeb7430166aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 12 Feb 2025 18:29:47 +0100 Subject: [PATCH 0160/1090] ASoC: SOF: Intel: Don't import non-existing module namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no module namespace "SND_SOC_SOF_INTEL_HIFI_EP_IPC", so don't import it. Historically there was such a namespace, but it was dropped in commit 97e22cbd0dc3 ("ASoC: SOF: Make Intel IPC stream ops generic"). Signed-off-by: Uwe Kleine-König Link: https://patch.msgid.link/20250212172947.38970-2-u.kleine-koenig@baylibre.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 1 - sound/soc/sof/intel/byt.c | 1 - sound/soc/sof/intel/pci-tng.c | 1 - 3 files changed, 3 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index e1f0e38c2407..79374dcde89f 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -694,6 +694,5 @@ module_platform_driver(snd_sof_acpi_intel_bdw_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF support for Broadwell platforms"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC"); MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); MODULE_IMPORT_NS("SND_SOC_SOF_ACPI_DEV"); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index cae7dc0036c6..900cc10a3b7f 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -475,7 +475,6 @@ module_platform_driver(snd_sof_acpi_intel_byt_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF support for Baytrail/Cherrytrail"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC"); MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); MODULE_IMPORT_NS("SND_SOC_SOF_ACPI_DEV"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_ATOM_HIFI_EP"); diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index b585ac4a85c2..3eb7400942dd 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -245,7 +245,6 @@ module_pci_driver(snd_sof_pci_intel_tng_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF support for Tangier platforms"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC"); MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA"); MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_ATOM_HIFI_EP"); From e0f421d73053eaeb441aa77054b75992705656c7 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 10 Feb 2025 23:44:54 +0100 Subject: [PATCH 0161/1090] ASoC: SOF: ipc3: Use str_enabled_disabled() helper function Remove hard-coded strings by using the str_enabled_disabled() helper function. Remove unnecessary curly braces. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250210224453.363638-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/sof/ipc3.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 7de5e3d285e7..4a194a705ace 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -801,20 +801,16 @@ int sof_ipc3_validate_fw_version(struct snd_sof_dev *sdev) return -EINVAL; } - if (ready->flags & SOF_IPC_INFO_BUILD) { + if (ready->flags & SOF_IPC_INFO_BUILD) dev_info(sdev->dev, "Firmware debug build %d on %s-%s - options:\n" " GDB: %s\n" " lock debug: %s\n" " lock vdebug: %s\n", v->build, v->date, v->time, - (ready->flags & SOF_IPC_INFO_GDB) ? - "enabled" : "disabled", - (ready->flags & SOF_IPC_INFO_LOCKS) ? - "enabled" : "disabled", - (ready->flags & SOF_IPC_INFO_LOCKSV) ? - "enabled" : "disabled"); - } + str_enabled_disabled(ready->flags & SOF_IPC_INFO_GDB), + str_enabled_disabled(ready->flags & SOF_IPC_INFO_LOCKS), + str_enabled_disabled(ready->flags & SOF_IPC_INFO_LOCKSV)); /* copy the fw_version into debugfs at first boot */ memcpy(&sdev->fw_version, v, sizeof(*v)); From 5c7e4c4da8586d2ef55a11a9f4df626b8ea9a146 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 7 Feb 2025 11:30:29 -0500 Subject: [PATCH 0162/1090] ASoC: dt-bindings: wlf,wm8960: add 'port' property The wm8960 codec may be used with audio graph card and thus may require an additional property: 'port'. Add it. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Daniel Baluta Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250207163029.3365-1-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/wlf,wm8960.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml index 62e62c335d07..3c2b9790ffcf 100644 --- a/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml +++ b/Documentation/devicetree/bindings/sound/wlf,wm8960.yaml @@ -75,6 +75,10 @@ properties: enable DACLRC pin. If shared-lrclk is present, no need to enable DAC for captrue. + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + required: - compatible - reg From 9f25b6f2568d50c247a8e3b031a0a5caee8c17d2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 10 Feb 2025 12:58:03 +0100 Subject: [PATCH 0163/1090] ASoC: wm_hubs: Use str_enable_disable() in wm_hubs_update_class_w() Remove hard-coded strings by using the str_enable_disable() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250210115804.53504-3-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 0c881846f485..196ddb224e6d 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -674,7 +675,7 @@ void wm_hubs_update_class_w(struct snd_soc_component *component) if (hubs->check_class_w_digital && !hubs->check_class_w_digital(component)) enable = false; - dev_vdbg(component->dev, "Class W %s\n", enable ? "enabled" : "disabled"); + dev_vdbg(component->dev, "Class W %s\n", str_enabled_disabled(enable)); snd_soc_component_update_bits(component, WM8993_CLASS_W_0, WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); From e08fe24c34d37d00e84009f2fb4c35f5978041e6 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 10 Feb 2025 13:01:30 +0100 Subject: [PATCH 0164/1090] ASoC: SOF: Intel: Use str_enable_disable() helper Remove hard-coded strings by using the str_enable_disable() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250210120132.53831-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index d07c68f431ba..4a6b1d56171e 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include "../ipc4-priv.h" @@ -176,7 +177,7 @@ static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); if (ret < 0) dev_err(sdev->dev, "failed to set SoundWire IPC interrupt %s\n", - enable ? "enable" : "disable"); + str_enable_disable(enable)); } int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) @@ -209,7 +210,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); if (ret < 0) { dev_err(sdev->dev, "failed to %s Host IPC and/or SOUNDWIRE\n", - enable ? "enable" : "disable"); + str_enable_disable(enable)); return ret; } @@ -228,7 +229,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); if (ret < 0) { dev_err(sdev->dev, "failed to set Host IPC interrupt %s\n", - enable ? "enable" : "disable"); + str_enable_disable(enable)); return ret; } From b20be2c77ce5341ded1a2d8aec119f6dca8ef1ad Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2025 10:32:44 +0300 Subject: [PATCH 0165/1090] ASoC: SOF: imx: Fix an IS_ERR() vs NULL bug in imx_parse_ioremap_memory() The devm_ioremap() function doesn't return error pointers, it returns NULL on error. Update the checking to match. Fixes: 651e0ed391b1 ("ASoC: SOF: imx: introduce more common structures and functions") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/68973636-eab8-4d82-8359-ae2c8f60f261@stanley.mountain Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx-common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index c3594815e60e..ea4651a0995c 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -338,9 +338,9 @@ static int imx_parse_ioremap_memory(struct snd_sof_dev *sdev) } sdev->bar[blk_type] = devm_ioremap(sdev->dev, base, size); - if (IS_ERR(sdev->bar[blk_type])) + if (!sdev->bar[blk_type]) return dev_err_probe(sdev->dev, - PTR_ERR(sdev->bar[blk_type]), + -ENOMEM, "failed to ioremap %s region\n", chip_info->memory[i].name); } From a78f244a9150da0878a37a1b59fb0608b1ccfb9d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2025 10:32:51 +0300 Subject: [PATCH 0166/1090] ASoC: SOF: imx: Fix error code in probe() This accidentally returns "common->clk_num" instead of "ret". Fixes: 651e0ed391b1 ("ASoC: SOF: imx: introduce more common structures and functions") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/b30ffe7f-21fd-45f9-9528-d6d689e04003@stanley.mountain Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx-common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index ea4651a0995c..62bf707aa909 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -425,8 +425,7 @@ static int imx_probe(struct snd_sof_dev *sdev) ret = devm_clk_bulk_get_all(sdev->dev, &common->clks); if (ret < 0) - return dev_err_probe(sdev->dev, common->clk_num, - "failed to fetch clocks\n"); + return dev_err_probe(sdev->dev, ret, "failed to fetch clocks\n"); common->clk_num = ret; ret = clk_bulk_prepare_enable(common->clk_num, common->clks); From 5d9fca12f54d3e25e02521aa8f3ec5d53759b334 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Tue, 18 Feb 2025 10:40:00 +0530 Subject: [PATCH 0167/1090] ASoC: amd: ps: fix inconsistent indenting warning in check_and_handle_sdw_dma_irq() Fix below inconsistent indenting smatch warning. smatch warnings: sound/soc/amd/ps/pci-ps.c:68 check_and_handle_sdw_dma_irq() warn: inconsistent indenting Fixes: 4516be370ced ("ASoC: amd: ps: refactor soundwire dma interrupt handling") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502132134.BlkNw1Iq-lkp@intel.com/ Signed-off-by: Vijendar Mukunda Link: https://patch.msgid.link/20250218051000.254265-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/ps/pci-ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 2ff8e67c19bd..221c65ff03c9 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -129,7 +129,7 @@ static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 if (ext_intr_stat1 & ACP63_P1_AUDIO1_RX_THRESHOLD) { writel(ACP63_P1_AUDIO1_RX_THRESHOLD, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); - adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; + adata->acp63_sdw1_dma_intr_stat[ACP63_SDW1_AUDIO1_RX] = 1; sdw_dma_irq_flag = 1; } if (ext_intr_stat1 & ACP63_P1_AUDIO1_TX_THRESHOLD) { From c893ee3f95f16fcb98da934d61483d0b7d8ed568 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:41 -0600 Subject: [PATCH 0168/1090] x86/amd_node: Add a smn_read_register() helper Some of the ACP drivers will poll registers through SMN using read_poll_timeout() which requires returning the result of the register read as the argument. Add a helper to do just that. Signed-off-by: Mario Limonciello Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20250217231747.1656228-2-superm1@kernel.org --- arch/x86/include/asm/amd_node.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/include/asm/amd_node.h b/arch/x86/include/asm/amd_node.h index 002c3afbd30f..23fe617898a8 100644 --- a/arch/x86/include/asm/amd_node.h +++ b/arch/x86/include/asm/amd_node.h @@ -46,4 +46,15 @@ static inline int __must_check amd_smn_hsmp_rdwr(u16 node, u32 address, u32 *val } #endif /* CONFIG_AMD_NODE */ +/* helper for use with read_poll_timeout */ +static inline int smn_read_register(u32 reg) +{ + int data, rc; + + rc = amd_smn_read(0, reg, &data); + if (rc) + return rc; + + return data; +} #endif /*_ASM_X86_AMD_NODE_H_*/ From 0c28e4d1e10d2aae608094620bb386e6fd73d55e Mon Sep 17 00:00:00 2001 From: Stuart Hayhurst Date: Thu, 13 Feb 2025 13:38:49 +0000 Subject: [PATCH 0169/1090] HID: corsair-void: Update power supply values with a unified work handler corsair_void_process_receiver can be called from an interrupt context, locking battery_mutex in it was causing a kernel panic. Fix it by moving the critical section into its own work, sharing this work with battery_add_work and battery_remove_work to remove the need for any locking Closes: https://bugzilla.suse.com/show_bug.cgi?id=1236843 Fixes: 6ea2a6fd3872 ("HID: corsair-void: Add Corsair Void headset family driver") Cc: stable@vger.kernel.org Signed-off-by: Stuart Hayhurst Reviewed-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/hid-corsair-void.c | 83 ++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/drivers/hid/hid-corsair-void.c b/drivers/hid/hid-corsair-void.c index 56e858066c3c..afbd67aa9719 100644 --- a/drivers/hid/hid-corsair-void.c +++ b/drivers/hid/hid-corsair-void.c @@ -71,11 +71,9 @@ #include #include -#include #include #include #include -#include #include #include #include @@ -120,6 +118,12 @@ enum { CORSAIR_VOID_BATTERY_CHARGING = 5, }; +enum { + CORSAIR_VOID_ADD_BATTERY = 0, + CORSAIR_VOID_REMOVE_BATTERY = 1, + CORSAIR_VOID_UPDATE_BATTERY = 2, +}; + static enum power_supply_property corsair_void_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, @@ -155,12 +159,12 @@ struct corsair_void_drvdata { struct power_supply *battery; struct power_supply_desc battery_desc; - struct mutex battery_mutex; struct delayed_work delayed_status_work; struct delayed_work delayed_firmware_work; - struct work_struct battery_remove_work; - struct work_struct battery_add_work; + + unsigned long battery_work_flags; + struct work_struct battery_work; }; /* @@ -260,11 +264,9 @@ success: /* Inform power supply if battery values changed */ if (memcmp(&orig_battery_data, battery_data, sizeof(*battery_data))) { - scoped_guard(mutex, &drvdata->battery_mutex) { - if (drvdata->battery) { - power_supply_changed(drvdata->battery); - } - } + set_bit(CORSAIR_VOID_UPDATE_BATTERY, + &drvdata->battery_work_flags); + schedule_work(&drvdata->battery_work); } } @@ -536,29 +538,11 @@ static void corsair_void_firmware_work_handler(struct work_struct *work) } -static void corsair_void_battery_remove_work_handler(struct work_struct *work) +static void corsair_void_add_battery(struct corsair_void_drvdata *drvdata) { - struct corsair_void_drvdata *drvdata; - - drvdata = container_of(work, struct corsair_void_drvdata, - battery_remove_work); - scoped_guard(mutex, &drvdata->battery_mutex) { - if (drvdata->battery) { - power_supply_unregister(drvdata->battery); - drvdata->battery = NULL; - } - } -} - -static void corsair_void_battery_add_work_handler(struct work_struct *work) -{ - struct corsair_void_drvdata *drvdata; struct power_supply_config psy_cfg = {}; struct power_supply *new_supply; - drvdata = container_of(work, struct corsair_void_drvdata, - battery_add_work); - guard(mutex)(&drvdata->battery_mutex); if (drvdata->battery) return; @@ -583,16 +567,42 @@ static void corsair_void_battery_add_work_handler(struct work_struct *work) drvdata->battery = new_supply; } +static void corsair_void_battery_work_handler(struct work_struct *work) +{ + struct corsair_void_drvdata *drvdata = container_of(work, + struct corsair_void_drvdata, battery_work); + + bool add_battery = test_and_clear_bit(CORSAIR_VOID_ADD_BATTERY, + &drvdata->battery_work_flags); + bool remove_battery = test_and_clear_bit(CORSAIR_VOID_REMOVE_BATTERY, + &drvdata->battery_work_flags); + bool update_battery = test_and_clear_bit(CORSAIR_VOID_UPDATE_BATTERY, + &drvdata->battery_work_flags); + + if (add_battery && !remove_battery) { + corsair_void_add_battery(drvdata); + } else if (remove_battery && !add_battery && drvdata->battery) { + power_supply_unregister(drvdata->battery); + drvdata->battery = NULL; + } + + if (update_battery && drvdata->battery) + power_supply_changed(drvdata->battery); + +} + static void corsair_void_headset_connected(struct corsair_void_drvdata *drvdata) { - schedule_work(&drvdata->battery_add_work); + set_bit(CORSAIR_VOID_ADD_BATTERY, &drvdata->battery_work_flags); + schedule_work(&drvdata->battery_work); schedule_delayed_work(&drvdata->delayed_firmware_work, msecs_to_jiffies(100)); } static void corsair_void_headset_disconnected(struct corsair_void_drvdata *drvdata) { - schedule_work(&drvdata->battery_remove_work); + set_bit(CORSAIR_VOID_REMOVE_BATTERY, &drvdata->battery_work_flags); + schedule_work(&drvdata->battery_work); corsair_void_set_unknown_wireless_data(drvdata); corsair_void_set_unknown_batt(drvdata); @@ -678,13 +688,7 @@ static int corsair_void_probe(struct hid_device *hid_dev, drvdata->battery_desc.get_property = corsair_void_battery_get_property; drvdata->battery = NULL; - INIT_WORK(&drvdata->battery_remove_work, - corsair_void_battery_remove_work_handler); - INIT_WORK(&drvdata->battery_add_work, - corsair_void_battery_add_work_handler); - ret = devm_mutex_init(drvdata->dev, &drvdata->battery_mutex); - if (ret) - return ret; + INIT_WORK(&drvdata->battery_work, corsair_void_battery_work_handler); ret = sysfs_create_group(&hid_dev->dev.kobj, &corsair_void_attr_group); if (ret) @@ -721,8 +725,7 @@ static void corsair_void_remove(struct hid_device *hid_dev) struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev); hid_hw_stop(hid_dev); - cancel_work_sync(&drvdata->battery_remove_work); - cancel_work_sync(&drvdata->battery_add_work); + cancel_work_sync(&drvdata->battery_work); if (drvdata->battery) power_supply_unregister(drvdata->battery); From e211adcf36d0ccdd31af7398af4725a47d74b3d4 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:42 -0600 Subject: [PATCH 0170/1090] ASoC: amd: acp: rembrandt: Use AMD_NODE All consumers of SMN in the kernel should be doing it through the functions provided by AMD_NODE. Stop using the local SMN read/write symbols and switch to the AMD_NODE provided ones. Tested by: Venkata Prasad Potturu Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-3-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/amd/acp/Kconfig | 1 + sound/soc/amd/acp/acp-rembrandt.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 03f3fcbba5af..cdc3add3ffdb 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -58,6 +58,7 @@ config SND_AMD_ASOC_REMBRANDT select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM select SND_SOC_AMD_ACP_LEGACY_COMMON + depends on AMD_NODE depends on X86 && PCI help This option enables Rembrandt I2S support on AMD platform. diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 2648256fa129..e727754a8231 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -22,6 +22,8 @@ #include #include +#include + #include "amd.h" #include "../mach-config.h" #include "acp-mach.h" @@ -31,7 +33,6 @@ #define MP1_C2PMSG_69 0x3B10A14 #define MP1_C2PMSG_85 0x3B10A54 #define MP1_C2PMSG_93 0x3B10A74 -#define HOST_BRIDGE_ID 0x14B5 static struct acp_resource rsrc = { .offset = 0, @@ -166,21 +167,20 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = { static int acp6x_master_clock_generate(struct device *dev) { - int data = 0; - struct pci_dev *smn_dev; + int data, rc; - smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL); - if (!smn_dev) { - dev_err(dev, "Failed to get host bridge device\n"); - return -ENODEV; - } + rc = amd_smn_write(0, MP1_C2PMSG_93, 0); + if (rc) + return rc; + rc = amd_smn_write(0, MP1_C2PMSG_85, 0xC4); + if (rc) + return rc; + rc = amd_smn_write(0, MP1_C2PMSG_69, 0x4); + if (rc) + return rc; - smn_write(smn_dev, MP1_C2PMSG_93, 0); - smn_write(smn_dev, MP1_C2PMSG_85, 0xC4); - smn_write(smn_dev, MP1_C2PMSG_69, 0x4); - read_poll_timeout(smn_read, data, data, DELAY_US, - ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93); - return 0; + return read_poll_timeout(smn_read_register, data, data > 0, DELAY_US, + ACP_TIMEOUT, false, MP1_C2PMSG_93); } static int rembrandt_audio_probe(struct platform_device *pdev) From 135c6af1cac5465529469700d16c0c44b24ce317 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:43 -0600 Subject: [PATCH 0171/1090] ASoC: amd: acp: acp70: Use AMD_NODE All consumers of SMN in the kernel should be doing it through the functions provided by AMD_NODE. Stop using the local SMN read/write symbols and switch to the AMD_NODE provided ones. Tested by: Venkata Prasad Potturu Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-4-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/amd/acp/Kconfig | 1 + sound/soc/amd/acp/acp70.c | 28 ++++------------------------ sound/soc/sof/amd/pci-acp70.c | 1 - 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index cdc3add3ffdb..811921931430 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -82,6 +82,7 @@ config SND_AMD_ASOC_ACP70 tristate "AMD ACP ASOC Acp7.0 Support" depends on X86 && PCI depends on ACPI + depends on AMD_NODE select SND_SOC_AMD_ACP_PCM select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 9e23729fd1a7..ef3f6504bc7f 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -23,6 +23,8 @@ #include "amd.h" #include "acp-mach.h" +#include + #define DRV_NAME "acp_asoc_acp70" #define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4 @@ -137,29 +139,6 @@ static struct snd_soc_dai_driver acp70_dai[] = { }, }; -static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata) -{ - struct pci_dev *smn_dev; - u32 device_id; - - if (adata->acp_rev == ACP70_PCI_ID) - device_id = 0x1507; - else if (adata->acp_rev == ACP71_PCI_ID) - device_id = 0x1122; - else - return -ENODEV; - - smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL); - - if (!smn_dev) - return -ENODEV; - - /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ - smn_write(smn_dev, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); - - return 0; -} - static int acp_acp70_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -215,7 +194,8 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) dev_set_drvdata(dev, adata); - ret = acp70_i2s_master_clock_generate(adata); + /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ + ret = amd_smn_write(0, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); if (ret) { dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); return ret; diff --git a/sound/soc/sof/amd/pci-acp70.c b/sound/soc/sof/amd/pci-acp70.c index 3647ec992e95..d886bdf3a112 100644 --- a/sound/soc/sof/amd/pci-acp70.c +++ b/sound/soc/sof/amd/pci-acp70.c @@ -28,7 +28,6 @@ #define ACP70_REG_END 0x125C000 static const struct sof_amd_acp_desc acp70_chip_info = { - .host_bridge_id = HOST_BRIDGE_ACP70, .pgfsm_base = ACP70_PGFSM_BASE, .ext_intr_enb = ACP70_EXTERNAL_INTR_ENB, .ext_intr_cntl = ACP70_EXTERNAL_INTR_CNTL, From 8f969537149d672d40a0e75a83f39451a5402780 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:44 -0600 Subject: [PATCH 0172/1090] ASoC: amd: acp: acp63: Use AMD_NODE All consumers of SMN in the kernel should be doing it through the functions provided by AMD_NODE. Stop using the local SMN read/write symbols and switch to the AMD_NODE provided ones. Tested by: Venkata Prasad Potturu Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-5-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/amd/acp/Kconfig | 1 + sound/soc/amd/acp/acp63.c | 55 +++++++++++++++++++++++------------ sound/soc/sof/amd/pci-acp63.c | 1 - 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 811921931430..de54237a211a 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -69,6 +69,7 @@ config SND_AMD_ASOC_ACP63 tristate "AMD ACP ASOC ACP6.3 Support" depends on X86 && PCI depends on ACPI + depends on AMD_NODE select SND_SOC_AMD_ACP_PCM select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 81496e713440..4187a8968de7 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -20,6 +20,9 @@ #include #include #include + +#include + #include "amd.h" #include "acp-mach.h" #include "../mach-config.h" @@ -160,37 +163,53 @@ static struct snd_soc_dai_driver acp63_dai[] = { static int acp63_i2s_master_clock_generate(struct acp_dev_data *adata) { + int rc; u32 data; union clk_pll_req_no clk_pll; - struct pci_dev *smn_dev; - - smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x14E8, NULL); - if (!smn_dev) - return -ENODEV; /* Clk5 pll register values to get mclk as 196.6MHz*/ clk_pll.bits.fb_mult_int = 0x31; clk_pll.bits.pll_spine_div = 0; clk_pll.bits.gb_mult_frac = 0x26E9; - data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0); - smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ); + rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ); + if (rc) + return rc; - data = smn_read(smn_dev, CLK_SPLL_FIELD_2_N0); - if (data & PLL_FRANCE_EN) - smn_write(smn_dev, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN); + rc = amd_smn_read(0, CLK_SPLL_FIELD_2_N0, &data); + if (rc) + return rc; + if (data & PLL_FRANCE_EN) { + rc = amd_smn_write(0, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN); + if (rc) + return rc; + } - smn_write(smn_dev, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg); + rc = amd_smn_write(0, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg); + if (rc) + return rc; - data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0); - smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ); + rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ); + if (rc) + return rc; - data = smn_read(smn_dev, CLK_DFSBYPASS_CONTR); - smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0); - smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1); + rc = amd_smn_read(0, CLK_DFSBYPASS_CONTR, &data); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0); + if (rc) + return rc; + rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1); + if (rc) + return rc; - smn_write(smn_dev, CLK_DFS_CNTL_N0, CLK0_DIVIDER); - return 0; + return amd_smn_write(0, CLK_DFS_CNTL_N0, CLK0_DIVIDER); } static int acp63_audio_probe(struct platform_device *pdev) diff --git a/sound/soc/sof/amd/pci-acp63.c b/sound/soc/sof/amd/pci-acp63.c index ffe7c755d655..13aa87cdeeac 100644 --- a/sound/soc/sof/amd/pci-acp63.c +++ b/sound/soc/sof/amd/pci-acp63.c @@ -28,7 +28,6 @@ #define ACP6x_REG_END 0x125C000 static const struct sof_amd_acp_desc acp63_chip_info = { - .host_bridge_id = HOST_BRIDGE_ACP63, .pgfsm_base = ACP6X_PGFSM_BASE, .ext_intr_enb = ACP6X_EXTERNAL_INTR_ENB, .ext_intr_cntl = ACP6X_EXTERNAL_INTR_CNTL, From f120cf33d2325fd95d063eccbff2e86ffc7f493a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:45 -0600 Subject: [PATCH 0173/1090] ASoC: SOF: amd: Use AMD_NODE All consumers of SMN in the kernel should be doing it through the functions provided by AMD_NODE. Stop using the local SMN read/write symbols and switch to the AMD_NODE provided ones. Tested by: Venkata Prasad Potturu Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-6-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/Kconfig | 1 + sound/soc/sof/amd/acp.c | 56 ++++++++++----------------------- sound/soc/sof/amd/acp.h | 1 - sound/soc/sof/amd/pci-rmb.c | 1 - sound/soc/sof/amd/pci-rn.c | 1 - sound/soc/sof/amd/pci-vangogh.c | 1 - 6 files changed, 17 insertions(+), 44 deletions(-) diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig index f4cafe801017..28216c8c1cf9 100644 --- a/sound/soc/sof/amd/Kconfig +++ b/sound/soc/sof/amd/Kconfig @@ -25,6 +25,7 @@ config SND_SOC_SOF_AMD_COMMON select SND_SOC_SOF_ACP_PROBES select SND_SOC_ACPI_AMD_MATCH select SND_SOC_ACPI if ACPI + depends on AMD_NODE help This option is not user-selectable but automatically handled by 'select' statements at a higher level diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 33648ff8b833..7007014423a4 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -16,6 +16,8 @@ #include #include +#include + #include "../ops.h" #include "acp.h" #include "acp-dsp-offset.h" @@ -42,24 +44,6 @@ const struct dmi_system_id acp_sof_quirk_table[] = { }; EXPORT_SYMBOL_GPL(acp_sof_quirk_table); -static int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data) -{ - pci_write_config_dword(dev, 0x60, smn_addr); - pci_write_config_dword(dev, 0x64, data); - - return 0; -} - -static int smn_read(struct pci_dev *dev, u32 smn_addr) -{ - u32 data = 0; - - pci_write_config_dword(dev, 0x60, smn_addr); - pci_read_config_dword(dev, 0x64, &data); - - return data; -} - static void init_dma_descriptor(struct acp_dev_data *adata) { struct snd_sof_dev *sdev = adata->dev; @@ -208,11 +192,11 @@ int configure_and_run_dma(struct acp_dev_data *adata, unsigned int src_addr, static int psp_mbox_ready(struct acp_dev_data *adata, bool ack) { struct snd_sof_dev *sdev = adata->dev; - int ret; - u32 data; + int ret, data; + + ret = read_poll_timeout(smn_read_register, data, data > 0 && data & MBOX_READY_MASK, + MBOX_DELAY_US, ACP_PSP_TIMEOUT_US, false, MP0_C2PMSG_114_REG); - ret = read_poll_timeout(smn_read, data, data & MBOX_READY_MASK, MBOX_DELAY_US, - ACP_PSP_TIMEOUT_US, false, adata->smn_dev, MP0_C2PMSG_114_REG); if (!ret) return 0; @@ -240,8 +224,8 @@ static int psp_send_cmd(struct acp_dev_data *adata, int cmd) return -EINVAL; /* Get a non-zero Doorbell value from PSP */ - ret = read_poll_timeout(smn_read, data, data, MBOX_DELAY_US, ACP_PSP_TIMEOUT_US, false, - adata->smn_dev, MP0_C2PMSG_73_REG); + ret = read_poll_timeout(smn_read_register, data, data > 0, MBOX_DELAY_US, + ACP_PSP_TIMEOUT_US, false, MP0_C2PMSG_73_REG); if (ret) { dev_err(sdev->dev, "Failed to get Doorbell from MBOX %x\n", MP0_C2PMSG_73_REG); @@ -253,10 +237,14 @@ static int psp_send_cmd(struct acp_dev_data *adata, int cmd) if (ret) return ret; - smn_write(adata->smn_dev, MP0_C2PMSG_114_REG, cmd); + ret = amd_smn_write(0, MP0_C2PMSG_114_REG, cmd); + if (ret) + return ret; /* Ring the Doorbell for PSP */ - smn_write(adata->smn_dev, MP0_C2PMSG_73_REG, data); + ret = amd_smn_write(0, MP0_C2PMSG_73_REG, data); + if (ret) + return ret; /* Check MBOX ready as PSP ack */ ret = psp_mbox_ready(adata, 1); @@ -770,16 +758,10 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) adata->pci_rev = pci->revision; mutex_init(&adata->acp_lock); sdev->pdata->hw_pdata = adata; - adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); - if (!adata->smn_dev) { - dev_err(sdev->dev, "Failed to get host bridge device\n"); - ret = -ENODEV; - goto unregister_dev; - } ret = acp_init(sdev); if (ret < 0) - goto free_smn_dev; + goto unregister_dev; sdev->ipc_irq = pci->irq; ret = request_threaded_irq(sdev->ipc_irq, acp_irq_handler, acp_irq_thread, @@ -787,7 +769,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "failed to register IRQ %d\n", sdev->ipc_irq); - goto free_smn_dev; + goto unregister_dev; } /* scan SoundWire capabilities exposed by DSDT */ @@ -800,7 +782,6 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: SoundWire probe error\n"); free_irq(sdev->ipc_irq, sdev); - pci_dev_put(adata->smn_dev); return ret; } @@ -846,8 +827,6 @@ skip_soundwire: free_ipc_irq: free_irq(sdev->ipc_irq, sdev); -free_smn_dev: - pci_dev_put(adata->smn_dev); unregister_dev: platform_device_unregister(adata->dmic_dev); return ret; @@ -858,9 +837,6 @@ void amd_sof_acp_remove(struct snd_sof_dev *sdev) { struct acp_dev_data *adata = sdev->pdata->hw_pdata; - if (adata->smn_dev) - pci_dev_put(adata->smn_dev); - if (adata->sdw) amd_sof_sdw_exit(sdev); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 800594440f73..514330106357 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -255,7 +255,6 @@ struct acp_dev_data { struct dma_descriptor dscr_info[ACP_MAX_DESC]; struct acp_dsp_stream stream_buf[ACP_MAX_STREAM]; struct acp_dsp_stream *dtrace_stream; - struct pci_dev *smn_dev; struct acp_dsp_stream *probe_stream; bool enable_fw_debug; bool is_dram_in_use; diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c index cbb4d5282664..0233b6ba2d2e 100644 --- a/sound/soc/sof/amd/pci-rmb.c +++ b/sound/soc/sof/amd/pci-rmb.c @@ -28,7 +28,6 @@ #define ACP6X_FUTURE_REG_ACLK_0 0x1854 static const struct sof_amd_acp_desc rembrandt_chip_info = { - .host_bridge_id = HOST_BRIDGE_RMB, .pgfsm_base = ACP6X_PGFSM_BASE, .ext_intr_stat = ACP6X_EXT_INTR_STAT, .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index b7d558cb1fd7..4a36029a00de 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -28,7 +28,6 @@ #define ACP3X_FUTURE_REG_ACLK_0 0x1860 static const struct sof_amd_acp_desc renoir_chip_info = { - .host_bridge_id = HOST_BRIDGE_CZN, .pgfsm_base = ACP3X_PGFSM_BASE, .ext_intr_stat = ACP3X_EXT_INTR_STAT, .dsp_intr_base = ACP3X_DSP_SW_INTR_BASE, diff --git a/sound/soc/sof/amd/pci-vangogh.c b/sound/soc/sof/amd/pci-vangogh.c index 53f64d6bc91b..18734cd21abf 100644 --- a/sound/soc/sof/amd/pci-vangogh.c +++ b/sound/soc/sof/amd/pci-vangogh.c @@ -27,7 +27,6 @@ static const struct sof_amd_acp_desc vangogh_chip_info = { .name = "vangogh", - .host_bridge_id = HOST_BRIDGE_VGH, .pgfsm_base = ACP5X_PGFSM_BASE, .ext_intr_stat = ACP5X_EXT_INTR_STAT, .dsp_intr_base = ACP5X_DSP_SW_INTR_BASE, From 40d05927830227f2a1701c61e8bbe65287a03490 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:46 -0600 Subject: [PATCH 0174/1090] ASoC: amd: acp: Drop local symbols for smn read/write As the ACP drivers use the AMD_NODE provided symbols, the local ones are no longer necessary. Tested by: Venkata Prasad Potturu Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-7-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 18 ------------------ sound/soc/amd/acp/amd.h | 3 --- 2 files changed, 21 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 7acc7ed2e8cc..89f5cda18a23 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -345,24 +345,6 @@ int acp_deinit(struct acp_chip_info *chip) } EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON"); -int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data) -{ - pci_write_config_dword(dev, 0x60, smn_addr); - pci_write_config_dword(dev, 0x64, data); - return 0; -} -EXPORT_SYMBOL_NS_GPL(smn_write, "SND_SOC_ACP_COMMON"); - -int smn_read(struct pci_dev *dev, u32 smn_addr) -{ - u32 data; - - pci_write_config_dword(dev, 0x60, smn_addr); - pci_read_config_dword(dev, 0x64, &data); - return data; -} -EXPORT_SYMBOL_NS_GPL(smn_read, "SND_SOC_ACP_COMMON"); - static void check_acp3x_config(struct acp_chip_info *chip) { u32 val; diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index ee69dfb10cb8..c921bcabbcec 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -235,9 +235,6 @@ int acp_platform_unregister(struct device *dev); int acp_machine_select(struct acp_dev_data *adata); -int smn_read(struct pci_dev *dev, u32 smn_addr); -int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data); - int acp_init(struct acp_chip_info *chip); int acp_deinit(struct acp_chip_info *chip); void acp_enable_interrupts(struct acp_dev_data *adata); From a261d77fec147b9974aacca8ae8f0693feede838 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 17 Feb 2025 17:17:47 -0600 Subject: [PATCH 0175/1090] ASoC: SOF: amd: Drop host bridge ID from struct host_bridge_id is no longer used by any of the SoCs as they all use AMD_NODE to communicate with SMN routers. Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250217231747.1656228-8-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 514330106357..a26a3f47ba53 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -197,7 +197,6 @@ struct acp_dsp_stream { struct sof_amd_acp_desc { const char *name; - unsigned int host_bridge_id; u32 pgfsm_base; u32 ext_intr_enb; u32 ext_intr_cntl; From 44afc10d4678d5a3a4ab8c25750be00f037298cf Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Thu, 16 Jan 2025 22:49:24 -0800 Subject: [PATCH 0176/1090] HID: nintendo: fix gencon button events map This fixes the button event map to match the 3-button recommendation as well as the redundant 'z' in the button map events for the Sega MD/Gen 6 Button. Signed-off-by: Ryan McClelland Reviewed-by: Daniel J. Ogorchock Signed-off-by: Jiri Kosina --- drivers/hid/hid-nintendo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c index 11ac246176ae..839d5bcd72b1 100644 --- a/drivers/hid/hid-nintendo.c +++ b/drivers/hid/hid-nintendo.c @@ -457,13 +457,13 @@ static const struct joycon_ctlr_button_mapping snescon_button_mappings[] = { }; static const struct joycon_ctlr_button_mapping gencon_button_mappings[] = { - { BTN_A, JC_BTN_A, }, - { BTN_B, JC_BTN_B, }, - { BTN_C, JC_BTN_R, }, - { BTN_X, JC_BTN_X, }, /* MD/GEN 6B Only */ - { BTN_Y, JC_BTN_Y, }, /* MD/GEN 6B Only */ - { BTN_Z, JC_BTN_L, }, /* MD/GEN 6B Only */ - { BTN_SELECT, JC_BTN_ZR, }, + { BTN_WEST, JC_BTN_A, }, /* A */ + { BTN_SOUTH, JC_BTN_B, }, /* B */ + { BTN_EAST, JC_BTN_R, }, /* C */ + { BTN_TL, JC_BTN_X, }, /* X MD/GEN 6B Only */ + { BTN_NORTH, JC_BTN_Y, }, /* Y MD/GEN 6B Only */ + { BTN_TR, JC_BTN_L, }, /* Z MD/GEN 6B Only */ + { BTN_SELECT, JC_BTN_ZR, }, /* Mode */ { BTN_START, JC_BTN_PLUS, }, { BTN_MODE, JC_BTN_HOME, }, { BTN_Z, JC_BTN_CAP, }, From 4bd0725c09f377ffaf22b834241f6c050742e4fc Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Tue, 18 Feb 2025 00:50:13 +0800 Subject: [PATCH 0177/1090] HID: google: fix unused variable warning under !CONFIG_ACPI As reported by the kernel test robot, the following warning occurs: >> drivers/hid/hid-google-hammer.c:261:36: warning: 'cbas_ec_acpi_ids' defined but not used [-Wunused-const-variable=] 261 | static const struct acpi_device_id cbas_ec_acpi_ids[] = { | ^~~~~~~~~~~~~~~~ The 'cbas_ec_acpi_ids' array is only used when CONFIG_ACPI is enabled. Wrapping its definition and 'MODULE_DEVICE_TABLE' in '#ifdef CONFIG_ACPI' prevents a compiler warning when ACPI is disabled. Fixes: eb1aac4c8744f75 ("HID: google: add support tablet mode switch for Whiskers") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501201141.jctFH5eB-lkp@intel.com/ Signed-off-by: Yu-Chun Lin Signed-off-by: Jiri Kosina --- drivers/hid/hid-google-hammer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index 0f292b5d3e26..eb6fd2dc75d0 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -268,11 +268,13 @@ static void cbas_ec_remove(struct platform_device *pdev) mutex_unlock(&cbas_ec_reglock); } +#ifdef CONFIG_ACPI static const struct acpi_device_id cbas_ec_acpi_ids[] = { { "GOOG000B", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids); +#endif #ifdef CONFIG_OF static const struct of_device_id cbas_ec_of_match[] = { From 823987841424289339fdb4ba90e6d2c3792836db Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Tue, 18 Feb 2025 14:37:29 +0800 Subject: [PATCH 0178/1090] HID: intel-ish-hid: Fix use-after-free issue in hid_ishtp_cl_remove() During the `rmmod` operation for the `intel_ishtp_hid` driver, a use-after-free issue can occur in the hid_ishtp_cl_remove() function. The function hid_ishtp_cl_deinit() is called before ishtp_hid_remove(), which can lead to accessing freed memory or resources during the removal process. Call Trace: ? ishtp_cl_send+0x168/0x220 [intel_ishtp] ? hid_output_report+0xe3/0x150 [hid] hid_ishtp_set_feature+0xb5/0x120 [intel_ishtp_hid] ishtp_hid_request+0x7b/0xb0 [intel_ishtp_hid] hid_hw_request+0x1f/0x40 [hid] sensor_hub_set_feature+0x11f/0x190 [hid_sensor_hub] _hid_sensor_power_state+0x147/0x1e0 [hid_sensor_trigger] hid_sensor_runtime_resume+0x22/0x30 [hid_sensor_trigger] sensor_hub_remove+0xa8/0xe0 [hid_sensor_hub] hid_device_remove+0x49/0xb0 [hid] hid_destroy_device+0x6f/0x90 [hid] ishtp_hid_remove+0x42/0x70 [intel_ishtp_hid] hid_ishtp_cl_remove+0x6b/0xb0 [intel_ishtp_hid] ishtp_cl_device_remove+0x4a/0x60 [intel_ishtp] ... Additionally, ishtp_hid_remove() is a HID level power off, which should occur before the ISHTP level disconnect. This patch resolves the issue by reordering the calls in hid_ishtp_cl_remove(). The function ishtp_hid_remove() is now called before hid_ishtp_cl_deinit(). Fixes: f645a90e8ff7 ("HID: intel-ish-hid: ishtp-hid-client: use helper functions for connection") Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ishtp-hid-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c index cb04cd1d980b..6550ad5bfbb5 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c @@ -832,9 +832,9 @@ static void hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device) hid_ishtp_cl); dev_dbg(ishtp_device(cl_device), "%s\n", __func__); - hid_ishtp_cl_deinit(hid_ishtp_cl); ishtp_put_device(cl_device); ishtp_hid_remove(client_data); + hid_ishtp_cl_deinit(hid_ishtp_cl); hid_ishtp_cl = NULL; From 07583a0010696a17fb0942e0b499a62785c5fc9f Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Tue, 18 Feb 2025 14:37:30 +0800 Subject: [PATCH 0179/1090] HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove() The system can experience a random crash a few minutes after the driver is removed. This issue occurs due to improper handling of memory freeing in the ishtp_hid_remove() function. The function currently frees the `driver_data` directly within the loop that destroys the HID devices, which can lead to accessing freed memory. Specifically, `hid_destroy_device()` uses `driver_data` when it calls `hid_ishtp_set_feature()` to power off the sensor, so freeing `driver_data` beforehand can result in accessing invalid memory. This patch resolves the issue by storing the `driver_data` in a temporary variable before calling `hid_destroy_device()`, and then freeing the `driver_data` after the device is destroyed. Fixes: 0b28cb4bcb17 ("HID: intel-ish-hid: ISH HID client driver") Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ishtp-hid.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c index 00c6f0ebf356..be2c62fc8251 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid.c @@ -261,12 +261,14 @@ err_hid_data: */ void ishtp_hid_remove(struct ishtp_cl_data *client_data) { + void *data; int i; for (i = 0; i < client_data->num_hid_devices; ++i) { if (client_data->hid_sensor_hubs[i]) { - kfree(client_data->hid_sensor_hubs[i]->driver_data); + data = client_data->hid_sensor_hubs[i]->driver_data; hid_destroy_device(client_data->hid_sensor_hubs[i]); + kfree(data); client_data->hid_sensor_hubs[i] = NULL; } } From a8e8ffcc3afce2ee5fb70162aeaef3f03573ee1e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 9 Feb 2025 13:05:50 +0200 Subject: [PATCH 0180/1090] mei: me: add panther lake P DID Add Panther Lake P device id. Cc: stable Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Link: https://lore.kernel.org/r/20250209110550.1582982-1-alexander.usyskin@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 2 ++ drivers/misc/mei/pci-me.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index c3a6657dcd4a..a5f88ec97df7 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -117,6 +117,8 @@ #define MEI_DEV_ID_LNL_M 0xA870 /* Lunar Lake Point M */ +#define MEI_DEV_ID_PTL_P 0xE470 /* Panther Lake P */ + /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 6589635f8ba3..d6ff9d82ae94 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -124,6 +124,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_P, MEI_ME_PCH15_CFG)}, + /* required last entry */ {0, } }; From fdb1ada57cf8b8752cdf54f08709d76d74999544 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 14 Feb 2025 22:24:25 +0100 Subject: [PATCH 0181/1090] mei: vsc: Use "wakeuphostint" when getting the host wakeup GPIO The _CRS ACPI resources table has 2 entries for the host wakeup GPIO, the first one being a regular GpioIo () resource while the second one is a GpioInt () resource for the same pin. The acpi_gpio_mapping table used by vsc-tp.c maps the first Gpio () resource to "wakeuphost-gpios" where as the second GpioInt () entry is mapped to "wakeuphostint-gpios". Using "wakeuphost" to request the GPIO as was done until now, means that the gpiolib-acpi code does not know that the GPIO is active-low as that info is only available in the GpioInt () entry. Things were still working before due to the following happening: 1. Since the 2 entries point to the same pin they share a struct gpio_desc 2. The SPI core creates the SPI device vsc-tp.c binds to and calls acpi_dev_gpio_irq_get(). This does use the second entry and sets FLAG_ACTIVE_LOW in gpio_desc.flags . 3. vsc_tp_probe() requests the "wakeuphost" GPIO and inherits the active-low flag set by acpi_dev_gpio_irq_get() But there is a possible scenario where things do not work: 1. - 3. happen as above 4. After requesting the "wakeuphost" GPIO, the "resetfw" GPIO is requested next, but its USB GPIO controller is not available yet, so this call returns -EPROBE_DEFER. 5. The gpio_desc for "wakeuphost" is put() and during this the active-low flag is cleared from gpio_desc.flags . 6. Later on vsc_tp_probe() requests the "wakeuphost" GPIO again, but now it is not marked active-low. The difference can also be seen in /sys/kernel/debug/gpio, which contains the following line for this GPIO: gpio-535 ( |wakeuphost ) in hi IRQ ACTIVE LOW If the second scenario is hit the "ACTIVE LOW" at the end disappears and things do not work. Fix this by requesting the GPIO through the "wakeuphostint" mapping instead which provides active-low info without relying on acpi_dev_gpio_irq_get() pre-populating this info in the gpio_desc. Link: https://bugzilla.redhat.com/show_bug.cgi?id=2316918 Signed-off-by: Hans de Goede Reviewed-by: Stanislaw Gruszka Tested-by: Sakari Ailus Fixes: 566f5ca97680 ("mei: Add transport driver for IVSC device") Cc: stable Link: https://lore.kernel.org/r/20250214212425.84021-1-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/vsc-tp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c index 35d349fee769..7be1649b1972 100644 --- a/drivers/misc/mei/vsc-tp.c +++ b/drivers/misc/mei/vsc-tp.c @@ -502,7 +502,7 @@ static int vsc_tp_probe(struct spi_device *spi) if (ret) return ret; - tp->wakeuphost = devm_gpiod_get(dev, "wakeuphost", GPIOD_IN); + tp->wakeuphost = devm_gpiod_get(dev, "wakeuphostint", GPIOD_IN); if (IS_ERR(tp->wakeuphost)) return PTR_ERR(tp->wakeuphost); From c90aad369899a607cfbc002bebeafd51e31900cd Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Thu, 13 Feb 2025 15:22:57 +0300 Subject: [PATCH 0182/1090] usb: atm: cxacru: fix a flaw in existing endpoint checks Syzbot once again identified a flaw in usb endpoint checking, see [1]. This time the issue stems from a commit authored by me (2eabb655a968 ("usb: atm: cxacru: fix endpoint checking in cxacru_bind()")). While using usb_find_common_endpoints() may usually be enough to discard devices with wrong endpoints, in this case one needs more than just finding and identifying the sufficient number of endpoints of correct types - one needs to check the endpoint's address as well. Since cxacru_bind() fills URBs with CXACRU_EP_CMD address in mind, switch the endpoint verification approach to usb_check_XXX_endpoints() instead to fix incomplete ep testing. [1] Syzbot report: usb 5-1: BOGUS urb xfer, pipe 3 != type 1 WARNING: CPU: 0 PID: 1378 at drivers/usb/core/urb.c:504 usb_submit_urb+0xc4e/0x18c0 drivers/usb/core/urb.c:503 ... RIP: 0010:usb_submit_urb+0xc4e/0x18c0 drivers/usb/core/urb.c:503 ... Call Trace: cxacru_cm+0x3c8/0xe50 drivers/usb/atm/cxacru.c:649 cxacru_card_status drivers/usb/atm/cxacru.c:760 [inline] cxacru_bind+0xcf9/0x1150 drivers/usb/atm/cxacru.c:1223 usbatm_usb_probe+0x314/0x1d30 drivers/usb/atm/usbatm.c:1058 cxacru_usb_probe+0x184/0x220 drivers/usb/atm/cxacru.c:1377 usb_probe_interface+0x641/0xbb0 drivers/usb/core/driver.c:396 really_probe+0x2b9/0xad0 drivers/base/dd.c:658 __driver_probe_device+0x1a2/0x390 drivers/base/dd.c:800 driver_probe_device+0x50/0x430 drivers/base/dd.c:830 ... Reported-and-tested-by: syzbot+ccbbc229a024fa3e13b5@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=ccbbc229a024fa3e13b5 Fixes: 2eabb655a968 ("usb: atm: cxacru: fix endpoint checking in cxacru_bind()") Cc: stable@kernel.org Signed-off-by: Nikita Zhandarovich Link: https://lore.kernel.org/r/20250213122259.730772-1-n.zhandarovich@fintech.ru Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 0dd85d2635b9..47d06af33747 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1131,7 +1131,10 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; - struct usb_endpoint_descriptor *in, *out; + static const u8 ep_addrs[] = { + CXACRU_EP_CMD + USB_DIR_IN, + CXACRU_EP_CMD + USB_DIR_OUT, + 0}; int ret; /* instance init */ @@ -1179,13 +1182,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, } if (usb_endpoint_xfer_int(&cmd_ep->desc)) - ret = usb_find_common_endpoints(intf->cur_altsetting, - NULL, NULL, &in, &out); + ret = usb_check_int_endpoints(intf, ep_addrs); else - ret = usb_find_common_endpoints(intf->cur_altsetting, - &in, &out, NULL, NULL); + ret = usb_check_bulk_endpoints(intf, ep_addrs); - if (ret) { + if (!ret) { usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n"); ret = -ENODEV; goto fail; From 17c2c87c37862c3e95b55f660681cc6e8d66660e Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Wed, 12 Feb 2025 15:38:40 +0530 Subject: [PATCH 0183/1090] usb: gadget: u_ether: Set is_suspend flag if remote wakeup fails Currently while UDC suspends, u_ether attempts to remote wakeup the host if there are any pending transfers. However, if remote wakeup fails, the UDC remains suspended but the is_suspend flag is not set. And since is_suspend flag isn't set, the subsequent eth_start_xmit() would queue USB requests to suspended UDC. To fix this, bail out from gether_suspend() only if remote wakeup operation is successful. Cc: stable Fixes: 0a1af6dfa077 ("usb: gadget: f_ecm: Add suspend/resume and remote wakeup support") Signed-off-by: Prashanth K Link: https://lore.kernel.org/r/20250212100840.3812153-1-prashanth.k@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/u_ether.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 09e2838917e2..f58590bf5e02 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -1052,8 +1052,8 @@ void gether_suspend(struct gether *link) * There is a transfer in progress. So we trigger a remote * wakeup to inform the host. */ - ether_wakeup_host(dev->port_usb); - return; + if (!ether_wakeup_host(dev->port_usb)) + return; } spin_lock_irqsave(&dev->lock, flags); link->is_suspend = true; From 40e89ff5750fca2c1d6da93f98a2038716bba86c Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Mon, 17 Feb 2025 17:33:28 +0530 Subject: [PATCH 0184/1090] usb: gadget: Set self-powered based on MaxPower and bmAttributes Currently the USB gadget will be set as bus-powered based solely on whether its bMaxPower is greater than 100mA, but this may miss devices that may legitimately draw less than 100mA but still want to report as bus-powered. Similarly during suspend & resume, USB gadget is incorrectly marked as bus/self powered without checking the bmAttributes field. Fix these by configuring the USB gadget as self or bus powered based on bmAttributes, and explicitly set it as bus-powered if it draws more than 100mA. Cc: stable Fixes: 5e5caf4fa8d3 ("usb: gadget: composite: Inform controller driver of self-powered") Signed-off-by: Prashanth K Link: https://lore.kernel.org/r/20250217120328.2446639-1-prashanth.k@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index bdda8c74602d..1fb28bbf6c45 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1050,10 +1050,11 @@ static int set_config(struct usb_composite_dev *cdev, else usb_gadget_set_remote_wakeup(gadget, 0); done: - if (power <= USB_SELF_POWER_VBUS_MAX_DRAW) - usb_gadget_set_selfpowered(gadget); - else + if (power > USB_SELF_POWER_VBUS_MAX_DRAW || + !(c->bmAttributes & USB_CONFIG_ATT_SELFPOWER)) usb_gadget_clear_selfpowered(gadget); + else + usb_gadget_set_selfpowered(gadget); usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) @@ -2615,7 +2616,9 @@ void composite_suspend(struct usb_gadget *gadget) cdev->suspended = 1; - usb_gadget_set_selfpowered(gadget); + if (cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER) + usb_gadget_set_selfpowered(gadget); + usb_gadget_vbus_draw(gadget, 2); } @@ -2649,8 +2652,11 @@ void composite_resume(struct usb_gadget *gadget) else maxpower = min(maxpower, 900U); - if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW) + if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW || + !(cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER)) usb_gadget_clear_selfpowered(gadget); + else + usb_gadget_set_selfpowered(gadget); usb_gadget_vbus_draw(gadget, maxpower); } else { From d6b82dafd17db0658f089b9cdec573982ca82bc5 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 19 Feb 2025 12:47:00 +0100 Subject: [PATCH 0185/1090] usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality During probe, the TCPC alert interrupts are getting masked to avoid unwanted interrupts during chip setup: this is ok to do but there is no unmasking happening at any later time, which means that the chip will not raise any interrupt, essentially making it not functional as, while internally it does perform all of the intended functions, it won't signal anything to the outside. Unmask the alert interrupts to fix functionality. Fixes: ce08eaeb6388 ("staging: typec: rt1711h typec chip driver") Cc: stable Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20250219114700.41700-1-angelogioacchino.delregno@collabora.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpci_rt1711h.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c index 64f6dd0dc660..88c50b984e8a 100644 --- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c +++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c @@ -334,6 +334,11 @@ static int rt1711h_probe(struct i2c_client *client) { int ret; struct rt1711h_chip *chip; + const u16 alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | + TCPC_ALERT_TX_FAILED | TCPC_ALERT_RX_HARD_RST | + TCPC_ALERT_RX_STATUS | TCPC_ALERT_POWER_STATUS | + TCPC_ALERT_CC_STATUS | TCPC_ALERT_RX_BUF_OVF | + TCPC_ALERT_FAULT; chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -382,6 +387,12 @@ static int rt1711h_probe(struct i2c_client *client) dev_name(chip->dev), chip); if (ret < 0) return ret; + + /* Enable alert interrupts */ + ret = rt1711h_write16(chip, TCPC_ALERT_MASK, alert_mask); + if (ret < 0) + return ret; + enable_irq_wake(client->irq); return 0; From 976e7e9bdc7719a023a4ecccd2e3daec9ab20a40 Mon Sep 17 00:00:00 2001 From: "Christian A. Ehrhardt" Date: Mon, 17 Feb 2025 13:54:39 +0300 Subject: [PATCH 0186/1090] acpi: typec: ucsi: Introduce a ->poll_cci method For the ACPI backend of UCSI the UCSI "registers" are just a memory copy of the register values in an opregion. The ACPI implementation in the BIOS ensures that the opregion contents are synced to the embedded controller and it ensures that the registers (in particular CCI) are synced back to the opregion on notifications. While there is an ACPI call that syncs the actual registers to the opregion there is rarely a need to do this and on some ACPI implementations it actually breaks in various interesting ways. The only reason to force a sync from the embedded controller is to poll CCI while notifications are disabled. Only the ucsi core knows if this is the case and guessing based on the current command is suboptimal, i.e. leading to the following spurious assertion splat: WARNING: CPU: 3 PID: 76 at drivers/usb/typec/ucsi/ucsi.c:1388 ucsi_reset_ppm+0x1b4/0x1c0 [typec_ucsi] CPU: 3 UID: 0 PID: 76 Comm: kworker/3:0 Not tainted 6.12.11-200.fc41.x86_64 #1 Hardware name: LENOVO 21D0/LNVNB161216, BIOS J6CN45WW 03/17/2023 Workqueue: events_long ucsi_init_work [typec_ucsi] RIP: 0010:ucsi_reset_ppm+0x1b4/0x1c0 [typec_ucsi] Call Trace: ucsi_init_work+0x3c/0xac0 [typec_ucsi] process_one_work+0x179/0x330 worker_thread+0x252/0x390 kthread+0xd2/0x100 ret_from_fork+0x34/0x50 ret_from_fork_asm+0x1a/0x30 Thus introduce a ->poll_cci() method that works like ->read_cci() with an additional forced sync and document that this should be used when polling with notifications disabled. For all other backends that presumably don't have this issue use the same implementation for both methods. Fixes: fa48d7e81624 ("usb: typec: ucsi: Do not call ACPI _DSM method for UCSI read operations") Cc: stable Signed-off-by: Christian A. Ehrhardt Tested-by: Fedor Pchelkin Signed-off-by: Fedor Pchelkin Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250217105442.113486-2-boddah8794@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 10 +++++----- drivers/usb/typec/ucsi/ucsi.h | 2 ++ drivers/usb/typec/ucsi/ucsi_acpi.c | 21 ++++++++++++++------- drivers/usb/typec/ucsi/ucsi_ccg.c | 1 + drivers/usb/typec/ucsi/ucsi_glink.c | 1 + drivers/usb/typec/ucsi/ucsi_stm32g0.c | 1 + drivers/usb/typec/ucsi/ucsi_yoga_c630.c | 1 + 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index fcf499cc9458..0fe1476f4c29 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1346,7 +1346,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) mutex_lock(&ucsi->ppm_lock); - ret = ucsi->ops->read_cci(ucsi, &cci); + ret = ucsi->ops->poll_cci(ucsi, &cci); if (ret < 0) goto out; @@ -1364,7 +1364,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); do { - ret = ucsi->ops->read_cci(ucsi, &cci); + ret = ucsi->ops->poll_cci(ucsi, &cci); if (ret < 0) goto out; if (cci & UCSI_CCI_COMMAND_COMPLETE) @@ -1393,7 +1393,7 @@ static int ucsi_reset_ppm(struct ucsi *ucsi) /* Give the PPM time to process a reset before reading CCI */ msleep(20); - ret = ucsi->ops->read_cci(ucsi, &cci); + ret = ucsi->ops->poll_cci(ucsi, &cci); if (ret) goto out; @@ -1929,8 +1929,8 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) struct ucsi *ucsi; if (!ops || - !ops->read_version || !ops->read_cci || !ops->read_message_in || - !ops->sync_control || !ops->async_control) + !ops->read_version || !ops->read_cci || !ops->poll_cci || + !ops->read_message_in || !ops->sync_control || !ops->async_control) return ERR_PTR(-EINVAL); ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL); diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 82735eb34f0e..28780acc4af2 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -62,6 +62,7 @@ struct dentry; * struct ucsi_operations - UCSI I/O operations * @read_version: Read implemented UCSI version * @read_cci: Read CCI register + * @poll_cci: Read CCI register while polling with notifications disabled * @read_message_in: Read message data from UCSI * @sync_control: Blocking control operation * @async_control: Non-blocking control operation @@ -76,6 +77,7 @@ struct dentry; struct ucsi_operations { int (*read_version)(struct ucsi *ucsi, u16 *version); int (*read_cci)(struct ucsi *ucsi, u32 *cci); + int (*poll_cci)(struct ucsi *ucsi, u32 *cci); int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len); int (*sync_control)(struct ucsi *ucsi, u64 command); int (*async_control)(struct ucsi *ucsi, u64 command); diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 5c5515551963..ac1ebb5d9527 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -59,19 +59,24 @@ static int ucsi_acpi_read_version(struct ucsi *ucsi, u16 *version) static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - int ret; - - if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) { - ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); - if (ret) - return ret; - } memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci)); return 0; } +static int ucsi_acpi_poll_cci(struct ucsi *ucsi, u32 *cci) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ); + if (ret) + return ret; + + return ucsi_acpi_read_cci(ucsi, cci); +} + static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len) { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); @@ -94,6 +99,7 @@ static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command) static const struct ucsi_operations ucsi_acpi_ops = { .read_version = ucsi_acpi_read_version, .read_cci = ucsi_acpi_read_cci, + .poll_cci = ucsi_acpi_poll_cci, .read_message_in = ucsi_acpi_read_message_in, .sync_control = ucsi_sync_control_common, .async_control = ucsi_acpi_async_control @@ -142,6 +148,7 @@ static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command) static const struct ucsi_operations ucsi_gram_ops = { .read_version = ucsi_acpi_read_version, .read_cci = ucsi_acpi_read_cci, + .poll_cci = ucsi_acpi_poll_cci, .read_message_in = ucsi_gram_read_message_in, .sync_control = ucsi_gram_sync_control, .async_control = ucsi_acpi_async_control diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 740171f24ef9..4b1668733a4b 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -664,6 +664,7 @@ err_put: static const struct ucsi_operations ucsi_ccg_ops = { .read_version = ucsi_ccg_read_version, .read_cci = ucsi_ccg_read_cci, + .poll_cci = ucsi_ccg_read_cci, .read_message_in = ucsi_ccg_read_message_in, .sync_control = ucsi_ccg_sync_control, .async_control = ucsi_ccg_async_control, diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index fed39d458090..8af79101a2fc 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -206,6 +206,7 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con) static const struct ucsi_operations pmic_glink_ucsi_ops = { .read_version = pmic_glink_ucsi_read_version, .read_cci = pmic_glink_ucsi_read_cci, + .poll_cci = pmic_glink_ucsi_read_cci, .read_message_in = pmic_glink_ucsi_read_message_in, .sync_control = ucsi_sync_control_common, .async_control = pmic_glink_ucsi_async_control, diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c index 6923fad31d79..57ef7d83a412 100644 --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c @@ -424,6 +424,7 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) static const struct ucsi_operations ucsi_stm32g0_ops = { .read_version = ucsi_stm32g0_read_version, .read_cci = ucsi_stm32g0_read_cci, + .poll_cci = ucsi_stm32g0_read_cci, .read_message_in = ucsi_stm32g0_read_message_in, .sync_control = ucsi_sync_control_common, .async_control = ucsi_stm32g0_async_control, diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c index 4cae85c0dc12..d33e3f2dd1d8 100644 --- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c @@ -74,6 +74,7 @@ static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command) static const struct ucsi_operations yoga_c630_ucsi_ops = { .read_version = yoga_c630_ucsi_read_version, .read_cci = yoga_c630_ucsi_read_cci, + .poll_cci = yoga_c630_ucsi_read_cci, .read_message_in = yoga_c630_ucsi_read_message_in, .sync_control = ucsi_sync_control_common, .async_control = yoga_c630_ucsi_async_control, From bf4f9ae1cb08ccaafbe6874be6c46f59b83ae778 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Mon, 17 Feb 2025 13:54:40 +0300 Subject: [PATCH 0187/1090] usb: typec: ucsi: increase timeout for PPM reset operations It is observed that on some systems an initial PPM reset during the boot phase can trigger a timeout: [ 6.482546] ucsi_acpi USBC000:00: failed to reset PPM! [ 6.482551] ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed Still, increasing the timeout value, albeit being the most straightforward solution, eliminates the problem: the initial PPM reset may take up to ~8000-10000ms on some Lenovo laptops. When it is reset after the above period of time (or even if ucsi_reset_ppm() is not called overall), UCSI works as expected. Moreover, if the ucsi_acpi module is loaded/unloaded manually after the system has booted, reading the CCI values and resetting the PPM works perfectly, without any timeout. Thus it's only a boot-time issue. The reason for this behavior is not clear but it may be the consequence of some tricks that the firmware performs or be an actual firmware bug. As a workaround, increase the timeout to avoid failing the UCSI initialization prematurely. Fixes: b1b59e16075f ("usb: typec: ucsi: Increase command completion timeout value") Cc: stable Signed-off-by: Fedor Pchelkin Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250217105442.113486-3-boddah8794@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 0fe1476f4c29..7a56d3f840d7 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -25,7 +25,7 @@ * difficult to estimate the time it takes for the system to process the command * before it is actually passed to the PPM. */ -#define UCSI_TIMEOUT_MS 5000 +#define UCSI_TIMEOUT_MS 10000 /* * UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests From a321d163de3d8aa38a6449ab2becf4b1581aed96 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 8 Jan 2025 19:09:27 +0530 Subject: [PATCH 0188/1090] bus: mhi: host: pci_generic: Use pci_try_reset_function() to avoid deadlock There are multiple places from where the recovery work gets scheduled asynchronously. Also, there are multiple places where the caller waits synchronously for the recovery to be completed. One such place is during the PM shutdown() callback. If the device is not alive during recovery_work, it will try to reset the device using pci_reset_function(). This function internally will take the device_lock() first before resetting the device. By this time, if the lock has already been acquired, then recovery_work will get stalled while waiting for the lock. And if the lock was already acquired by the caller which waits for the recovery_work to be completed, it will lead to deadlock. This is what happened on the X1E80100 CRD device when the device died before shutdown() callback. Driver core calls the driver's shutdown() callback while holding the device_lock() leading to deadlock. And this deadlock scenario can occur on other paths as well, like during the PM suspend() callback, where the driver core would hold the device_lock() before calling driver's suspend() callback. And if the recovery_work was already started, it could lead to deadlock. This is also observed on the X1E80100 CRD. So to fix both issues, use pci_try_reset_function() in recovery_work. This function first checks for the availability of the device_lock() before trying to reset the device. If the lock is available, it will acquire it and reset the device. Otherwise, it will return -EAGAIN. If that happens, recovery_work will fail with the error message "Recovery failed" as not much could be done. Cc: stable@vger.kernel.org # 5.12 Reported-by: Johan Hovold Closes: https://lore.kernel.org/mhi/Z1me8iaK7cwgjL92@hovoldconsulting.com Fixes: 7389337f0a78 ("mhi: pci_generic: Add suspend/resume/recovery procedure") Reviewed-by: Johan Hovold Tested-by: Johan Hovold Analyzed-by: Johan Hovold Link: https://lore.kernel.org/mhi/Z2KKjWY2mPen6GPL@hovoldconsulting.com/ Reviewed-by: Loic Poulain Link: https://lore.kernel.org/r/20250108-mhi_recovery_fix-v1-1-a0a00a17da46@linaro.org Signed-off-by: Manivannan Sadhasivam --- drivers/bus/mhi/host/pci_generic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c index c41119b9079f..7ffea0f98162 100644 --- a/drivers/bus/mhi/host/pci_generic.c +++ b/drivers/bus/mhi/host/pci_generic.c @@ -1095,8 +1095,9 @@ static void mhi_pci_recovery_work(struct work_struct *work) err_unprepare: mhi_unprepare_after_power_down(mhi_cntrl); err_try_reset: - if (pci_reset_function(pdev)) - dev_err(&pdev->dev, "Recovery failed\n"); + err = pci_try_reset_function(pdev); + if (err) + dev_err(&pdev->dev, "Recovery failed: %d\n", err); } static void health_check(struct timer_list *t) From fa2e55811ae25020a5e9b23a8932e67e6d6261a4 Mon Sep 17 00:00:00 2001 From: Mike Lothian Date: Fri, 14 Feb 2025 12:28:00 +0000 Subject: [PATCH 0189/1090] ntsync: Set the permissions to be 0666 This allows ntsync to be usuable by non-root processes out of the box Signed-off-by: Mike Lothian Reviewed-by: Elizabeth Figura Link: https://lore.kernel.org/r/20250214122759.2629-2-mike@fireburn.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ntsync.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c index 055395cde42b..0b4e56d59b3d 100644 --- a/drivers/misc/ntsync.c +++ b/drivers/misc/ntsync.c @@ -1208,6 +1208,7 @@ static struct miscdevice ntsync_misc = { .minor = MISC_DYNAMIC_MINOR, .name = NTSYNC_NAME, .fops = &ntsync_fops, + .mode = 0666, }; module_misc_device(ntsync_misc); From c8d08464bce947ee060e0174a3f4e87503269d0c Mon Sep 17 00:00:00 2001 From: Balakrishnan Sambath Date: Wed, 19 Feb 2025 11:22:27 +0530 Subject: [PATCH 0190/1090] ASoC: dt-bindings: atmel-at91sam9g20ek: convert to json-schema Convert atmel-at91sam9g20ek-wm8731-audio DT binding to yaml based json-schema.Change file name to match json-scheme naming. Signed-off-by: Balakrishnan Sambath Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250219-sound-atmel-at91sam9g20ek-v3-1-d7c082af4e14@microchip.com Signed-off-by: Mark Brown --- .../sound/atmel,at91sam9g20ek-wm8731.yaml | 72 +++++++++++++++++++ .../atmel-at91sam9g20ek-wm8731-audio.txt | 26 ------- 2 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/atmel,at91sam9g20ek-wm8731.yaml delete mode 100644 Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt diff --git a/Documentation/devicetree/bindings/sound/atmel,at91sam9g20ek-wm8731.yaml b/Documentation/devicetree/bindings/sound/atmel,at91sam9g20ek-wm8731.yaml new file mode 100644 index 000000000000..627da2d890b2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/atmel,at91sam9g20ek-wm8731.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/atmel,at91sam9g20ek-wm8731.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel at91sam9g20ek wm8731 audio complex + +maintainers: + - Balakrishnan Sambath + +description: + The audio complex configuration for Atmel at91sam9g20ek with WM8731 audio codec. + +properties: + compatible: + const: atmel,at91sam9g20ek-wm8731-audio + + atmel,model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex. + + atmel,audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: A list of the connections between audio components. + minItems: 2 + maxItems: 4 + items: + enum: + # Board Connectors + - Ext Spk + - Int Mic + + # CODEC Pins + - LOUT + - ROUT + - LHPOUT + - RHPOUT + - LLINEIN + - RLINEIN + - MICIN + + atmel,ssc-controller: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of the SSC controller. + + atmel,audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of WM8731 audio codec. + +required: + - compatible + - atmel,model + - atmel,audio-routing + - atmel,ssc-controller + - atmel,audio-codec + +additionalProperties: false + +examples: + - | + sound { + compatible = "atmel,at91sam9g20ek-wm8731-audio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pck0_as_mck>; + atmel,model = "wm8731 @ AT91SAMG20EK"; + atmel,audio-routing = + "Ext Spk", "LHPOUT", + "Int Mic", "MICIN"; + atmel,ssc-controller = <&ssc0>; + atmel,audio-codec = <&wm8731>; + }; diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt deleted file mode 100644 index 9c5a9947b64d..000000000000 --- a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt +++ /dev/null @@ -1,26 +0,0 @@ -* Atmel at91sam9g20ek wm8731 audio complex - -Required properties: - - compatible: "atmel,at91sam9g20ek-wm8731-audio" - - atmel,model: The user-visible name of this sound complex. - - atmel,audio-routing: A list of the connections between audio components. - - atmel,ssc-controller: The phandle of the SSC controller - - atmel,audio-codec: The phandle of the WM8731 audio codec -Optional properties: - - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt - -Example: -sound { - compatible = "atmel,at91sam9g20ek-wm8731-audio"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pck0_as_mck>; - - atmel,model = "wm8731 @ AT91SAMG20EK"; - - atmel,audio-routing = - "Ext Spk", "LHPOUT", - "Int MIC", "MICIN"; - - atmel,ssc-controller = <&ssc0>; - atmel,audio-codec = <&wm8731>; -}; From 954b8915ff86353037d4246c7129d807a75f898b Mon Sep 17 00:00:00 2001 From: Eddie James Date: Thu, 13 Feb 2025 16:57:46 -0600 Subject: [PATCH 0191/1090] MAINTAINERS: change maintainer for FSI Due to job transitions, both Joel and Jeremy can no longer maintain the FSI subsystem. I will take over. I also replaced Alistair with Ninad as a reviewer, as Alistair doesn't have access to hardware and hasn't been active. I also removed the link to Joel's FSI tree as he won't be maintaining it. Signed-off-by: Eddie James Acked-by: Jeremy Kerr Link: https://lore.kernel.org/r/20250213225746.2159118-1-eajames@linux.ibm.com Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 25c86f47353d..f6026443526b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9439,14 +9439,11 @@ F: include/linux/fscrypt.h F: include/uapi/linux/fscrypt.h FSI SUBSYSTEM -M: Jeremy Kerr -M: Joel Stanley -R: Alistar Popple -R: Eddie James +M: Eddie James +R: Ninad Palsule L: linux-fsi@lists.ozlabs.org S: Supported Q: http://patchwork.ozlabs.org/project/linux-fsi/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi.git F: drivers/fsi/ F: include/linux/fsi*.h F: include/trace/events/fsi*.h From 2e2f89b184644f0e29f1ec0b4dcfd0361d2635cb Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 19 Feb 2025 15:21:32 +0000 Subject: [PATCH 0192/1090] firmware: cs_dsp: test_bin_error: Use same test cases for adsp2 and Halo Core Re-use the adsp2 test cases for the Halo Core test run. Before this the Halo Core kunit_case array was an empty placeholder. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20250219152132.1285941-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- .../firmware/cirrus/test/cs_dsp_test_bin_error.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c b/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c index 5dcf62f19faf..8748874f0552 100644 --- a/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c +++ b/drivers/firmware/cirrus/test/cs_dsp_test_bin_error.c @@ -534,11 +534,6 @@ static int cs_dsp_bin_err_test_adsp2_16bit_init(struct kunit *test) return cs_dsp_bin_err_test_common_init(test, dsp, 1); } -static struct kunit_case cs_dsp_bin_err_test_cases_halo[] = { - - { } /* terminator */ -}; - static void cs_dsp_bin_err_block_types_desc(const struct cs_dsp_bin_test_param *param, char *desc) { @@ -560,7 +555,7 @@ KUNIT_ARRAY_PARAM(bin_test_block_types, bin_test_block_types_cases, cs_dsp_bin_err_block_types_desc); -static struct kunit_case cs_dsp_bin_err_test_cases_adsp2[] = { +static struct kunit_case cs_dsp_bin_err_test_cases[] = { KUNIT_CASE(bin_load_with_unknown_blocks), KUNIT_CASE(bin_err_wrong_magic), KUNIT_CASE(bin_err_too_short_for_header), @@ -578,21 +573,21 @@ static struct kunit_suite cs_dsp_bin_err_test_halo = { .name = "cs_dsp_bin_err_halo", .init = cs_dsp_bin_err_test_halo_init, .exit = cs_dsp_bin_err_test_exit, - .test_cases = cs_dsp_bin_err_test_cases_halo, + .test_cases = cs_dsp_bin_err_test_cases, }; static struct kunit_suite cs_dsp_bin_err_test_adsp2_32bit = { .name = "cs_dsp_bin_err_adsp2_32bit", .init = cs_dsp_bin_err_test_adsp2_32bit_init, .exit = cs_dsp_bin_err_test_exit, - .test_cases = cs_dsp_bin_err_test_cases_adsp2, + .test_cases = cs_dsp_bin_err_test_cases, }; static struct kunit_suite cs_dsp_bin_err_test_adsp2_16bit = { .name = "cs_dsp_bin_err_adsp2_16bit", .init = cs_dsp_bin_err_test_adsp2_16bit_init, .exit = cs_dsp_bin_err_test_exit, - .test_cases = cs_dsp_bin_err_test_cases_adsp2, + .test_cases = cs_dsp_bin_err_test_cases, }; kunit_test_suites(&cs_dsp_bin_err_test_halo, From 42ae6e2559e63c2d4096b698cd47aaeb974436df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Tue, 11 Feb 2025 16:00:02 +0100 Subject: [PATCH 0193/1090] firmware: cs_dsp: test_control_parse: null-terminate test strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The char pointers in 'struct cs_dsp_mock_coeff_def' are expected to point to C strings. They need to be terminated by a null byte. However the code does not allocate that trailing null byte and only works if by chance the allocation is followed by such a null byte. Refactor the repeated string allocation logic into a new helper which makes sure the terminating null is always present. It also makes the code more readable. Signed-off-by: Thomas Weißschuh Fixes: 83baecd92e7c ("firmware: cs_dsp: Add KUnit testing of control parsing") Cc: stable@vger.kernel.org Reviewed-by: Richard Fitzgerald Tested-by: Richard Fitzgerald Link: https://patch.msgid.link/20250211-cs_dsp-kunit-strings-v1-1-d9bc2035d154@linutronix.de Signed-off-by: Mark Brown --- .../cirrus/test/cs_dsp_test_control_parse.c | 51 +++++++------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c b/drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c index cb90964740ea..942ba1af5e7c 100644 --- a/drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c +++ b/drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c @@ -73,6 +73,18 @@ static const struct cs_dsp_mock_coeff_def mock_coeff_template = { .length_bytes = 4, }; +static char *cs_dsp_ctl_alloc_test_string(struct kunit *test, char c, size_t len) +{ + char *str; + + str = kunit_kmalloc(test, len + 1, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str); + memset(str, c, len); + str[len] = '\0'; + + return str; +} + /* Algorithm info block without controls should load */ static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test) { @@ -160,12 +172,8 @@ static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test) struct cs_dsp_mock_coeff_def def = mock_coeff_template; struct cs_dsp_coeff_ctl *ctl; struct firmware *wmfw; - char *name; - name = kunit_kzalloc(test, 256, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name); - memset(name, 'A', 255); - def.fullname = name; + def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, cs_dsp_ctl_parse_test_algs[0].id, @@ -252,14 +260,9 @@ static void cs_dsp_ctl_parse_max_short_name(struct kunit *test) struct cs_dsp_test_local *local = priv->local; struct cs_dsp_mock_coeff_def def = mock_coeff_template; struct cs_dsp_coeff_ctl *ctl; - char *name; struct firmware *wmfw; - name = kunit_kmalloc(test, 255, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name); - memset(name, 'A', 255); - - def.shortname = name; + def.shortname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, cs_dsp_ctl_parse_test_algs[0].id, @@ -273,7 +276,7 @@ static void cs_dsp_ctl_parse_max_short_name(struct kunit *test) ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); KUNIT_ASSERT_NOT_NULL(test, ctl); KUNIT_EXPECT_EQ(test, ctl->subname_len, 255); - KUNIT_EXPECT_MEMEQ(test, ctl->subname, name, ctl->subname_len); + KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); KUNIT_EXPECT_EQ(test, ctl->type, def.type); KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); @@ -323,12 +326,8 @@ static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test) struct cs_dsp_mock_coeff_def def = mock_coeff_template; struct cs_dsp_coeff_ctl *ctl; struct firmware *wmfw; - char *fullname; - fullname = kunit_kmalloc(test, 255, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname); - memset(fullname, 'A', 255); - def.fullname = fullname; + def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, cs_dsp_ctl_parse_test_algs[0].id, @@ -392,12 +391,8 @@ static void cs_dsp_ctl_parse_with_max_description(struct kunit *test) struct cs_dsp_mock_coeff_def def = mock_coeff_template; struct cs_dsp_coeff_ctl *ctl; struct firmware *wmfw; - char *description; - description = kunit_kmalloc(test, 65535, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description); - memset(description, 'A', 65535); - def.description = description; + def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535); cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, cs_dsp_ctl_parse_test_algs[0].id, @@ -429,17 +424,9 @@ static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *tes struct cs_dsp_mock_coeff_def def = mock_coeff_template; struct cs_dsp_coeff_ctl *ctl; struct firmware *wmfw; - char *fullname, *description; - fullname = kunit_kmalloc(test, 255, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname); - memset(fullname, 'A', 255); - def.fullname = fullname; - - description = kunit_kmalloc(test, 65535, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description); - memset(description, 'A', 65535); - def.description = description; + def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); + def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535); cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, cs_dsp_ctl_parse_test_algs[0].id, From 4738d3d3e12d70a5067baba147daf57e57b77548 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Feb 2025 20:50:13 +0200 Subject: [PATCH 0194/1090] intel_th: msu: Fix kernel-doc warnings Correct function comments to prevent kernel-doc warnings found when using "W=1". msu.c:162: warning: Function parameter or struct member 'mbuf_priv' not described in 'msc' msu.c:164: warning: Function parameter or struct member 'orig_addr' not described in 'msc' msu.c:164: warning: Function parameter or struct member 'orig_sz' not described in 'msc' Signed-off-by: Andy Shevchenko Signed-off-by: Alexander Shishkin Link: https://lore.kernel.org/r/20250211185017.1759193-2-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/msu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 66123d684ac9..492d8eba37eb 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -108,7 +108,7 @@ struct msc_iter { * @reg_base: register window base address * @thdev: intel_th_device pointer * @mbuf: MSU buffer, if assigned - * @mbuf_priv MSU buffer's private data, if @mbuf + * @mbuf_priv: MSU buffer's private data, if @mbuf * @win_list: list of windows in multiblock mode * @single_sgt: single mode buffer * @cur_win: current window @@ -117,6 +117,8 @@ struct msc_iter { * @single_wrap: single mode wrap occurred * @base: buffer's base pointer * @base_addr: buffer's base address + * @orig_addr: MSC0 buffer's base address + * @orig_sz: MSC0 buffer's size * @user_count: number of users of the buffer * @mmap_count: number of mappings * @buf_mutex: mutex to serialize access to buffer-related bits From 04190ec6d02aa8fee0f03189bb7762b44739c253 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Tue, 11 Feb 2025 20:50:14 +0200 Subject: [PATCH 0195/1090] intel_th: msu: Fix less trivial kernel-doc warnings Correct function comments to prevent kernel-doc warnings found when using "W=1" that the drive-by fixers had trouble documenting and skipped over. msu.c:168: warning: Function parameter or struct member 'msu_base' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'work' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'switch_on_unlock' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'iter_list' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'stop_on_full' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'do_irq' not described in 'msc' msu.c:168: warning: Function parameter or struct member 'multi_is_broken' not described in 'msc' Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250211185017.1759193-3-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/msu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 492d8eba37eb..bf99d79a4192 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -105,13 +105,16 @@ struct msc_iter { /** * struct msc - MSC device representation - * @reg_base: register window base address + * @reg_base: register window base address for the entire MSU + * @msu_base: register window base address for this MSC * @thdev: intel_th_device pointer * @mbuf: MSU buffer, if assigned * @mbuf_priv: MSU buffer's private data, if @mbuf + * @work: a work to stop the trace when the buffer is full * @win_list: list of windows in multiblock mode * @single_sgt: single mode buffer * @cur_win: current window + * @switch_on_unlock: window to switch to when it becomes available * @nr_pages: total number of pages allocated for this buffer * @single_sz: amount of data in single mode * @single_wrap: single mode wrap occurred @@ -122,8 +125,12 @@ struct msc_iter { * @user_count: number of users of the buffer * @mmap_count: number of mappings * @buf_mutex: mutex to serialize access to buffer-related bits + * @iter_list: list of open file descriptor iterators + * @stop_on_full: stop the trace if the current window is full * @enabled: MSC is enabled * @wrap: wrapping is enabled + * @do_irq: IRQ resource is available, handle interrupts + * @multi_is_broken: multiblock mode enabled (not disabled by PCI drvdata) * @mode: MSC operating mode * @burst_len: write burst length * @index: number of this MSC in the MSU From b5edccae9f447a92d475267d94c33f4926963eec Mon Sep 17 00:00:00 2001 From: Pawel Chmielewski Date: Tue, 11 Feb 2025 20:50:15 +0200 Subject: [PATCH 0196/1090] intel_th: pci: Add Arrow Lake support Add support for the Trace Hub in Arrow Lake. Signed-off-by: Pawel Chmielewski Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Cc: stable@kernel.org Link: https://lore.kernel.org/r/20250211185017.1759193-4-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index e9d8d28e055f..3e03ee788bb9 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -334,6 +334,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa824), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Arrow Lake */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7724), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { /* Alder Lake CPU */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f), From a70034d6c0d5f3cdee40bb00a578e17fd2ebe426 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Tue, 11 Feb 2025 20:50:16 +0200 Subject: [PATCH 0197/1090] intel_th: pci: Add Panther Lake-H support Add support for the Trace Hub in Panther Lake-H. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Cc: stable@kernel.org Link: https://lore.kernel.org/r/20250211185017.1759193-5-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index 3e03ee788bb9..004e68286fd4 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -339,6 +339,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7724), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Panther Lake-H */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe324), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { /* Alder Lake CPU */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f), From 49114ff05770264ae233f50023fc64a719a9dcf9 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Tue, 11 Feb 2025 20:50:17 +0200 Subject: [PATCH 0198/1090] intel_th: pci: Add Panther Lake-P/U support Add support for the Trace Hub in Panther Lake-P/U. Signed-off-by: Alexander Shishkin Reviewed-by: Andy Shevchenko Cc: stable@kernel.org Link: https://lore.kernel.org/r/20250211185017.1759193-6-alexander.shishkin@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index 004e68286fd4..e3def163d5cf 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -344,6 +344,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe324), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Panther Lake-P/U */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe424), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { /* Alder Lake CPU */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f), From 78eb41f518f414378643ab022241df2a9dcd008b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 13 Feb 2025 15:05:13 +0100 Subject: [PATCH 0199/1090] drivers: core: fix device leak in __fw_devlink_relax_cycles() Commit bac3b10b78e5 ("driver core: fw_devlink: Stop trying to optimize cycle detection logic") introduced a new struct device *con_dev and a get_dev_from_fwnode() call to get it, but without adding a corresponding put_device(). Closes: https://lore.kernel.org/all/20241204124826.2e055091@booty/ Fixes: bac3b10b78e5 ("driver core: fw_devlink: Stop trying to optimize cycle detection logic") Cc: stable@vger.kernel.org Reviewed-by: Saravana Kannan Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20250213-fix__fw_devlink_relax_cycles_missing_device_put-v2-1-8cd3b03e6a3f@bootlin.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 5a1f05198114..2fde698430df 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2079,6 +2079,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle, out: sup_handle->flags &= ~FWNODE_FLAG_VISITED; put_device(sup_dev); + put_device(con_dev); put_device(par_dev); return ret; } From c783e1258f29c5caac9eea0aea6b172870f1baf8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 20 Feb 2025 13:03:14 +0100 Subject: [PATCH 0200/1090] usb: gadget: Fix setting self-powered state on suspend cdev->config might be NULL, so check it before dereferencing. CC: stable Fixes: 40e89ff5750f ("usb: gadget: Set self-powered based on MaxPower and bmAttributes") Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20250220120314.3614330-1-m.szyprowski@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 1fb28bbf6c45..4bcf73bae761 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2616,7 +2616,8 @@ void composite_suspend(struct usb_gadget *gadget) cdev->suspended = 1; - if (cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER) + if (cdev->config && + cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER) usb_gadget_set_selfpowered(gadget); usb_gadget_vbus_draw(gadget, 2); From 64899904d6103500ad01be7b763298dc939285ae Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 20 Feb 2025 13:01:56 +0100 Subject: [PATCH 0201/1090] ASoC: soc-core: Use str_yes_no() in snd_soc_close_delayed_work() Remove hard-coded strings by using the str_yes_no() helper function. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250220120156.1663-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ae7b3e39d5ff..3f97d1f132c6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -430,7 +431,7 @@ void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd) codec_dai->driver->playback.stream_name, snd_soc_dai_stream_active(codec_dai, playback) ? "active" : "inactive", - rtd->pop_wait ? "yes" : "no"); + str_yes_no(rtd->pop_wait)); /* are we waiting on this codec DAI stream */ if (rtd->pop_wait == 1) { From 91d44c1afc61a2fec37a9c7a3485368309391e0b Mon Sep 17 00:00:00 2001 From: Qiu-ji Chen Date: Sat, 18 Jan 2025 15:08:33 +0800 Subject: [PATCH 0202/1090] cdx: Fix possible UAF error in driver_override_show() Fixed a possible UAF problem in driver_override_show() in drivers/cdx/cdx.c This function driver_override_show() is part of DEVICE_ATTR_RW, which includes both driver_override_show() and driver_override_store(). These functions can be executed concurrently in sysfs. The driver_override_store() function uses driver_set_override() to update the driver_override value, and driver_set_override() internally locks the device (device_lock(dev)). If driver_override_show() reads cdx_dev->driver_override without locking, it could potentially access a freed pointer if driver_override_store() frees the string concurrently. This could lead to printing a kernel address, which is a security risk since DEVICE_ATTR can be read by all users. Additionally, a similar pattern is used in drivers/amba/bus.c, as well as many other bus drivers, where device_lock() is taken in the show function, and it has been working without issues. This potential bug was detected by our experimental static analysis tool, which analyzes locking APIs and paired functions to identify data races and atomicity violations. Fixes: 1f86a00c1159 ("bus/fsl-mc: add support for 'driver_override' in the mc-bus") Cc: stable Signed-off-by: Qiu-ji Chen Link: https://lore.kernel.org/r/20250118070833.27201-1-chenqiuji666@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/cdx/cdx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c index c573ed2ee71a..7811aa734053 100644 --- a/drivers/cdx/cdx.c +++ b/drivers/cdx/cdx.c @@ -473,8 +473,12 @@ static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr, char *buf) { struct cdx_device *cdx_dev = to_cdx_device(dev); + ssize_t len; - return sysfs_emit(buf, "%s\n", cdx_dev->driver_override); + device_lock(dev); + len = sysfs_emit(buf, "%s\n", cdx_dev->driver_override); + device_unlock(dev); + return len; } static DEVICE_ATTR_RW(driver_override); From c99e1e1d0850ff157f1bc16871acd2dff5a9bcc3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 22 Jan 2025 07:54:33 +0100 Subject: [PATCH 0203/1090] vbox: add HAS_IOPORT dependency The vboxguest driver depends on port I/O for debug output: include/asm-generic/io.h:626:15: error: call to '_outl' declared with attribute error: outl() requires CONFIG_HAS_IOPORT 626 | #define _outl _outl include/asm-generic/io.h:663:14: note: in expansion of macro '_outl' 663 | #define outl _outl | ^~~~~ drivers/virt/vboxguest/vboxguest_utils.c:102:9: note: in expansion of macro 'outl' 102 | outl(phys_req, gdev->io_port + VMMDEV_PORT_OFF_REQUEST); | ^~~~ Most arm64 platforms don't actually support port I/O, though it is currently enabled unconditionally. Refine the vbox dependency to allow turning HAS_IOPORT off in the future when building for platforms without port I/O and allow compile-testing on all architectures. Fixes: 5cf8f938bf5c ("vbox: Enable VBOXGUEST and VBOXSF_FS on ARM64") Signed-off-by: Arnd Bergmann Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20250122065445.1469218-1-arnd@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/virt/vboxguest/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/virt/vboxguest/Kconfig b/drivers/virt/vboxguest/Kconfig index 11b153e7454e..eaba28c95e73 100644 --- a/drivers/virt/vboxguest/Kconfig +++ b/drivers/virt/vboxguest/Kconfig @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only config VBOXGUEST tristate "Virtual Box Guest integration support" - depends on (ARM64 || X86) && PCI && INPUT + depends on (ARM64 || X86 || COMPILE_TEST) && PCI && INPUT + depends on HAS_IOPORT help This is a driver for the Virtual Box Guest PCI device used in Virtual Box virtual machines. Enabling this driver will add From dcb0d43ba8eb9517e70b1a0e4b0ae0ab657a0e5a Mon Sep 17 00:00:00 2001 From: Visweswara Tanuku Date: Fri, 24 Jan 2025 04:57:40 -0800 Subject: [PATCH 0204/1090] slimbus: messaging: Free transaction ID in delayed interrupt scenario In case of interrupt delay for any reason, slim_do_transfer() returns timeout error but the transaction ID (TID) is not freed. This results into invalid memory access inside qcom_slim_ngd_rx_msgq_cb() due to invalid TID. Fix the issue by freeing the TID in slim_do_transfer() before returning timeout error to avoid invalid memory access. Call trace: __memcpy_fromio+0x20/0x190 qcom_slim_ngd_rx_msgq_cb+0x130/0x290 [slim_qcom_ngd_ctrl] vchan_complete+0x2a0/0x4a0 tasklet_action_common+0x274/0x700 tasklet_action+0x28/0x3c _stext+0x188/0x620 run_ksoftirqd+0x34/0x74 smpboot_thread_fn+0x1d8/0x464 kthread+0x178/0x238 ret_from_fork+0x10/0x20 Code: aa0003e8 91000429 f100044a 3940002b (3800150b) ---[ end trace 0fe00bec2b975c99 ]--- Kernel panic - not syncing: Oops: Fatal exception in interrupt. Fixes: afbdcc7c384b ("slimbus: Add messaging APIs to slimbus framework") Cc: stable Signed-off-by: Visweswara Tanuku Link: https://lore.kernel.org/r/20250124125740.16897-1-quic_vtanuku@quicinc.com Signed-off-by: Greg Kroah-Hartman --- drivers/slimbus/messaging.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/slimbus/messaging.c b/drivers/slimbus/messaging.c index e7aa9bd4b44b..6f01d944f9c6 100644 --- a/drivers/slimbus/messaging.c +++ b/drivers/slimbus/messaging.c @@ -148,8 +148,9 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn) } ret = ctrl->xfer_msg(ctrl, txn); - - if (!ret && need_tid && !txn->msg->comp) { + if (ret == -ETIMEDOUT) { + slim_free_txn_tid(ctrl, txn); + } else if (!ret && need_tid && !txn->msg->comp) { unsigned long ms = txn->rl + HZ; time_left = wait_for_completion_timeout(txn->comp, From e77aff5528a183462714f750e45add6cc71e276a Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Thu, 30 Jan 2025 21:58:22 +0000 Subject: [PATCH 0205/1090] binderfs: fix use-after-free in binder_devices Devices created through binderfs are added to the global binder_devices list but are not removed before being destroyed. This leads to dangling pointers in the list and subsequent use-after-free errors: ================================================================== BUG: KASAN: slab-use-after-free in binder_add_device+0x5c/0x9c Write of size 8 at addr ffff0000c258d708 by task mount/653 CPU: 7 UID: 0 PID: 653 Comm: mount Not tainted 6.13.0-09030-g6d61a53dd6f5 #1 Hardware name: linux,dummy-virt (DT) Call trace: binder_add_device+0x5c/0x9c binderfs_binder_device_create+0x690/0x84c [...] __arm64_sys_mount+0x324/0x3bc Allocated by task 632: binderfs_binder_device_create+0x168/0x84c binder_ctl_ioctl+0xfc/0x184 [...] __arm64_sys_ioctl+0x110/0x150 Freed by task 649: kfree+0xe0/0x338 binderfs_evict_inode+0x138/0x1dc [...] ================================================================== Remove devices from binder_devices before destroying them. Cc: Li Li Reported-by: syzbot+7015dcf45953112c8b45@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7015dcf45953112c8b45 Fixes: 12d909cac1e1 ("binderfs: add new binder devices to binder_devices") Signed-off-by: Carlos Llamas Tested-by: syzbot+7015dcf45953112c8b45@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/20250130215823.1518990-1-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/android/binderfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index bc6bae76ccaf..94c6446604fc 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -274,6 +274,7 @@ static void binderfs_evict_inode(struct inode *inode) mutex_unlock(&binderfs_minors_mutex); if (refcount_dec_and_test(&device->ref)) { + hlist_del_init(&device->hlist); kfree(device->context.name); kfree(device); } From 819cec1dc47cdeac8f5dd6ba81c1dbee2a68c3bb Mon Sep 17 00:00:00 2001 From: Haoyu Li Date: Thu, 30 Jan 2025 19:58:11 +0800 Subject: [PATCH 0206/1090] drivers: virt: acrn: hsm: Use kzalloc to avoid info leak in pmcmd_ioctl In the "pmcmd_ioctl" function, three memory objects allocated by kmalloc are initialized by "hcall_get_cpu_state", which are then copied to user space. The initializer is indeed implemented in "acrn_hypercall2" (arch/x86/include/asm/acrn.h). There is a risk of information leakage due to uninitialized bytes. Fixes: 3d679d5aec64 ("virt: acrn: Introduce interfaces to query C-states and P-states allowed by hypervisor") Signed-off-by: Haoyu Li Cc: stable Acked-by: Fei Li Link: https://lore.kernel.org/r/20250130115811.92424-1-lihaoyu499@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/virt/acrn/hsm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c index c24036c4e51e..e4e196abdaac 100644 --- a/drivers/virt/acrn/hsm.c +++ b/drivers/virt/acrn/hsm.c @@ -49,7 +49,7 @@ static int pmcmd_ioctl(u64 cmd, void __user *uptr) switch (cmd & PMCMD_TYPE_MASK) { case ACRN_PMCMD_GET_PX_CNT: case ACRN_PMCMD_GET_CX_CNT: - pm_info = kmalloc(sizeof(u64), GFP_KERNEL); + pm_info = kzalloc(sizeof(u64), GFP_KERNEL); if (!pm_info) return -ENOMEM; @@ -64,7 +64,7 @@ static int pmcmd_ioctl(u64 cmd, void __user *uptr) kfree(pm_info); break; case ACRN_PMCMD_GET_PX_DATA: - px_data = kmalloc(sizeof(*px_data), GFP_KERNEL); + px_data = kzalloc(sizeof(*px_data), GFP_KERNEL); if (!px_data) return -ENOMEM; @@ -79,7 +79,7 @@ static int pmcmd_ioctl(u64 cmd, void __user *uptr) kfree(px_data); break; case ACRN_PMCMD_GET_CX_DATA: - cx_data = kmalloc(sizeof(*cx_data), GFP_KERNEL); + cx_data = kzalloc(sizeof(*cx_data), GFP_KERNEL); if (!cx_data) return -ENOMEM; From 038ef0754aae76f79b147b8867f9250e6a976872 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 7 Feb 2025 00:03:11 +0200 Subject: [PATCH 0207/1090] eeprom: digsy_mtc: Make GPIO lookup table match the device The dev_id value in the GPIO lookup table must match to the device instance name, which in this case is combined of name and platform device ID, i.e. "spi_gpio.1". But the table assumed that there was no platform device ID defined, which is wrong. Fix the dev_id value accordingly. Fixes: 9b00bc7b901f ("spi: spi-gpio: Rewrite to use GPIO descriptors") Cc: stable Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250206220311.1554075-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/digsy_mtc_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c index 88888485e6f8..ee58f7ce5bfa 100644 --- a/drivers/misc/eeprom/digsy_mtc_eeprom.c +++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c @@ -50,7 +50,7 @@ static struct platform_device digsy_mtc_eeprom = { }; static struct gpiod_lookup_table eeprom_spi_gpiod_table = { - .dev_id = "spi_gpio", + .dev_id = "spi_gpio.1", .table = { GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CLK, "sck", GPIO_ACTIVE_HIGH), From 6d991f569c5ef6eaeadf1238df2c36e3975233ad Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 23 Jan 2025 09:32:49 -0300 Subject: [PATCH 0208/1090] char: misc: deallocate static minor in error path When creating sysfs files fail, the allocated minor must be freed such that it can be later reused. That is specially harmful for static minor numbers, since those would always fail to register later on. Fixes: 6d04d2b554b1 ("misc: misc_minor_alloc to use ida for all dynamic/misc dynamic minors") Cc: stable Signed-off-by: Thadeu Lima de Souza Cascardo Link: https://lore.kernel.org/r/20250123123249.4081674-5-cascardo@igalia.com Signed-off-by: Greg Kroah-Hartman --- drivers/char/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 2cf595d2e10b..f7dd455dd0dd 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -264,8 +264,8 @@ int misc_register(struct miscdevice *misc) device_create_with_groups(&misc_class, misc->parent, dev, misc, misc->groups, "%s", misc->name); if (IS_ERR(misc->this_device)) { + misc_minor_free(misc->minor); if (is_dynamic) { - misc_minor_free(misc->minor); misc->minor = MISC_DYNAMIC_MINOR; } err = PTR_ERR(misc->this_device); From 32ce5d87d52213a50a513750f01a56f4d01f50cb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 14 Feb 2025 11:21:30 +0100 Subject: [PATCH 0209/1090] bus: simple-pm-bus: fix forced runtime PM use The simple-pm-bus driver only enables runtime PM for some buses ('simple-pm-bus') yet has started calling pm_runtime_force_suspend() and pm_runtime_force_resume() during system suspend unconditionally. This currently works, but that is not obvious and depends on implementation details which may change at some point. Add dedicated system sleep ops and only call pm_runtime_force_suspend() and pm_runtime_force_resume() for buses that use runtime PM to avoid any future surprises. Fixes: c45839309c3d ("drivers: bus: simple-pm-bus: Use clocks") Cc: Liu Ying Signed-off-by: Johan Hovold Reviewed-by: Ulf Hansson Acked-by: Liu Ying Acked-by: Rafael J. Wysocki Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20250214102130.3000-1-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/bus/simple-pm-bus.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c index 5dea31769f9a..d8e029e7e53f 100644 --- a/drivers/bus/simple-pm-bus.c +++ b/drivers/bus/simple-pm-bus.c @@ -109,9 +109,29 @@ static int simple_pm_bus_runtime_resume(struct device *dev) return 0; } +static int simple_pm_bus_suspend(struct device *dev) +{ + struct simple_pm_bus *bus = dev_get_drvdata(dev); + + if (!bus) + return 0; + + return pm_runtime_force_suspend(dev); +} + +static int simple_pm_bus_resume(struct device *dev) +{ + struct simple_pm_bus *bus = dev_get_drvdata(dev); + + if (!bus) + return 0; + + return pm_runtime_force_resume(dev); +} + static const struct dev_pm_ops simple_pm_bus_pm_ops = { RUNTIME_PM_OPS(simple_pm_bus_runtime_suspend, simple_pm_bus_runtime_resume, NULL) - NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(simple_pm_bus_suspend, simple_pm_bus_resume) }; #define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */ From b47834ee4485bbdcc6d36f086ff61c3efd8870d4 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 20 Feb 2025 12:48:20 -0600 Subject: [PATCH 0210/1090] ASoC: SOF: amd: Add depends on CPU_SUP_AMD When SMN support was switched to the kernel wide AMD_NODE instead of local implementation this broke compilation on the allyesconfig for some architectures. AMD_NODE is only supported on AMD platforms, so modify all the AMD drivers that use it to also require CPU_SUP_AMD. Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/linux-next/20250220160950.2cd64bdb@canb.auug.org.au/ Fixes: f120cf33d232 ("ASoC: SOF: amd: Use AMD_NODE") Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250220184822.916090-1-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig index 28216c8c1cf9..6eb5b2d14843 100644 --- a/sound/soc/sof/amd/Kconfig +++ b/sound/soc/sof/amd/Kconfig @@ -33,6 +33,7 @@ config SND_SOC_SOF_AMD_COMMON config SND_SOC_SOF_AMD_RENOIR tristate "SOF support for RENOIR" depends on SND_SOC_SOF_PCI + depends on CPU_SUP_AMD select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on AMD Renoir platform @@ -40,6 +41,7 @@ config SND_SOC_SOF_AMD_RENOIR config SND_SOC_SOF_AMD_VANGOGH tristate "SOF support for VANGOGH" depends on SND_SOC_SOF_PCI + depends on CPU_SUP_AMD select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support @@ -50,6 +52,7 @@ config SND_SOC_SOF_AMD_VANGOGH config SND_SOC_SOF_AMD_REMBRANDT tristate "SOF support for REMBRANDT" depends on SND_SOC_SOF_PCI + depends on CPU_SUP_AMD select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on AMD Rembrandt platform @@ -82,6 +85,7 @@ config SND_SOC_SOF_AMD_SOUNDWIRE config SND_SOC_SOF_AMD_ACP63 tristate "SOF support for ACP6.3 platform" depends on SND_SOC_SOF_PCI + depends on CPU_SUP_AMD select SND_SOC_SOF_AMD_COMMON select SND_SOC_SOF_AMD_SOUNDWIRE_LINK_BASELINE help @@ -93,6 +97,7 @@ config SND_SOC_SOF_AMD_ACP63 config SND_SOC_SOF_AMD_ACP70 tristate "SOF support for ACP7.0 platform" depends on SND_SOC_SOF_PCI + depends on CPU_SUP_AMD select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on From 92527e473911b835c2c18b0c55c337c33e85ff00 Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Thu, 20 Feb 2025 13:23:34 -0600 Subject: [PATCH 0211/1090] ntsync: Check wait count based on byte size. GCC versions below 13 incorrectly detect the copy size as being static and too small to fit in the "fds" array. Work around this by explicitly calculating the size and returning EINVAL based on that, instead of based on the object count. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502072019.LYoCR9bF-lkp@intel.com/ Suggested-by: Arnd Bergmann Signed-off-by: Elizabeth Figura -- Suggested-by as per Arnd's request, but the only thing I changed was preserving array_size() [as noted by Geert in the linked thread]. I tested and found no regressions. v2: Add missing sign-off Link: https://lore.kernel.org/r/20250220192334.549167-1-zfigura@codeweavers.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ntsync.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c index 0b4e56d59b3d..999026a1ae04 100644 --- a/drivers/misc/ntsync.c +++ b/drivers/misc/ntsync.c @@ -873,6 +873,7 @@ static int setup_wait(struct ntsync_device *dev, { int fds[NTSYNC_MAX_WAIT_COUNT + 1]; const __u32 count = args->count; + size_t size = array_size(count, sizeof(fds[0])); struct ntsync_q *q; __u32 total_count; __u32 i, j; @@ -880,15 +881,14 @@ static int setup_wait(struct ntsync_device *dev, if (args->pad || (args->flags & ~NTSYNC_WAIT_REALTIME)) return -EINVAL; - if (args->count > NTSYNC_MAX_WAIT_COUNT) + if (size >= sizeof(fds)) return -EINVAL; total_count = count; if (args->alert) total_count++; - if (copy_from_user(fds, u64_to_user_ptr(args->objs), - array_size(count, sizeof(*fds)))) + if (copy_from_user(fds, u64_to_user_ptr(args->objs), size)) return -EFAULT; if (args->alert) fds[count] = args->alert; From 7241c886a71797cc51efc6fadec7076fcf6435c2 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Sun, 9 Feb 2025 15:52:52 -0800 Subject: [PATCH 0212/1090] fbdev: hyperv_fb: iounmap() the correct memory when removing a device When a Hyper-V framebuffer device is removed, or the driver is unbound from a device, any allocated and/or mapped memory must be released. In particular, MMIO address space that was mapped to the framebuffer must be unmapped. Current code unmaps the wrong address, resulting in an error like: [ 4093.980597] iounmap: bad address 00000000c936c05c followed by a stack dump. Commit d21987d709e8 ("video: hyperv: hyperv_fb: Support deferred IO for Hyper-V frame buffer driver") changed the kind of address stored in info->screen_base, and the iounmap() call in hvfb_putmem() was not updated accordingly. Fix this by updating hvfb_putmem() to unmap the correct address. Fixes: d21987d709e8 ("video: hyperv: hyperv_fb: Support deferred IO for Hyper-V frame buffer driver") Signed-off-by: Michael Kelley Reviewed-by: Saurabh Sengar Link: https://lore.kernel.org/r/20250209235252.2987-1-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20250209235252.2987-1-mhklinux@outlook.com> --- drivers/video/fbdev/hyperv_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 7fdb5edd7e2e..363e4ccfcdb7 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -1080,7 +1080,7 @@ static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info) if (par->need_docopy) { vfree(par->dio_vp); - iounmap(info->screen_base); + iounmap(par->mmio_vp); vmbus_free_mmio(par->mem->start, screen_fb_size); } else { hvfb_release_phymem(hdev, info->fix.smem_start, From 50cef76d5cb0e199cda19f026842560f6eedc4f7 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 23 Jan 2025 14:44:53 +0100 Subject: [PATCH 0213/1090] x86/microcode/AMD: Load only SHA256-checksummed patches Load patches for which the driver carries a SHA256 checksum of the patch blob. This can be disabled by adding "microcode.amd_sha_check=off" on the kernel cmdline. But it is highly NOT recommended. Signed-off-by: Borislav Petkov (AMD) --- arch/x86/Kconfig | 1 + arch/x86/kernel/cpu/microcode/amd.c | 111 +++++- arch/x86/kernel/cpu/microcode/amd_shas.c | 444 +++++++++++++++++++++++ 3 files changed, 554 insertions(+), 2 deletions(-) create mode 100644 arch/x86/kernel/cpu/microcode/amd_shas.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index be2c311f5118..0e27ebd7e36a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1341,6 +1341,7 @@ config X86_REBOOTFIXUPS config MICROCODE def_bool y depends on CPU_SUP_AMD || CPU_SUP_INTEL + select CRYPTO_LIB_SHA256 if CPU_SUP_AMD config MICROCODE_INITRD32 def_bool y diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 31f90e129b08..95ac1c6a84fb 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -23,14 +23,18 @@ #include #include +#include #include #include #include #include #include +#include + #include #include +#include #include #include #include @@ -145,6 +149,98 @@ ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin"; */ static u32 bsp_cpuid_1_eax __ro_after_init; +static bool sha_check = true; + +struct patch_digest { + u32 patch_id; + u8 sha256[SHA256_DIGEST_SIZE]; +}; + +#include "amd_shas.c" + +static int cmp_id(const void *key, const void *elem) +{ + struct patch_digest *pd = (struct patch_digest *)elem; + u32 patch_id = *(u32 *)key; + + if (patch_id == pd->patch_id) + return 0; + else if (patch_id < pd->patch_id) + return -1; + else + return 1; +} + +static bool need_sha_check(u32 cur_rev) +{ + switch (cur_rev >> 8) { + case 0x80012: return cur_rev <= 0x800126f; break; + case 0x83010: return cur_rev <= 0x830107c; break; + case 0x86001: return cur_rev <= 0x860010e; break; + case 0x86081: return cur_rev <= 0x8608108; break; + case 0x87010: return cur_rev <= 0x8701034; break; + case 0x8a000: return cur_rev <= 0x8a0000a; break; + case 0xa0011: return cur_rev <= 0xa0011da; break; + case 0xa0012: return cur_rev <= 0xa001243; break; + case 0xa1011: return cur_rev <= 0xa101153; break; + case 0xa1012: return cur_rev <= 0xa10124e; break; + case 0xa1081: return cur_rev <= 0xa108109; break; + case 0xa2010: return cur_rev <= 0xa20102f; break; + case 0xa2012: return cur_rev <= 0xa201212; break; + case 0xa6012: return cur_rev <= 0xa60120a; break; + case 0xa7041: return cur_rev <= 0xa704109; break; + case 0xa7052: return cur_rev <= 0xa705208; break; + case 0xa7080: return cur_rev <= 0xa708009; break; + case 0xa70c0: return cur_rev <= 0xa70C009; break; + case 0xaa002: return cur_rev <= 0xaa00218; break; + default: break; + } + + pr_info("You should not be seeing this. Please send the following couple of lines to x86--kernel.org\n"); + pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev); + return true; +} + +static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsigned int len) +{ + struct patch_digest *pd = NULL; + u8 digest[SHA256_DIGEST_SIZE]; + struct sha256_state s; + int i; + + if (x86_family(bsp_cpuid_1_eax) < 0x17 || + x86_family(bsp_cpuid_1_eax) > 0x19) + return true; + + if (!need_sha_check(cur_rev)) + return true; + + if (!sha_check) + return true; + + pd = bsearch(&patch_id, phashes, ARRAY_SIZE(phashes), sizeof(struct patch_digest), cmp_id); + if (!pd) { + pr_err("No sha256 digest for patch ID: 0x%x found\n", patch_id); + return false; + } + + sha256_init(&s); + sha256_update(&s, data, len); + sha256_final(&s, digest); + + if (memcmp(digest, pd->sha256, sizeof(digest))) { + pr_err("Patch 0x%x SHA256 digest mismatch!\n", patch_id); + + for (i = 0; i < SHA256_DIGEST_SIZE; i++) + pr_cont("0x%x ", digest[i]); + pr_info("\n"); + + return false; + } + + return true; +} + static u32 get_patch_level(void) { u32 rev, dummy __always_unused; @@ -497,6 +593,9 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev, { unsigned long p_addr = (unsigned long)&mc->hdr.data_code; + if (!verify_sha256_digest(mc->hdr.patch_id, *cur_rev, (const u8 *)p_addr, psize)) + return -1; + native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr); if (x86_family(bsp_cpuid_1_eax) == 0x17) { @@ -571,8 +670,17 @@ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_ struct cont_desc desc = { }; struct microcode_amd *mc; struct cpio_data cp = { }; + char buf[4]; u32 rev; + if (cmdline_find_option(boot_command_line, "microcode.amd_sha_check", buf, 4)) { + if (!strncmp(buf, "off", 3)) { + sha_check = false; + pr_warn_once("It is a very very bad idea to disable the blobs SHA check!\n"); + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + } + } + bsp_cpuid_1_eax = cpuid_1_eax; rev = get_patch_level(); @@ -902,8 +1010,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, } /* Scan the blob in @data and add microcode patches to the cache. */ -static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, - size_t size) +static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, size_t size) { u8 *fw = (u8 *)data; size_t offset; diff --git a/arch/x86/kernel/cpu/microcode/amd_shas.c b/arch/x86/kernel/cpu/microcode/amd_shas.c new file mode 100644 index 000000000000..2a1655b1fdd8 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/amd_shas.c @@ -0,0 +1,444 @@ +/* Keep 'em sorted. */ +static const struct patch_digest phashes[] = { + { 0x8001227, { + 0x99,0xc0,0x9b,0x2b,0xcc,0x9f,0x52,0x1b, + 0x1a,0x5f,0x1d,0x83,0xa1,0x6c,0xc4,0x46, + 0xe2,0x6c,0xda,0x73,0xfb,0x2d,0x23,0xa8, + 0x77,0xdc,0x15,0x31,0x33,0x4a,0x46,0x18, + } + }, + { 0x8001250, { + 0xc0,0x0b,0x6b,0x19,0xfd,0x5c,0x39,0x60, + 0xd5,0xc3,0x57,0x46,0x54,0xe4,0xd1,0xaa, + 0xa8,0xf7,0x1f,0xa8,0x6a,0x60,0x3e,0xe3, + 0x27,0x39,0x8e,0x53,0x30,0xf8,0x49,0x19, + } + }, + { 0x800126e, { + 0xf3,0x8b,0x2b,0xb6,0x34,0xe3,0xc8,0x2c, + 0xef,0xec,0x63,0x6d,0xc8,0x76,0x77,0xb3, + 0x25,0x5a,0xb7,0x52,0x8c,0x83,0x26,0xe6, + 0x4c,0xbe,0xbf,0xe9,0x7d,0x22,0x6a,0x43, + } + }, + { 0x800126f, { + 0x2b,0x5a,0xf2,0x9c,0xdd,0xd2,0x7f,0xec, + 0xec,0x96,0x09,0x57,0xb0,0x96,0x29,0x8b, + 0x2e,0x26,0x91,0xf0,0x49,0x33,0x42,0x18, + 0xdd,0x4b,0x65,0x5a,0xd4,0x15,0x3d,0x33, + } + }, + { 0x800820d, { + 0x68,0x98,0x83,0xcd,0x22,0x0d,0xdd,0x59, + 0x73,0x2c,0x5b,0x37,0x1f,0x84,0x0e,0x67, + 0x96,0x43,0x83,0x0c,0x46,0x44,0xab,0x7c, + 0x7b,0x65,0x9e,0x57,0xb5,0x90,0x4b,0x0e, + } + }, + { 0x8301025, { + 0xe4,0x7d,0xdb,0x1e,0x14,0xb4,0x5e,0x36, + 0x8f,0x3e,0x48,0x88,0x3c,0x6d,0x76,0xa1, + 0x59,0xc6,0xc0,0x72,0x42,0xdf,0x6c,0x30, + 0x6f,0x0b,0x28,0x16,0x61,0xfc,0x79,0x77, + } + }, + { 0x8301055, { + 0x81,0x7b,0x99,0x1b,0xae,0x2d,0x4f,0x9a, + 0xef,0x13,0xce,0xb5,0x10,0xaf,0x6a,0xea, + 0xe5,0xb0,0x64,0x98,0x10,0x68,0x34,0x3b, + 0x9d,0x7a,0xd6,0x22,0x77,0x5f,0xb3,0x5b, + } + }, + { 0x8301072, { + 0xcf,0x76,0xa7,0x1a,0x49,0xdf,0x2a,0x5e, + 0x9e,0x40,0x70,0xe5,0xdd,0x8a,0xa8,0x28, + 0x20,0xdc,0x91,0xd8,0x2c,0xa6,0xa0,0xb1, + 0x2d,0x22,0x26,0x94,0x4b,0x40,0x85,0x30, + } + }, + { 0x830107a, { + 0x2a,0x65,0x8c,0x1a,0x5e,0x07,0x21,0x72, + 0xdf,0x90,0xa6,0x51,0x37,0xd3,0x4b,0x34, + 0xc4,0xda,0x03,0xe1,0x8a,0x6c,0xfb,0x20, + 0x04,0xb2,0x81,0x05,0xd4,0x87,0xf4,0x0a, + } + }, + { 0x830107b, { + 0xb3,0x43,0x13,0x63,0x56,0xc1,0x39,0xad, + 0x10,0xa6,0x2b,0xcc,0x02,0xe6,0x76,0x2a, + 0x1e,0x39,0x58,0x3e,0x23,0x6e,0xa4,0x04, + 0x95,0xea,0xf9,0x6d,0xc2,0x8a,0x13,0x19, + } + }, + { 0x830107c, { + 0x21,0x64,0xde,0xfb,0x9f,0x68,0x96,0x47, + 0x70,0x5c,0xe2,0x8f,0x18,0x52,0x6a,0xac, + 0xa4,0xd2,0x2e,0xe0,0xde,0x68,0x66,0xc3, + 0xeb,0x1e,0xd3,0x3f,0xbc,0x51,0x1d,0x38, + } + }, + { 0x860010d, { + 0x86,0xb6,0x15,0x83,0xbc,0x3b,0x9c,0xe0, + 0xb3,0xef,0x1d,0x99,0x84,0x35,0x15,0xf7, + 0x7c,0x2a,0xc6,0x42,0xdb,0x73,0x07,0x5c, + 0x7d,0xc3,0x02,0xb5,0x43,0x06,0x5e,0xf8, + } + }, + { 0x8608108, { + 0x14,0xfe,0x57,0x86,0x49,0xc8,0x68,0xe2, + 0x11,0xa3,0xcb,0x6e,0xff,0x6e,0xd5,0x38, + 0xfe,0x89,0x1a,0xe0,0x67,0xbf,0xc4,0xcc, + 0x1b,0x9f,0x84,0x77,0x2b,0x9f,0xaa,0xbd, + } + }, + { 0x8701034, { + 0xc3,0x14,0x09,0xa8,0x9c,0x3f,0x8d,0x83, + 0x9b,0x4c,0xa5,0xb7,0x64,0x8b,0x91,0x5d, + 0x85,0x6a,0x39,0x26,0x1e,0x14,0x41,0xa8, + 0x75,0xea,0xa6,0xf9,0xc9,0xd1,0xea,0x2b, + } + }, + { 0x8a00008, { + 0xd7,0x2a,0x93,0xdc,0x05,0x2f,0xa5,0x6e, + 0x0c,0x61,0x2c,0x07,0x9f,0x38,0xe9,0x8e, + 0xef,0x7d,0x2a,0x05,0x4d,0x56,0xaf,0x72, + 0xe7,0x56,0x47,0x6e,0x60,0x27,0xd5,0x8c, + } + }, + { 0x8a0000a, { + 0x73,0x31,0x26,0x22,0xd4,0xf9,0xee,0x3c, + 0x07,0x06,0xe7,0xb9,0xad,0xd8,0x72,0x44, + 0x33,0x31,0xaa,0x7d,0xc3,0x67,0x0e,0xdb, + 0x47,0xb5,0xaa,0xbc,0xf5,0xbb,0xd9,0x20, + } + }, + { 0xa00104c, { + 0x3c,0x8a,0xfe,0x04,0x62,0xd8,0x6d,0xbe, + 0xa7,0x14,0x28,0x64,0x75,0xc0,0xa3,0x76, + 0xb7,0x92,0x0b,0x97,0x0a,0x8e,0x9c,0x5b, + 0x1b,0xc8,0x9d,0x3a,0x1e,0x81,0x3d,0x3b, + } + }, + { 0xa00104e, { + 0xc4,0x35,0x82,0x67,0xd2,0x86,0xe5,0xb2, + 0xfd,0x69,0x12,0x38,0xc8,0x77,0xba,0xe0, + 0x70,0xf9,0x77,0x89,0x10,0xa6,0x74,0x4e, + 0x56,0x58,0x13,0xf5,0x84,0x70,0x28,0x0b, + } + }, + { 0xa001053, { + 0x92,0x0e,0xf4,0x69,0x10,0x3b,0xf9,0x9d, + 0x31,0x1b,0xa6,0x99,0x08,0x7d,0xd7,0x25, + 0x7e,0x1e,0x89,0xba,0x35,0x8d,0xac,0xcb, + 0x3a,0xb4,0xdf,0x58,0x12,0xcf,0xc0,0xc3, + } + }, + { 0xa001058, { + 0x33,0x7d,0xa9,0xb5,0x4e,0x62,0x13,0x36, + 0xef,0x66,0xc9,0xbd,0x0a,0xa6,0x3b,0x19, + 0xcb,0xf5,0xc2,0xc3,0x55,0x47,0x20,0xec, + 0x1f,0x7b,0xa1,0x44,0x0e,0x8e,0xa4,0xb2, + } + }, + { 0xa001075, { + 0x39,0x02,0x82,0xd0,0x7c,0x26,0x43,0xe9, + 0x26,0xa3,0xd9,0x96,0xf7,0x30,0x13,0x0a, + 0x8a,0x0e,0xac,0xe7,0x1d,0xdc,0xe2,0x0f, + 0xcb,0x9e,0x8d,0xbc,0xd2,0xa2,0x44,0xe0, + } + }, + { 0xa001078, { + 0x2d,0x67,0xc7,0x35,0xca,0xef,0x2f,0x25, + 0x4c,0x45,0x93,0x3f,0x36,0x01,0x8c,0xce, + 0xa8,0x5b,0x07,0xd3,0xc1,0x35,0x3c,0x04, + 0x20,0xa2,0xfc,0xdc,0xe6,0xce,0x26,0x3e, + } + }, + { 0xa001079, { + 0x43,0xe2,0x05,0x9c,0xfd,0xb7,0x5b,0xeb, + 0x5b,0xe9,0xeb,0x3b,0x96,0xf4,0xe4,0x93, + 0x73,0x45,0x3e,0xac,0x8d,0x3b,0xe4,0xdb, + 0x10,0x31,0xc1,0xe4,0xa2,0xd0,0x5a,0x8a, + } + }, + { 0xa00107a, { + 0x5f,0x92,0xca,0xff,0xc3,0x59,0x22,0x5f, + 0x02,0xa0,0x91,0x3b,0x4a,0x45,0x10,0xfd, + 0x19,0xe1,0x8a,0x6d,0x9a,0x92,0xc1,0x3f, + 0x75,0x78,0xac,0x78,0x03,0x1d,0xdb,0x18, + } + }, + { 0xa001143, { + 0x56,0xca,0xf7,0x43,0x8a,0x4c,0x46,0x80, + 0xec,0xde,0xe5,0x9c,0x50,0x84,0x9a,0x42, + 0x27,0xe5,0x51,0x84,0x8f,0x19,0xc0,0x8d, + 0x0c,0x25,0xb4,0xb0,0x8f,0x10,0xf3,0xf8, + } + }, + { 0xa001144, { + 0x42,0xd5,0x9b,0xa7,0xd6,0x15,0x29,0x41, + 0x61,0xc4,0x72,0x3f,0xf3,0x06,0x78,0x4b, + 0x65,0xf3,0x0e,0xfa,0x9c,0x87,0xde,0x25, + 0xbd,0xb3,0x9a,0xf4,0x75,0x13,0x53,0xdc, + } + }, + { 0xa00115d, { + 0xd4,0xc4,0x49,0x36,0x89,0x0b,0x47,0xdd, + 0xfb,0x2f,0x88,0x3b,0x5f,0xf2,0x8e,0x75, + 0xc6,0x6c,0x37,0x5a,0x90,0x25,0x94,0x3e, + 0x36,0x9c,0xae,0x02,0x38,0x6c,0xf5,0x05, + } + }, + { 0xa001173, { + 0x28,0xbb,0x9b,0xd1,0xa0,0xa0,0x7e,0x3a, + 0x59,0x20,0xc0,0xa9,0xb2,0x5c,0xc3,0x35, + 0x53,0x89,0xe1,0x4c,0x93,0x2f,0x1d,0xc3, + 0xe5,0xf7,0xf3,0xc8,0x9b,0x61,0xaa,0x9e, + } + }, + { 0xa0011a8, { + 0x97,0xc6,0x16,0x65,0x99,0xa4,0x85,0x3b, + 0xf6,0xce,0xaa,0x49,0x4a,0x3a,0xc5,0xb6, + 0x78,0x25,0xbc,0x53,0xaf,0x5d,0xcf,0xf4, + 0x23,0x12,0xbb,0xb1,0xbc,0x8a,0x02,0x2e, + } + }, + { 0xa0011ce, { + 0xcf,0x1c,0x90,0xa3,0x85,0x0a,0xbf,0x71, + 0x94,0x0e,0x80,0x86,0x85,0x4f,0xd7,0x86, + 0xae,0x38,0x23,0x28,0x2b,0x35,0x9b,0x4e, + 0xfe,0xb8,0xcd,0x3d,0x3d,0x39,0xc9,0x6a, + } + }, + { 0xa0011d1, { + 0xdf,0x0e,0xca,0xde,0xf6,0xce,0x5c,0x1e, + 0x4c,0xec,0xd7,0x71,0x83,0xcc,0xa8,0x09, + 0xc7,0xc5,0xfe,0xb2,0xf7,0x05,0xd2,0xc5, + 0x12,0xdd,0xe4,0xf3,0x92,0x1c,0x3d,0xb8, + } + }, + { 0xa0011d3, { + 0x91,0xe6,0x10,0xd7,0x57,0xb0,0x95,0x0b, + 0x9a,0x24,0xee,0xf7,0xcf,0x56,0xc1,0xa6, + 0x4a,0x52,0x7d,0x5f,0x9f,0xdf,0xf6,0x00, + 0x65,0xf7,0xea,0xe8,0x2a,0x88,0xe2,0x26, + } + }, + { 0xa0011d5, { + 0xed,0x69,0x89,0xf4,0xeb,0x64,0xc2,0x13, + 0xe0,0x51,0x1f,0x03,0x26,0x52,0x7d,0xb7, + 0x93,0x5d,0x65,0xca,0xb8,0x12,0x1d,0x62, + 0x0d,0x5b,0x65,0x34,0x69,0xb2,0x62,0x21, + } + }, + { 0xa001223, { + 0xfb,0x32,0x5f,0xc6,0x83,0x4f,0x8c,0xb8, + 0xa4,0x05,0xf9,0x71,0x53,0x01,0x16,0xc4, + 0x83,0x75,0x94,0xdd,0xeb,0x7e,0xb7,0x15, + 0x8e,0x3b,0x50,0x29,0x8a,0x9c,0xcc,0x45, + } + }, + { 0xa001224, { + 0x0e,0x0c,0xdf,0xb4,0x89,0xee,0x35,0x25, + 0xdd,0x9e,0xdb,0xc0,0x69,0x83,0x0a,0xad, + 0x26,0xa9,0xaa,0x9d,0xfc,0x3c,0xea,0xf9, + 0x6c,0xdc,0xd5,0x6d,0x8b,0x6e,0x85,0x4a, + } + }, + { 0xa001227, { + 0xab,0xc6,0x00,0x69,0x4b,0x50,0x87,0xad, + 0x5f,0x0e,0x8b,0xea,0x57,0x38,0xce,0x1d, + 0x0f,0x75,0x26,0x02,0xf6,0xd6,0x96,0xe9, + 0x87,0xb9,0xd6,0x20,0x27,0x7c,0xd2,0xe0, + } + }, + { 0xa001229, { + 0x7f,0x49,0x49,0x48,0x46,0xa5,0x50,0xa6, + 0x28,0x89,0x98,0xe2,0x9e,0xb4,0x7f,0x75, + 0x33,0xa7,0x04,0x02,0xe4,0x82,0xbf,0xb4, + 0xa5,0x3a,0xba,0x24,0x8d,0x31,0x10,0x1d, + } + }, + { 0xa00122e, { + 0x56,0x94,0xa9,0x5d,0x06,0x68,0xfe,0xaf, + 0xdf,0x7a,0xff,0x2d,0xdf,0x74,0x0f,0x15, + 0x66,0xfb,0x00,0xb5,0x51,0x97,0x9b,0xfa, + 0xcb,0x79,0x85,0x46,0x25,0xb4,0xd2,0x10, + } + }, + { 0xa001231, { + 0x0b,0x46,0xa5,0xfc,0x18,0x15,0xa0,0x9e, + 0xa6,0xdc,0xb7,0xff,0x17,0xf7,0x30,0x64, + 0xd4,0xda,0x9e,0x1b,0xc3,0xfc,0x02,0x3b, + 0xe2,0xc6,0x0e,0x41,0x54,0xb5,0x18,0xdd, + } + }, + { 0xa001234, { + 0x88,0x8d,0xed,0xab,0xb5,0xbd,0x4e,0xf7, + 0x7f,0xd4,0x0e,0x95,0x34,0x91,0xff,0xcc, + 0xfb,0x2a,0xcd,0xf7,0xd5,0xdb,0x4c,0x9b, + 0xd6,0x2e,0x73,0x50,0x8f,0x83,0x79,0x1a, + } + }, + { 0xa001236, { + 0x3d,0x30,0x00,0xb9,0x71,0xba,0x87,0x78, + 0xa8,0x43,0x55,0xc4,0x26,0x59,0xcf,0x9d, + 0x93,0xce,0x64,0x0e,0x8b,0x72,0x11,0x8b, + 0xa3,0x8f,0x51,0xe9,0xca,0x98,0xaa,0x25, + } + }, + { 0xa001238, { + 0x72,0xf7,0x4b,0x0c,0x7d,0x58,0x65,0xcc, + 0x00,0xcc,0x57,0x16,0x68,0x16,0xf8,0x2a, + 0x1b,0xb3,0x8b,0xe1,0xb6,0x83,0x8c,0x7e, + 0xc0,0xcd,0x33,0xf2,0x8d,0xf9,0xef,0x59, + } + }, + { 0xa00820c, { + 0xa8,0x0c,0x81,0xc0,0xa6,0x00,0xe7,0xf3, + 0x5f,0x65,0xd3,0xb9,0x6f,0xea,0x93,0x63, + 0xf1,0x8c,0x88,0x45,0xd7,0x82,0x80,0xd1, + 0xe1,0x3b,0x8d,0xb2,0xf8,0x22,0x03,0xe2, + } + }, + { 0xa10113e, { + 0x05,0x3c,0x66,0xd7,0xa9,0x5a,0x33,0x10, + 0x1b,0xf8,0x9c,0x8f,0xed,0xfc,0xa7,0xa0, + 0x15,0xe3,0x3f,0x4b,0x1d,0x0d,0x0a,0xd5, + 0xfa,0x90,0xc4,0xed,0x9d,0x90,0xaf,0x53, + } + }, + { 0xa101144, { + 0xb3,0x0b,0x26,0x9a,0xf8,0x7c,0x02,0x26, + 0x35,0x84,0x53,0xa4,0xd3,0x2c,0x7c,0x09, + 0x68,0x7b,0x96,0xb6,0x93,0xef,0xde,0xbc, + 0xfd,0x4b,0x15,0xd2,0x81,0xd3,0x51,0x47, + } + }, + { 0xa101148, { + 0x20,0xd5,0x6f,0x40,0x4a,0xf6,0x48,0x90, + 0xc2,0x93,0x9a,0xc2,0xfd,0xac,0xef,0x4f, + 0xfa,0xc0,0x3d,0x92,0x3c,0x6d,0x01,0x08, + 0xf1,0x5e,0xb0,0xde,0xb4,0x98,0xae,0xc4, + } + }, + { 0xa10123e, { + 0x03,0xb9,0x2c,0x76,0x48,0x93,0xc9,0x18, + 0xfb,0x56,0xfd,0xf7,0xe2,0x1d,0xca,0x4d, + 0x1d,0x13,0x53,0x63,0xfe,0x42,0x6f,0xfc, + 0x19,0x0f,0xf1,0xfc,0xa7,0xdd,0x89,0x1b, + } + }, + { 0xa101244, { + 0x71,0x56,0xb5,0x9f,0x21,0xbf,0xb3,0x3c, + 0x8c,0xd7,0x36,0xd0,0x34,0x52,0x1b,0xb1, + 0x46,0x2f,0x04,0xf0,0x37,0xd8,0x1e,0x72, + 0x24,0xa2,0x80,0x84,0x83,0x65,0x84,0xc0, + } + }, + { 0xa101248, { + 0xed,0x3b,0x95,0xa6,0x68,0xa7,0x77,0x3e, + 0xfc,0x17,0x26,0xe2,0x7b,0xd5,0x56,0x22, + 0x2c,0x1d,0xef,0xeb,0x56,0xdd,0xba,0x6e, + 0x1b,0x7d,0x64,0x9d,0x4b,0x53,0x13,0x75, + } + }, + { 0xa108108, { + 0xed,0xc2,0xec,0xa1,0x15,0xc6,0x65,0xe9, + 0xd0,0xef,0x39,0xaa,0x7f,0x55,0x06,0xc6, + 0xf5,0xd4,0x3f,0x7b,0x14,0xd5,0x60,0x2c, + 0x28,0x1e,0x9c,0x59,0x69,0x99,0x4d,0x16, + } + }, + { 0xa20102d, { + 0xf9,0x6e,0xf2,0x32,0xd3,0x0f,0x5f,0x11, + 0x59,0xa1,0xfe,0xcc,0xcd,0x9b,0x42,0x89, + 0x8b,0x89,0x2f,0xb5,0xbb,0x82,0xef,0x23, + 0x8c,0xe9,0x19,0x3e,0xcc,0x3f,0x7b,0xb4, + } + }, + { 0xa201210, { + 0xe8,0x6d,0x51,0x6a,0x8e,0x72,0xf3,0xfe, + 0x6e,0x16,0xbc,0x62,0x59,0x40,0x17,0xe9, + 0x6d,0x3d,0x0e,0x6b,0xa7,0xac,0xe3,0x68, + 0xf7,0x55,0xf0,0x13,0xbb,0x22,0xf6,0x41, + } + }, + { 0xa404107, { + 0xbb,0x04,0x4e,0x47,0xdd,0x5e,0x26,0x45, + 0x1a,0xc9,0x56,0x24,0xa4,0x4c,0x82,0xb0, + 0x8b,0x0d,0x9f,0xf9,0x3a,0xdf,0xc6,0x81, + 0x13,0xbc,0xc5,0x25,0xe4,0xc5,0xc3,0x99, + } + }, + { 0xa500011, { + 0x23,0x3d,0x70,0x7d,0x03,0xc3,0xc4,0xf4, + 0x2b,0x82,0xc6,0x05,0xda,0x80,0x0a,0xf1, + 0xd7,0x5b,0x65,0x3a,0x7d,0xab,0xdf,0xa2, + 0x11,0x5e,0x96,0x7e,0x71,0xe9,0xfc,0x74, + } + }, + { 0xa601209, { + 0x66,0x48,0xd4,0x09,0x05,0xcb,0x29,0x32, + 0x66,0xb7,0x9a,0x76,0xcd,0x11,0xf3,0x30, + 0x15,0x86,0xcc,0x5d,0x97,0x0f,0xc0,0x46, + 0xe8,0x73,0xe2,0xd6,0xdb,0xd2,0x77,0x1d, + } + }, + { 0xa704107, { + 0xf3,0xc6,0x58,0x26,0xee,0xac,0x3f,0xd6, + 0xce,0xa1,0x72,0x47,0x3b,0xba,0x2b,0x93, + 0x2a,0xad,0x8e,0x6b,0xea,0x9b,0xb7,0xc2, + 0x64,0x39,0x71,0x8c,0xce,0xe7,0x41,0x39, + } + }, + { 0xa705206, { + 0x8d,0xc0,0x76,0xbd,0x58,0x9f,0x8f,0xa4, + 0x12,0x9d,0x21,0xfb,0x48,0x21,0xbc,0xe7, + 0x67,0x6f,0x04,0x18,0xae,0x20,0x87,0x4b, + 0x03,0x35,0xe9,0xbe,0xfb,0x06,0xdf,0xfc, + } + }, + { 0xa708007, { + 0x6b,0x76,0xcc,0x78,0xc5,0x8a,0xa3,0xe3, + 0x32,0x2d,0x79,0xe4,0xc3,0x80,0xdb,0xb2, + 0x07,0xaa,0x3a,0xe0,0x57,0x13,0x72,0x80, + 0xdf,0x92,0x73,0x84,0x87,0x3c,0x73,0x93, + } + }, + { 0xa70c005, { + 0x88,0x5d,0xfb,0x79,0x64,0xd8,0x46,0x3b, + 0x4a,0x83,0x8e,0x77,0x7e,0xcf,0xb3,0x0f, + 0x1f,0x1f,0xf1,0x97,0xeb,0xfe,0x56,0x55, + 0xee,0x49,0xac,0xe1,0x8b,0x13,0xc5,0x13, + } + }, + { 0xaa00116, { + 0xe8,0x4c,0x2c,0x88,0xa1,0xac,0x24,0x63, + 0x65,0xe5,0xaa,0x2d,0x16,0xa9,0xc3,0xf5, + 0xfe,0x1d,0x5e,0x65,0xc7,0xaa,0x92,0x4d, + 0x91,0xee,0x76,0xbb,0x4c,0x66,0x78,0xc9, + } + }, + { 0xaa00212, { + 0xbd,0x57,0x5d,0x0a,0x0a,0x30,0xc1,0x75, + 0x95,0x58,0x5e,0x93,0x02,0x28,0x43,0x71, + 0xed,0x42,0x29,0xc8,0xec,0x34,0x2b,0xb2, + 0x1a,0x65,0x4b,0xfe,0x07,0x0f,0x34,0xa1, + } + }, + { 0xaa00213, { + 0xed,0x58,0xb7,0x76,0x81,0x7f,0xd9,0x3a, + 0x1a,0xff,0x8b,0x34,0xb8,0x4a,0x99,0x0f, + 0x28,0x49,0x6c,0x56,0x2b,0xdc,0xb7,0xed, + 0x96,0xd5,0x9d,0xc1,0x7a,0xd4,0x51,0x9b, + } + }, + { 0xaa00215, { + 0x55,0xd3,0x28,0xcb,0x87,0xa9,0x32,0xe9, + 0x4e,0x85,0x4b,0x7c,0x6b,0xd5,0x7c,0xd4, + 0x1b,0x51,0x71,0x3a,0x0e,0x0b,0xdc,0x9b, + 0x68,0x2f,0x46,0xee,0xfe,0xc6,0x6d,0xef, + } + }, +}; From 18311a766c587fc69b1806f1d5943305903b7e6e Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Wed, 12 Feb 2025 11:55:02 +0530 Subject: [PATCH 0214/1090] err.h: move IOMEM_ERR_PTR() to err.h Since IOMEM_ERR_PTR() macro deals with an error pointer, a better place for it is err.h. This helps avoid dependency on io.h for the users that don't need it. Suggested-by: Andy Shevchenko Signed-off-by: Raag Jadav Acked-by: Arnd Bergmann Signed-off-by: Andy Shevchenko --- include/linux/err.h | 3 +++ include/linux/io.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/err.h b/include/linux/err.h index a4dacd745fcf..1d60aa86db53 100644 --- a/include/linux/err.h +++ b/include/linux/err.h @@ -44,6 +44,9 @@ static inline void * __must_check ERR_PTR(long error) /* Return the pointer in the percpu address space. */ #define ERR_PTR_PCPU(error) ((void __percpu *)(unsigned long)ERR_PTR(error)) +/* Cast an error pointer to __iomem. */ +#define IOMEM_ERR_PTR(error) (__force void __iomem *)ERR_PTR(error) + /** * PTR_ERR - Extract the error code from an error pointer. * @ptr: An error pointer. diff --git a/include/linux/io.h b/include/linux/io.h index 59ec5eea696c..40cb2de73f5e 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -65,8 +65,6 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr) } #endif -#define IOMEM_ERR_PTR(err) (__force void __iomem *)ERR_PTR(err) - void __iomem *devm_ioremap(struct device *dev, resource_size_t offset, resource_size_t size); void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset, From a21cad9312767d26b5257ce0662699bb202cdda1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Feb 2025 11:55:03 +0530 Subject: [PATCH 0215/1090] driver core: Split devres APIs to device/devres.h device.h is a huge header which is hard to follow and easy to miss something. Improve that by splitting devres APIs to device/devres.h. In particular this helps to speedup the build of the code that includes device.h solely for a devres APIs. While at it, cast the error pointers to __iomem using IOMEM_ERR_PTR() and fix sparse warnings. Signed-off-by: Raag Jadav Acked-by: Arnd Bergmann Reviewed-by: Greg Kroah-Hartman Signed-off-by: Andy Shevchenko --- include/linux/device.h | 119 +------------------------------- include/linux/device/devres.h | 124 ++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 118 deletions(-) create mode 100644 include/linux/device/devres.h diff --git a/include/linux/device.h b/include/linux/device.h index 80a5b3268986..78ca7fd0e625 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -26,9 +26,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -281,123 +281,6 @@ int __must_check device_create_bin_file(struct device *dev, void device_remove_bin_file(struct device *dev, const struct bin_attribute *attr); -/* device resource management */ -typedef void (*dr_release_t)(struct device *dev, void *res); -typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); - -void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, - int nid, const char *name) __malloc; -#define devres_alloc(release, size, gfp) \ - __devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release) -#define devres_alloc_node(release, size, gfp, nid) \ - __devres_alloc_node(release, size, gfp, nid, #release) - -void devres_for_each_res(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data, - void (*fn)(struct device *, void *, void *), - void *data); -void devres_free(void *res); -void devres_add(struct device *dev, void *res); -void *devres_find(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -void *devres_get(struct device *dev, void *new_res, - dr_match_t match, void *match_data); -void *devres_remove(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -int devres_destroy(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); -int devres_release(struct device *dev, dr_release_t release, - dr_match_t match, void *match_data); - -/* devres group */ -void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp); -void devres_close_group(struct device *dev, void *id); -void devres_remove_group(struct device *dev, void *id); -int devres_release_group(struct device *dev, void *id); - -/* managed devm_k.alloc/kfree for device drivers */ -void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __alloc_size(2); -void *devm_krealloc(struct device *dev, void *ptr, size_t size, - gfp_t gfp) __must_check __realloc_size(3); -__printf(3, 0) char *devm_kvasprintf(struct device *dev, gfp_t gfp, - const char *fmt, va_list ap) __malloc; -__printf(3, 4) char *devm_kasprintf(struct device *dev, gfp_t gfp, - const char *fmt, ...) __malloc; -static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) -{ - return devm_kmalloc(dev, size, gfp | __GFP_ZERO); -} -static inline void *devm_kmalloc_array(struct device *dev, - size_t n, size_t size, gfp_t flags) -{ - size_t bytes; - - if (unlikely(check_mul_overflow(n, size, &bytes))) - return NULL; - - return devm_kmalloc(dev, bytes, flags); -} -static inline void *devm_kcalloc(struct device *dev, - size_t n, size_t size, gfp_t flags) -{ - return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO); -} -static inline __realloc_size(3, 4) void * __must_check -devm_krealloc_array(struct device *dev, void *p, size_t new_n, size_t new_size, gfp_t flags) -{ - size_t bytes; - - if (unlikely(check_mul_overflow(new_n, new_size, &bytes))) - return NULL; - - return devm_krealloc(dev, p, bytes, flags); -} - -void devm_kfree(struct device *dev, const void *p); -char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; -const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp); -void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp) - __realloc_size(3); - -unsigned long devm_get_free_pages(struct device *dev, - gfp_t gfp_mask, unsigned int order); -void devm_free_pages(struct device *dev, unsigned long addr); - -#ifdef CONFIG_HAS_IOMEM -void __iomem *devm_ioremap_resource(struct device *dev, - const struct resource *res); -void __iomem *devm_ioremap_resource_wc(struct device *dev, - const struct resource *res); - -void __iomem *devm_of_iomap(struct device *dev, - struct device_node *node, int index, - resource_size_t *size); -#else - -static inline -void __iomem *devm_ioremap_resource(struct device *dev, - const struct resource *res) -{ - return ERR_PTR(-EINVAL); -} - -static inline -void __iomem *devm_ioremap_resource_wc(struct device *dev, - const struct resource *res) -{ - return ERR_PTR(-EINVAL); -} - -static inline -void __iomem *devm_of_iomap(struct device *dev, - struct device_node *node, int index, - resource_size_t *size) -{ - return ERR_PTR(-EINVAL); -} - -#endif - /* allows to add/remove a custom action to devres stack */ int devm_remove_action_nowarn(struct device *dev, void (*action)(void *), void *data); diff --git a/include/linux/device/devres.h b/include/linux/device/devres.h new file mode 100644 index 000000000000..6b0b265058bc --- /dev/null +++ b/include/linux/device/devres.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _DEVICE_DEVRES_H_ +#define _DEVICE_DEVRES_H_ + +#include +#include +#include +#include +#include +#include + +struct device; +struct device_node; +struct resource; + +/* device resource management */ +typedef void (*dr_release_t)(struct device *dev, void *res); +typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data); + +void * __malloc +__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, const char *name); +#define devres_alloc(release, size, gfp) \ + __devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release) +#define devres_alloc_node(release, size, gfp, nid) \ + __devres_alloc_node(release, size, gfp, nid, #release) + +void devres_for_each_res(struct device *dev, dr_release_t release, + dr_match_t match, void *match_data, + void (*fn)(struct device *, void *, void *), + void *data); +void devres_free(void *res); +void devres_add(struct device *dev, void *res); +void *devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); +void *devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data); +void *devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); +int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); +int devres_release(struct device *dev, dr_release_t release, dr_match_t match, void *match_data); + +/* devres group */ +void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp); +void devres_close_group(struct device *dev, void *id); +void devres_remove_group(struct device *dev, void *id); +int devres_release_group(struct device *dev, void *id); + +/* managed devm_k.alloc/kfree for device drivers */ +void * __alloc_size(2) +devm_kmalloc(struct device *dev, size_t size, gfp_t gfp); +void * __must_check __realloc_size(3) +devm_krealloc(struct device *dev, void *ptr, size_t size, gfp_t gfp); +static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) +{ + return devm_kmalloc(dev, size, gfp | __GFP_ZERO); +} +static inline void *devm_kmalloc_array(struct device *dev, size_t n, size_t size, gfp_t flags) +{ + size_t bytes; + + if (unlikely(check_mul_overflow(n, size, &bytes))) + return NULL; + + return devm_kmalloc(dev, bytes, flags); +} +static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags) +{ + return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO); +} +static inline __realloc_size(3, 4) void * __must_check +devm_krealloc_array(struct device *dev, void *p, size_t new_n, size_t new_size, gfp_t flags) +{ + size_t bytes; + + if (unlikely(check_mul_overflow(new_n, new_size, &bytes))) + return NULL; + + return devm_krealloc(dev, p, bytes, flags); +} + +void devm_kfree(struct device *dev, const void *p); + +void * __realloc_size(3) +devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp); + +char * __malloc +devm_kstrdup(struct device *dev, const char *s, gfp_t gfp); +const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp); +char * __printf(3, 0) __malloc +devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, va_list ap); +char * __printf(3, 4) __malloc +devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...); + +unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order); +void devm_free_pages(struct device *dev, unsigned long addr); + +#ifdef CONFIG_HAS_IOMEM + +void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res); +void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res); + +void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index, + resource_size_t *size); +#else + +static inline +void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res) +{ + return IOMEM_ERR_PTR(-EINVAL); +} + +static inline +void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res) +{ + return IOMEM_ERR_PTR(-EINVAL); +} + +static inline +void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index, + resource_size_t *size) +{ + return IOMEM_ERR_PTR(-EINVAL); +} + +#endif + +#endif /* _DEVICE_DEVRES_H_ */ From 99e297cdd338b8a18c986ed4e088676579b7fe96 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Feb 2025 11:55:04 +0530 Subject: [PATCH 0216/1090] iio: imu: st_lsm9ds0: Replace device.h with what is needed Instead of including a huge device.h with tons of dependencies include only what driver actually uses. Acked-by: Jonathan Cameron Signed-off-by: Andy Shevchenko --- drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c | 2 +- drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c index 0732cfa258c4..8cc071463249 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c @@ -7,7 +7,7 @@ * Author: Andy Shevchenko */ -#include +#include #include #include #include diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c index 43ec57c1e604..806e55f75f65 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c @@ -7,7 +7,7 @@ * Author: Andy Shevchenko */ -#include +#include #include #include #include From a103b833ac3806b816bc993cba77d0b17cf801f1 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Wed, 12 Feb 2025 11:55:05 +0530 Subject: [PATCH 0217/1090] devres: Introduce devm_kmemdup_array() Introduce '_array' variant of devm_kmemdup() which is more robust and consistent with alloc family of helpers. Suggested-by: Andy Shevchenko Signed-off-by: Raag Jadav Reviewed-by: Dmitry Torokhov Reviewed-by: Linus Walleij Signed-off-by: Andy Shevchenko --- include/linux/device/devres.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/device/devres.h b/include/linux/device/devres.h index 6b0b265058bc..9b49f9915850 100644 --- a/include/linux/device/devres.h +++ b/include/linux/device/devres.h @@ -79,6 +79,11 @@ void devm_kfree(struct device *dev, const void *p); void * __realloc_size(3) devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp); +static inline void *devm_kmemdup_array(struct device *dev, const void *src, + size_t n, size_t size, gfp_t flags) +{ + return devm_kmemdup(dev, src, size_mul(size, n), flags); +} char * __malloc devm_kstrdup(struct device *dev, const char *s, gfp_t gfp); From 2fa56dae1a65e8124d417a31d7b02c37df013817 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 23 Feb 2025 21:27:41 +0100 Subject: [PATCH 0218/1090] ASoC: fsl: fsl_qmc_audio: Remove unnecessary bool conversions Remove unnecessary bool conversions and simplify the code. Signed-off-by: Thorsten Blum Acked-by: Herve Codina Link: https://patch.msgid.link/20250223202741.1916-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_qmc_audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index e257b8adafe0..b2979290c973 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -892,7 +892,7 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts; } qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts, - count > 1 ? true : false); + count > 1); qmc_soc_dai_driver->capture.channels_min = 0; qmc_soc_dai_driver->capture.channels_max = 0; @@ -901,7 +901,7 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts; } qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts, - count > 1 ? true : false); + count > 1); qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate); qmc_soc_dai_driver->playback.rate_min = tx_fs_rate; From 91b75129149429bb16927cda8b5642c04c59e6b0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 21 Feb 2025 12:18:12 -0600 Subject: [PATCH 0219/1090] ASoC: SOF: amd: Move depends on AMD_NODE to consumers CONFIG_SND_SOC_SOF_AMD_COMMON is a hidden option that is only selected by other options. It can't have a direct depends on AMD_NODE because select can't pick another option automatically. This was attempted to be fixed in commit b47834ee4485b ("ASoC: SOF: amd: Add depends on CPU_SUP_AMD") but this just masked the issue as it was found in another config. Instead move the `depends on AMD_NODE` out of SND_SOC_SOF_AMD_COMMON to all the consumers and drop `depends on CPU_SUP_AMD`. Fixes: b47834ee4485b ("ASoC: SOF: amd: Add depends on CPU_SUP_AMD") Fixes: f120cf33d232 ("ASoC: SOF: amd: Use AMD_NODE") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502220104.a8P6ApQN-lkp@intel.com/ Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250221181840.2639793-1-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/Kconfig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig index 6eb5b2d14843..3ea82fa72e35 100644 --- a/sound/soc/sof/amd/Kconfig +++ b/sound/soc/sof/amd/Kconfig @@ -25,7 +25,6 @@ config SND_SOC_SOF_AMD_COMMON select SND_SOC_SOF_ACP_PROBES select SND_SOC_ACPI_AMD_MATCH select SND_SOC_ACPI if ACPI - depends on AMD_NODE help This option is not user-selectable but automatically handled by 'select' statements at a higher level @@ -33,7 +32,7 @@ config SND_SOC_SOF_AMD_COMMON config SND_SOC_SOF_AMD_RENOIR tristate "SOF support for RENOIR" depends on SND_SOC_SOF_PCI - depends on CPU_SUP_AMD + depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on AMD Renoir platform @@ -41,7 +40,7 @@ config SND_SOC_SOF_AMD_RENOIR config SND_SOC_SOF_AMD_VANGOGH tristate "SOF support for VANGOGH" depends on SND_SOC_SOF_PCI - depends on CPU_SUP_AMD + depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support @@ -52,7 +51,7 @@ config SND_SOC_SOF_AMD_VANGOGH config SND_SOC_SOF_AMD_REMBRANDT tristate "SOF support for REMBRANDT" depends on SND_SOC_SOF_PCI - depends on CPU_SUP_AMD + depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on AMD Rembrandt platform @@ -85,7 +84,7 @@ config SND_SOC_SOF_AMD_SOUNDWIRE config SND_SOC_SOF_AMD_ACP63 tristate "SOF support for ACP6.3 platform" depends on SND_SOC_SOF_PCI - depends on CPU_SUP_AMD + depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON select SND_SOC_SOF_AMD_SOUNDWIRE_LINK_BASELINE help @@ -97,7 +96,7 @@ config SND_SOC_SOF_AMD_ACP63 config SND_SOC_SOF_AMD_ACP70 tristate "SOF support for ACP7.0 platform" depends on SND_SOC_SOF_PCI - depends on CPU_SUP_AMD + depends on AMD_NODE select SND_SOC_SOF_AMD_COMMON help Select this option for SOF support on From 88e09306b7e0f8a9e9f9c729ac13ccd11ed9679d Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 22 Feb 2025 23:59:25 +0100 Subject: [PATCH 0220/1090] ASoC: atmel: atmel-classd: Use str_enabled_disabled() helper Remove hard-coded strings by using the str_enabled_disabled() helper function. Signed-off-by: Thorsten Blum Reviewed-by: Andrei Simion Link: https://patch.msgid.link/20250222225925.539840-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index ba314b279919..1f8c60d2de82 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -275,7 +276,7 @@ static int atmel_classd_component_probe(struct snd_soc_component *component) dev_info(component->dev, "PWM modulation type is %s, non-overlapping is %s\n", pwm_type[pdata->pwm_type], - pdata->non_overlap_enable?"enabled":"disabled"); + str_enabled_disabled(pdata->non_overlap_enable)); return 0; } From 10efa807929084a8a1c38655942a3bf83bce587a Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Thu, 20 Feb 2025 13:01:01 +0100 Subject: [PATCH 0221/1090] ASoC: cros_ec_codec: Use str_enable_disable() helper in wov_enable_put() Remove hard-coded strings by using the str_enable_disable() helper function. Signed-off-by: Thorsten Blum Acked-by: Tzung-Bi Shih Link: https://patch.msgid.link/20250220120100.1530-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 11e7b3f6d410..571222ec520c 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -657,7 +658,7 @@ static int wov_enable_put(struct snd_kcontrol *kcontrol, (uint8_t *)&p, sizeof(p), NULL, 0); if (ret) { dev_err(priv->dev, "failed to %s wov\n", - enabled ? "enable" : "disable"); + str_enable_disable(enabled)); return ret; } From 8c6ede5cc4226fd841f252d02ab0372cb92ee75c Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 17 Feb 2025 10:17:14 +0800 Subject: [PATCH 0222/1090] ASoC: dt-bindings: imx-card: Add playback-only and capture-only property Refer to audio graph card, add playback-only and capture-only property for imx-audio-card.yaml for the case that only playback or capture is supported. Signed-off-by: Shengjiu Wang Reviewed-by: Daniel Baluta Reviewed-by: Iuliana Prodan Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250217021715.284951-2-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/imx-audio-card.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml index f7ad5ea2491e..3c75c8c78987 100644 --- a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml +++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml @@ -46,6 +46,14 @@ patternProperties: description: see tdm-slot.txt. $ref: /schemas/types.yaml#/definitions/uint32 + playback-only: + description: link is used only for playback + $ref: /schemas/types.yaml#/definitions/flag + + capture-only: + description: link is used only for capture + $ref: /schemas/types.yaml#/definitions/flag + cpu: description: Holds subnode which indicates cpu dai. type: object @@ -71,6 +79,12 @@ patternProperties: - link-name - cpu + allOf: + - not: + required: + - playback-only + - capture-only + additionalProperties: false required: From 1877c3e7937fb2b9373ba263a4900448d50917b7 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 17 Feb 2025 10:17:15 +0800 Subject: [PATCH 0223/1090] ASoC: imx-card: Add playback_only or capture_only support With the DPCM case, the backend only support capture or playback, then the linked frontend can only support capture or playback, but frontend can't automatically enable only capture or playback, it needs the input from dt-binding. Signed-off-by: Shengjiu Wang Reviewed-by: Daniel Baluta Reviewed-by: Iuliana Prodan Link: https://patch.msgid.link/20250217021715.284951-3-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-card.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index ac043ad367ac..905294682996 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -518,6 +518,7 @@ static int imx_card_parse_of(struct imx_card_data *data) struct snd_soc_dai_link *link; struct dai_link_data *link_data; struct of_phandle_args args; + bool playback_only, capture_only; int ret, num_links; u32 asrc_fmt = 0; u32 width; @@ -679,6 +680,10 @@ static int imx_card_parse_of(struct imx_card_data *data) link->ops = &imx_aif_ops; } + graph_util_parse_link_direction(np, &playback_only, &capture_only); + link->playback_only = playback_only; + link->capture_only = capture_only; + /* Get dai fmt */ ret = simple_util_parse_daifmt(dev, np, codec, NULL, &link->dai_fmt); From 758beab0252912395efb79f34095c5ae7e3e58b1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:06 +0100 Subject: [PATCH 0224/1090] ASoC: topology: Create kcontrols based on their type Fields ->ops.info and ->type of struct snd_soc_tplg_ctl_hdr denote info-operation type and control type respectively. These are two different pieces of information. The info type is represented by SND_SOC_TPLG_CTL_xxx and SND_SOC_TPLG_DAPM_CTL_xxx on UAPI side whereas for control type it is SND_SOC_TPLG_TYPE_xxx (mixer, bytes or enum). The type of the kcontrol to be created is currently guessed based on the value of the ->ops.info. Use the ->type instead to correct and simplify the code. With this change ops.info() can be customized by sound drivers utilizing the ASoC-topology just like ops.get() and ops.put() can be. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 58 +++++++++++----------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 9f4da061eff9..921521a84e29 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -220,15 +220,6 @@ static int get_widget_id(int tplg_type) return -EINVAL; } -static inline void soc_bind_err(struct soc_tplg *tplg, - struct snd_soc_tplg_ctl_hdr *hdr, int index) -{ - dev_err(tplg->dev, - "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n", - hdr->ops.get, hdr->ops.put, hdr->ops.info, index, - soc_tplg_get_offset(tplg)); -} - static inline void soc_control_err(struct soc_tplg *tplg, struct snd_soc_tplg_ctl_hdr *hdr, const char *name) { @@ -992,35 +983,26 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, return -EINVAL; } - switch (le32_to_cpu(control_hdr->ops.info)) { - case SND_SOC_TPLG_CTL_VOLSW: - case SND_SOC_TPLG_CTL_STROBE: - case SND_SOC_TPLG_CTL_VOLSW_SX: - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: - case SND_SOC_TPLG_CTL_RANGE: - case SND_SOC_TPLG_DAPM_CTL_VOLSW: - case SND_SOC_TPLG_DAPM_CTL_PIN: + switch (le32_to_cpu(control_hdr->type)) { + case SND_SOC_TPLG_TYPE_MIXER: ret = soc_tplg_dmixer_create(tplg, le32_to_cpu(hdr->payload_size)); break; - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_CTL_ENUM_VALUE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: + case SND_SOC_TPLG_TYPE_ENUM: ret = soc_tplg_denum_create(tplg, le32_to_cpu(hdr->payload_size)); break; - case SND_SOC_TPLG_CTL_BYTES: + case SND_SOC_TPLG_TYPE_BYTES: ret = soc_tplg_dbytes_create(tplg, le32_to_cpu(hdr->payload_size)); break; default: - soc_bind_err(tplg, control_hdr, i); - return -EINVAL; - } - if (ret < 0) { - dev_err(tplg->dev, "ASoC: invalid control\n"); - return ret; + ret = -EINVAL; + break; } + if (ret < 0) { + dev_err(tplg->dev, "ASoC: invalid control type: %d, index: %d at 0x%lx\n", + control_hdr->type, i, soc_tplg_get_offset(tplg)); + return ret; + } } return 0; @@ -1184,13 +1166,9 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; - switch (le32_to_cpu(control_hdr->ops.info)) { - case SND_SOC_TPLG_CTL_VOLSW: - case SND_SOC_TPLG_CTL_STROBE: - case SND_SOC_TPLG_CTL_VOLSW_SX: - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: - case SND_SOC_TPLG_CTL_RANGE: - case SND_SOC_TPLG_DAPM_CTL_VOLSW: + + switch (le32_to_cpu(control_hdr->type)) { + case SND_SOC_TPLG_TYPE_MIXER: /* volume mixer */ kc[i].index = mixer_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_MIXER; @@ -1199,11 +1177,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, if (ret < 0) goto hdr_err; break; - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_CTL_ENUM_VALUE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: + case SND_SOC_TPLG_TYPE_ENUM: /* enumerated mixer */ kc[i].index = enum_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_ENUM; @@ -1212,7 +1186,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, if (ret < 0) goto hdr_err; break; - case SND_SOC_TPLG_CTL_BYTES: + case SND_SOC_TPLG_TYPE_BYTES: /* bytes control */ kc[i].index = bytes_count; kcontrol_type[i] = SND_SOC_TPLG_TYPE_BYTES; From 81eb3a2bd273b84fa9808e6b13b533f9c55e16eb Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:07 +0100 Subject: [PATCH 0225/1090] ASoC: topology: Save num_channels value for mixer controls To provide minimal support for multi-channel kcontrols i.e.: more than stereo configuration, store the number of channels specified within the SectionControlMixer. The field is part of the topology standard, currently skipped by the ASoC core. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-topology.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 644cfe26022e..6bb2fca044c5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1254,6 +1254,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + u32 num_channels; unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 921521a84e29..2b86cc3311f7 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -669,6 +669,7 @@ static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcon sm->min = le32_to_cpu(mc->min); sm->invert = le32_to_cpu(mc->invert); sm->platform_max = le32_to_cpu(mc->platform_max); + sm->num_channels = le32_to_cpu(mc->num_channels); /* map io handlers */ err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); From 28feec15fa285e561c626b3490bc5a10f5d177c8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:08 +0100 Subject: [PATCH 0226/1090] ASoC: Intel: avs: Make PEAKVOL configurable from topology The driver exposes volume kcontrols if PEAKVOL/GAIN module is present in the streaming path. Currently there is no control over their default values including the effect that may accompany the volume change event. Add template for PEAKVOL/GAIN module which holds all the information needed to address the limitation. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/uapi/sound/intel/avs/tokens.h | 4 ++++ sound/soc/intel/avs/path.c | 4 ++-- sound/soc/intel/avs/topology.c | 18 ++++++++++++++++++ sound/soc/intel/avs/topology.h | 5 +++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/uapi/sound/intel/avs/tokens.h b/include/uapi/sound/intel/avs/tokens.h index 06ff30537f47..c9f845b3c523 100644 --- a/include/uapi/sound/intel/avs/tokens.h +++ b/include/uapi/sound/intel/avs/tokens.h @@ -84,6 +84,10 @@ enum avs_tplg_token { AVS_TKN_MODCFG_WHM_DMA_TYPE_U32 = 437, AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32 = 438, AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32 = 439, + AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32 = 440, + AVS_TKN_MODCFG_PEAKVOL_CHANNEL_ID_U32 = 441, /* reserved */ + AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32 = 442, + AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32 = 443, /* struct avs_tplg_pplcfg */ AVS_TKN_PPLCFG_ID_U32 = 1401, diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index dfb85bd2b665..329838119015 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -350,8 +350,8 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) cfg->base.audio_fmt = *t->in_fmt; cfg->vols[0].target_volume = volume; cfg->vols[0].channel_id = AVS_ALL_CHANNELS_MASK; - cfg->vols[0].curve_type = AVS_AUDIO_CURVE_NONE; - cfg->vols[0].curve_duration = 0; + cfg->vols[0].curve_type = t->cfg_ext->peakvol.curve_type; + cfg->vols[0].curve_duration = t->cfg_ext->peakvol.curve_duration; ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, t->domain, cfg, cfg_size, &mod->instance_id); diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 471b00b9a149..45952fbe9694 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -857,6 +857,24 @@ static const struct avs_tplg_token_parser modcfg_ext_parsers[] = { .offset = offsetof(struct avs_tplg_modcfg_ext, whm.blob_fmt), .parse = avs_parse_audio_format_ptr, }, + { + .token = AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.target_volume), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_type), + .parse = avs_parse_word_token, + }, + { + .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32, + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_duration), + .parse = avs_parse_word_token, + }, }; static const struct avs_tplg_token_parser pin_format_parsers[] = { diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index 23d5ccd19959..304880997717 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -113,6 +113,11 @@ struct avs_tplg_modcfg_ext { struct { struct avs_audio_format *out_fmt; } micsel; + struct { + u32 target_volume; + u32 curve_type; + u32 curve_duration; + } peakvol; }; }; From 4c43a930e3e165ca6890147a309508ccb6768faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Feb 2025 11:21:09 +0100 Subject: [PATCH 0227/1090] ASoC: Intel: avs: Add volume control for GAIN module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AudioDSP firmware's GAIN module has same initialization payload as PEAKVOL and user volume setting can be applied up-front. Update existing code to account for PEAKVOL and GAIN both. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/control.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c index dc7dc45e0a0a..a55723289600 100644 --- a/sound/soc/intel/avs/control.c +++ b/sound/soc/intel/avs/control.c @@ -31,8 +31,11 @@ static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 i list_for_each_entry(path, &adev->path_list, node) { list_for_each_entry(ppl, &path->ppl_list, node) { list_for_each_entry(mod, &ppl->mod_list, node) { - if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID) - && mod->template->ctl_id == id) { + guid_t *type = &mod->template->cfg_ext->type; + + if ((guid_equal(type, &AVS_PEAKVOL_MOD_UUID) || + guid_equal(type, &AVS_GAIN_MOD_UUID)) && + mod->template->ctl_id == id) { spin_unlock(&adev->path_list_lock); return mod; } From 10188a25c9b5944c0a912482011b484b7c2e22d4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:10 +0100 Subject: [PATCH 0228/1090] ASoC: Intel: avs: Update VOLUME and add MUTE IPCs For mute kcontrols to have an effect add IPCs for triggering the mute operation on the DSP side. On top of basic get/set, an aggregated variant of the latter is provided for both MUTE and, to already present VOLUME IPC. It allows for efficient transmission of multiple parameters at once. While at it, sort the functions - getters come before setters in the AudioDSP firmware interface as well as in the kcontrol one. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/messages.c | 111 ++++++++++++++++++++++++++++++--- sound/soc/intel/avs/messages.h | 24 ++++++- 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index 242a175381c2..a5ba27983091 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -677,13 +677,6 @@ int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, (u8 *)&cpr_fmt, sizeof(cpr_fmt)); } -int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, - struct avs_volume_cfg *vol) -{ - return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, (u8 *)vol, - sizeof(*vol)); -} - int avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, struct avs_volume_cfg **vols, size_t *num_vols) { @@ -706,6 +699,110 @@ int avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_ return 0; } +int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_volume_cfg *vol) +{ + return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, + (u8 *)vol, sizeof(*vol)); +} + +int avs_ipc_peakvol_set_volumes(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_volume_cfg *vols, size_t num_vols) +{ + struct avs_tlv *tlv; + size_t offset; + size_t size; + u8 *payload; + int ret, i; + + size = num_vols * sizeof(*vols); + size += num_vols * sizeof(*tlv); + if (size > AVS_MAILBOX_SIZE) + return -EINVAL; + + payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!payload) + return -ENOMEM; + + for (offset = i = 0; i < num_vols; i++) { + tlv = (struct avs_tlv *)(payload + offset); + + tlv->type = AVS_PEAKVOL_VOLUME; + tlv->length = sizeof(*vols); + memcpy(tlv->value, &vols[i], tlv->length); + + offset += sizeof(*tlv) + tlv->length; + } + + ret = avs_ipc_set_large_config(adev, module_id, instance_id, AVS_VENDOR_CONFIG, payload, + size); + kfree(payload); + return ret; +} + +int avs_ipc_peakvol_get_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg **mutes, size_t *num_mutes) +{ + size_t payload_size; + u8 *payload; + int ret; + + ret = avs_ipc_get_large_config(adev, module_id, instance_id, AVS_PEAKVOL_MUTE, NULL, 0, + &payload, &payload_size); + if (ret) + return ret; + + /* Non-zero payload expected for PEAKVOL_MUTE. */ + if (!payload_size) + return -EREMOTEIO; + + *mutes = (struct avs_mute_cfg *)payload; + *num_mutes = payload_size / sizeof(**mutes); + + return 0; +} + +int avs_ipc_peakvol_set_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg *mute) +{ + return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_MUTE, + (u8 *)mute, sizeof(*mute)); +} + +int avs_ipc_peakvol_set_mutes(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg *mutes, size_t num_mutes) +{ + struct avs_tlv *tlv; + size_t offset; + size_t size; + u8 *payload; + int ret, i; + + size = num_mutes * sizeof(*mutes); + size += num_mutes * sizeof(*tlv); + if (size > AVS_MAILBOX_SIZE) + return -EINVAL; + + payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); + if (!payload) + return -ENOMEM; + + for (offset = i = 0; i < num_mutes; i++) { + tlv = (struct avs_tlv *)(payload + offset); + + tlv->type = AVS_PEAKVOL_MUTE; + tlv->length = sizeof(*mutes); + memcpy(tlv->value, &mutes[i], tlv->length); + + offset += sizeof(*tlv) + tlv->length; + } + + ret = avs_ipc_set_large_config(adev, module_id, instance_id, AVS_VENDOR_CONFIG, payload, + size); + kfree(payload); + return ret; +} + #ifdef CONFIG_DEBUG_FS int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size) { diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index f44fcfc81de7..2f243802ccc2 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -814,6 +814,15 @@ struct avs_volume_cfg { } __packed; static_assert(sizeof(struct avs_volume_cfg) == 24); +struct avs_mute_cfg { + u32 channel_id; + u32 mute; + u32 curve_type; + u32 reserved; /* alignment */ + u64 curve_duration; +} __packed; +static_assert(sizeof(struct avs_mute_cfg) == 24); + struct avs_peakvol_cfg { struct avs_modcfg_base base; struct avs_volume_cfg vols[]; @@ -896,6 +905,8 @@ static_assert(sizeof(struct avs_whm_cfg) == 108); /* Module runtime parameters */ +#define AVS_VENDOR_CONFIG 0xFF + enum avs_copier_runtime_param { AVS_COPIER_SET_SINK_FORMAT = 2, }; @@ -914,6 +925,7 @@ int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, enum avs_peakvol_runtime_param { AVS_PEAKVOL_VOLUME = 0, + AVS_PEAKVOL_MUTE = 3, }; enum avs_audio_curve_type { @@ -921,10 +933,18 @@ enum avs_audio_curve_type { AVS_AUDIO_CURVE_WINDOWS_FADE = 1, }; -int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, - struct avs_volume_cfg *vol); int avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, struct avs_volume_cfg **vols, size_t *num_vols); +int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_volume_cfg *vol); +int avs_ipc_peakvol_set_volumes(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_volume_cfg *vols, size_t num_vols); +int avs_ipc_peakvol_get_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg **mutes, size_t *num_mutes); +int avs_ipc_peakvol_set_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg *mute); +int avs_ipc_peakvol_set_mutes(struct avs_dev *adev, u16 module_id, u8 instance_id, + struct avs_mute_cfg *mutes, size_t num_mutes); #define AVS_PROBE_INST_ID 0 From c321a4d705a31a50d7580516422aaa5b853e7602 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:11 +0100 Subject: [PATCH 0229/1090] ASoC: Intel: avs: New volume control operations To provide multi-channel - more than 2 - capability to volume controls implement operations that honor the num_channels of a mixer control. As mc->num_channels can be 0 and is in fact the default behavior, the new functions decide between ALL_CHANNELS_MASK and individual channels based on the field value. To avoid hard-to-review delta when refactoring the code, first implement the new behavior with follow up changes cleaning things up. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/control.c | 84 +++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/control.h | 5 +++ sound/soc/intel/avs/path.c | 36 +++++++++++++++ sound/soc/intel/avs/path.h | 3 ++ 4 files changed, 128 insertions(+) diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c index a55723289600..a1c7431cfe13 100644 --- a/sound/soc/intel/avs/control.c +++ b/sound/soc/intel/avs/control.c @@ -6,6 +6,7 @@ // Cezary Rojewski // +#include #include #include "avs.h" #include "control.h" @@ -114,3 +115,86 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va return ret ? ret : changed; } + +int avs_control_volume_get2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + struct avs_control_data *ctl_data = mc->dobj.private; + struct avs_path_module *active_module; + struct avs_volume_cfg *dspvols; + struct avs_dev *adev; + size_t num_dspvols; + int ret, i; + + adev = avs_get_kcontrol_adev(kctl); + + /* Prevent access to modules while path is being constructed. */ + guard(mutex)(&adev->path_mutex); + + active_module = avs_get_volume_module(adev, ctl_data->id); + if (active_module) { + ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id, + active_module->instance_id, &dspvols, + &num_dspvols); + if (ret) + return AVS_IPC_RET(ret); + + /* Do not copy more than the control can store. */ + num_dspvols = min_t(u32, num_dspvols, SND_SOC_TPLG_MAX_CHAN); + for (i = 0; i < num_dspvols; i++) + ctl_data->values[i] = dspvols[i].target_volume; + kfree(dspvols); + } + + memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); + return 0; +} + +int avs_control_volume_put2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +{ + struct avs_path_module *active_module; + struct avs_control_data *ctl_data; + struct soc_mixer_control *mc; + struct avs_dev *adev; + long *input; + int ret, i; + + mc = (struct soc_mixer_control *)kctl->private_value; + ctl_data = mc->dobj.private; + adev = avs_get_kcontrol_adev(kctl); + input = uctl->value.integer.value; + i = 0; + + /* mc->num_channels can be 0. */ + do { + if (input[i] < mc->min || input[i] > mc->max) + return -EINVAL; + } while (++i < mc->num_channels); + + if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) + return 0; + + /* Prevent access to modules while path is being constructed. */ + guard(mutex)(&adev->path_mutex); + + active_module = avs_get_volume_module(adev, ctl_data->id); + if (active_module) { + ret = avs_peakvol_set_volume(adev, active_module, mc, input); + if (ret) + return ret; + } + + memcpy(ctl_data->values, input, sizeof(ctl_data->values)); + return 1; +} + +int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = max_t(u32, 1, mc->num_channels); + uinfo->value.integer.min = 0; + uinfo->value.integer.max = mc->max; + return 0; +} diff --git a/sound/soc/intel/avs/control.h b/sound/soc/intel/avs/control.h index d9fac3569e8d..e16fa79962de 100644 --- a/sound/soc/intel/avs/control.h +++ b/sound/soc/intel/avs/control.h @@ -10,14 +10,19 @@ #define __SOUND_SOC_INTEL_AVS_CTRL_H #include +#include struct avs_control_data { u32 id; long volume; + long values[SND_SOC_TPLG_MAX_CHAN]; }; int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int avs_control_volume_get2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_volume_put2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); #endif diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 329838119015..a72ebde7d011 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -323,6 +323,42 @@ static struct avs_control_data *avs_get_module_control(struct avs_path_module *m return NULL; } +int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, + struct soc_mixer_control *mc, long *input) +{ + struct avs_volume_cfg vols[SND_SOC_TPLG_MAX_CHAN] = {{0}}; + struct avs_control_data *ctl_data; + struct avs_tplg_module *t; + int ret, i; + + ctl_data = mc->dobj.private; + t = mod->template; + if (!input) + input = ctl_data->values; + + if (mc->num_channels) { + for (i = 0; i < mc->num_channels; i++) { + vols[i].channel_id = i; + vols[i].target_volume = input[i]; + vols[i].curve_type = t->cfg_ext->peakvol.curve_type; + vols[i].curve_duration = t->cfg_ext->peakvol.curve_duration; + } + + ret = avs_ipc_peakvol_set_volumes(adev, mod->module_id, mod->instance_id, vols, + mc->num_channels); + return AVS_IPC_RET(ret); + } + + /* Target all channels if no individual selected. */ + vols[0].channel_id = AVS_ALL_CHANNELS_MASK; + vols[0].target_volume = input[0]; + vols[0].curve_type = t->cfg_ext->peakvol.curve_type; + vols[0].curve_duration = t->cfg_ext->peakvol.curve_duration; + + ret = avs_ipc_peakvol_set_volume(adev, mod->module_id, mod->instance_id, &vols[0]); + return AVS_IPC_RET(ret); +} + static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; diff --git a/sound/soc/intel/avs/path.h b/sound/soc/intel/avs/path.h index bfd253c9fa95..e9317b64de86 100644 --- a/sound/soc/intel/avs/path.h +++ b/sound/soc/intel/avs/path.h @@ -69,4 +69,7 @@ int avs_path_reset(struct avs_path *path); int avs_path_pause(struct avs_path *path); int avs_path_run(struct avs_path *path, int trigger); +int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, + struct soc_mixer_control *mc, long *input); + #endif From 4c32ebcc8650ce506632a32136993c85537fb01a Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:12 +0100 Subject: [PATCH 0230/1090] ASoC: Intel: avs: Move to the new control operations Allow for multi-channel volume controls to be utilized by an application by moving over to the new implementation. Drop all unused code in the process. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/control.c | 72 +--------------------------------- sound/soc/intel/avs/control.h | 8 +--- sound/soc/intel/avs/path.c | 2 +- sound/soc/intel/avs/topology.c | 1 + 4 files changed, 6 insertions(+), 77 deletions(-) diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c index a1c7431cfe13..64283aa35281 100644 --- a/sound/soc/intel/avs/control.c +++ b/sound/soc/intel/avs/control.c @@ -48,75 +48,7 @@ static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 i return NULL; } -int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private; - struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol); - struct avs_volume_cfg *dspvols = NULL; - struct avs_path_module *active_module; - size_t num_dspvols; - int ret = 0; - - /* prevent access to modules while path is being constructed */ - mutex_lock(&adev->path_mutex); - - active_module = avs_get_volume_module(adev, ctl_data->id); - if (active_module) { - ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id, - active_module->instance_id, &dspvols, - &num_dspvols); - if (!ret) - ucontrol->value.integer.value[0] = dspvols[0].target_volume; - - ret = AVS_IPC_RET(ret); - kfree(dspvols); - } else { - ucontrol->value.integer.value[0] = ctl_data->volume; - } - - mutex_unlock(&adev->path_mutex); - return ret; -} - -int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private; - struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol); - long *volume = &ctl_data->volume; - struct avs_path_module *active_module; - struct avs_volume_cfg dspvol = {0}; - long ctlvol = ucontrol->value.integer.value[0]; - int ret = 0, changed = 0; - - if (ctlvol < 0 || ctlvol > mc->max) - return -EINVAL; - - /* prevent access to modules while path is being constructed */ - mutex_lock(&adev->path_mutex); - - if (*volume != ctlvol) { - *volume = ctlvol; - changed = 1; - } - - active_module = avs_get_volume_module(adev, ctl_data->id); - if (active_module) { - dspvol.channel_id = AVS_ALL_CHANNELS_MASK; - dspvol.target_volume = *volume; - - ret = avs_ipc_peakvol_set_volume(adev, active_module->module_id, - active_module->instance_id, &dspvol); - ret = AVS_IPC_RET(ret); - } - - mutex_unlock(&adev->path_mutex); - - return ret ? ret : changed; -} - -int avs_control_volume_get2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; struct avs_control_data *ctl_data = mc->dobj.private; @@ -150,7 +82,7 @@ int avs_control_volume_get2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value return 0; } -int avs_control_volume_put2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct avs_path_module *active_module; struct avs_control_data *ctl_data; diff --git a/sound/soc/intel/avs/control.h b/sound/soc/intel/avs/control.h index e16fa79962de..66f3fe064e1d 100644 --- a/sound/soc/intel/avs/control.h +++ b/sound/soc/intel/avs/control.h @@ -14,15 +14,11 @@ struct avs_control_data { u32 id; - - long volume; long values[SND_SOC_TPLG_MAX_CHAN]; }; -int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int avs_control_volume_get2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); -int avs_control_volume_put2(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); #endif diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index a72ebde7d011..56a2916eec5e 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -370,7 +370,7 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) ctl_data = avs_get_module_control(mod); if (ctl_data) - volume = ctl_data->volume; + volume = ctl_data->values[0]; /* As 2+ channels controls are unsupported, have a single block for all channels. */ cfg_size = struct_size(cfg, vols, 1); diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 45952fbe9694..ee70e3d0e889 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1912,6 +1912,7 @@ static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { .id = AVS_CONTROL_OPS_VOLUME, .get = avs_control_volume_get, .put = avs_control_volume_put, + .info = avs_control_volume_info, }, }; From a4217a03686989c4a79530fe54fa17576aff7330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Mon, 17 Feb 2025 11:21:13 +0100 Subject: [PATCH 0231/1090] ASoC: Intel: avs: Add support for mute for PEAKVOL and GAIN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With recent updates to AudioDSP firmware, mute functionality has been added to PEAKVOL and GAIN modules. The operation occurs over IPC similarly to how volume is configured. Wire it up to kcontrol infrastructure present in the avs-driver. Signed-off-by: Amadeusz SÅ‚awiÅ„ski Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/control.c | 83 ++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/control.h | 3 ++ sound/soc/intel/avs/path.c | 36 +++++++++++++++ sound/soc/intel/avs/path.h | 2 + sound/soc/intel/avs/topology.c | 11 ++++- 5 files changed, 134 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c index 64283aa35281..2e01dc75a15a 100644 --- a/sound/soc/intel/avs/control.c +++ b/sound/soc/intel/avs/control.c @@ -130,3 +130,86 @@ int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info uinfo->value.integer.max = mc->max; return 0; } + +int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + struct avs_control_data *ctl_data = mc->dobj.private; + struct avs_path_module *active_module; + struct avs_mute_cfg *dspmutes; + struct avs_dev *adev; + size_t num_dspmutes; + int ret, i; + + adev = avs_get_kcontrol_adev(kctl); + + /* Prevent access to modules while path is being constructed. */ + guard(mutex)(&adev->path_mutex); + + active_module = avs_get_volume_module(adev, ctl_data->id); + if (active_module) { + ret = avs_ipc_peakvol_get_mute(adev, active_module->module_id, + active_module->instance_id, &dspmutes, + &num_dspmutes); + if (ret) + return AVS_IPC_RET(ret); + + /* Do not copy more than the control can store. */ + num_dspmutes = min_t(u32, num_dspmutes, SND_SOC_TPLG_MAX_CHAN); + for (i = 0; i < num_dspmutes; i++) + ctl_data->values[i] = !dspmutes[i].mute; + kfree(dspmutes); + } + + memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); + return 0; +} + +int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) +{ + struct avs_path_module *active_module; + struct avs_control_data *ctl_data; + struct soc_mixer_control *mc; + struct avs_dev *adev; + long *input; + int ret, i; + + mc = (struct soc_mixer_control *)kctl->private_value; + ctl_data = mc->dobj.private; + adev = avs_get_kcontrol_adev(kctl); + input = uctl->value.integer.value; + i = 0; + + /* mc->num_channels can be 0. */ + do { + if (input[i] < mc->min || input[i] > mc->max) + return -EINVAL; + } while (++i < mc->num_channels); + + if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) + return 0; + + /* Prevent access to modules while path is being constructed. */ + guard(mutex)(&adev->path_mutex); + + active_module = avs_get_volume_module(adev, ctl_data->id); + if (active_module) { + ret = avs_peakvol_set_mute(adev, active_module, mc, input); + if (ret) + return ret; + } + + memcpy(ctl_data->values, input, sizeof(ctl_data->values)); + return 1; +} + +int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = max_t(u32, 1, mc->num_channels); + uinfo->value.integer.min = 0; + uinfo->value.integer.max = mc->max; + return 0; +} diff --git a/sound/soc/intel/avs/control.h b/sound/soc/intel/avs/control.h index 66f3fe064e1d..08b2919e4629 100644 --- a/sound/soc/intel/avs/control.h +++ b/sound/soc/intel/avs/control.h @@ -20,5 +20,8 @@ struct avs_control_data { int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); +int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); +int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); #endif diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 56a2916eec5e..403510494e77 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -359,6 +359,42 @@ int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, return AVS_IPC_RET(ret); } +int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod, + struct soc_mixer_control *mc, long *input) +{ + struct avs_mute_cfg mutes[SND_SOC_TPLG_MAX_CHAN] = {{0}}; + struct avs_control_data *ctl_data; + struct avs_tplg_module *t; + int ret, i; + + ctl_data = mc->dobj.private; + t = mod->template; + if (!input) + input = ctl_data->values; + + if (mc->num_channels) { + for (i = 0; i < mc->num_channels; i++) { + mutes[i].channel_id = i; + mutes[i].mute = !input[i]; + mutes[i].curve_type = t->cfg_ext->peakvol.curve_type; + mutes[i].curve_duration = t->cfg_ext->peakvol.curve_duration; + } + + ret = avs_ipc_peakvol_set_mutes(adev, mod->module_id, mod->instance_id, mutes, + mc->num_channels); + return AVS_IPC_RET(ret); + } + + /* Target all channels if no individual selected. */ + mutes[0].channel_id = AVS_ALL_CHANNELS_MASK; + mutes[0].mute = !input[0]; + mutes[0].curve_type = t->cfg_ext->peakvol.curve_type; + mutes[0].curve_duration = t->cfg_ext->peakvol.curve_duration; + + ret = avs_ipc_peakvol_set_mute(adev, mod->module_id, mod->instance_id, &mutes[0]); + return AVS_IPC_RET(ret); +} + static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; diff --git a/sound/soc/intel/avs/path.h b/sound/soc/intel/avs/path.h index e9317b64de86..7ed7e94e0a56 100644 --- a/sound/soc/intel/avs/path.h +++ b/sound/soc/intel/avs/path.h @@ -71,5 +71,7 @@ int avs_path_run(struct avs_path *path, int trigger); int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, struct soc_mixer_control *mc, long *input); +int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod, + struct soc_mixer_control *mc, long *input); #endif diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index ee70e3d0e889..9ef1adb077f4 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1905,7 +1905,10 @@ static int avs_manifest(struct snd_soc_component *comp, int index, return 0; } -#define AVS_CONTROL_OPS_VOLUME 257 +enum { + AVS_CONTROL_OPS_VOLUME = 257, + AVS_CONTROL_OPS_MUTE, +}; static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { { @@ -1914,6 +1917,12 @@ static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { .put = avs_control_volume_put, .info = avs_control_volume_info, }, + { + .id = AVS_CONTROL_OPS_MUTE, + .get = avs_control_mute_get, + .put = avs_control_mute_put, + .info = avs_control_mute_info, + }, }; static const struct avs_tplg_token_parser control_parsers[] = { From 76e013152891a69dfe68a28706a51a7df9ed4c42 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:14 +0100 Subject: [PATCH 0232/1090] ASoC: Intel: avs: Honor the invert flag for mixer controls Values for the mute flag represented on the AudioDSP side are inverted. Check mixer control description and initialize default values accordingly. Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/topology.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 9ef1adb077f4..3c222c352701 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1943,18 +1943,20 @@ avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_ struct avs_control_data *ctl_data; struct soc_mixer_control *mc; size_t block_size; - int ret; + int ret, i; switch (le32_to_cpu(hdr->type)) { case SND_SOC_TPLG_TYPE_MIXER: - tmc = container_of(hdr, typeof(*tmc), hdr); - tuples = tmc->priv.array; - block_size = le32_to_cpu(tmc->priv.size); break; default: return -EINVAL; } + mc = (struct soc_mixer_control *)ctmpl->private_value; + tmc = container_of(hdr, typeof(*tmc), hdr); + tuples = tmc->priv.array; + block_size = le32_to_cpu(tmc->priv.size); + ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL); if (!ctl_data) return -ENOMEM; @@ -1965,8 +1967,13 @@ avs_control_load(struct snd_soc_component *comp, int index, struct snd_kcontrol_ if (ret) return ret; - mc = (struct soc_mixer_control *)ctmpl->private_value; mc->dobj.private = ctl_data; + if (tmc->invert) { + ctl_data->values[0] = mc->max; + for (i = 1; i < mc->num_channels; i++) + ctl_data->values[i] = mc->max; + } + return 0; } From a9409fcb979eaff401837b955b234ca1ee05fdbd Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 17 Feb 2025 11:21:15 +0100 Subject: [PATCH 0233/1090] ASoC: Intel: avs: Support multi-channel PEAKVOL instantiation The PEAKVOL module initialization procedure allows for specifying default configuration for all individual channels. To reflect that in the code, first update avs_get_module_control() to allow for selecting Volume or Mute control based on needs and then apply the settings with newly added avs_peakvol_set_volume() and avs_peakvol_set_mute(). Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20250217102115.3539427-11-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 403510494e77..ef0c1d125d66 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -300,7 +300,8 @@ static int avs_whm_create(struct avs_dev *adev, struct avs_path_module *mod) return ret; } -static struct avs_control_data *avs_get_module_control(struct avs_path_module *mod) +static struct soc_mixer_control *avs_get_module_control(struct avs_path_module *mod, + const char *name) { struct avs_tplg_module *t = mod->template; struct avs_tplg_path_template *path_tmpl; @@ -316,8 +317,8 @@ static struct avs_control_data *avs_get_module_control(struct avs_path_module *m mc = (struct soc_mixer_control *)w->kcontrols[i]->private_value; ctl_data = (struct avs_control_data *)mc->dobj.private; - if (ctl_data->id == t->ctl_id) - return ctl_data; + if (ctl_data->id == t->ctl_id && strstr(w->kcontrols[i]->id.name, name)) + return mc; } return NULL; @@ -398,17 +399,11 @@ int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod, static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) { struct avs_tplg_module *t = mod->template; - struct avs_control_data *ctl_data; + struct soc_mixer_control *mc; struct avs_peakvol_cfg *cfg; - int volume = S32_MAX; size_t cfg_size; int ret; - ctl_data = avs_get_module_control(mod); - if (ctl_data) - volume = ctl_data->values[0]; - - /* As 2+ channels controls are unsupported, have a single block for all channels. */ cfg_size = struct_size(cfg, vols, 1); if (cfg_size > AVS_MAILBOX_SIZE) return -EINVAL; @@ -420,15 +415,28 @@ static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) cfg->base.obs = t->cfg_base->obs; cfg->base.is_pages = t->cfg_base->is_pages; cfg->base.audio_fmt = *t->in_fmt; - cfg->vols[0].target_volume = volume; cfg->vols[0].channel_id = AVS_ALL_CHANNELS_MASK; + cfg->vols[0].target_volume = S32_MAX; cfg->vols[0].curve_type = t->cfg_ext->peakvol.curve_type; cfg->vols[0].curve_duration = t->cfg_ext->peakvol.curve_duration; ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, t->domain, cfg, cfg_size, &mod->instance_id); + if (ret) + return ret; - return ret; + /* Now configure both VOLUME and MUTE parameters. */ + mc = avs_get_module_control(mod, "Volume"); + if (mc) { + ret = avs_peakvol_set_volume(adev, mod, mc, NULL); + if (ret) + return ret; + } + + mc = avs_get_module_control(mod, "Switch"); + if (mc) + return avs_peakvol_set_mute(adev, mod, mc, NULL); + return 0; } static int avs_updown_mix_create(struct avs_dev *adev, struct avs_path_module *mod) From 39ec9eaaa165d297d008d1fa385748430bd18e4d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 19 Feb 2025 11:53:16 -0800 Subject: [PATCH 0234/1090] coredump: Only sort VMAs when core_sort_vma sysctl is set The sorting of VMAs by size in commit 7d442a33bfe8 ("binfmt_elf: Dump smaller VMAs first in ELF cores") breaks elfutils[1]. Instead, sort based on the setting of the new sysctl, core_sort_vma, which defaults to 0, no sorting. Reported-by: Michael Stapelberg Closes: https://lore.kernel.org/all/20250218085407.61126-1-michael@stapelberg.de/ [1] Fixes: 7d442a33bfe8 ("binfmt_elf: Dump smaller VMAs first in ELF cores") Signed-off-by: Kees Cook --- Documentation/admin-guide/sysctl/kernel.rst | 11 +++++++++++ fs/coredump.c | 15 +++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst index a43b78b4b646..dd49a89a62d3 100644 --- a/Documentation/admin-guide/sysctl/kernel.rst +++ b/Documentation/admin-guide/sysctl/kernel.rst @@ -212,6 +212,17 @@ pid>/``). This value defaults to 0. +core_sort_vma +============= + +The default coredump writes VMAs in address order. By setting +``core_sort_vma`` to 1, VMAs will be written from smallest size +to largest size. This is known to break at least elfutils, but +can be handy when dealing with very large (and truncated) +coredumps where the more useful debugging details are included +in the smaller VMAs. + + core_uses_pid ============= diff --git a/fs/coredump.c b/fs/coredump.c index 591700e1b2ce..4375c70144d0 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -63,6 +63,7 @@ static void free_vma_snapshot(struct coredump_params *cprm); static int core_uses_pid; static unsigned int core_pipe_limit; +static unsigned int core_sort_vma; static char core_pattern[CORENAME_MAX_SIZE] = "core"; static int core_name_size = CORENAME_MAX_SIZE; unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT; @@ -1026,6 +1027,15 @@ static const struct ctl_table coredump_sysctls[] = { .extra1 = (unsigned int *)&core_file_note_size_min, .extra2 = (unsigned int *)&core_file_note_size_max, }, + { + .procname = "core_sort_vma", + .data = &core_sort_vma, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, }; static int __init init_fs_coredump_sysctls(void) @@ -1256,8 +1266,9 @@ static bool dump_vma_snapshot(struct coredump_params *cprm) cprm->vma_data_size += m->dump_size; } - sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta), - cmp_vma_size, NULL); + if (core_sort_vma) + sort(cprm->vma_meta, cprm->vma_count, sizeof(*cprm->vma_meta), + cmp_vma_size, NULL); return true; } From 8c1624b63a7d24142a2bbc3a5ee7e95f004ea36e Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Thu, 20 Feb 2025 13:18:30 +0200 Subject: [PATCH 0235/1090] nvme-tcp: fix possible UAF in nvme_tcp_poll nvme_tcp_poll() may race with the send path error handler because it may complete the request while it is actively being polled for completion, resulting in a UAF panic [1]: We should make sure to stop polling when we see an error when trying to read from the socket. Hence make sure to propagate the error so that the block layer breaks the polling cycle. [1]: -- [35665.692310] nvme nvme2: failed to send request -13 [35665.702265] nvme nvme2: unsupported pdu type (3) [35665.702272] BUG: kernel NULL pointer dereference, address: 0000000000000000 [35665.702542] nvme nvme2: queue 1 receive failed: -22 [35665.703209] #PF: supervisor write access in kernel mode [35665.703213] #PF: error_code(0x0002) - not-present page [35665.703214] PGD 8000003801cce067 P4D 8000003801cce067 PUD 37e6f79067 PMD 0 [35665.703220] Oops: 0002 [#1] SMP PTI [35665.703658] nvme nvme2: starting error recovery [35665.705809] Hardware name: Inspur aaabbb/YZMB-00882-104, BIOS 4.1.26 09/22/2022 [35665.705812] Workqueue: kblockd blk_mq_requeue_work [35665.709172] RIP: 0010:_raw_spin_lock+0xc/0x30 [35665.715788] Call Trace: [35665.716201] [35665.716613] ? show_trace_log_lvl+0x1c1/0x2d9 [35665.717049] ? show_trace_log_lvl+0x1c1/0x2d9 [35665.717457] ? blk_mq_request_bypass_insert+0x2c/0xb0 [35665.717950] ? __die_body.cold+0x8/0xd [35665.718361] ? page_fault_oops+0xac/0x140 [35665.718749] ? blk_mq_start_request+0x30/0xf0 [35665.719144] ? nvme_tcp_queue_rq+0xc7/0x170 [nvme_tcp] [35665.719547] ? exc_page_fault+0x62/0x130 [35665.719938] ? asm_exc_page_fault+0x22/0x30 [35665.720333] ? _raw_spin_lock+0xc/0x30 [35665.720723] blk_mq_request_bypass_insert+0x2c/0xb0 [35665.721101] blk_mq_requeue_work+0xa5/0x180 [35665.721451] process_one_work+0x1e8/0x390 [35665.721809] worker_thread+0x53/0x3d0 [35665.722159] ? process_one_work+0x390/0x390 [35665.722501] kthread+0x124/0x150 [35665.722849] ? set_kthread_struct+0x50/0x50 [35665.723182] ret_from_fork+0x1f/0x30 Reported-by: Zhang Guanghui Signed-off-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Keith Busch --- drivers/nvme/host/tcp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 8a9131c95a3d..8c14018201db 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -2699,6 +2699,7 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) { struct nvme_tcp_queue *queue = hctx->driver_data; struct sock *sk = queue->sock->sk; + int ret; if (!test_bit(NVME_TCP_Q_LIVE, &queue->flags)) return 0; @@ -2706,9 +2707,9 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) set_bit(NVME_TCP_Q_POLLING, &queue->flags); if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue)) sk_busy_loop(sk, true); - nvme_tcp_try_recv(queue); + ret = nvme_tcp_try_recv(queue); clear_bit(NVME_TCP_Q_POLLING, &queue->flags); - return queue->nr_cqe; + return ret < 0 ? ret : queue->nr_cqe; } static int nvme_tcp_get_address(struct nvme_ctrl *ctrl, char *buf, int size) From 6a3572e10f740acd48e2713ef37e92186a3ce5e8 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 13 Feb 2025 01:04:43 +0800 Subject: [PATCH 0236/1090] nvme-pci: clean up CMBMSC when registering CMB fails CMB decoding should get disabled when the CMB block isn't successfully registered to P2P DMA subsystem. Clean up the CMBMSC register in this error handling codepath to disable CMB decoding (and CMBLOC/CMBSZ registers). Signed-off-by: Icenowy Zheng Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 950289405ef2..218506e3dabe 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2003,6 +2003,7 @@ static void nvme_map_cmb(struct nvme_dev *dev) if (pci_p2pdma_add_resource(pdev, bar, size, offset)) { dev_warn(dev->ctrl.device, "failed to register the CMB\n"); + hi_lo_writeq(0, dev->bar + NVME_REG_CMBMSC); return; } From 56cf7ef0d490b28fad8f8629fc135c5ab7c9f54e Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 13 Feb 2025 01:04:44 +0800 Subject: [PATCH 0237/1090] nvme-pci: skip CMB blocks incompatible with PCI P2P DMA The PCI P2PDMA code will register the CMB block to the memory hot-plugging subsystem, which have an alignment requirement. Memory blocks that do not satisfy this alignment requirement (usually 2MB) will lead to a WARNING from memory hotplugging. Verify the CMB block's address and size against the alignment and only try to send CMB blocks compatible with it to prevent this warning. Tested on Intel DC D4502 SSD, which has a 512K CMB block that is too small for memory hotplugging (thus PCI P2PDMA). Signed-off-by: Icenowy Zheng Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 218506e3dabe..640590b21728 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1982,6 +1982,18 @@ static void nvme_map_cmb(struct nvme_dev *dev) if (offset > bar_size) return; + /* + * Controllers may support a CMB size larger than their BAR, for + * example, due to being behind a bridge. Reduce the CMB to the + * reported size of the BAR + */ + size = min(size, bar_size - offset); + + if (!IS_ALIGNED(size, memremap_compat_align()) || + !IS_ALIGNED(pci_resource_start(pdev, bar), + memremap_compat_align())) + return; + /* * Tell the controller about the host side address mapping the CMB, * and enable CMB decoding for the NVMe 1.4+ scheme: @@ -1992,14 +2004,6 @@ static void nvme_map_cmb(struct nvme_dev *dev) dev->bar + NVME_REG_CMBMSC); } - /* - * Controllers may support a CMB size larger than their BAR, - * for example, due to being behind a bridge. Reduce the CMB to - * the reported size of the BAR - */ - if (size > bar_size - offset) - size = bar_size - offset; - if (pci_p2pdma_add_resource(pdev, bar, size, offset)) { dev_warn(dev->ctrl.device, "failed to register the CMB\n"); From f5be37ca2c99fc764408ceeeaf941bea062cdc9b Mon Sep 17 00:00:00 2001 From: Andras Sebok Date: Mon, 24 Feb 2025 10:03:56 +0100 Subject: [PATCH 0238/1090] dt-bindings: input/touchscreen: imagis: add compatible for ist3038h IST3038H is a touchscreen IC which seems mostly compatible with IST3038C except that it reports a different chip ID value. Signed-off-by: Andras Sebok Link: https://lore.kernel.org/r/20250224090354.102903-4-sebokandris2009@gmail.com Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml index e24cbd960993..bd8ede3a4ad8 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml @@ -19,6 +19,7 @@ properties: - imagis,ist3038 - imagis,ist3038b - imagis,ist3038c + - imagis,ist3038h reg: maxItems: 1 From 5797c04400ee117bfe459ff1e468d0ea38054ab4 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 23 Jan 2025 15:20:02 +0300 Subject: [PATCH 0239/1090] hwmon: (peci/dimmtemp) Do not provide fake thresholds data When an Icelake or Sapphire Rapids CPU isn't providing the maximum and critical thresholds for particular DIMM the driver should return an error to the userspace instead of giving it stale (best case) or wrong (the structure contains all zeros after kzalloc() call) data. The issue can be reproduced by binding the peci driver while the host is fully booted and idle, this makes PECI interaction unreliable enough. Fixes: 73bc1b885dae ("hwmon: peci: Add dimmtemp driver") Fixes: 621995b6d795 ("hwmon: (peci/dimmtemp) Add Sapphire Rapids support") Cc: stable@vger.kernel.org Signed-off-by: Paul Fertser Reviewed-by: Iwona Winiarska Link: https://lore.kernel.org/r/20250123122003.6010-1-fercerpav@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/peci/dimmtemp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/peci/dimmtemp.c b/drivers/hwmon/peci/dimmtemp.c index d6762259dd69..fbe82d9852e0 100644 --- a/drivers/hwmon/peci/dimmtemp.c +++ b/drivers/hwmon/peci/dimmtemp.c @@ -127,8 +127,6 @@ static int update_thresholds(struct peci_dimmtemp *priv, int dimm_no) return 0; ret = priv->gen_info->read_thresholds(priv, dimm_order, chan_rank, &data); - if (ret == -ENODATA) /* Use default or previous value */ - return 0; if (ret) return ret; @@ -509,11 +507,11 @@ read_thresholds_icx(struct peci_dimmtemp *priv, int dimm_order, int chan_rank, u ret = peci_ep_pci_local_read(priv->peci_dev, 0, 13, 0, 2, 0xd4, ®_val); if (ret || !(reg_val & BIT(31))) - return -ENODATA; /* Use default or previous value */ + return -ENODATA; ret = peci_ep_pci_local_read(priv->peci_dev, 0, 13, 0, 2, 0xd0, ®_val); if (ret) - return -ENODATA; /* Use default or previous value */ + return -ENODATA; /* * Device 26, Offset 224e0: IMC 0 channel 0 -> rank 0 @@ -546,11 +544,11 @@ read_thresholds_spr(struct peci_dimmtemp *priv, int dimm_order, int chan_rank, u ret = peci_ep_pci_local_read(priv->peci_dev, 0, 30, 0, 2, 0xd4, ®_val); if (ret || !(reg_val & BIT(31))) - return -ENODATA; /* Use default or previous value */ + return -ENODATA; ret = peci_ep_pci_local_read(priv->peci_dev, 0, 30, 0, 2, 0xd0, ®_val); if (ret) - return -ENODATA; /* Use default or previous value */ + return -ENODATA; /* * Device 26, Offset 219a8: IMC 0 channel 0 -> rank 0 From 83a4a5a82a154277dfe61d135a445901cd6d0e6f Mon Sep 17 00:00:00 2001 From: Andras Sebok Date: Mon, 24 Feb 2025 10:03:54 +0100 Subject: [PATCH 0240/1090] Input: imagis - add support for imagis IST3038H Add support for imagis IST3038H, which seems mostly compatible with IST3038C except that it reports a different chip ID value. Tested on samsung,j5y17lte. Signed-off-by: Andras Sebok Link: https://lore.kernel.org/r/20250224090354.102903-2-sebokandris2009@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/imagis.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c index abeae9102323..3c8bbe284b73 100644 --- a/drivers/input/touchscreen/imagis.c +++ b/drivers/input/touchscreen/imagis.c @@ -22,6 +22,7 @@ #define IST3032C_WHOAMI 0x32c #define IST3038C_WHOAMI 0x38c +#define IST3038H_WHOAMI 0x38d #define IST3038B_REG_CHIPID 0x30 #define IST3038B_WHOAMI 0x30380b @@ -428,11 +429,19 @@ static const struct imagis_properties imagis_3038c_data = { .protocol_b = true, }; +static const struct imagis_properties imagis_3038h_data = { + .interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE, + .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, + .whoami_cmd = IST3038C_REG_CHIPID, + .whoami_val = IST3038H_WHOAMI, +}; + static const struct of_device_id imagis_of_match[] = { { .compatible = "imagis,ist3032c", .data = &imagis_3032c_data }, { .compatible = "imagis,ist3038", .data = &imagis_3038_data }, { .compatible = "imagis,ist3038b", .data = &imagis_3038b_data }, { .compatible = "imagis,ist3038c", .data = &imagis_3038c_data }, + { .compatible = "imagis,ist3038h", .data = &imagis_3038h_data }, { }, }; MODULE_DEVICE_TABLE(of, imagis_of_match); From 5bab1ae5a375ccde25ac9a142ea933a5d3bdf38d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 3 Jan 2025 10:21:35 +0100 Subject: [PATCH 0241/1090] Input: goodix-berlin - fix comment referencing wrong regulator In the statement above AVDD gets enabled, and not IOVDD, so fix this copy-paste mistake. Fixes: 44362279bdd4 ("Input: add core support for Goodix Berlin Touchscreen IC") Reported-by: Jens Reidel Signed-off-by: Luca Weiss Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250103-goodix-berlin-fixes-v1-1-b014737b08b2@fairphone.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix_berlin_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c index 3fc03cf0ca23..e273fb8edc6b 100644 --- a/drivers/input/touchscreen/goodix_berlin_core.c +++ b/drivers/input/touchscreen/goodix_berlin_core.c @@ -263,7 +263,7 @@ static int goodix_berlin_power_on(struct goodix_berlin_core *cd) goto err_iovdd_disable; } - /* Vendor waits 15ms for IOVDD to settle */ + /* Vendor waits 15ms for AVDD to settle */ usleep_range(15000, 15100); gpiod_set_value_cansleep(cd->reset_gpio, 0); From 3b0011059334a1cf554c2c1f67d7a7b822d8238a Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Fri, 3 Jan 2025 10:21:36 +0100 Subject: [PATCH 0242/1090] Input: goodix-berlin - fix vddio regulator references As per dt-bindings the property is called vddio-supply, so use the correct name in the driver instead of iovdd. The datasheet also calls the supply 'VDDIO'. Fixes: 44362279bdd4 ("Input: add core support for Goodix Berlin Touchscreen IC") Cc: stable@vger.kernel.org Signed-off-by: Luca Weiss Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250103-goodix-berlin-fixes-v1-2-b014737b08b2@fairphone.com Signed-off-by: Dmitry Torokhov --- .../input/touchscreen/goodix_berlin_core.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c index e273fb8edc6b..7f8cfdd106fa 100644 --- a/drivers/input/touchscreen/goodix_berlin_core.c +++ b/drivers/input/touchscreen/goodix_berlin_core.c @@ -165,7 +165,7 @@ struct goodix_berlin_core { struct device *dev; struct regmap *regmap; struct regulator *avdd; - struct regulator *iovdd; + struct regulator *vddio; struct gpio_desc *reset_gpio; struct touchscreen_properties props; struct goodix_berlin_fw_version fw_version; @@ -248,19 +248,19 @@ static int goodix_berlin_power_on(struct goodix_berlin_core *cd) { int error; - error = regulator_enable(cd->iovdd); + error = regulator_enable(cd->vddio); if (error) { - dev_err(cd->dev, "Failed to enable iovdd: %d\n", error); + dev_err(cd->dev, "Failed to enable vddio: %d\n", error); return error; } - /* Vendor waits 3ms for IOVDD to settle */ + /* Vendor waits 3ms for VDDIO to settle */ usleep_range(3000, 3100); error = regulator_enable(cd->avdd); if (error) { dev_err(cd->dev, "Failed to enable avdd: %d\n", error); - goto err_iovdd_disable; + goto err_vddio_disable; } /* Vendor waits 15ms for AVDD to settle */ @@ -283,8 +283,8 @@ static int goodix_berlin_power_on(struct goodix_berlin_core *cd) err_dev_reset: gpiod_set_value_cansleep(cd->reset_gpio, 1); regulator_disable(cd->avdd); -err_iovdd_disable: - regulator_disable(cd->iovdd); +err_vddio_disable: + regulator_disable(cd->vddio); return error; } @@ -292,7 +292,7 @@ static void goodix_berlin_power_off(struct goodix_berlin_core *cd) { gpiod_set_value_cansleep(cd->reset_gpio, 1); regulator_disable(cd->avdd); - regulator_disable(cd->iovdd); + regulator_disable(cd->vddio); } static int goodix_berlin_read_version(struct goodix_berlin_core *cd) @@ -744,10 +744,10 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, return dev_err_probe(dev, PTR_ERR(cd->avdd), "Failed to request avdd regulator\n"); - cd->iovdd = devm_regulator_get(dev, "iovdd"); - if (IS_ERR(cd->iovdd)) - return dev_err_probe(dev, PTR_ERR(cd->iovdd), - "Failed to request iovdd regulator\n"); + cd->vddio = devm_regulator_get(dev, "vddio"); + if (IS_ERR(cd->vddio)) + return dev_err_probe(dev, PTR_ERR(cd->vddio), + "Failed to request vddio regulator\n"); error = goodix_berlin_power_on(cd); if (error) { From 4b90de5bc0f5a6d1151acd74c838275f9b7be3a5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 24 Feb 2025 15:48:52 -0800 Subject: [PATCH 0243/1090] xfs: reduce context switches for synchronous buffered I/O Currently all metadata I/O completions happen in the m_buf_workqueue workqueue. But for synchronous I/O (i.e. all buffer reads) there is no need for that, as there always is a called in process context that is waiting for the I/O. Factor out the guts of xfs_buf_ioend into a separate helper and call it from xfs_buf_iowait to avoid a double an extra context switch to the workqueue. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_buf.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 15bb790359f8..dfc1849b3314 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1345,6 +1345,7 @@ xfs_buf_ioend_handle_error( resubmit: xfs_buf_ioerror(bp, 0); bp->b_flags |= (XBF_DONE | XBF_WRITE_FAIL); + reinit_completion(&bp->b_iowait); xfs_buf_submit(bp); return true; out_stale: @@ -1355,8 +1356,9 @@ out_stale: return false; } -static void -xfs_buf_ioend( +/* returns false if the caller needs to resubmit the I/O, else true */ +static bool +__xfs_buf_ioend( struct xfs_buf *bp) { trace_xfs_buf_iodone(bp, _RET_IP_); @@ -1376,7 +1378,7 @@ xfs_buf_ioend( } if (unlikely(bp->b_error) && xfs_buf_ioend_handle_error(bp)) - return; + return false; /* clear the retry state */ bp->b_last_error = 0; @@ -1397,7 +1399,15 @@ xfs_buf_ioend( bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD | _XBF_LOGRECOVERY); + return true; +} +static void +xfs_buf_ioend( + struct xfs_buf *bp) +{ + if (!__xfs_buf_ioend(bp)) + return; if (bp->b_flags & XBF_ASYNC) xfs_buf_relse(bp); else @@ -1411,15 +1421,8 @@ xfs_buf_ioend_work( struct xfs_buf *bp = container_of(work, struct xfs_buf, b_ioend_work); - xfs_buf_ioend(bp); -} - -static void -xfs_buf_ioend_async( - struct xfs_buf *bp) -{ - INIT_WORK(&bp->b_ioend_work, xfs_buf_ioend_work); - queue_work(bp->b_mount->m_buf_workqueue, &bp->b_ioend_work); + if (__xfs_buf_ioend(bp)) + xfs_buf_relse(bp); } void @@ -1491,7 +1494,13 @@ xfs_buf_bio_end_io( XFS_TEST_ERROR(false, bp->b_mount, XFS_ERRTAG_BUF_IOERROR)) xfs_buf_ioerror(bp, -EIO); - xfs_buf_ioend_async(bp); + if (bp->b_flags & XBF_ASYNC) { + INIT_WORK(&bp->b_ioend_work, xfs_buf_ioend_work); + queue_work(bp->b_mount->m_buf_workqueue, &bp->b_ioend_work); + } else { + complete(&bp->b_iowait); + } + bio_put(bio); } @@ -1568,9 +1577,11 @@ xfs_buf_iowait( { ASSERT(!(bp->b_flags & XBF_ASYNC)); - trace_xfs_buf_iowait(bp, _RET_IP_); - wait_for_completion(&bp->b_iowait); - trace_xfs_buf_iowait_done(bp, _RET_IP_); + do { + trace_xfs_buf_iowait(bp, _RET_IP_); + wait_for_completion(&bp->b_iowait); + trace_xfs_buf_iowait_done(bp, _RET_IP_); + } while (!__xfs_buf_ioend(bp)); return bp->b_error; } From efc5f7a9f3d887ce44b7610bc39388094b6f97d5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 24 Feb 2025 15:48:53 -0800 Subject: [PATCH 0244/1090] xfs: decouple buffer readahead from the normal buffer read path xfs_buf_readahead_map is the only caller of xfs_buf_read_map and thus _xfs_buf_read that is not synchronous. Split it from xfs_buf_read_map so that the asynchronous path is self-contained and the now purely synchronous xfs_buf_read_map / _xfs_buf_read implementation can be simplified. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_buf.c | 41 ++++++++++++++++++++-------------------- fs/xfs/xfs_buf.h | 2 +- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_trace.h | 1 + 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index dfc1849b3314..4ea20483d521 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -794,18 +794,13 @@ out_put_perag: int _xfs_buf_read( - struct xfs_buf *bp, - xfs_buf_flags_t flags) + struct xfs_buf *bp) { - ASSERT(!(flags & XBF_WRITE)); ASSERT(bp->b_maps[0].bm_bn != XFS_BUF_DADDR_NULL); bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD | XBF_DONE); - bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); - + bp->b_flags |= XBF_READ; xfs_buf_submit(bp); - if (flags & XBF_ASYNC) - return 0; return xfs_buf_iowait(bp); } @@ -857,6 +852,8 @@ xfs_buf_read_map( struct xfs_buf *bp; int error; + ASSERT(!(flags & (XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD))); + flags |= XBF_READ; *bpp = NULL; @@ -870,21 +867,11 @@ xfs_buf_read_map( /* Initiate the buffer read and wait. */ XFS_STATS_INC(target->bt_mount, xb_get_read); bp->b_ops = ops; - error = _xfs_buf_read(bp, flags); - - /* Readahead iodone already dropped the buffer, so exit. */ - if (flags & XBF_ASYNC) - return 0; + error = _xfs_buf_read(bp); } else { /* Buffer already read; all we need to do is check it. */ error = xfs_buf_reverify(bp, ops); - /* Readahead already finished; drop the buffer and exit. */ - if (flags & XBF_ASYNC) { - xfs_buf_relse(bp); - return 0; - } - /* We do not want read in the flags */ bp->b_flags &= ~XBF_READ; ASSERT(bp->b_ops != NULL || ops == NULL); @@ -936,6 +923,7 @@ xfs_buf_readahead_map( int nmaps, const struct xfs_buf_ops *ops) { + const xfs_buf_flags_t flags = XBF_READ | XBF_ASYNC | XBF_READ_AHEAD; struct xfs_buf *bp; /* @@ -945,9 +933,20 @@ xfs_buf_readahead_map( if (xfs_buftarg_is_mem(target)) return; - xfs_buf_read_map(target, map, nmaps, - XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD, &bp, ops, - __this_address); + if (xfs_buf_get_map(target, map, nmaps, flags | XBF_TRYLOCK, &bp)) + return; + trace_xfs_buf_readahead(bp, 0, _RET_IP_); + + if (bp->b_flags & XBF_DONE) { + xfs_buf_reverify(bp, ops); + xfs_buf_relse(bp); + return; + } + XFS_STATS_INC(target->bt_mount, xb_get_read); + bp->b_ops = ops; + bp->b_flags &= ~(XBF_WRITE | XBF_DONE); + bp->b_flags |= flags; + xfs_buf_submit(bp); } /* diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 3b4ed42e11c0..2e747555ad3f 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -291,7 +291,7 @@ int xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks, int xfs_buf_read_uncached(struct xfs_buftarg *target, xfs_daddr_t daddr, size_t numblks, xfs_buf_flags_t flags, struct xfs_buf **bpp, const struct xfs_buf_ops *ops); -int _xfs_buf_read(struct xfs_buf *bp, xfs_buf_flags_t flags); +int _xfs_buf_read(struct xfs_buf *bp); void xfs_buf_hold(struct xfs_buf *bp); /* Releasing Buffers */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index b3c27dbccce8..2f76531842f8 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3380,7 +3380,7 @@ xlog_do_recover( */ xfs_buf_lock(bp); xfs_buf_hold(bp); - error = _xfs_buf_read(bp, XBF_READ); + error = _xfs_buf_read(bp); if (error) { if (!xlog_is_shutdown(log)) { xfs_buf_ioerror_alert(bp, __this_address); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index b29462363b81..bfc2f1249022 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -593,6 +593,7 @@ DEFINE_EVENT(xfs_buf_flags_class, name, \ DEFINE_BUF_FLAGS_EVENT(xfs_buf_find); DEFINE_BUF_FLAGS_EVENT(xfs_buf_get); DEFINE_BUF_FLAGS_EVENT(xfs_buf_read); +DEFINE_BUF_FLAGS_EVENT(xfs_buf_readahead); TRACE_EVENT(xfs_buf_ioerror, TP_PROTO(struct xfs_buf *bp, int error, xfs_failaddr_t caller_ip), From 0d1120b9bbe48a2d119afe0dc64f9c0666745bc8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 24 Feb 2025 15:48:54 -0800 Subject: [PATCH 0245/1090] xfs: remove most in-flight buffer accounting The buffer cache keeps a bt_io_count per-CPU counter to track all in-flight I/O, which is used to ensure no I/O is in flight when unmounting the file system. For most I/O we already keep track of inflight I/O at higher levels: - for synchronous I/O (xfs_buf_read/xfs_bwrite/xfs_buf_delwri_submit), the caller has a reference and waits for I/O completions using xfs_buf_iowait - for xfs_buf_delwri_submit_nowait the only caller (AIL writeback) tracks the log items that the buffer attached to This only leaves only xfs_buf_readahead_map as a submitter of asynchronous I/O that is not tracked by anything else. Replace the bt_io_count per-cpu counter with a more specific bt_readahead_count counter only tracking readahead I/O. This allows to simply increment it when submitting readahead I/O and decrementing it when it completed, and thus simplify xfs_buf_rele and remove the needed for the XBF_NO_IOACCT flags and the XFS_BSTATE_IN_FLIGHT buffer state. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_buf.c | 90 ++++++++------------------------------------ fs/xfs/xfs_buf.h | 5 +-- fs/xfs/xfs_buf_mem.c | 2 +- fs/xfs/xfs_mount.c | 7 +--- fs/xfs/xfs_rtalloc.c | 2 +- 5 files changed, 20 insertions(+), 86 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 4ea20483d521..e161f3ab4108 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -29,11 +29,6 @@ struct kmem_cache *xfs_buf_cache; /* * Locking orders * - * xfs_buf_ioacct_inc: - * xfs_buf_ioacct_dec: - * b_sema (caller holds) - * b_lock - * * xfs_buf_stale: * b_sema (caller holds) * b_lock @@ -81,51 +76,6 @@ xfs_buf_vmap_len( return (bp->b_page_count * PAGE_SIZE); } -/* - * Bump the I/O in flight count on the buftarg if we haven't yet done so for - * this buffer. The count is incremented once per buffer (per hold cycle) - * because the corresponding decrement is deferred to buffer release. Buffers - * can undergo I/O multiple times in a hold-release cycle and per buffer I/O - * tracking adds unnecessary overhead. This is used for sychronization purposes - * with unmount (see xfs_buftarg_drain()), so all we really need is a count of - * in-flight buffers. - * - * Buffers that are never released (e.g., superblock, iclog buffers) must set - * the XBF_NO_IOACCT flag before I/O submission. Otherwise, the buftarg count - * never reaches zero and unmount hangs indefinitely. - */ -static inline void -xfs_buf_ioacct_inc( - struct xfs_buf *bp) -{ - if (bp->b_flags & XBF_NO_IOACCT) - return; - - ASSERT(bp->b_flags & XBF_ASYNC); - spin_lock(&bp->b_lock); - if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) { - bp->b_state |= XFS_BSTATE_IN_FLIGHT; - percpu_counter_inc(&bp->b_target->bt_io_count); - } - spin_unlock(&bp->b_lock); -} - -/* - * Clear the in-flight state on a buffer about to be released to the LRU or - * freed and unaccount from the buftarg. - */ -static inline void -__xfs_buf_ioacct_dec( - struct xfs_buf *bp) -{ - lockdep_assert_held(&bp->b_lock); - - if (bp->b_state & XFS_BSTATE_IN_FLIGHT) { - bp->b_state &= ~XFS_BSTATE_IN_FLIGHT; - percpu_counter_dec(&bp->b_target->bt_io_count); - } -} - /* * When we mark a buffer stale, we remove the buffer from the LRU and clear the * b_lru_ref count so that the buffer is freed immediately when the buffer @@ -156,8 +106,6 @@ xfs_buf_stale( * status now to preserve accounting consistency. */ spin_lock(&bp->b_lock); - __xfs_buf_ioacct_dec(bp); - atomic_set(&bp->b_lru_ref, 0); if (!(bp->b_state & XFS_BSTATE_DISPOSE) && (list_lru_del_obj(&bp->b_target->bt_lru, &bp->b_lru))) @@ -946,6 +894,7 @@ xfs_buf_readahead_map( bp->b_ops = ops; bp->b_flags &= ~(XBF_WRITE | XBF_DONE); bp->b_flags |= flags; + percpu_counter_inc(&target->bt_readahead_count); xfs_buf_submit(bp); } @@ -1002,10 +951,12 @@ xfs_buf_get_uncached( struct xfs_buf *bp; DEFINE_SINGLE_BUF_MAP(map, XFS_BUF_DADDR_NULL, numblks); + /* there are currently no valid flags for xfs_buf_get_uncached */ + ASSERT(flags == 0); + *bpp = NULL; - /* flags might contain irrelevant bits, pass only what we care about */ - error = _xfs_buf_alloc(target, &map, 1, flags & XBF_NO_IOACCT, &bp); + error = _xfs_buf_alloc(target, &map, 1, flags, &bp); if (error) return error; @@ -1059,7 +1010,6 @@ xfs_buf_rele_uncached( spin_unlock(&bp->b_lock); return; } - __xfs_buf_ioacct_dec(bp); spin_unlock(&bp->b_lock); xfs_buf_free(bp); } @@ -1078,19 +1028,11 @@ xfs_buf_rele_cached( spin_lock(&bp->b_lock); ASSERT(bp->b_hold >= 1); if (bp->b_hold > 1) { - /* - * Drop the in-flight state if the buffer is already on the LRU - * and it holds the only reference. This is racy because we - * haven't acquired the pag lock, but the use of _XBF_IN_FLIGHT - * ensures the decrement occurs only once per-buf. - */ - if (--bp->b_hold == 1 && !list_empty(&bp->b_lru)) - __xfs_buf_ioacct_dec(bp); + bp->b_hold--; goto out_unlock; } /* we are asked to drop the last reference */ - __xfs_buf_ioacct_dec(bp); if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { /* * If the buffer is added to the LRU, keep the reference to the @@ -1370,6 +1312,8 @@ __xfs_buf_ioend( bp->b_ops->verify_read(bp); if (!bp->b_error) bp->b_flags |= XBF_DONE; + if (bp->b_flags & XBF_READ_AHEAD) + percpu_counter_dec(&bp->b_target->bt_readahead_count); } else { if (!bp->b_error) { bp->b_flags &= ~XBF_WRITE_FAIL; @@ -1658,9 +1602,6 @@ xfs_buf_submit( */ bp->b_error = 0; - if (bp->b_flags & XBF_ASYNC) - xfs_buf_ioacct_inc(bp); - if ((bp->b_flags & XBF_WRITE) && !xfs_buf_verify_write(bp)) { xfs_force_shutdown(bp->b_mount, SHUTDOWN_CORRUPT_INCORE); xfs_buf_ioend(bp); @@ -1786,9 +1727,8 @@ xfs_buftarg_wait( struct xfs_buftarg *btp) { /* - * First wait on the buftarg I/O count for all in-flight buffers to be - * released. This is critical as new buffers do not make the LRU until - * they are released. + * First wait for all in-flight readahead buffers to be released. This is + * critical as new buffers do not make the LRU until they are released. * * Next, flush the buffer workqueue to ensure all completion processing * has finished. Just waiting on buffer locks is not sufficient for @@ -1797,7 +1737,7 @@ xfs_buftarg_wait( * all reference counts have been dropped before we start walking the * LRU list. */ - while (percpu_counter_sum(&btp->bt_io_count)) + while (percpu_counter_sum(&btp->bt_readahead_count)) delay(100); flush_workqueue(btp->bt_mount->m_buf_workqueue); } @@ -1914,8 +1854,8 @@ xfs_destroy_buftarg( struct xfs_buftarg *btp) { shrinker_free(btp->bt_shrinker); - ASSERT(percpu_counter_sum(&btp->bt_io_count) == 0); - percpu_counter_destroy(&btp->bt_io_count); + ASSERT(percpu_counter_sum(&btp->bt_readahead_count) == 0); + percpu_counter_destroy(&btp->bt_readahead_count); list_lru_destroy(&btp->bt_lru); } @@ -1969,7 +1909,7 @@ xfs_init_buftarg( if (list_lru_init(&btp->bt_lru)) return -ENOMEM; - if (percpu_counter_init(&btp->bt_io_count, 0, GFP_KERNEL)) + if (percpu_counter_init(&btp->bt_readahead_count, 0, GFP_KERNEL)) goto out_destroy_lru; btp->bt_shrinker = @@ -1983,7 +1923,7 @@ xfs_init_buftarg( return 0; out_destroy_io_count: - percpu_counter_destroy(&btp->bt_io_count); + percpu_counter_destroy(&btp->bt_readahead_count); out_destroy_lru: list_lru_destroy(&btp->bt_lru); return -ENOMEM; diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 2e747555ad3f..80e06eecaf56 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -27,7 +27,6 @@ struct xfs_buf; #define XBF_READ (1u << 0) /* buffer intended for reading from device */ #define XBF_WRITE (1u << 1) /* buffer intended for writing to device */ #define XBF_READ_AHEAD (1u << 2) /* asynchronous read-ahead */ -#define XBF_NO_IOACCT (1u << 3) /* bypass I/O accounting (non-LRU bufs) */ #define XBF_ASYNC (1u << 4) /* initiator will not wait for completion */ #define XBF_DONE (1u << 5) /* all pages in the buffer uptodate */ #define XBF_STALE (1u << 6) /* buffer has been staled, do not find it */ @@ -58,7 +57,6 @@ typedef unsigned int xfs_buf_flags_t; { XBF_READ, "READ" }, \ { XBF_WRITE, "WRITE" }, \ { XBF_READ_AHEAD, "READ_AHEAD" }, \ - { XBF_NO_IOACCT, "NO_IOACCT" }, \ { XBF_ASYNC, "ASYNC" }, \ { XBF_DONE, "DONE" }, \ { XBF_STALE, "STALE" }, \ @@ -77,7 +75,6 @@ typedef unsigned int xfs_buf_flags_t; * Internal state flags. */ #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ -#define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ struct xfs_buf_cache { struct rhashtable bc_hash; @@ -116,7 +113,7 @@ struct xfs_buftarg { struct shrinker *bt_shrinker; struct list_lru bt_lru; - struct percpu_counter bt_io_count; + struct percpu_counter bt_readahead_count; struct ratelimit_state bt_ioerror_rl; /* Atomic write unit values */ diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c index 07bebbfb16ee..5b64a2b3b113 100644 --- a/fs/xfs/xfs_buf_mem.c +++ b/fs/xfs/xfs_buf_mem.c @@ -117,7 +117,7 @@ xmbuf_free( struct xfs_buftarg *btp) { ASSERT(xfs_buftarg_is_mem(btp)); - ASSERT(percpu_counter_sum(&btp->bt_io_count) == 0); + ASSERT(percpu_counter_sum(&btp->bt_readahead_count) == 0); trace_xmbuf_free(btp); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 477c5262cf91..b69356582b86 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -181,14 +181,11 @@ xfs_readsb( /* * Allocate a (locked) buffer to hold the superblock. This will be kept - * around at all times to optimize access to the superblock. Therefore, - * set XBF_NO_IOACCT to make sure it doesn't hold the buftarg count - * elevated. + * around at all times to optimize access to the superblock. */ reread: error = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), XBF_NO_IOACCT, &bp, - buf_ops); + BTOBB(sector_size), 0, &bp, buf_ops); if (error) { if (loud) xfs_warn(mp, "SB validate failed with error %d.", error); diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index d8e6d073d64d..57bef567e011 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1407,7 +1407,7 @@ xfs_rtmount_readsb( /* m_blkbb_log is not set up yet */ error = xfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR, - mp->m_sb.sb_blocksize >> BBSHIFT, XBF_NO_IOACCT, &bp, + mp->m_sb.sb_blocksize >> BBSHIFT, 0, &bp, &xfs_rtsb_buf_ops); if (error) { xfs_warn(mp, "rt sb validate failed with error %d.", error); From 9b47d37496e2669078c8616334e5a7200f91681a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 24 Feb 2025 15:48:55 -0800 Subject: [PATCH 0246/1090] xfs: remove the XBF_STALE check from xfs_buf_rele_cached xfs_buf_stale already set b_lru_ref to 0, and thus prevents the buffer from moving to the LRU. Remove the duplicate check. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Darrick J. Wong Signed-off-by: Carlos Maiolino --- fs/xfs/xfs_buf.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index e161f3ab4108..5d560e9073f4 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -99,12 +99,6 @@ xfs_buf_stale( */ bp->b_flags &= ~_XBF_DELWRI_Q; - /* - * Once the buffer is marked stale and unlocked, a subsequent lookup - * could reset b_flags. There is no guarantee that the buffer is - * unaccounted (released to LRU) before that occurs. Drop in-flight - * status now to preserve accounting consistency. - */ spin_lock(&bp->b_lock); atomic_set(&bp->b_lru_ref, 0); if (!(bp->b_state & XFS_BSTATE_DISPOSE) && @@ -1033,7 +1027,7 @@ xfs_buf_rele_cached( } /* we are asked to drop the last reference */ - if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { + if (atomic_read(&bp->b_lru_ref)) { /* * If the buffer is added to the LRU, keep the reference to the * buffer for the LRU and clear the (now stale) dispose list From 5a09e179024e76afdf9ad3a6ae767b4e06884ea8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2025 01:19:10 +0000 Subject: [PATCH 0247/1090] ASoC: Documentation: DPCM: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikp6vii9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dpcm.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/soc/dpcm.rst b/Documentation/sound/soc/dpcm.rst index 02419a6f8213..a12636552f50 100644 --- a/Documentation/sound/soc/dpcm.rst +++ b/Documentation/sound/soc/dpcm.rst @@ -362,7 +362,7 @@ The machine driver sets some additional parameters to the DAI link i.e. .codec_dai_name = "modem-aif1", .codec_name = "modem", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .c2c_params = &dai_params, .num_c2c_params = 1, } From 1c4749873bd0f769a47372636a428484e7035f59 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2025 01:19:48 +0000 Subject: [PATCH 0248/1090] ASoC: kirkwood: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczuvih7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/kirkwood/armada-370-db.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index 79ee7599f06a..77a5f440364e 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -73,20 +73,20 @@ static struct snd_soc_dai_link a370db_dai[] = { { .name = "CS42L51", .stream_name = "analog", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC, .ops = &a370db_ops, SND_SOC_DAILINK_REG(analog), }, { .name = "S/PDIF out", .stream_name = "spdif-out", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(spdif_out), }, { .name = "S/PDIF in", .stream_name = "spdif-in", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(spdif_in), }, }; From 38399716e353776dca7f04dbae98a07af68f2880 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2025 01:19:31 +0000 Subject: [PATCH 0249/1090] ASoC: ti: rx51: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frkaviho.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/rx51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index d9900c69e536..e969031657e9 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -307,7 +307,7 @@ static struct snd_soc_dai_link rx51_dai[] = { .name = "TLV320AIC34", .stream_name = "AIC34", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .init = rx51_aic34_init, .ops = &rx51_ops, SND_SOC_DAILINK_REG(aic34), From a5a3de8990f47f4c54ca5daeeea8ff7daa42f9de Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 19 Feb 2025 01:19:21 +0000 Subject: [PATCH 0250/1090] ASoC: sh: migor: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64qvihz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/renesas/migor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/renesas/migor.c b/sound/soc/renesas/migor.c index 5a0bc6edac0a..45fc594d331b 100644 --- a/sound/soc/renesas/migor.c +++ b/sound/soc/renesas/migor.c @@ -132,7 +132,7 @@ static struct snd_soc_dai_link migor_dai = { .name = "wm8978", .stream_name = "WM8978", .dai_fmt = SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &migor_dai_ops, SND_SOC_DAILINK_REG(wm8978), }; From 63d93f4d0f38fbb95a55729fbd2cc4920743931c Mon Sep 17 00:00:00 2001 From: Ethan Carter Edwards Date: Sat, 22 Feb 2025 14:55:20 -0500 Subject: [PATCH 0251/1090] ASoC: q6dsp: q6apm: replace kzalloc() with kcalloc() in q6apm_map_memory_regions() We are trying to get rid of all multiplications from allocation functions to prevent integer overflows[1]. Here the multiplication is obviously safe, but using kcalloc() is more appropriate and improves readability. This patch has no effect on runtime behavior. Link: https://github.com/KSPP/linux/issues/162 [1] Link: https://www.kernel.org/doc/html/next/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Ethan Carter Edwards Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20250222-q6apm-kcalloc-v1-1-6f09dae6c31c@ethancedwards.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 2a2a5bd98110..11e252a70f69 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -230,7 +230,7 @@ int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_a return 0; } - buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_KERNEL); + buf = kcalloc(periods, sizeof(struct audio_buffer), GFP_KERNEL); if (!buf) { mutex_unlock(&graph->lock); return -ENOMEM; From 8fd0e127d8da856e34391399df40b33af2b307e0 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Mon, 24 Feb 2025 23:12:12 +0100 Subject: [PATCH 0252/1090] ASoC: amd: acp: acp70: Remove unnecessary if-check Since list_for_each_entry() expects the list to not be empty, the iterator variable cannot be NULL and the unnecessary if-check can be removed. Remove it and indent the code accordingly. Compile-tested only. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250224221214.199849-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp70.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index ef3f6504bc7f..7f4ec3bfaeab 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -230,18 +230,16 @@ static int __maybe_unused acp70_pcm_resume(struct device *dev) spin_lock(&adata->acp_lock); list_for_each_entry(stream, &adata->stream_list, list) { - if (stream) { - substream = stream->substream; - if (substream && substream->runtime) { - buf_in_frames = (substream->runtime->buffer_size); - buf_size = frames_to_bytes(substream->runtime, buf_in_frames); - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, buf_size); - if (stream->dai_id) - restore_acp_i2s_params(substream, adata, stream); - else - restore_acp_pdm_params(substream, adata); - } + substream = stream->substream; + if (substream && substream->runtime) { + buf_in_frames = (substream->runtime->buffer_size); + buf_size = frames_to_bytes(substream->runtime, buf_in_frames); + config_pte_for_stream(adata, stream); + config_acp_dma(adata, stream, buf_size); + if (stream->dai_id) + restore_acp_i2s_params(substream, adata, stream); + else + restore_acp_pdm_params(substream, adata); } } spin_unlock(&adata->acp_lock); From 6542db20caf4987b938ed8feec07d199779823f2 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 24 Feb 2025 17:04:12 +0800 Subject: [PATCH 0253/1090] ASoC: dt-bindings: fsl,easrc: Reference common DAI properties Reference the dai-common.yaml schema to allow '#sound-dai-cells' and "sound-name-prefix' to be used. Signed-off-by: Shengjiu Wang Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250224090413.727911-2-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,easrc.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml index c454110f4281..8f1108e7e14e 100644 --- a/Documentation/devicetree/bindings/sound/fsl,easrc.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,easrc.yaml @@ -80,7 +80,10 @@ required: - fsl,asrc-rate - fsl,asrc-format -additionalProperties: false +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false examples: - | From 3e7b375752b5e4de56e92dfb9c43309cd985b869 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 24 Feb 2025 17:04:13 +0800 Subject: [PATCH 0254/1090] ASoC: dt-bindings: fsl,imx-asrc: Reference common DAI properties Reference the dai-common.yaml schema to allow '#sound-dai-cells' and "sound-name-prefix' to be used. Signed-off-by: Shengjiu Wang Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250224090413.727911-3-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml index 76aa1f248488..abac5084d63b 100644 --- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml @@ -120,6 +120,7 @@ required: - fsl,asrc-width allOf: + - $ref: dai-common.yaml# - if: properties: compatible: @@ -145,7 +146,7 @@ allOf: required: - power-domains -additionalProperties: false +unevaluatedProperties: false examples: - | From ef6a24c79d5047c029577113af43eddd1d0f1bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 25 Feb 2025 11:33:47 -0300 Subject: [PATCH 0255/1090] ASoC: mediatek: mt8188: Add audsys hires clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Describe and register the aud_dmic_hires audsys clocks, which are needed when recording the DMIC at a sample rate of 96k. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250225-genio700-dmic-v2-1-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-audsys-clk.c | 4 ++++ sound/soc/mediatek/mt8188/mt8188-audsys-clkid.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c index c796ad8b62ee..40d2ab0a7677 100644 --- a/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c +++ b/sound/soc/mediatek/mt8188/mt8188-audsys-clk.c @@ -84,6 +84,10 @@ static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = { GATE_AUD1(CLK_AUD_AFE_26M_DMIC_TM, "aud_afe_26m_dmic_tm", "top_a1sys_hp", 14), GATE_AUD1(CLK_AUD_UL_TML_HIRES, "aud_ul_tml_hires", "top_audio_h", 16), GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "top_audio_h", 17), + GATE_AUD1(CLK_AUD_DMIC_HIRES1, "aud_dmic_hires1", "top_audio_h", 20), + GATE_AUD1(CLK_AUD_DMIC_HIRES2, "aud_dmic_hires2", "top_audio_h", 21), + GATE_AUD1(CLK_AUD_DMIC_HIRES3, "aud_dmic_hires3", "top_audio_h", 22), + GATE_AUD1(CLK_AUD_DMIC_HIRES4, "aud_dmic_hires4", "top_audio_h", 23), /* AUD3 */ GATE_AUD3(CLK_AUD_LINEIN_TUNER, "aud_linein_tuner", "top_apll5", 5), diff --git a/sound/soc/mediatek/mt8188/mt8188-audsys-clkid.h b/sound/soc/mediatek/mt8188/mt8188-audsys-clkid.h index 6f34ffc760e0..9cb732863c10 100644 --- a/sound/soc/mediatek/mt8188/mt8188-audsys-clkid.h +++ b/sound/soc/mediatek/mt8188/mt8188-audsys-clkid.h @@ -33,6 +33,10 @@ enum{ CLK_AUD_AFE_26M_DMIC_TM, CLK_AUD_UL_TML_HIRES, CLK_AUD_ADC_HIRES, + CLK_AUD_DMIC_HIRES1, + CLK_AUD_DMIC_HIRES2, + CLK_AUD_DMIC_HIRES3, + CLK_AUD_DMIC_HIRES4, CLK_AUD_LINEIN_TUNER, CLK_AUD_EARC_TUNER, CLK_AUD_I2SIN, From bf1800073f4d55f08191b034c86b95881e99b6fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 25 Feb 2025 11:33:48 -0300 Subject: [PATCH 0256/1090] ASoC: mediatek: mt8188: Add reference for dmic clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the names for the dmic clocks, aud_afe_dmic* and aud_dmic_hires*, so they can be acquired and enabled by the platform driver. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250225-genio700-dmic-v2-2-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-afe-clk.c | 8 ++++++++ sound/soc/mediatek/mt8188/mt8188-afe-clk.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c index e69c1bb2cb23..7f411b857782 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c @@ -58,7 +58,15 @@ static const char *aud_clks[MT8188_CLK_NUM] = { [MT8188_CLK_AUD_ADC] = "aud_adc", [MT8188_CLK_AUD_DAC_HIRES] = "aud_dac_hires", [MT8188_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp", + [MT8188_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1", + [MT8188_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2", + [MT8188_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3", + [MT8188_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4", [MT8188_CLK_AUD_ADC_HIRES] = "aud_adc_hires", + [MT8188_CLK_AUD_DMIC_HIRES1] = "aud_dmic_hires1", + [MT8188_CLK_AUD_DMIC_HIRES2] = "aud_dmic_hires2", + [MT8188_CLK_AUD_DMIC_HIRES3] = "aud_dmic_hires3", + [MT8188_CLK_AUD_DMIC_HIRES4] = "aud_dmic_hires4", [MT8188_CLK_AUD_I2SIN] = "aud_i2sin", [MT8188_CLK_AUD_TDM_IN] = "aud_tdm_in", [MT8188_CLK_AUD_I2S_OUT] = "aud_i2s_out", diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h index ec53c171c170..c6c78d684f3e 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.h +++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.h @@ -54,7 +54,15 @@ enum { MT8188_CLK_AUD_ADC, MT8188_CLK_AUD_DAC_HIRES, MT8188_CLK_AUD_A1SYS_HP, + MT8188_CLK_AUD_AFE_DMIC1, + MT8188_CLK_AUD_AFE_DMIC2, + MT8188_CLK_AUD_AFE_DMIC3, + MT8188_CLK_AUD_AFE_DMIC4, MT8188_CLK_AUD_ADC_HIRES, + MT8188_CLK_AUD_DMIC_HIRES1, + MT8188_CLK_AUD_DMIC_HIRES2, + MT8188_CLK_AUD_DMIC_HIRES3, + MT8188_CLK_AUD_DMIC_HIRES4, MT8188_CLK_AUD_I2SIN, MT8188_CLK_AUD_TDM_IN, MT8188_CLK_AUD_I2S_OUT, From 7d87bde21c73731ddaf15e572020f80999c38ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 25 Feb 2025 11:33:49 -0300 Subject: [PATCH 0257/1090] ASoC: mediatek: mt8188: Treat DMIC_GAINx_CUR as non-volatile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DMIC_GAINx_CUR registers contain the current (as in present) gain of each DMIC. During capture, this gain will ramp up until a target value is reached, and therefore the register is volatile since it is updated automatically by hardware. However, after capture the register's value returns to the value that was written to it. So reading these registers returns the current gain, and writing configures the initial gain for every capture. >From an audio configuration perspective, reading the instantaneous gain is not really useful. Instead, reading back the initial gain that was configured is the desired behavior. For that reason, consider the DMIC_GAINx_CUR registers as non-volatile, so the regmap's cache can be used to retrieve the values, rather than requiring pm runtime resuming the device. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250225-genio700-dmic-v2-3-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index 73e5c63aeec8..d36520c6272d 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -2855,10 +2855,6 @@ static bool mt8188_is_volatile_reg(struct device *dev, unsigned int reg) case AFE_DMIC3_SRC_DEBUG_MON0: case AFE_DMIC3_UL_SRC_MON0: case AFE_DMIC3_UL_SRC_MON1: - case DMIC_GAIN1_CUR: - case DMIC_GAIN2_CUR: - case DMIC_GAIN3_CUR: - case DMIC_GAIN4_CUR: case ETDM_IN1_MONITOR: case ETDM_IN2_MONITOR: case ETDM_OUT1_MONITOR: From c1e42ec04197ac013d049dde40d9c72cf543b5f6 Mon Sep 17 00:00:00 2001 From: parkeryang Date: Tue, 25 Feb 2025 11:33:50 -0300 Subject: [PATCH 0258/1090] ASoC: mediatek: mt8188: Add support for DMIC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the DMIC DAIs present on the MT8188 SoC. To achieve that, add a DAI driver for DMIC and register it during probe, and describe the AFE routes that connect the DMIC (I004-I011) to the UL9 frontend (O002-O009). Signed-off-by: parkeryang Co-developed-by: Nícolas F. R. A. Prado Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250225-genio700-dmic-v2-4-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/Makefile | 1 + sound/soc/mediatek/mt8188/mt8188-afe-common.h | 1 + sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 24 + sound/soc/mediatek/mt8188/mt8188-dai-dmic.c | 682 ++++++++++++++++++ sound/soc/mediatek/mt8188/mt8188-reg.h | 17 +- 5 files changed, 723 insertions(+), 2 deletions(-) create mode 100644 sound/soc/mediatek/mt8188/mt8188-dai-dmic.c diff --git a/sound/soc/mediatek/mt8188/Makefile b/sound/soc/mediatek/mt8188/Makefile index 1178bce45c50..b9f3e4ad7b07 100644 --- a/sound/soc/mediatek/mt8188/Makefile +++ b/sound/soc/mediatek/mt8188/Makefile @@ -6,6 +6,7 @@ snd-soc-mt8188-afe-y := \ mt8188-afe-pcm.o \ mt8188-audsys-clk.o \ mt8188-dai-adda.o \ + mt8188-dai-dmic.o \ mt8188-dai-etdm.o \ mt8188-dai-pcm.o diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-common.h b/sound/soc/mediatek/mt8188/mt8188-afe-common.h index 1304d685a306..01aa11242e29 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-common.h +++ b/sound/soc/mediatek/mt8188/mt8188-afe-common.h @@ -137,6 +137,7 @@ struct mt8188_afe_private { int mt8188_afe_fs_timing(unsigned int rate); /* dai register */ int mt8188_dai_adda_register(struct mtk_base_afe *afe); +int mt8188_dai_dmic_register(struct mtk_base_afe *afe); int mt8188_dai_etdm_register(struct mtk_base_afe *afe); int mt8188_dai_pcm_register(struct mtk_base_afe *afe); diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index d36520c6272d..a2b57e00ff4e 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -652,6 +652,7 @@ static struct snd_soc_dai_driver mt8188_memif_dai_driver[] = { static const struct snd_kcontrol_new o002_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN2, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I004 Switch", AFE_CONN2, 4, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN2, 12, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN2, 20, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN2, 22, 1, 0), @@ -662,6 +663,8 @@ static const struct snd_kcontrol_new o002_mix[] = { static const struct snd_kcontrol_new o003_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN3, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I005 Switch", AFE_CONN3, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I006 Switch", AFE_CONN3, 6, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN3, 13, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN3, 21, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN3, 23, 1, 0), @@ -672,6 +675,8 @@ static const struct snd_kcontrol_new o003_mix[] = { static const struct snd_kcontrol_new o004_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN4, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I006 Switch", AFE_CONN4, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I008 Switch", AFE_CONN4, 8, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN4, 14, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN4, 24, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN4_2, 10, 1, 0), @@ -679,6 +684,8 @@ static const struct snd_kcontrol_new o004_mix[] = { static const struct snd_kcontrol_new o005_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN5, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I007 Switch", AFE_CONN5, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I010 Switch", AFE_CONN5, 10, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN5, 15, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN5, 25, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN5_2, 11, 1, 0), @@ -686,6 +693,7 @@ static const struct snd_kcontrol_new o005_mix[] = { static const struct snd_kcontrol_new o006_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN6, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I008 Switch", AFE_CONN6, 8, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN6, 16, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN6, 26, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN6_2, 12, 1, 0), @@ -693,18 +701,21 @@ static const struct snd_kcontrol_new o006_mix[] = { static const struct snd_kcontrol_new o007_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN7, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I009 Switch", AFE_CONN7, 9, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN7, 17, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN7, 27, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN7_2, 13, 1, 0), }; static const struct snd_kcontrol_new o008_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I010 Switch", AFE_CONN8, 10, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN8, 18, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN8, 28, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN8_2, 14, 1, 0), }; static const struct snd_kcontrol_new o009_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I011 Switch", AFE_CONN9, 11, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN9, 19, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN9, 29, 1, 0), SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN9_2, 15, 1, 0), @@ -1275,6 +1286,18 @@ static const struct snd_soc_dapm_route mt8188_memif_routes[] = { {"O002", "I070 Switch", "I070"}, {"O003", "I071 Switch", "I071"}, + {"O002", "I004 Switch", "I004"}, + {"O003", "I005 Switch", "I005"}, + {"O003", "I006 Switch", "I006"}, + {"O004", "I006 Switch", "I006"}, + {"O004", "I008 Switch", "I008"}, + {"O005", "I007 Switch", "I007"}, + {"O005", "I010 Switch", "I010"}, + {"O006", "I008 Switch", "I008"}, + {"O007", "I009 Switch", "I009"}, + {"O008", "I010 Switch", "I010"}, + {"O009", "I011 Switch", "I011"}, + {"O034", "I000 Switch", "I000"}, {"O035", "I001 Switch", "I001"}, {"O034", "I002 Switch", "I002"}, @@ -3072,6 +3095,7 @@ static int mt8188_dai_memif_register(struct mtk_base_afe *afe) typedef int (*dai_register_cb)(struct mtk_base_afe *); static const dai_register_cb dai_register_cbs[] = { mt8188_dai_adda_register, + mt8188_dai_dmic_register, mt8188_dai_etdm_register, mt8188_dai_pcm_register, mt8188_dai_memif_register, diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c b/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c new file mode 100644 index 000000000000..4cfbcb71d2d9 --- /dev/null +++ b/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c @@ -0,0 +1,682 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI DMIC I/F Control + * + * Copyright (c) 2020 MediaTek Inc. + * Author: Bicycle Tsai + * Trevor Wu + * Parker Yang + */ + +#include +#include +#include +#include +#include "mt8188-afe-clk.h" +#include "mt8188-afe-common.h" +#include "mt8188-reg.h" + +/* DMIC HW Gain configuration maximum value. */ +#define DMIC_GAIN_MAX_STEP GENMASK(19, 0) +#define DMIC_GAIN_MAX_PER_STEP GENMASK(7, 0) +#define DMIC_GAIN_MAX_TARGET GENMASK(27, 0) +#define DMIC_GAIN_MAX_CURRENT GENMASK(27, 0) + +#define CLK_PHASE_SEL_CH1 0 +#define CLK_PHASE_SEL_CH2 ((CLK_PHASE_SEL_CH1) + 4) + +#define DMIC1_SRC_SEL 0 +#define DMIC2_SRC_SEL 0 +#define DMIC3_SRC_SEL 2 +#define DMIC4_SRC_SEL 0 +#define DMIC5_SRC_SEL 4 +#define DMIC6_SRC_SEL 0 +#define DMIC7_SRC_SEL 6 +#define DMIC8_SRC_SEL 0 + +enum { + SUPPLY_SEQ_DMIC_GAIN, + SUPPLY_SEQ_DMIC_CK, +}; + +enum { + DMIC0, + DMIC1, + DMIC2, + DMIC3, + DMIC_NUM, +}; + +struct mtk_dai_dmic_ctrl_reg { + unsigned int con0; +}; + +struct mtk_dai_dmic_hw_gain_ctrl_reg { + unsigned int bypass; + unsigned int con0; +}; + +struct mtk_dai_dmic_priv { + unsigned int gain_on[DMIC_NUM]; + unsigned int channels; + bool hires_required; +}; + +static const struct mtk_dai_dmic_ctrl_reg dmic_ctrl_regs[DMIC_NUM] = { + [DMIC0] = { + .con0 = AFE_DMIC0_UL_SRC_CON0, + }, + [DMIC1] = { + .con0 = AFE_DMIC1_UL_SRC_CON0, + }, + [DMIC2] = { + .con0 = AFE_DMIC2_UL_SRC_CON0, + }, + [DMIC3] = { + .con0 = AFE_DMIC3_UL_SRC_CON0, + }, +}; + +static const struct mtk_dai_dmic_ctrl_reg *get_dmic_ctrl_reg(int id) +{ + if (id < 0 || id >= DMIC_NUM) + return NULL; + + return &dmic_ctrl_regs[id]; +} + +static const struct mtk_dai_dmic_hw_gain_ctrl_reg + dmic_hw_gain_ctrl_regs[DMIC_NUM] = { + [DMIC0] = { + .bypass = DMIC_BYPASS_HW_GAIN, + .con0 = DMIC_GAIN1_CON0, + }, + [DMIC1] = { + .bypass = DMIC_BYPASS_HW_GAIN, + .con0 = DMIC_GAIN2_CON0, + }, + [DMIC2] = { + .bypass = DMIC_BYPASS_HW_GAIN, + .con0 = DMIC_GAIN3_CON0, + }, + [DMIC3] = { + .bypass = DMIC_BYPASS_HW_GAIN, + .con0 = DMIC_GAIN4_CON0, + }, +}; + +static const struct mtk_dai_dmic_hw_gain_ctrl_reg + *get_dmic_hw_gain_ctrl_reg(struct mtk_base_afe *afe, int id) +{ + if ((id < 0) || (id >= DMIC_NUM)) { + dev_dbg(afe->dev, "%s invalid id\n", __func__); + return NULL; + } + + return &dmic_hw_gain_ctrl_regs[id]; +} + +static void mtk_dai_dmic_hw_gain_bypass(struct mtk_base_afe *afe, + unsigned int id, bool bypass) +{ + const struct mtk_dai_dmic_hw_gain_ctrl_reg *reg; + unsigned int msk; + + reg = get_dmic_hw_gain_ctrl_reg(afe, id); + if (!reg) + return; + + switch (id) { + case DMIC0: + msk = DMIC_BYPASS_HW_GAIN_DMIC1_BYPASS; + break; + case DMIC1: + msk = DMIC_BYPASS_HW_GAIN_DMIC2_BYPASS; + break; + case DMIC2: + msk = DMIC_BYPASS_HW_GAIN_DMIC3_BYPASS; + break; + case DMIC3: + msk = DMIC_BYPASS_HW_GAIN_DMIC4_BYPASS; + break; + default: + return; + } + + if (bypass) + regmap_set_bits(afe->regmap, reg->bypass, msk); + else + regmap_clear_bits(afe->regmap, reg->bypass, msk); +} + +static void mtk_dai_dmic_hw_gain_on(struct mtk_base_afe *afe, unsigned int id, + bool on) +{ + const struct mtk_dai_dmic_hw_gain_ctrl_reg *reg = get_dmic_hw_gain_ctrl_reg(afe, id); + + if (!reg) + return; + + if (on) + regmap_set_bits(afe->regmap, reg->con0, DMIC_GAIN_CON0_GAIN_ON); + else + regmap_clear_bits(afe->regmap, reg->con0, DMIC_GAIN_CON0_GAIN_ON); +} + +static const struct reg_sequence mtk_dai_dmic_iir_coeff_reg_defaults[] = { + { AFE_DMIC0_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC0_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC0_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC0_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC0_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC1_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC1_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC1_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC1_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC1_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC2_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC2_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC2_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC2_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC2_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC3_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC3_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC3_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC3_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC3_IIR_COEF_10_09, 0x0000C048 }, +}; + +static int mtk_dai_dmic_load_iir_coeff_table(struct mtk_base_afe *afe) +{ + return regmap_multi_reg_write(afe->regmap, + mtk_dai_dmic_iir_coeff_reg_defaults, + ARRAY_SIZE(mtk_dai_dmic_iir_coeff_reg_defaults)); +} + +static int mtk_dai_dmic_configure_array(struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + const u32 mask = PWR2_TOP_CON_DMIC8_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC7_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC6_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC5_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC4_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC3_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC2_SRC_SEL_MASK | + PWR2_TOP_CON_DMIC1_SRC_SEL_MASK; + const u32 val = PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(DMIC8_SRC_SEL) | + PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(DMIC7_SRC_SEL) | + PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(DMIC6_SRC_SEL) | + PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(DMIC5_SRC_SEL) | + PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(DMIC4_SRC_SEL) | + PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(DMIC3_SRC_SEL) | + PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(DMIC2_SRC_SEL) | + PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(DMIC1_SRC_SEL); + + return regmap_update_bits(afe->regmap, PWR2_TOP_CON0, mask, val); +} + +/* This function assumes that the caller checked that channels is valid */ +static u8 mtk_dmic_channels_to_dmic_number(unsigned int channels) +{ + switch (channels) { + case 1: + return DMIC0; + case 2: + return DMIC1; + case 3: + return DMIC2; + case 4: + default: + return DMIC3; + } +} + +static void mtk_dai_dmic_hw_gain_enable(struct mtk_base_afe *afe, + unsigned int channels, bool enable) +{ + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + u8 dmic_num; + int i; + + dmic_num = mtk_dmic_channels_to_dmic_number(channels); + for (i = dmic_num; i >= DMIC0; i--) { + if (enable && dmic_priv->gain_on[i]) { + mtk_dai_dmic_hw_gain_bypass(afe, i, false); + mtk_dai_dmic_hw_gain_on(afe, i, true); + } else { + mtk_dai_dmic_hw_gain_on(afe, i, false); + mtk_dai_dmic_hw_gain_bypass(afe, i, true); + } + } +} + +static int mtk_dmic_gain_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + unsigned int channels = dmic_priv->channels; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + if (!channels) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mtk_dai_dmic_hw_gain_enable(afe, channels, true); + break; + case SND_SOC_DAPM_POST_PMD: + mtk_dai_dmic_hw_gain_enable(afe, channels, false); + break; + default: + break; + } + + return 0; +} + +static int mtk_dmic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + const struct mtk_dai_dmic_ctrl_reg *reg = NULL; + unsigned int channels = dmic_priv->channels; + unsigned int msk; + u8 dmic_num; + int i; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + if (!channels) + return -EINVAL; + + dmic_num = mtk_dmic_channels_to_dmic_number(channels); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* request fifo soft rst */ + for (i = dmic_num; i >= DMIC0; i--) + msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i); + + regmap_set_bits(afe->regmap, PWR2_TOP_CON1, msk); + + msk = AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL | + AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL | + AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL | + AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL; + + for (i = dmic_num; i >= DMIC0; i--) { + reg = get_dmic_ctrl_reg(i); + if (reg) + regmap_set_bits(afe->regmap, reg->con0, msk); + } + break; + case SND_SOC_DAPM_POST_PMU: + msk = AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL; + + for (i = dmic_num; i >= DMIC0; i--) { + reg = get_dmic_ctrl_reg(i); + if (reg) + regmap_set_bits(afe->regmap, reg->con0, msk); + } + + if (dmic_priv->hires_required) { + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES1]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES2]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES3]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES4]); + } + + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC1]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC2]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC3]); + mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC4]); + + /* release fifo soft rst */ + msk = 0; + for (i = dmic_num; i >= DMIC0; i--) + msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i); + + regmap_clear_bits(afe->regmap, PWR2_TOP_CON1, msk); + break; + case SND_SOC_DAPM_PRE_PMD: + msk = AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL | + AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL | + AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL | + AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL | + AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL; + + for (i = dmic_num; i >= DMIC0; i--) { + reg = get_dmic_ctrl_reg(i); + if (reg) + regmap_set_bits(afe->regmap, reg->con0, msk); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 126); + + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC1]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC2]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC3]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC4]); + + if (dmic_priv->hires_required) { + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES1]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES2]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES3]); + mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES4]); + } + break; + default: + break; + } + + return 0; +} + +static int mtk_dai_dmic_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + const struct mtk_dai_dmic_ctrl_reg *reg = NULL; + u32 val = AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(CLK_PHASE_SEL_CH1) | + AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(CLK_PHASE_SEL_CH2) | + AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(0); + const u32 msk = AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL | + AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_MASK | + AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL_MASK | + AFE_DMIC_UL_VOICE_MODE_MASK; + u8 dmic_num; + int ret; + int i; + + if (!channels || channels > 8) + return -EINVAL; + + ret = mtk_dai_dmic_configure_array(dai); + if (ret < 0) + return ret; + + ret = mtk_dai_dmic_load_iir_coeff_table(afe); + if (ret < 0) + return ret; + + switch (rate) { + case 96000: + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_96K; + dmic_priv->hires_required = 1; + break; + case 48000: + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_48K; + dmic_priv->hires_required = 0; + break; + case 32000: + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_32K; + dmic_priv->hires_required = 0; + break; + case 16000: + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_16K; + dmic_priv->hires_required = 0; + break; + case 8000: + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_8K; + dmic_priv->hires_required = 0; + break; + default: + dev_dbg(afe->dev, "%s invalid rate %u, use 48000Hz\n", __func__, rate); + val |= AFE_DMIC_UL_CON0_VOCIE_MODE_48K; + dmic_priv->hires_required = 0; + break; + } + + dmic_num = mtk_dmic_channels_to_dmic_number(channels); + for (i = dmic_num; i >= DMIC0; i--) { + reg = get_dmic_ctrl_reg(i); + if (reg) { + ret = regmap_update_bits(afe->regmap, reg->con0, msk, val); + if (ret < 0) + return ret; + } + } + + dmic_priv->channels = channels; + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_dmic_ops = { + .hw_params = mtk_dai_dmic_hw_params, +}; + +#define MTK_DMIC_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000) + +#define MTK_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = { + { + .name = "DMIC", + .id = MT8188_AFE_IO_DMIC_IN, + .capture = { + .stream_name = "DMIC Capture", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_DMIC_RATES, + .formats = MTK_DMIC_FORMATS, + }, + .ops = &mtk_dai_dmic_ops, + }, +}; + +static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = { + SND_SOC_DAPM_MIXER("I004", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I005", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I006", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I007", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I008", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I009", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I010", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I011", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("DMIC_GAIN_ON", SUPPLY_SEQ_DMIC_GAIN, + SND_SOC_NOPM, 0, 0, + mtk_dmic_gain_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("DMIC_CK_ON", SUPPLY_SEQ_DMIC_CK, + PWR2_TOP_CON1, + PWR2_TOP_CON1_DMIC_CKDIV_ON_SHIFT, 0, + mtk_dmic_event, + SND_SOC_DAPM_PRE_POST_PMU | + SND_SOC_DAPM_PRE_POST_PMD), + SND_SOC_DAPM_INPUT("DMIC_INPUT"), +}; + +static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = { + {"I004", NULL, "DMIC Capture"}, + {"I005", NULL, "DMIC Capture"}, + {"I006", NULL, "DMIC Capture"}, + {"I007", NULL, "DMIC Capture"}, + {"I008", NULL, "DMIC Capture"}, + {"I009", NULL, "DMIC Capture"}, + {"I010", NULL, "DMIC Capture"}, + {"I011", NULL, "DMIC Capture"}, + {"DMIC Capture", NULL, "DMIC_CK_ON"}, + {"DMIC Capture", NULL, "DMIC_GAIN_ON"}, + {"DMIC Capture", NULL, "DMIC_INPUT"}, +}; + +static const char * const mt8188_dmic_gain_enable_text[] = { + "Bypass", "Connect", +}; + +static SOC_ENUM_SINGLE_EXT_DECL(dmic_gain_on_enum, + mt8188_dmic_gain_enable_text); + +static int mtk_dai_dmic_hw_gain_ctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + unsigned int source = ucontrol->value.enumerated.item[0]; + unsigned int *cached; + + if (source >= e->items) + return -EINVAL; + + if (!strcmp(kcontrol->id.name, "DMIC1_HW_GAIN_EN")) + cached = &dmic_priv->gain_on[0]; + else if (!strcmp(kcontrol->id.name, "DMIC2_HW_GAIN_EN")) + cached = &dmic_priv->gain_on[1]; + else if (!strcmp(kcontrol->id.name, "DMIC3_HW_GAIN_EN")) + cached = &dmic_priv->gain_on[2]; + else if (!strcmp(kcontrol->id.name, "DMIC4_HW_GAIN_EN")) + cached = &dmic_priv->gain_on[3]; + else + return -EINVAL; + + if (source == *cached) + return 0; + + *cached = source; + return 1; +} + +static int mtk_dai_dmic_hw_gain_ctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN]; + unsigned int val; + + if (!strcmp(kcontrol->id.name, "DMIC1_HW_GAIN_EN")) + val = dmic_priv->gain_on[0]; + else if (!strcmp(kcontrol->id.name, "DMIC2_HW_GAIN_EN")) + val = dmic_priv->gain_on[1]; + else if (!strcmp(kcontrol->id.name, "DMIC3_HW_GAIN_EN")) + val = dmic_priv->gain_on[2]; + else if (!strcmp(kcontrol->id.name, "DMIC4_HW_GAIN_EN")) + val = dmic_priv->gain_on[3]; + else + return -EINVAL; + + ucontrol->value.enumerated.item[0] = val; + return 0; +} + +static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = { + SOC_ENUM_EXT("DMIC1_HW_GAIN_EN", dmic_gain_on_enum, + mtk_dai_dmic_hw_gain_ctrl_get, + mtk_dai_dmic_hw_gain_ctrl_put), + SOC_ENUM_EXT("DMIC2_HW_GAIN_EN", dmic_gain_on_enum, + mtk_dai_dmic_hw_gain_ctrl_get, + mtk_dai_dmic_hw_gain_ctrl_put), + SOC_ENUM_EXT("DMIC3_HW_GAIN_EN", dmic_gain_on_enum, + mtk_dai_dmic_hw_gain_ctrl_get, + mtk_dai_dmic_hw_gain_ctrl_put), + SOC_ENUM_EXT("DMIC4_HW_GAIN_EN", dmic_gain_on_enum, + mtk_dai_dmic_hw_gain_ctrl_get, + mtk_dai_dmic_hw_gain_ctrl_put), + SOC_SINGLE("DMIC1_HW_GAIN_TARGET", DMIC_GAIN1_CON1, + 0, DMIC_GAIN_MAX_TARGET, 0), + SOC_SINGLE("DMIC2_HW_GAIN_TARGET", DMIC_GAIN2_CON1, + 0, DMIC_GAIN_MAX_TARGET, 0), + SOC_SINGLE("DMIC3_HW_GAIN_TARGET", DMIC_GAIN3_CON1, + 0, DMIC_GAIN_MAX_TARGET, 0), + SOC_SINGLE("DMIC4_HW_GAIN_TARGET", DMIC_GAIN4_CON1, + 0, DMIC_GAIN_MAX_TARGET, 0), + SOC_SINGLE("DMIC1_HW_GAIN_CURRENT", DMIC_GAIN1_CUR, + 0, DMIC_GAIN_MAX_CURRENT, 0), + SOC_SINGLE("DMIC2_HW_GAIN_CURRENT", DMIC_GAIN2_CUR, + 0, DMIC_GAIN_MAX_CURRENT, 0), + SOC_SINGLE("DMIC3_HW_GAIN_CURRENT", DMIC_GAIN3_CUR, + 0, DMIC_GAIN_MAX_CURRENT, 0), + SOC_SINGLE("DMIC4_HW_GAIN_CURRENT", DMIC_GAIN4_CUR, + 0, DMIC_GAIN_MAX_CURRENT, 0), + SOC_SINGLE("DMIC1_HW_GAIN_UP_STEP", DMIC_GAIN1_CON3, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC2_HW_GAIN_UP_STEP", DMIC_GAIN2_CON3, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC3_HW_GAIN_UP_STEP", DMIC_GAIN3_CON3, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC4_HW_GAIN_UP_STEP", DMIC_GAIN4_CON3, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC1_HW_GAIN_DOWN_STEP", DMIC_GAIN1_CON2, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC2_HW_GAIN_DOWN_STEP", DMIC_GAIN2_CON2, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC3_HW_GAIN_DOWN_STEP", DMIC_GAIN3_CON2, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC4_HW_GAIN_DOWN_STEP", DMIC_GAIN4_CON2, + 0, DMIC_GAIN_MAX_STEP, 0), + SOC_SINGLE("DMIC1_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN1_CON0, + DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0), + SOC_SINGLE("DMIC2_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN2_CON0, + DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0), + SOC_SINGLE("DMIC3_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN3_CON0, + DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0), + SOC_SINGLE("DMIC4_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN4_CON0, + DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0), +}; + +static int init_dmic_priv_data(struct mtk_base_afe *afe) +{ + struct mt8188_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_dmic_priv *dmic_priv; + + dmic_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_dmic_priv), + GFP_KERNEL); + if (!dmic_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN] = dmic_priv; + return 0; +} + +int mt8188_dai_dmic_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_dmic_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver); + dai->dapm_widgets = mtk_dai_dmic_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets); + dai->dapm_routes = mtk_dai_dmic_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes); + dai->controls = mtk_dai_dmic_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls); + + return init_dmic_priv_data(afe); +} diff --git a/sound/soc/mediatek/mt8188/mt8188-reg.h b/sound/soc/mediatek/mt8188/mt8188-reg.h index bdd885419ff3..2e9c65de249d 100644 --- a/sound/soc/mediatek/mt8188/mt8188-reg.h +++ b/sound/soc/mediatek/mt8188/mt8188-reg.h @@ -2837,9 +2837,20 @@ #define PWR2_TOP_CON_DMIC3_SRC_SEL_MASK GENMASK(16, 14) #define PWR2_TOP_CON_DMIC2_SRC_SEL_MASK GENMASK(13, 11) #define PWR2_TOP_CON_DMIC1_SRC_SEL_MASK GENMASK(10, 8) +#define PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(x) ((x) << 29) +#define PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(x) ((x) << 26) +#define PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(x) ((x) << 23) +#define PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(x) ((x) << 20) +#define PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(x) ((x) << 17) +#define PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(x) ((x) << 14) +#define PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(x) ((x) << 11) +#define PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(x) ((x) << 8) /* PWR2_TOP_CON1 */ -#define PWR2_TOP_CON1_DMIC_CKDIV_ON BIT(1) +#define PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(x) BIT(5 + 6 * (x)) +#define PWR2_TOP_CON1_DMIC_CKDIV_ON BIT(1) +#define PWR2_TOP_CON1_DMIC_CKDIV_ON_SHIFT 1 + /* PCM_INTF_CON1 */ #define PCM_INTF_CON1_SYNC_OUT_INV BIT(23) @@ -2921,13 +2932,14 @@ #define AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL BIT(23) #define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL BIT(22) #define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL BIT(21) - +#define AFE_DMIC_UL_VOICE_MODE(x) (((x) & GENMASK(2, 0)) << 17) #define AFE_DMIC_UL_VOICE_MODE_MASK GENMASK(19, 17) #define AFE_DMIC_UL_CON0_VOCIE_MODE_8K AFE_DMIC_UL_VOICE_MODE(0) #define AFE_DMIC_UL_CON0_VOCIE_MODE_16K AFE_DMIC_UL_VOICE_MODE(1) #define AFE_DMIC_UL_CON0_VOCIE_MODE_32K AFE_DMIC_UL_VOICE_MODE(2) #define AFE_DMIC_UL_CON0_VOCIE_MODE_48K AFE_DMIC_UL_VOICE_MODE(3) #define AFE_DMIC_UL_CON0_VOCIE_MODE_96K AFE_DMIC_UL_VOICE_MODE(4) +#define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(x) (((x) & GENMASK(2, 0)) << 7) #define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL_MASK GENMASK(9, 7) #define AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL BIT(10) #define AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL BIT(1) @@ -2944,6 +2956,7 @@ /* DMIC_GAINx_CON0 */ #define DMIC_GAIN_CON0_GAIN_ON BIT(0) +#define DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT 8 #define DMIC_GAIN_CON0_SAMPLE_PER_STEP_MASK GENMASK(15, 8) /* DMIC_GAINx_CON1 */ From 390ebb24b3c3a95e109c28e14c2ec9fe3f0f8aaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 25 Feb 2025 11:33:51 -0300 Subject: [PATCH 0259/1090] ASoC: mediatek: mt8188-mt6359: Add DMIC support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the DMIC backend, which connects to the DMIC DAI in the platform driver, as well as a "AP DMIC" mic widget. On the Genio 700 EVK board the dual DMIC on-board are wired through that DMIC DAI. Co-developed-by: parkeryang Signed-off-by: parkeryang Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250225-genio700-dmic-v2-5-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-mt6359.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index 2d0d04e0232d..420b1427b71d 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -150,6 +150,11 @@ SND_SOC_DAILINK_DEFS(dl_src, "mt6359-snd-codec-aif1")), DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(DMIC_BE, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + SND_SOC_DAILINK_DEFS(dptx, DAILINK_COMP_ARRAY(COMP_CPU("DPTX")), DAILINK_COMP_ARRAY(COMP_DUMMY()), @@ -297,6 +302,7 @@ static const struct snd_soc_dapm_widget mt8188_rear_spk_widgets[] = { static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("AP DMIC", NULL), SND_SOC_DAPM_SINK("HDMI"), SND_SOC_DAPM_SINK("DP"), SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0), @@ -533,6 +539,7 @@ enum { DAI_LINK_UL9_FE, DAI_LINK_UL10_FE, DAI_LINK_DL_SRC_BE, + DAI_LINK_DMIC_BE, DAI_LINK_DPTX_BE, DAI_LINK_ETDM1_IN_BE, DAI_LINK_ETDM2_IN_BE, @@ -1120,6 +1127,13 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { .playback_only = 1, SND_SOC_DAILINK_REG(dl_src), }, + [DAI_LINK_DMIC_BE] = { + .name = "DMIC_BE", + .no_pcm = 1, + .capture_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(DMIC_BE), + }, [DAI_LINK_DPTX_BE] = { .name = "DPTX_BE", .ops = &mt8188_dptx_ops, From f00b3056843d14754ac1bab2106cf5599680f115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 25 Feb 2025 11:33:53 -0300 Subject: [PATCH 0260/1090] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add DMIC backend to dai-link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MT8188 platforms also have DMIC DAIs, which were previously undescribed. Add DMIC_BE as a possible backend for the dai-link property. Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250225-genio700-dmic-v2-7-3076f5b50ef7@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml index 362e729b51b4..8c77e7f68ad7 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml @@ -62,6 +62,7 @@ patternProperties: - PCM1_BE - DL_SRC_BE - UL_SRC_BE + - DMIC_BE codec: description: Holds subnode which indicates codec dai. From 709329c48214ad2acf12eed1b5c0eb798e40a64c Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Mon, 24 Feb 2025 22:59:34 -0800 Subject: [PATCH 0261/1090] Input: xpad - add support for ZOTAC Gaming Zone ZOTAC Gaming Zone is ZOTAC's 2024 handheld release. As it is common with these handhelds, it uses a hybrid USB device with an xpad endpoint, a keyboard endpoint, and a vendor-specific endpoint for RGB control et al. Signed-off-by: Antheas Kapenekakis Link: https://lore.kernel.org/r/20250222170010.188761-2-lkml@antheas.dev Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 16493235bf9e..29d7e6eb51cf 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -349,6 +349,7 @@ static const struct xpad_device { { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, + { 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 }, { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE }, { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE }, { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 }, @@ -538,6 +539,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ XPAD_XBOX360_VENDOR(0x1a86), /* QH Electronics */ XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ + XPAD_XBOX360_VENDOR(0x1ee9), /* ZOTAC Technology Limited */ XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */ XPAD_XBOX360_VENDOR(0x2345), /* Machenike Controllers */ From 95a54a96f657fd069d2a9922b6c2d293a72a001f Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Mon, 24 Feb 2025 23:00:29 -0800 Subject: [PATCH 0262/1090] Input: xpad - add support for TECNO Pocket Go TECNO Pocket Go is a kickstarter handheld by manufacturer TECNO Mobile. It poses a unique feature: it does not have a display. Instead, the handheld is essentially a pc in a controller. As customary, it has an xpad endpoint, a keyboard endpoint, and a vendor endpoint for its vendor software. Signed-off-by: Antheas Kapenekakis Link: https://lore.kernel.org/r/20250222170010.188761-3-lkml@antheas.dev Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 29d7e6eb51cf..79e1c8f1f99c 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -382,6 +382,7 @@ static const struct xpad_device { { 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 }, { 0x294b, 0x3303, "Snakebyte GAMEPAD BASE X", 0, XTYPE_XBOXONE }, { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE }, + { 0x2993, 0x2001, "TECNO Pocket Go", 0, XTYPE_XBOX360 }, { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE }, { 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, { 0x2dc8, 0x3109, "8BitDo Ultimate Wireless Bluetooth", 0, XTYPE_XBOX360 }, @@ -548,6 +549,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */ XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */ XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */ + XPAD_XBOX360_VENDOR(0x2993), /* TECNO Mobile */ XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */ XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Controllers */ XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Controllers */ From 659a7614dd72e2835ac0b220c2fa68fabd8d1df9 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Mon, 24 Feb 2025 23:01:55 -0800 Subject: [PATCH 0263/1090] Input: xpad - rename QH controller to Legion Go S The QH controller is actually the controller of the Legion Go S, with the manufacturer string wch.cn and product name Legion Go S in its USB descriptor. A cursory lookup of the VID reveals the same. Therefore, rename the xpad entries to match. Signed-off-by: Antheas Kapenekakis Link: https://lore.kernel.org/r/20250222170010.188761-4-lkml@antheas.dev Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 79e1c8f1f99c..c33e6f33265b 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -312,7 +312,7 @@ static const struct xpad_device { { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, - { 0x1a86, 0xe310, "QH Electronics Controller", 0, XTYPE_XBOX360 }, + { 0x1a86, 0xe310, "Legion Go S", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, @@ -538,7 +538,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ - XPAD_XBOX360_VENDOR(0x1a86), /* QH Electronics */ + XPAD_XBOX360_VENDOR(0x1a86), /* Nanjing Qinheng Microelectronics (WCH) */ XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ XPAD_XBOX360_VENDOR(0x1ee9), /* ZOTAC Technology Limited */ XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ From 68283c1cb573143c0b7515e93206f3503616bc10 Mon Sep 17 00:00:00 2001 From: Artur Weber Date: Fri, 7 Feb 2025 21:02:41 +0100 Subject: [PATCH 0264/1090] pinctrl: bcm281xx: Fix incorrect regmap max_registers value The max_registers value does not take into consideration the stride; currently, it's set to the number of the last pin, but this does not accurately represent the final register. Fix this by multiplying the current value by 4. Fixes: 54b1aa5a5b16 ("ARM: pinctrl: Add Broadcom Capri pinctrl driver") Signed-off-by: Artur Weber Link: https://lore.kernel.org/20250207-bcm21664-pinctrl-v1-2-e7cfac9b2d3b@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c index 73dbf29c002f..cf6efa9c0364 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c @@ -974,7 +974,7 @@ static const struct regmap_config bcm281xx_pinctrl_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = BCM281XX_PIN_VC_CAM3_SDA, + .max_register = BCM281XX_PIN_VC_CAM3_SDA * 4, }; static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) From acf40ab42799e4ae1397ee6f5c5941092d66f999 Mon Sep 17 00:00:00 2001 From: Charles Han Date: Wed, 12 Feb 2025 18:05:32 +0800 Subject: [PATCH 0265/1090] pinctrl: nuvoton: npcm8xx: Add NULL check in npcm8xx_gpio_fw devm_kasprintf() calls can return null pointers on failure. But the return values were not checked in npcm8xx_gpio_fw(). Add NULL check in npcm8xx_gpio_fw(), to handle kernel NULL pointer dereference error. Fixes: acf4884a5717 ("pinctrl: nuvoton: add NPCM8XX pinctrl and GPIO driver") Signed-off-by: Charles Han Link: https://lore.kernel.org/20250212100532.4317-1-hanchunchao@inspur.com Signed-off-by: Linus Walleij --- drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c index 471f644c5eef..d09a5e9b2eca 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c @@ -2374,6 +2374,9 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl) pctrl->gpio_bank[id].gc.parent = dev; pctrl->gpio_bank[id].gc.fwnode = child; pctrl->gpio_bank[id].gc.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", child); + if (pctrl->gpio_bank[id].gc.label == NULL) + return -ENOMEM; + pctrl->gpio_bank[id].gc.dbg_show = npcmgpio_dbg_show; pctrl->gpio_bank[id].direction_input = pctrl->gpio_bank[id].gc.direction_input; pctrl->gpio_bank[id].gc.direction_input = npcmgpio_direction_input; From 7ff4faba63571c51004280f7eb5d6362b15ec61f Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Tue, 18 Feb 2025 08:31:44 +0800 Subject: [PATCH 0266/1090] pinctrl: spacemit: enable config option Pinctrl is an essential driver for SpacemiT's SoC, The uart driver requires it, same as sd card driver, so let's enable it by default for this SoC. The CONFIG_PINCTRL_SPACEMIT_K1 isn't enabled when using 'make defconfig' to select kernel configuration options. This result in a broken uart driver where fail at probe() stage due to no pins found. Fixes: a83c29e1d145 ("pinctrl: spacemit: add support for SpacemiT K1 SoC") Reported-by: Alex Elder Acked-by: Conor Dooley Tested-by: Alex Elder Signed-off-by: Yixun Lan Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Link: https://lore.kernel.org/20250218-k1-pinctrl-option-v3-1-36e031e0da1b@gentoo.org Signed-off-by: Linus Walleij --- arch/riscv/Kconfig.socs | 1 + drivers/pinctrl/spacemit/Kconfig | 3 ++- drivers/pinctrl/spacemit/pinctrl-k1.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 1916cf7ba450..17606940bb52 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -26,6 +26,7 @@ config ARCH_SOPHGO config ARCH_SPACEMIT bool "SpacemiT SoCs" + select PINCTRL help This enables support for SpacemiT SoC platform hardware. diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig index 168f8a5ffbb9..a2f98b3f8a75 100644 --- a/drivers/pinctrl/spacemit/Kconfig +++ b/drivers/pinctrl/spacemit/Kconfig @@ -4,9 +4,10 @@ # config PINCTRL_SPACEMIT_K1 - tristate "SpacemiT K1 SoC Pinctrl driver" + bool "SpacemiT K1 SoC Pinctrl driver" depends on ARCH_SPACEMIT || COMPILE_TEST depends on OF + default y select GENERIC_PINCTRL_GROUPS select GENERIC_PINMUX_FUNCTIONS select GENERIC_PINCONF diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c index a32579d73613..59fd555ff38d 100644 --- a/drivers/pinctrl/spacemit/pinctrl-k1.c +++ b/drivers/pinctrl/spacemit/pinctrl-k1.c @@ -1044,7 +1044,7 @@ static struct platform_driver k1_pinctrl_driver = { .of_match_table = k1_pinctrl_ids, }, }; -module_platform_driver(k1_pinctrl_driver); +builtin_platform_driver(k1_pinctrl_driver); MODULE_AUTHOR("Yixun Lan "); MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1 SoC"); From 00817f0f1c45b007965f5676b9a2013bb39c7228 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 24 Feb 2025 17:13:30 -0800 Subject: [PATCH 0267/1090] nvme-ioctl: fix leaked requests on mapping error All the callers assume nvme_map_user_request() frees the request on a failure. This wasn't happening on invalid metadata or io_uring command flags, so we've been leaking those requests. Fixes: 23fd22e55b767b ("nvme: wire up fixed buffer support for nvme passthrough") Fixes: 7c2fd76048e95d ("nvme: fix metadata handling in nvme-passthrough") Reviewed-by: Damien Le Moal Reviewed-by: Kanchan Joshi Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/host/ioctl.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index b1b46c2713e1..24e2c702da7a 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -128,8 +128,10 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, if (!nvme_ctrl_sgl_supported(ctrl)) dev_warn_once(ctrl->device, "using unchecked data buffer\n"); if (has_metadata) { - if (!supports_metadata) - return -EINVAL; + if (!supports_metadata) { + ret = -EINVAL; + goto out; + } if (!nvme_ctrl_meta_sgl_supported(ctrl)) dev_warn_once(ctrl->device, "using unchecked metadata buffer\n"); @@ -139,8 +141,10 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, struct iov_iter iter; /* fixedbufs is only for non-vectored io */ - if (WARN_ON_ONCE(flags & NVME_IOCTL_VEC)) - return -EINVAL; + if (WARN_ON_ONCE(flags & NVME_IOCTL_VEC)) { + ret = -EINVAL; + goto out; + } ret = io_uring_cmd_import_fixed(ubuffer, bufflen, rq_data_dir(req), &iter, ioucmd); if (ret < 0) From 729d163232971672d0f41b93c02092fb91f0e758 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 22 Feb 2025 00:01:22 +0100 Subject: [PATCH 0268/1090] Input: i8042 - swap old quirk combination with new quirk for NHxxRZQ Some older Clevo barebones have problems like no or laggy keyboard after resume or boot which can be fixed with the SERIO_QUIRK_FORCENORESTORE quirk. With the old i8042 quirks this devices keyboard is sometimes laggy after resume. With the new quirk this issue doesn't happen. Cc: stable@vger.kernel.org Signed-off-by: Werner Sembach Link: https://lore.kernel.org/r/20250221230137.70292-1-wse@tuxedocomputers.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-acpipnpio.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 127cfdc8668a..a764248ea11d 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1209,18 +1209,10 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, { - /* - * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes - * the keyboard very laggy for ~5 seconds after boot and - * sometimes also after resume. - * However both are required for the keyboard to not fail - * completely sometimes after boot or resume. - */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "NHxxRZQ"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { From 9ed468e17d5b80e7116fd35842df3648e808ae47 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 22 Feb 2025 00:01:23 +0100 Subject: [PATCH 0269/1090] Input: i8042 - add required quirks for missing old boardnames Some older Clevo barebones have problems like no or laggy keyboard after resume or boot which can be fixed with the SERIO_QUIRK_FORCENORESTORE quirk. The PB71RD keyboard is sometimes laggy after resume and the PC70DR, PB51RF, P640RE, and PCX0DX_GN20 keyboard is sometimes unresponsive after resume. This quirk fixes that. Cc: stable@vger.kernel.org Signed-off-by: Werner Sembach Link: https://lore.kernel.org/r/20250221230137.70292-2-wse@tuxedocomputers.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-acpipnpio.h | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index a764248ea11d..57a6eec4c2a5 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1260,6 +1260,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "P640RE"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, { /* * This is only a partial board_name and might be followed by @@ -1335,6 +1341,24 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PB51RF"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PB71RD"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PC70DR"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"), @@ -1342,6 +1366,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PCX0DX_GN20"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, /* See comment on TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU above */ { .matches = { From 75ee4ebebbbe8dc4b55ba37f388924fa96bf1564 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 22 Feb 2025 00:01:24 +0100 Subject: [PATCH 0270/1090] Input: i8042 - swap old quirk combination with new quirk for several devices Some older Clevo barebones have problems like no or laggy keyboard after resume or boot which can be fixed with the SERIO_QUIRK_FORCENORESTORE quirk. While the old quirk combination did not show negative effects on these devices specifically, the new quirk works just as well and seems more stable in general. Cc: stable@vger.kernel.org Signed-off-by: Werner Sembach Link: https://lore.kernel.org/r/20250221230137.70292-3-wse@tuxedocomputers.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-acpipnpio.h | 40 ++++++++++----------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 57a6eec4c2a5..9df1ef6032dd 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1080,16 +1080,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* Mivvy M310 */ @@ -1171,8 +1169,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "LAPQC71A"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1205,8 +1202,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1218,8 +1214,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, /* * At least one modern Clevo barebone has the touchpad connected both @@ -1235,17 +1230,15 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NS50MU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | - SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | - SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_NOAUX | + SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NS50_70MU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | - SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | - SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_NOAUX | + SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1319,8 +1312,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RS"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1338,8 +1330,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "PB50_70DFx,DDx"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1363,8 +1354,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1383,15 +1373,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170SM"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170KM-G"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* From d85862ccca452eeb19329e9f4f9a6ce1d1e53561 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 22 Feb 2025 00:01:25 +0100 Subject: [PATCH 0271/1090] Input: i8042 - swap old quirk combination with new quirk for more devices Some older Clevo barebones have problems like no or laggy keyboard after resume or boot which can be fixed with the SERIO_QUIRK_FORCENORESTORE quirk. We could not activly retest these devices because we no longer have them in our archive, but based on the other old Clevo barebones we tested where the new quirk had the same or a better behaviour I think it would be good to apply it on these too. Cc: stable@vger.kernel.org Signed-off-by: Werner Sembach Link: https://lore.kernel.org/r/20250221230137.70292-4-wse@tuxedocomputers.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-acpipnpio.h | 31 +++++++++------------------ 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index 9df1ef6032dd..6ed9fc34948c 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -1157,9 +1157,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { }, /* * A lot of modern Clevo barebones have touchpad and/or keyboard issues - * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, - * none of them have an external PS/2 port so this can safely be set for - * all of them. + * after suspend fixable with the forcenorestore quirk. * Clevo barebones come with board_vendor and/or system_vendor set to * either the very generic string "Notebook" and/or a different value * for each individual reseller. The only somewhat universal way to @@ -1175,22 +1173,19 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "LAPQC71B"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "N140CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "N141CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1250,8 +1245,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1268,16 +1262,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65xH"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1288,8 +1280,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_P67H"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1300,8 +1291,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1323,8 +1313,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P67xRP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { From 5a4041f2c47247575a6c2e53ce14f7b0ac946c33 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Wed, 19 Feb 2025 16:02:11 +0900 Subject: [PATCH 0272/1090] btrfs: zoned: fix extent range end unlock in cow_file_range() Running generic/751 on the for-next branch often results in a hang like below. They are both stack by locking an extent. This suggests someone forget to unlock an extent. INFO: task kworker/u128:1:12 blocked for more than 323 seconds. Not tainted 6.13.0-BTRFS-ZNS+ #503 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/u128:1 state:D stack:0 pid:12 tgid:12 ppid:2 flags:0x00004000 Workqueue: btrfs-fixup btrfs_work_helper [btrfs] Call Trace: __schedule+0x534/0xdd0 schedule+0x39/0x140 __lock_extent+0x31b/0x380 [btrfs] ? __pfx_autoremove_wake_function+0x10/0x10 btrfs_writepage_fixup_worker+0xf1/0x3a0 [btrfs] btrfs_work_helper+0xff/0x480 [btrfs] ? lock_release+0x178/0x2c0 process_one_work+0x1ee/0x570 ? srso_return_thunk+0x5/0x5f worker_thread+0x1d1/0x3b0 ? __pfx_worker_thread+0x10/0x10 kthread+0x10b/0x230 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x30/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 INFO: task kworker/u134:0:184 blocked for more than 323 seconds. Not tainted 6.13.0-BTRFS-ZNS+ #503 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/u134:0 state:D stack:0 pid:184 tgid:184 ppid:2 flags:0x00004000 Workqueue: writeback wb_workfn (flush-btrfs-4) Call Trace: __schedule+0x534/0xdd0 schedule+0x39/0x140 __lock_extent+0x31b/0x380 [btrfs] ? __pfx_autoremove_wake_function+0x10/0x10 find_lock_delalloc_range+0xdb/0x260 [btrfs] writepage_delalloc+0x12f/0x500 [btrfs] ? srso_return_thunk+0x5/0x5f extent_write_cache_pages+0x232/0x840 [btrfs] btrfs_writepages+0x72/0x130 [btrfs] do_writepages+0xe7/0x260 ? srso_return_thunk+0x5/0x5f ? lock_acquire+0xd2/0x300 ? srso_return_thunk+0x5/0x5f ? find_held_lock+0x2b/0x80 ? wbc_attach_and_unlock_inode.part.0+0x102/0x250 ? wbc_attach_and_unlock_inode.part.0+0x102/0x250 __writeback_single_inode+0x5c/0x4b0 writeback_sb_inodes+0x22d/0x550 __writeback_inodes_wb+0x4c/0xe0 wb_writeback+0x2f6/0x3f0 wb_workfn+0x32a/0x510 process_one_work+0x1ee/0x570 ? srso_return_thunk+0x5/0x5f worker_thread+0x1d1/0x3b0 ? __pfx_worker_thread+0x10/0x10 kthread+0x10b/0x230 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x30/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 This happens because we have another success path for the zoned mode. When there is no active zone available, btrfs_reserve_extent() returns -EAGAIN. In this case, we have two reactions. (1) If the given range is never allocated, we can only wait for someone to finish a zone, so wait on BTRFS_FS_NEED_ZONE_FINISH bit and retry afterward. (2) Or, if some allocations are already done, we must bail out and let the caller to send IOs for the allocation. This is because these IOs may be necessary to finish a zone. The commit 06f364284794 ("btrfs: do proper folio cleanup when cow_file_range() failed") moved the unlock code from the inside of the loop to the outside. So, previously, the allocated extents are unlocked just after the allocation and so before returning from the function. However, they are no longer unlocked on the case (2) above. That caused the hang issue. Fix the issue by modifying the 'end' to the end of the allocated range. Then, we can exit the loop and the same unlock code can properly handle the case. Reported-by: Shin'ichiro Kawasaki Tested-by: Johannes Thumshirn Fixes: 06f364284794 ("btrfs: do proper folio cleanup when cow_file_range() failed") CC: stable@vger.kernel.org Reviewed-by: Qu Wenruo Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- fs/btrfs/inode.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fe2c810335ff..69e90ed33cfe 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1382,8 +1382,13 @@ static noinline int cow_file_range(struct btrfs_inode *inode, continue; } if (done_offset) { - *done_offset = start - 1; - return 0; + /* + * Move @end to the end of the processed range, + * and exit the loop to unlock the processed extents. + */ + end = start - 1; + ret = 0; + break; } ret = -ENOSPC; } From 2df2c6ed89600a02e1c7a581a6a55e53c38ce0f5 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 25 Feb 2025 20:26:14 +0100 Subject: [PATCH 0273/1090] btrfs: replace deprecated strncpy() with strscpy() strncpy() is deprecated for NUL-terminated destination buffers. Use strscpy() instead and don't zero-initialize the param array. Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Thorsten Blum Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 53b846d99ece..14f53f757555 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -1330,13 +1330,13 @@ MODULE_PARM_DESC(read_policy, int btrfs_read_policy_to_enum(const char *str, s64 *value_ret) { - char param[32] = { 0 }; + char param[32]; char __maybe_unused *value_str; if (!str || strlen(str) == 0) return 0; - strncpy(param, str, sizeof(param) - 1); + strscpy(param, str); #ifdef CONFIG_BTRFS_EXPERIMENTAL /* Separate value from input in policy:value format. */ From 62142da241a08006f89b0620f7291e3a08c0a094 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Wed, 26 Feb 2025 16:47:28 +0800 Subject: [PATCH 0274/1090] ASoC: rt712-sdca: Add FU05 playback switch control Because there is no playback switch control for rt712-sdw headphone endpoint, it causes there is no way to control HP on and off in ALSA UCM config. Signed-off-by: derek.fang Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20250226084728.1889082-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca.c | 80 +++++++++++++++++++++++++++-------- sound/soc/codecs/rt712-sdca.h | 3 ++ 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c index 78dbf9eed494..19d99b9d4ab2 100644 --- a/sound/soc/codecs/rt712-sdca.c +++ b/sound/soc/codecs/rt712-sdca.c @@ -652,6 +652,61 @@ static int rt712_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol, return 1; } +static int rt712_sdca_set_fu05_playback_ctl(struct rt712_sdca_priv *rt712) +{ + int err; + unsigned int ch_01, ch_02; + + ch_01 = (rt712->fu05_dapm_mute || rt712->fu05_mixer_l_mute) ? 0x01 : 0x00; + ch_02 = (rt712->fu05_dapm_mute || rt712->fu05_mixer_r_mute) ? 0x01 : 0x00; + + err = regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, + RT712_SDCA_CTL_FU_MUTE, CH_01), ch_01); + if (err < 0) + return err; + + err = regmap_write(rt712->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, + RT712_SDCA_CTL_FU_MUTE, CH_02), ch_02); + if (err < 0) + return err; + + return 0; +} + +static int rt712_sdca_fu05_playback_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !rt712->fu05_mixer_l_mute; + ucontrol->value.integer.value[1] = !rt712->fu05_mixer_r_mute; + return 0; +} + +static int rt712_sdca_fu05_playback_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); + int err; + + if (rt712->fu05_mixer_l_mute == !ucontrol->value.integer.value[0] && + rt712->fu05_mixer_r_mute == !ucontrol->value.integer.value[1]) + return 0; + + rt712->fu05_mixer_l_mute = !ucontrol->value.integer.value[0]; + rt712->fu05_mixer_r_mute = !ucontrol->value.integer.value[1]; + + err = rt712_sdca_set_fu05_playback_ctl(rt712); + if (err < 0) + return err; + + return 1; +} + static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(boost_vol_tlv, 0, 1000, 0); @@ -674,6 +729,8 @@ static const struct snd_kcontrol_new rt712_sdca_controls[] = { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 8, 3, 0, rt712_sdca_set_gain_get, rt712_sdca_set_gain_put, boost_vol_tlv), + SOC_DOUBLE_EXT("FU05 Playback Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt712_sdca_fu05_playback_get, rt712_sdca_fu05_playback_put), }; static const struct snd_kcontrol_new rt712_sdca_spk_controls[] = { @@ -766,28 +823,15 @@ static int rt712_sdca_fu05_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); - unsigned char unmute = 0x0, mute = 0x1; switch (event) { case SND_SOC_DAPM_POST_PMU: - regmap_write(rt712->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, - RT712_SDCA_CTL_FU_MUTE, CH_01), - unmute); - regmap_write(rt712->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, - RT712_SDCA_CTL_FU_MUTE, CH_02), - unmute); + rt712->fu05_dapm_mute = false; + rt712_sdca_set_fu05_playback_ctl(rt712); break; case SND_SOC_DAPM_PRE_PMD: - regmap_write(rt712->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, - RT712_SDCA_CTL_FU_MUTE, CH_01), - mute); - regmap_write(rt712->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, - RT712_SDCA_CTL_FU_MUTE, CH_02), - mute); + rt712->fu05_dapm_mute = true; + rt712_sdca_set_fu05_playback_ctl(rt712); break; } return 0; @@ -1640,6 +1684,8 @@ int rt712_sdca_init(struct device *dev, struct regmap *regmap, rt712->fu1e_dapm_mute = true; rt712->fu1e_mixer_mute[0] = rt712->fu1e_mixer_mute[1] = rt712->fu1e_mixer_mute[2] = rt712->fu1e_mixer_mute[3] = true; + rt712->fu05_dapm_mute = true; + rt712->fu05_mixer_l_mute = rt712->fu05_mixer_r_mute = false; /* JD source uses JD1 in default */ rt712->jd_src = RT712_JD1; diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h index a08491496d90..7ab7d5feb50a 100644 --- a/sound/soc/codecs/rt712-sdca.h +++ b/sound/soc/codecs/rt712-sdca.h @@ -42,6 +42,9 @@ struct rt712_sdca_priv { bool fu0f_mixer_r_mute; bool fu1e_dapm_mute; bool fu1e_mixer_mute[4]; + bool fu05_dapm_mute; + bool fu05_mixer_l_mute; + bool fu05_mixer_r_mute; }; struct rt712_dmic_kctrl_priv { From a206376b425472c7c3a824f47a9967a4c97ae32c Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 26 Feb 2025 12:23:22 +0000 Subject: [PATCH 0275/1090] ASoC: dt-bindings: xlnx,i2s: Convert to json-schema Convert the Xilinx I2S device tree binding documentation to json-schema. Reviewed-by: Rob Herring (Arm) Signed-off-by: Vincenzo Frascino Link: https://patch.msgid.link/20250226122325.2014547-2-vincenzo.frascino@arm.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/xlnx,i2s.txt | 28 -------- .../devicetree/bindings/sound/xlnx,i2s.yaml | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 28 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/xlnx,i2s.txt create mode 100644 Documentation/devicetree/bindings/sound/xlnx,i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/xlnx,i2s.txt b/Documentation/devicetree/bindings/sound/xlnx,i2s.txt deleted file mode 100644 index 5e7c7d5bb60a..000000000000 --- a/Documentation/devicetree/bindings/sound/xlnx,i2s.txt +++ /dev/null @@ -1,28 +0,0 @@ -Device-Tree bindings for Xilinx I2S PL block - -The IP supports I2S based playback/capture audio - -Required property: - - compatible: "xlnx,i2s-transmitter-1.0" for playback and - "xlnx,i2s-receiver-1.0" for capture - -Required property common to both I2S playback and capture: - - reg: Base address and size of the IP core instance. - - xlnx,dwidth: sample data width. Can be any of 16, 24. - - xlnx,num-channels: Number of I2S streams. Can be any of 1, 2, 3, 4. - supported channels = 2 * xlnx,num-channels - -Example: - - i2s_receiver@a0080000 { - compatible = "xlnx,i2s-receiver-1.0"; - reg = <0x0 0xa0080000 0x0 0x10000>; - xlnx,dwidth = <0x18>; - xlnx,num-channels = <1>; - }; - i2s_transmitter@a0090000 { - compatible = "xlnx,i2s-transmitter-1.0"; - reg = <0x0 0xa0090000 0x0 0x10000>; - xlnx,dwidth = <0x18>; - xlnx,num-channels = <1>; - }; diff --git a/Documentation/devicetree/bindings/sound/xlnx,i2s.yaml b/Documentation/devicetree/bindings/sound/xlnx,i2s.yaml new file mode 100644 index 000000000000..3c2b0be07c53 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/xlnx,i2s.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/xlnx,i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx I2S PL block + +description: + The IP supports I2S based playback/capture audio. + +maintainers: + - Vincenzo Frascino + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - xlnx,i2s-receiver-1.0 + - xlnx,i2s-transmitter-1.0 + + reg: + maxItems: 1 + + xlnx,dwidth: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 16 + - 24 + description: | + Sample data width. + + xlnx,num-channels: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 4 + description: | + Number of I2S streams. + +required: + - compatible + - reg + - xlnx,dwidth + - xlnx,num-channels + +additionalProperties: false + +examples: + - | + i2s@a0080000 { + compatible = "xlnx,i2s-receiver-1.0"; + reg = <0xa0080000 0x10000>; + xlnx,dwidth = <0x18>; + xlnx,num-channels = <1>; + }; + i2s@a0090000 { + compatible = "xlnx,i2s-transmitter-1.0"; + reg = <0xa0090000 0x10000>; + xlnx,dwidth = <0x18>; + xlnx,num-channels = <1>; + }; + +... From 1b8b6dd0c91b7db58e344f01781932458ac43da3 Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 26 Feb 2025 12:23:23 +0000 Subject: [PATCH 0276/1090] ASoC: dt-bindings: xlnx,audio-formatter: Convert to json-schema Convert the Xilinx Audio Formatter 1.0 device tree binding documentation to json-schema. Reviewed-by: Rob Herring (Arm) Signed-off-by: Vincenzo Frascino Link: https://patch.msgid.link/20250226122325.2014547-3-vincenzo.frascino@arm.com Signed-off-by: Mark Brown --- .../bindings/sound/xlnx,audio-formatter.txt | 29 -------- .../bindings/sound/xlnx,audio-formatter.yaml | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 29 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt create mode 100644 Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml diff --git a/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt b/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt deleted file mode 100644 index cbc93c8f4963..000000000000 --- a/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt +++ /dev/null @@ -1,29 +0,0 @@ -Device-Tree bindings for Xilinx PL audio formatter - -The IP core supports DMA, data formatting(AES<->PCM conversion) -of audio samples. - -Required properties: - - compatible: "xlnx,audio-formatter-1.0" - - interrupt-names: Names specified to list of interrupts in same - order mentioned under "interrupts". - List of supported interrupt names are: - "irq_mm2s" : interrupt from MM2S block - "irq_s2mm" : interrupt from S2MM block - - interrupts-parent: Phandle for interrupt controller. - - interrupts: List of Interrupt numbers. - - reg: Base address and size of the IP core instance. - - clock-names: List of input clocks. - Required elements: "s_axi_lite_aclk", "aud_mclk" - - clocks: Input clock specifier. Refer to common clock bindings. - -Example: - audio_ss_0_audio_formatter_0: audio_formatter@80010000 { - compatible = "xlnx,audio-formatter-1.0"; - interrupt-names = "irq_mm2s", "irq_s2mm"; - interrupt-parent = <&gic>; - interrupts = <0 104 4>, <0 105 4>; - reg = <0x0 0x80010000 0x0 0x1000>; - clock-names = "s_axi_lite_aclk", "aud_mclk"; - clocks = <&clk 71>, <&clk_wiz_1 0>; - }; diff --git a/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml b/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml new file mode 100644 index 000000000000..82fa448bd2e9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/xlnx,audio-formatter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx PL audio formatter + +description: + The IP core supports DMA, data formatting(AES<->PCM conversion) + of audio samples. + +maintainers: + - Vincenzo Frascino + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - xlnx,audio-formatter-1.0 + + reg: + maxItems: 1 + + interrupt-names: + minItems: 1 + items: + - const: irq_mm2s + - const: irq_s2mm + + interrupts: + minItems: 1 + items: + - description: interrupt from MM2S block + - description: interrupt from S2MM block + + clock-names: + minItems: 1 + items: + - const: s_axi_lite_aclk + - const: aud_mclk + + clocks: + minItems: 1 + items: + - description: clock for the axi data stream + - description: clock for the MEMS microphone data stream + +required: + - compatible + - reg + - interrupt-names + - interrupts + - clock-names + - clocks + +additionalProperties: false + +examples: + - | + audio_formatter@80010000 { + compatible = "xlnx,audio-formatter-1.0"; + reg = <0x80010000 0x1000>; + interrupt-names = "irq_mm2s", "irq_s2mm"; + interrupt-parent = <&gic>; + interrupts = <0 104 4>, <0 105 4>; + clock-names = "s_axi_lite_aclk", "aud_mclk"; + clocks = <&clk 71>, <&clk_wiz_1 0>; + }; +... From 7ed7065dfbbac1b5405a0c8029299847e408cf97 Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 26 Feb 2025 12:23:24 +0000 Subject: [PATCH 0277/1090] ASoC: dt-bindings: xlnx,spdif: Convert to json-schema Convert the Xilinx SPDIF 2.0 device tree binding documentation to json-schema. Reviewed-by: Rob Herring (Arm) Signed-off-by: Vincenzo Frascino Link: https://patch.msgid.link/20250226122325.2014547-4-vincenzo.frascino@arm.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/xlnx,spdif.txt | 28 ------- .../devicetree/bindings/sound/xlnx,spdif.yaml | 77 +++++++++++++++++++ 2 files changed, 77 insertions(+), 28 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/xlnx,spdif.txt create mode 100644 Documentation/devicetree/bindings/sound/xlnx,spdif.yaml diff --git a/Documentation/devicetree/bindings/sound/xlnx,spdif.txt b/Documentation/devicetree/bindings/sound/xlnx,spdif.txt deleted file mode 100644 index 15c2d64d247c..000000000000 --- a/Documentation/devicetree/bindings/sound/xlnx,spdif.txt +++ /dev/null @@ -1,28 +0,0 @@ -Device-Tree bindings for Xilinx SPDIF IP - -The IP supports playback and capture of SPDIF audio - -Required properties: - - compatible: "xlnx,spdif-2.0" - - clock-names: List of input clocks. - Required elements: "s_axi_aclk", "aud_clk_i" - - clocks: Input clock specifier. Refer to common clock bindings. - - reg: Base address and address length of the IP core instance. - - interrupts-parent: Phandle for interrupt controller. - - interrupts: List of Interrupt numbers. - - xlnx,spdif-mode: 0 :- receiver mode - 1 :- transmitter mode - - xlnx,aud_clk_i: input audio clock value. - -Example: - spdif_0: spdif@80010000 { - clock-names = "aud_clk_i", "s_axi_aclk"; - clocks = <&misc_clk_0>, <&clk 71>; - compatible = "xlnx,spdif-2.0"; - interrupt-names = "spdif_interrupt"; - interrupt-parent = <&gic>; - interrupts = <0 91 4>; - reg = <0x0 0x80010000 0x0 0x10000>; - xlnx,spdif-mode = <1>; - xlnx,aud_clk_i = <49152913>; - }; diff --git a/Documentation/devicetree/bindings/sound/xlnx,spdif.yaml b/Documentation/devicetree/bindings/sound/xlnx,spdif.yaml new file mode 100644 index 000000000000..a45d8a0755fe --- /dev/null +++ b/Documentation/devicetree/bindings/sound/xlnx,spdif.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/xlnx,spdif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx SPDIF IP + +description: + The IP supports playback and capture of SPDIF audio. + +maintainers: + - Vincenzo Frascino + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - xlnx,spdif-2.0 + + reg: + maxItems: 1 + + interrupts: + items: + - description: SPDIF audio interrupt + + clock-names: + items: + - const: aud_clk_i + - const: s_axi_aclk + + clocks: + minItems: 1 + items: + - description: input audio clock + - description: clock for the AXI data stream + + xlnx,spdif-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 + - 1 + description: | + 0 - receiver + 1 - transmitter + + xlnx,aud_clk_i: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Input audio clock frequency. It affects the sampling rate. + +required: + - compatible + - reg + - interrupts + - clock-names + - clocks + +additionalProperties: false + +examples: + - | + spdif@80010000 { + compatible = "xlnx,spdif-2.0"; + reg = <0x80010000 0x10000>; + clock-names = "aud_clk_i", "s_axi_aclk"; + clocks = <&misc_clk_0>, <&clk 71>; + interrupt-parent = <&gic>; + interrupts = <0 91 4>; + xlnx,spdif-mode = <1>; + xlnx,aud_clk_i = <49152913>; + }; + +... From 55a1abd6e76ce91eb6049f32efec3a8506686748 Mon Sep 17 00:00:00 2001 From: Vincenzo Frascino Date: Wed, 26 Feb 2025 12:23:25 +0000 Subject: [PATCH 0278/1090] MAINTAINERS: Add Vincenzo Frascino as Xilinx Sound Driver Maintainer Add Vincenzo Frascino as Xilinx Sound Driver Maintainer. Signed-off-by: Vincenzo Frascino Link: https://patch.msgid.link/20250226122325.2014547-5-vincenzo.frascino@arm.com Signed-off-by: Mark Brown --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7671b498d5e8..51a9992b4da3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -26009,6 +26009,14 @@ S: Maintained F: drivers/pwm/pwm-xilinx.c F: include/clocksource/timer-xilinx.h +XILINX SOUND DRIVERS +M: Vincenzo Frascino +S: Maintained +F: Documentation/devicetree/bindings/sound/xlnx,i2s.yaml +F: Documentation/devicetree/bindings/sound/xlnx,audio-formatter.yaml +F: Documentation/devicetree/bindings/sound/xlnx,spdif.yaml +F: sound/soc/xilinx/* + XILINX SD-FEC IP CORES M: Derek Kiernan M: Dragan Cvetic From 99ca2c28e6b68084a0fb65585df09b9e28c3ec16 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 21 Feb 2025 11:24:50 +0100 Subject: [PATCH 0279/1090] wifi: mac80211: fix MLE non-inheritance parsing The code is erroneously applying the non-inheritance element to the inner elements rather than the outer, which is clearly completely wrong. Fix it by finding the MLE basic element at the beginning, and then applying the non-inheritance for the outer parsing. While at it, do some general cleanups such as not allowing callers to try looking for a specific non-transmitted BSS and link at the same time. Fixes: 45ebac4f059b ("wifi: mac80211: Parse station profile from association response") Reviewed-by: Ilan Peer Reviewed-by: Miriam Rachel Korenblit Link: https://patch.msgid.link/20250221112451.b46d42f45b66.If5b95dc3c80208e0c62d8895fb6152aa54b6620b@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 1 + net/mac80211/parse.c | 127 ++++++++++++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f8d52b3b0d0e..36a9be9a66c8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4959,6 +4959,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, parse_params.start = bss_ies->data; parse_params.len = bss_ies->len; parse_params.bss = cbss; + parse_params.link_id = -1; bss_elems = ieee802_11_parse_elems_full(&parse_params); if (!bss_elems) { ret = false; diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c index cd318c1c67be..3d5d6658fe8d 100644 --- a/net/mac80211/parse.c +++ b/net/mac80211/parse.c @@ -47,6 +47,8 @@ struct ieee80211_elems_parse { /* The EPCS Multi-Link element in the original elements */ const struct element *ml_epcs_elem; + bool multi_link_inner; + /* * scratch buffer that can be used for various element parsing related * tasks, e.g., element de-fragmentation etc. @@ -152,12 +154,11 @@ ieee80211_parse_extension_element(u32 *crc, switch (le16_get_bits(mle->control, IEEE80211_ML_CONTROL_TYPE)) { case IEEE80211_ML_CONTROL_TYPE_BASIC: - if (elems_parse->ml_basic_elem) { + if (elems_parse->multi_link_inner) { elems->parse_error |= IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC; break; } - elems_parse->ml_basic_elem = elem; break; case IEEE80211_ML_CONTROL_TYPE_RECONF: elems_parse->ml_reconf_elem = elem; @@ -866,21 +867,36 @@ ieee80211_mle_get_sta_prof(struct ieee80211_elems_parse *elems_parse, } } -static void ieee80211_mle_parse_link(struct ieee80211_elems_parse *elems_parse, - struct ieee80211_elems_parse_params *params) +static const struct element * +ieee80211_prep_mle_link_parse(struct ieee80211_elems_parse *elems_parse, + struct ieee80211_elems_parse_params *params, + struct ieee80211_elems_parse_params *sub) { struct ieee802_11_elems *elems = &elems_parse->elems; struct ieee80211_mle_per_sta_profile *prof; - struct ieee80211_elems_parse_params sub = { - .mode = params->mode, - .action = params->action, - .from_ap = params->from_ap, - .link_id = -1, - }; - ssize_t ml_len = elems->ml_basic_len; - const struct element *non_inherit = NULL; + const struct element *tmp; + ssize_t ml_len; const u8 *end; + if (params->mode < IEEE80211_CONN_MODE_EHT) + return NULL; + + for_each_element_extid(tmp, WLAN_EID_EXT_EHT_MULTI_LINK, + elems->ie_start, elems->total_len) { + const struct ieee80211_multi_link_elem *mle = + (void *)tmp->data + 1; + + if (!ieee80211_mle_size_ok(tmp->data + 1, tmp->datalen - 1)) + continue; + + if (le16_get_bits(mle->control, IEEE80211_ML_CONTROL_TYPE) != + IEEE80211_ML_CONTROL_TYPE_BASIC) + continue; + + elems_parse->ml_basic_elem = tmp; + break; + } + ml_len = cfg80211_defragment_element(elems_parse->ml_basic_elem, elems->ie_start, elems->total_len, @@ -891,26 +907,26 @@ static void ieee80211_mle_parse_link(struct ieee80211_elems_parse *elems_parse, WLAN_EID_FRAGMENT); if (ml_len < 0) - return; + return NULL; elems->ml_basic = (const void *)elems_parse->scratch_pos; elems->ml_basic_len = ml_len; elems_parse->scratch_pos += ml_len; if (params->link_id == -1) - return; + return NULL; ieee80211_mle_get_sta_prof(elems_parse, params->link_id); prof = elems->prof; if (!prof) - return; + return NULL; /* check if we have the 4 bytes for the fixed part in assoc response */ if (elems->sta_prof_len < sizeof(*prof) + prof->sta_info_len - 1 + 4) { elems->prof = NULL; elems->sta_prof_len = 0; - return; + return NULL; } /* @@ -919,13 +935,17 @@ static void ieee80211_mle_parse_link(struct ieee80211_elems_parse *elems_parse, * the -1 is because the 'sta_info_len' is accounted to as part of the * per-STA profile, but not part of the 'u8 variable[]' portion. */ - sub.start = prof->variable + prof->sta_info_len - 1 + 4; + sub->start = prof->variable + prof->sta_info_len - 1 + 4; end = (const u8 *)prof + elems->sta_prof_len; - sub.len = end - sub.start; + sub->len = end - sub->start; - non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, - sub.start, sub.len); - _ieee802_11_parse_elems_full(&sub, elems_parse, non_inherit); + sub->mode = params->mode; + sub->action = params->action; + sub->from_ap = params->from_ap; + sub->link_id = -1; + + return cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, + sub->start, sub->len); } static void @@ -973,15 +993,19 @@ ieee80211_mle_defrag_epcs(struct ieee80211_elems_parse *elems_parse) struct ieee802_11_elems * ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) { + struct ieee80211_elems_parse_params sub = {}; struct ieee80211_elems_parse *elems_parse; - struct ieee802_11_elems *elems; const struct element *non_inherit = NULL; - u8 *nontransmitted_profile; - int nontransmitted_profile_len = 0; + struct ieee802_11_elems *elems; size_t scratch_len = 3 * params->len; + bool multi_link_inner = false; BUILD_BUG_ON(offsetof(typeof(*elems_parse), elems) != 0); + /* cannot parse for both a specific link and non-transmitted BSS */ + if (WARN_ON(params->link_id >= 0 && params->bss)) + return NULL; + elems_parse = kzalloc(struct_size(elems_parse, scratch, scratch_len), GFP_ATOMIC); if (!elems_parse) @@ -998,34 +1022,47 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) ieee80211_clear_tpe(&elems->tpe); ieee80211_clear_tpe(&elems->csa_tpe); - nontransmitted_profile = elems_parse->scratch_pos; - nontransmitted_profile_len = - ieee802_11_find_bssid_profile(params->start, params->len, - elems, params->bss, - nontransmitted_profile); - elems_parse->scratch_pos += nontransmitted_profile_len; - non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, - nontransmitted_profile, - nontransmitted_profile_len); + /* + * If we're looking for a non-transmitted BSS then we cannot at + * the same time be looking for a second link as the two can only + * appear in the same frame carrying info for different BSSes. + * + * In any case, we only look for one at a time, as encoded by + * the WARN_ON above. + */ + if (params->bss) { + int nontx_len = + ieee802_11_find_bssid_profile(params->start, + params->len, + elems, params->bss, + elems_parse->scratch_pos); + sub.start = elems_parse->scratch_pos; + sub.mode = params->mode; + sub.len = nontx_len; + sub.action = params->action; + sub.link_id = params->link_id; + + /* consume the space used for non-transmitted profile */ + elems_parse->scratch_pos += nontx_len; + + non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, + sub.start, nontx_len); + } else { + /* must always parse to get elems_parse->ml_basic_elem */ + non_inherit = ieee80211_prep_mle_link_parse(elems_parse, params, + &sub); + multi_link_inner = true; + } elems->crc = _ieee802_11_parse_elems_full(params, elems_parse, non_inherit); - /* Override with nontransmitted profile, if found */ - if (nontransmitted_profile_len) { - struct ieee80211_elems_parse_params sub = { - .mode = params->mode, - .start = nontransmitted_profile, - .len = nontransmitted_profile_len, - .action = params->action, - .link_id = params->link_id, - }; - + /* Override with nontransmitted/per-STA profile if found */ + if (sub.len) { + elems_parse->multi_link_inner = multi_link_inner; _ieee802_11_parse_elems_full(&sub, elems_parse, NULL); } - ieee80211_mle_parse_link(elems_parse, params); - ieee80211_mle_defrag_reconf(elems_parse); ieee80211_mle_defrag_epcs(elems_parse); From 130067e9c13bdc4820748ef16076a6972364745f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 21 Feb 2025 11:24:51 +0100 Subject: [PATCH 0280/1090] wifi: mac80211: fix vendor-specific inheritance If there's any vendor-specific element in the subelements then the outer element parsing must not parse any vendor element at all. This isn't implemented correctly now due to parsing into the pointers and then overriding them, so explicitly skip vendor elements if any exist in the sub- elements (non-transmitted profile or per-STA profile). Fixes: 671042a4fb77 ("mac80211: support non-inheritance element") Reviewed-by: Ilan Peer Reviewed-by: Miriam Rachel Korenblit Link: https://patch.msgid.link/20250221112451.fd71e5268840.I9db3e6a3367e6ff38d052d07dc07005f0dd3bd5c@changeid Signed-off-by: Johannes Berg --- net/mac80211/parse.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c index 3d5d6658fe8d..6da39c864f45 100644 --- a/net/mac80211/parse.c +++ b/net/mac80211/parse.c @@ -48,6 +48,7 @@ struct ieee80211_elems_parse { const struct element *ml_epcs_elem; bool multi_link_inner; + bool skip_vendor; /* * scratch buffer that can be used for various element parsing related @@ -400,6 +401,9 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params, IEEE80211_PARSE_ERR_BAD_ELEM_SIZE; break; case WLAN_EID_VENDOR_SPECIFIC: + if (elems_parse->skip_vendor) + break; + if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && pos[2] == 0xf2) { /* Microsoft OUI (00:50:F2) */ @@ -1054,12 +1058,16 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) multi_link_inner = true; } + elems_parse->skip_vendor = + cfg80211_find_elem(WLAN_EID_VENDOR_SPECIFIC, + sub.start, sub.len); elems->crc = _ieee802_11_parse_elems_full(params, elems_parse, non_inherit); /* Override with nontransmitted/per-STA profile if found */ if (sub.len) { elems_parse->multi_link_inner = multi_link_inner; + elems_parse->skip_vendor = false; _ieee802_11_parse_elems_full(&sub, elems_parse, NULL); } From 861d0445e72e9e33797f2ceef882c74decb16a87 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Thu, 13 Feb 2025 22:43:30 +0100 Subject: [PATCH 0281/1090] wifi: mac80211: Fix sparse warning for monitor_sdata Use rcu_access_pointer() to avoid sparse warning in drv_remove_interface(). Signed-off-by: Alexander Wetzel Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502130534.bVrZZBK0-lkp@intel.com/ Fixes: 646262c71aca ("wifi: mac80211: remove debugfs dir for virtual monitor") Link: https://patch.msgid.link/20250213214330.6113-1-Alexander@wetzel-home.de Signed-off-by: Johannes Berg --- net/mac80211/driver-ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index 2fc60e1e77a5..35349a7f16cb 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -121,7 +121,7 @@ void drv_remove_interface(struct ieee80211_local *local, * The virtual monitor interface doesn't get a debugfs * entry, so it's exempt here. */ - if (sdata != local->monitor_sdata) + if (sdata != rcu_access_pointer(local->monitor_sdata)) ieee80211_debugfs_recreate_netdev(sdata, sdata->vif.valid_links); From 8c3170628a9ce24a59647bd24f897e666af919b8 Mon Sep 17 00:00:00 2001 From: Matthias Proske Date: Wed, 12 Feb 2025 19:59:35 +0100 Subject: [PATCH 0282/1090] wifi: brcmfmac: keep power during suspend if board requires it After commit 92cadedd9d5f ("brcmfmac: Avoid keeping power to SDIO card unless WOWL is used"), the wifi adapter by default is turned off on suspend and then re-probed on resume. This conflicts with some embedded boards that require to remain powered. They will fail on resume with: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout ieee80211 phy1: brcmf_bus_started: failed: -110 ieee80211 phy1: brcmf_attach: dongle is not responding: err=-110 brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed This commit checks for the Device Tree property 'cap-power-off-cards'. If this property is not set, it means that we do not have the capability to power off and should therefore remain powered. Signed-off-by: Matthias Proske Acked-by: Arend van Spriel Link: https://patch.msgid.link/20250212185941.146958-2-email@matthias-proske.de Signed-off-by: Johannes Berg --- .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 60eb95fc19a5..6bc107476a2a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -1172,6 +1172,7 @@ static int brcmf_ops_sdio_suspend(struct device *dev) struct brcmf_bus *bus_if; struct brcmf_sdio_dev *sdiodev; mmc_pm_flag_t sdio_flags; + bool cap_power_off; int ret = 0; func = container_of(dev, struct sdio_func, dev); @@ -1179,19 +1180,23 @@ static int brcmf_ops_sdio_suspend(struct device *dev) if (func->num != 1) return 0; + cap_power_off = !!(func->card->host->caps & MMC_CAP_POWER_OFF_CARD); bus_if = dev_get_drvdata(dev); sdiodev = bus_if->bus_priv.sdio; - if (sdiodev->wowl_enabled) { + if (sdiodev->wowl_enabled || !cap_power_off) { brcmf_sdiod_freezer_on(sdiodev); brcmf_sdio_wd_timer(sdiodev->bus, 0); sdio_flags = MMC_PM_KEEP_POWER; - if (sdiodev->settings->bus.sdio.oob_irq_supported) - enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); - else - sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; + + if (sdiodev->wowl_enabled) { + if (sdiodev->settings->bus.sdio.oob_irq_supported) + enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); + else + sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; + } if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) brcmf_err("Failed to set pm_flags %x\n", sdio_flags); @@ -1213,18 +1218,19 @@ static int brcmf_ops_sdio_resume(struct device *dev) struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct sdio_func *func = container_of(dev, struct sdio_func, dev); int ret = 0; + bool cap_power_off = !!(func->card->host->caps & MMC_CAP_POWER_OFF_CARD); brcmf_dbg(SDIO, "Enter: F%d\n", func->num); if (func->num != 2) return 0; - if (!sdiodev->wowl_enabled) { + if (!sdiodev->wowl_enabled && cap_power_off) { /* bus was powered off and device removed, probe again */ ret = brcmf_sdiod_probe(sdiodev); if (ret) brcmf_err("Failed to probe device on resume\n"); } else { - if (sdiodev->settings->bus.sdio.oob_irq_supported) + if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported) disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); brcmf_sdiod_freezer_off(sdiodev); From e4cf8ec4de4e13f156c1d61977d282d90c221085 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 20 Feb 2025 08:14:43 +0000 Subject: [PATCH 0283/1090] affs: generate OFS sequence numbers starting at 1 If I write a file to an OFS floppy image, and try to read it back on an emulated Amiga running Workbench 1.3, the Amiga reports a disk error trying to read the file. (That is, it's unable to read it _at all_, even to copy it to the NIL: device. It isn't a matter of getting the wrong data and being unable to parse the file format.) This is because the 'sequence number' field in the OFS data block header is supposed to be based at 1, but affs writes it based at 0. All three locations changed by this patch were setting the sequence number to a variable 'bidx' which was previously obtained by dividing a file position by bsize, so bidx will naturally use 0 for the first block. Therefore all three should add 1 to that value before writing it into the sequence number field. With this change, the Amiga successfully reads the file. For data block reference: https://wiki.osdev.org/FFS_(Amiga) Signed-off-by: Simon Tatham Signed-off-by: David Sterba --- fs/affs/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/affs/file.c b/fs/affs/file.c index a5a861dd5223..226308f8627e 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -596,7 +596,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize) BUG_ON(tmp > bsize); AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); - AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); + AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1); AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp); affs_fix_checksum(sb, bh); bh->b_state &= ~(1UL << BH_New); @@ -746,7 +746,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, if (buffer_new(bh)) { AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); - AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); + AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1); AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize); AFFS_DATA_HEAD(bh)->next = 0; bh->b_state &= ~(1UL << BH_New); @@ -780,7 +780,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, if (buffer_new(bh)) { AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino); - AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx); + AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1); AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp); AFFS_DATA_HEAD(bh)->next = 0; bh->b_state &= ~(1UL << BH_New); From 011ea742a25a77bac3d995f457886a67d178c6f0 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 20 Feb 2025 08:14:44 +0000 Subject: [PATCH 0284/1090] affs: don't write overlarge OFS data block size fields If a data sector on an OFS floppy contains a value > 0x1e8 (the largest amount of data that fits in the sector after its header), then an Amiga reading the file can return corrupt data, by taking the overlarge size at its word and reading past the end of the buffer it read the disk sector into! The cause: when affs_write_end_ofs() writes data to an OFS filesystem, the new size field for a data block was computed by adding the amount of data currently being written (into the block) to the existing value of the size field. This is correct if you're extending the file at the end, but if you seek backwards in the file and overwrite _existing_ data, it can lead to the size field being larger than the maximum legal value. This commit changes the calculation so that it sets the size field to the max of its previous size and the position within the block that we just wrote up to. Signed-off-by: Simon Tatham Signed-off-by: David Sterba --- fs/affs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/affs/file.c b/fs/affs/file.c index 226308f8627e..7a71018e3f67 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -724,7 +724,8 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, tmp = min(bsize - boff, to - from); BUG_ON(boff + tmp > bsize || tmp > bsize); memcpy(AFFS_DATA(bh) + boff, data + from, tmp); - be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp); + AFFS_DATA_HEAD(bh)->size = cpu_to_be32( + max(boff + tmp, be32_to_cpu(AFFS_DATA_HEAD(bh)->size))); affs_fix_checksum(sb, bh); mark_buffer_dirty_inode(bh, inode); written += tmp; From be1e3607f29a5a182eaa70e3058aef32fd0cc4f8 Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Wed, 26 Feb 2025 22:43:28 +0800 Subject: [PATCH 0285/1090] ASoC: tas2781: Clean up for some define Do some clean up for some define in header file. Like change lower case in value, up case in define, space add in recommends, change date of files and add author. Signed-off-by: Baojun Xu Link: https://patch.msgid.link/20250226144328.11645-1-baojun.xu@ti.com Signed-off-by: Mark Brown --- include/sound/tas2781.h | 21 +++++++++++---------- sound/soc/codecs/tas2781-fmwlib.c | 7 ++++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 0f1e585635bb..4d9a37544354 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -2,7 +2,7 @@ // // ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier // -// Copyright (C) 2022 - 2024 Texas Instruments Incorporated +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated // https://www.ti.com // // The TAS2563/TAS2781 driver implements a flexible and configurable @@ -11,6 +11,7 @@ // // Author: Shenghao Ding // Author: Kevin Lu +// Author: Baojun Xu // #ifndef __TAS2781_H__ @@ -31,7 +32,7 @@ SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) -/*PAGE Control Register (available in page0 of each book) */ +/* PAGE Control Register (available in page0 of each book) */ #define TASDEVICE_PAGE_SELECT 0x00 #define TASDEVICE_BOOKCTL_PAGE 0x00 #define TASDEVICE_BOOKCTL_REG 127 @@ -42,12 +43,12 @@ #define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \ (page * 128)) + reg) -/*Software Reset */ -#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01) +/* Software Reset */ +#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01) #define TASDEVICE_REG_SWRESET_RESET BIT(0) -/*I2C Checksum */ -#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E) +/* I2C Checksum */ +#define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e) /* XM_340 */ #define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x63, 0x3c) @@ -55,8 +56,8 @@ #define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x63, 0x38) /* Volume control */ -#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C) -#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A) +#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0c) +#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1a) #define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03) #define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1) @@ -95,8 +96,8 @@ #define TAS2781_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x14, 0x40) #define TAS2781_PRM_SINEGAIN2_REG TASDEVICE_REG(0x00, 0x14, 0x44) -#define TAS2781_TEST_UNLOCK_REG TASDEVICE_REG(0x00, 0xFD, 0x0D) -#define TAS2781_TEST_PAGE_UNLOCK 0x0D +#define TAS2781_TEST_UNLOCK_REG TASDEVICE_REG(0x00, 0xfd, 0x0d) +#define TAS2781_TEST_PAGE_UNLOCK 0x0d #define TAS2781_RUNTIME_LATCH_RE_REG TASDEVICE_REG(0x00, 0x00, 0x49) #define TAS2781_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x62, 0x48) diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 61d9c220b6a4..bc2f68bd9846 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -2,9 +2,10 @@ // // tas2781-fmwlib.c -- TASDEVICE firmware support // -// Copyright 2023 - 2024 Texas Instruments, Inc. +// Copyright 2023 - 2025 Texas Instruments, Inc. // // Author: Shenghao Ding +// Author: Baojun Xu #include #include @@ -1496,7 +1497,7 @@ static int tasdev_block_chksum(struct tasdevice_priv *tas_priv, unsigned int nr_value; int ret; - ret = tasdevice_dev_read(tas_priv, chn, TASDEVICE_I2CChecksum, + ret = tasdevice_dev_read(tas_priv, chn, TASDEVICE_CHECKSUM_REG, &nr_value); if (ret < 0) { dev_err(tas_priv->dev, "%s: Chn %d\n", __func__, chn); @@ -1540,7 +1541,7 @@ static int tasdev_load_blk(struct tasdevice_priv *tas_priv, while (block->nr_retry > 0) { if (block->is_pchksum_present) { ret = tasdevice_dev_write(tas_priv, chn, - TASDEVICE_I2CChecksum, 0); + TASDEVICE_CHECKSUM_REG, 0); if (ret < 0) break; } From 75f1f311d883dfaffb98be3c1da208d6ed5d4df9 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Wed, 26 Feb 2025 13:38:19 -0600 Subject: [PATCH 0286/1090] Revert "of: reserved-memory: Fix using wrong number of cells to get property 'alignment'" This reverts commit 267b21d0bef8e67dbe6c591c9991444e58237ec9. Turns out some DTs do depend on this behavior. Specifically, a downstream Pixel 6 DT. Revert the change at least until we can decide if the DT spec can be changed instead. Cc: stable@vger.kernel.org Signed-off-by: Rob Herring (Arm) --- drivers/of/of_reserved_mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 75e819f66a56..ee2e31522d7e 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -415,12 +415,12 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unam prop = of_get_flat_dt_prop(node, "alignment", &len); if (prop) { - if (len != dt_root_size_cells * sizeof(__be32)) { + if (len != dt_root_addr_cells * sizeof(__be32)) { pr_err("invalid alignment property in '%s' node.\n", uname); return -EINVAL; } - align = dt_mem_next_cell(dt_root_size_cells, &prop); + align = dt_mem_next_cell(dt_root_addr_cells, &prop); } nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; From b8501febdc513541afc5663d063bfac7ea575b71 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 29 Jan 2025 16:45:19 +0100 Subject: [PATCH 0287/1090] clk: qcom: dispcc-sm8750: Drop incorrect CLK_SET_RATE_PARENT on byte intf parent The parent of disp_cc_mdss_byte0_intf_clk clock should not propagate up the rates, because this messes up entire clock hierarchy when setting clock rates in MSM DSI driver. The dsi_link_clk_set_rate_6g() first sets entire clock hierarchy rates via dev_pm_opp_set_rate() on byte clock and then sets individual clock rates, like pixel and byte_intf clocks, to proper frequencies. Having CLK_SET_RATE_PARENT caused that entire tree was re-calced and the byte clock received halved frequency. Drop CLK_SET_RATE_PARENT to fix this and align with SM8550 and SM8650. Fixes: f1080d8dab0f ("clk: qcom: dispcc-sm8750: Add SM8750 Display clock controller") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250129154519.209791-1-krzysztof.kozlowski@linaro.org Reviewed-by: Neil Armstrong Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Signed-off-by: Stephen Boyd --- drivers/clk/qcom/dispcc-sm8750.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm8750.c b/drivers/clk/qcom/dispcc-sm8750.c index 0358dff91da5..e9bca179998b 100644 --- a/drivers/clk/qcom/dispcc-sm8750.c +++ b/drivers/clk/qcom/dispcc-sm8750.c @@ -827,7 +827,6 @@ static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { &disp_cc_mdss_byte0_clk_src.clkr.hw, }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_regmap_div_ops, }, }; @@ -842,7 +841,6 @@ static struct clk_regmap_div disp_cc_mdss_byte1_div_clk_src = { &disp_cc_mdss_byte1_clk_src.clkr.hw, }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_regmap_div_ops, }, }; From ac965d7d88fc36fb42e3d50225c0a44dd8326da4 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 26 Feb 2025 15:18:46 +0900 Subject: [PATCH 0288/1090] tracing: tprobe-events: Fix a memory leak when tprobe with $retval Fix a memory leak when a tprobe is defined with $retval. This combination is not allowed, but the parse_symbol_and_return() does not free the *symbol which should not be used if it returns the error. Thus, it leaks the *symbol memory in that error path. Link: https://lore.kernel.org/all/174055072650.4079315.3063014346697447838.stgit@mhiramat.tok.corp.google.com/ Fixes: ce51e6153f77 ("tracing: fprobe-event: Fix to check tracepoint event and return") Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Steven Rostedt (Google) Cc: stable@vger.kernel.org --- kernel/trace/trace_fprobe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index b8f3c4ba309b..8826f44f69a4 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -1056,6 +1056,8 @@ static int parse_symbol_and_return(int argc, const char *argv[], if (is_tracepoint) { trace_probe_log_set_index(i); trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE); + kfree(*symbol); + *symbol = NULL; return -EINVAL; } *is_return = true; From d0453655b6ddc685a4837f3cc0776ae8eef62d01 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 26 Feb 2025 15:18:54 +0900 Subject: [PATCH 0289/1090] tracing: tprobe-events: Reject invalid tracepoint name Commit 57a7e6de9e30 ("tracing/fprobe: Support raw tracepoints on future loaded modules") allows user to set a tprobe on non-exist tracepoint but it does not check the tracepoint name is acceptable. So it leads tprobe has a wrong character for events (e.g. with subsystem prefix). In this case, the event is not shown in the events directory. Reject such invalid tracepoint name. The tracepoint name must consist of alphabet or digit or '_'. Link: https://lore.kernel.org/all/174055073461.4079315.15875502830565214255.stgit@mhiramat.tok.corp.google.com/ Fixes: 57a7e6de9e30 ("tracing/fprobe: Support raw tracepoints on future loaded modules") Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Steven Rostedt (Google) Cc: stable@vger.kernel.org --- kernel/trace/trace_fprobe.c | 13 +++++++++++++ kernel/trace/trace_probe.h | 1 + 2 files changed, 14 insertions(+) diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 8826f44f69a4..85f037dc1462 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -1049,6 +1049,19 @@ static int parse_symbol_and_return(int argc, const char *argv[], if (*is_return) return 0; + if (is_tracepoint) { + tmp = *symbol; + while (*tmp && (isalnum(*tmp) || *tmp == '_')) + tmp++; + if (*tmp) { + /* find a wrong character. */ + trace_probe_log_err(tmp - *symbol, BAD_TP_NAME); + kfree(*symbol); + *symbol = NULL; + return -EINVAL; + } + } + /* If there is $retval, this should be a return fprobe. */ for (i = 2; i < argc; i++) { tmp = strstr(argv[i], "$retval"); diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 5803e6a41570..fba3ede87054 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -481,6 +481,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, C(NON_UNIQ_SYMBOL, "The symbol is not unique"), \ C(BAD_RETPROBE, "Retprobe address must be an function entry"), \ C(NO_TRACEPOINT, "Tracepoint is not found"), \ + C(BAD_TP_NAME, "Invalid character in tracepoint name"),\ C(BAD_ADDR_SUFFIX, "Invalid probed address suffix"), \ C(NO_GROUP_NAME, "Group name is not specified"), \ C(GROUP_TOO_LONG, "Group name is too long"), \ From db5e228611b118cf7b1f8084063feda5c037f4a7 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 26 Feb 2025 15:19:02 +0900 Subject: [PATCH 0290/1090] tracing: fprobe-events: Log error for exceeding the number of entry args Add error message when the number of entry argument exceeds the maximum size of entry data. This is currently checked when registering fprobe, but in this case no error message is shown in the error_log file. Link: https://lore.kernel.org/all/174055074269.4079315.17809232650360988538.stgit@mhiramat.tok.corp.google.com/ Fixes: 25f00e40ce79 ("tracing/probes: Support $argN in return probe (kprobe and fprobe)") Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Steven Rostedt (Google) --- kernel/trace/trace_fprobe.c | 5 +++++ kernel/trace/trace_probe.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 85f037dc1462..e27305d31fc5 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -1230,6 +1230,11 @@ static int trace_fprobe_create_internal(int argc, const char *argv[], if (is_return && tf->tp.entry_arg) { tf->fp.entry_handler = trace_fprobe_entry_handler; tf->fp.entry_data_size = traceprobe_get_entry_data_size(&tf->tp); + if (ALIGN(tf->fp.entry_data_size, sizeof(long)) > MAX_FPROBE_DATA_SIZE) { + trace_probe_log_set_index(2); + trace_probe_log_err(0, TOO_MANY_EARGS); + return -E2BIG; + } } ret = traceprobe_set_print_fmt(&tf->tp, diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index fba3ede87054..c47ca002347a 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -545,7 +545,8 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, C(NO_BTF_FIELD, "This field is not found."), \ C(BAD_BTF_TID, "Failed to get BTF type info."),\ C(BAD_TYPE4STR, "This type does not fit for string."),\ - C(NEED_STRING_TYPE, "$comm and immediate-string only accepts string type"), + C(NEED_STRING_TYPE, "$comm and immediate-string only accepts string type"),\ + C(TOO_MANY_EARGS, "Too many entry arguments specified"), #undef C #define C(a, b) TP_ERR_##a From fd80df352ba1884ce2b62dd8d9495582308101b7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 17 Feb 2025 14:01:56 +0000 Subject: [PATCH 0291/1090] regcache: Add support for sorting defaults arrays The defaults array in regcache must be sorted into ascending register address order, because binary search is used to locate values in the array. Add a helper to sort the register defaults array which can be useful for systems that dynamically create a defaults array based on external information. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250217140159.2288784-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 31 +++++++++++++++++++++++++++++++ include/linux/regmap.h | 7 +++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index b1f8508c3966..f7fcf2de1301 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -21,6 +21,37 @@ static const struct regcache_ops *cache_types[] = { ®cache_flat_ops, }; +static int regcache_defaults_cmp(const void *a, const void *b) +{ + const struct reg_default *x = a; + const struct reg_default *y = b; + + if (x->reg > y->reg) + return 1; + else if (x->reg < y->reg) + return -1; + else + return 0; +} + +static void regcache_defaults_swap(void *a, void *b, int size) +{ + struct reg_default *x = a; + struct reg_default *y = b; + struct reg_default tmp; + + tmp = *x; + *x = *y; + *y = tmp; +} + +void regcache_sort_defaults(struct reg_default *defaults, unsigned int ndefaults) +{ + sort(defaults, ndefaults, sizeof(*defaults), + regcache_defaults_cmp, regcache_defaults_swap); +} +EXPORT_SYMBOL_GPL(regcache_sort_defaults); + static int regcache_hw_init(struct regmap *map) { int i, j; diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 3a96d068915f..d17c5ea3d55d 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -1352,6 +1352,7 @@ bool regmap_can_raw_write(struct regmap *map); size_t regmap_get_raw_read_max(struct regmap *map); size_t regmap_get_raw_write_max(struct regmap *map); +void regcache_sort_defaults(struct reg_default *defaults, unsigned int ndefaults); int regcache_sync(struct regmap *map); int regcache_sync_region(struct regmap *map, unsigned int min, unsigned int max); @@ -2043,6 +2044,12 @@ static inline bool regmap_might_sleep(struct regmap *map) return true; } +static inline void regcache_sort_defaults(struct reg_default *defaults, + unsigned int ndefaults) +{ + WARN_ONCE(1, "regmap API is disabled"); +} + static inline int regcache_sync(struct regmap *map) { WARN_ONCE(1, "regmap API is disabled"); From e3f7caf74b795621252e3c25b4a9fb6888336ef1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 17 Feb 2025 14:01:57 +0000 Subject: [PATCH 0292/1090] ASoC: SDCA: Add generic regmap SDCA helpers Add helper functions that SDCA drivers can use to calculate the properties of SDCA Controls (registers) specified through DisCo. Most of these are fairly obvious from the SDCA Access Modes. DisCo Constants, values which are specified in the ACPI rather than on the device, are handled as unreadable and unwritable registers. The intention is these will be populated in the register defaults table allowing drivers to read them normally. This means the drivers can be agnostic as to which values are DisCo Constants. Finally, support for SDCA Dual Ranked Controls is currently limited here, at the moment the current value will be used directly. Writing the current value directly is valid as per the specification although the synchronicity of updates across multiple registers is lost. Support for this will probably need to be added later. But its a fairly hard problem and doesn't need to be solved immediately. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250217140159.2288784-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_regmap.h | 21 ++++ sound/soc/sdca/Makefile | 2 +- sound/soc/sdca/sdca_regmap.c | 192 +++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 include/sound/sdca_regmap.h create mode 100644 sound/soc/sdca/sdca_regmap.c diff --git a/include/sound/sdca_regmap.h b/include/sound/sdca_regmap.h new file mode 100644 index 000000000000..11826f4f0726 --- /dev/null +++ b/include/sound/sdca_regmap.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_REGMAP_H__ +#define __SDCA_REGMAP_H__ + +struct sdca_function_data; + +bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg); +int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg); + +#endif // __SDCA_REGMAP_H__ diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile index 5d1ddbbfbf62..dddc3e694256 100644 --- a/sound/soc/sdca/Makefile +++ b/sound/soc/sdca/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-sdca-y := sdca_functions.o sdca_device.o +snd-soc-sdca-y := sdca_functions.o sdca_device.o sdca_regmap.o obj-$(CONFIG_SND_SOC_SDCA) += snd-soc-sdca.o diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c new file mode 100644 index 000000000000..ae6358f0fc26 --- /dev/null +++ b/sound/soc/sdca/sdca_regmap.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2025 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct sdca_entity * +function_find_entity(struct sdca_function_data *function, unsigned int reg) +{ + int i; + + for (i = 0; i < function->num_entities; i++) + if (SDW_SDCA_CTL_ENT(reg) == function->entities[i].id) + return &function->entities[i]; + + return NULL; +} + +static struct sdca_control * +entity_find_control(struct sdca_entity *entity, unsigned int reg) +{ + int i; + + for (i = 0; i < entity->num_controls; i++) { + if (SDW_SDCA_CTL_CSEL(reg) == entity->controls[i].sel) + return &entity->controls[i]; + } + + return NULL; +} + +static struct sdca_control * +function_find_control(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_entity *entity; + + entity = function_find_entity(function, reg); + if (!entity) + return NULL; + + return entity_find_control(entity, reg); +} + +/** + * sdca_regmap_readable - return if a given SDCA Control is readable + * @function: Pointer to the Function information. + * @reg: Register address/Control to be processed. + * + * Return: Returns true if the register is readable. + */ +bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_control *control; + + if (!SDW_SDCA_VALID_CTL(reg)) + return false; + + control = function_find_control(function, reg); + if (!control) + return false; + + switch (control->mode) { + case SDCA_ACCESS_MODE_RW: + case SDCA_ACCESS_MODE_RO: + case SDCA_ACCESS_MODE_DUAL: + case SDCA_ACCESS_MODE_RW1S: + case SDCA_ACCESS_MODE_RW1C: + /* No access to registers marked solely for device use */ + return control->layers & ~SDCA_ACCESS_LAYER_DEVICE; + default: + return false; + } +} +EXPORT_SYMBOL_NS(sdca_regmap_readable, "SND_SOC_SDCA"); + +/** + * sdca_regmap_writeable - return if a given SDCA Control is writeable + * @function: Pointer to the Function information. + * @reg: Register address/Control to be processed. + * + * Return: Returns true if the register is writeable. + */ +bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_control *control; + + if (!SDW_SDCA_VALID_CTL(reg)) + return false; + + control = function_find_control(function, reg); + if (!control) + return false; + + switch (control->mode) { + case SDCA_ACCESS_MODE_RW: + case SDCA_ACCESS_MODE_DUAL: + case SDCA_ACCESS_MODE_RW1S: + case SDCA_ACCESS_MODE_RW1C: + /* No access to registers marked solely for device use */ + return control->layers & ~SDCA_ACCESS_LAYER_DEVICE; + default: + return false; + } +} +EXPORT_SYMBOL_NS(sdca_regmap_writeable, "SND_SOC_SDCA"); + +/** + * sdca_regmap_volatile - return if a given SDCA Control is volatile + * @function: Pointer to the Function information. + * @reg: Register address/Control to be processed. + * + * Return: Returns true if the register is volatile. + */ +bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_control *control; + + if (!SDW_SDCA_VALID_CTL(reg)) + return false; + + control = function_find_control(function, reg); + if (!control) + return false; + + switch (control->mode) { + case SDCA_ACCESS_MODE_RO: + case SDCA_ACCESS_MODE_RW1S: + case SDCA_ACCESS_MODE_RW1C: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_NS(sdca_regmap_volatile, "SND_SOC_SDCA"); + +/** + * sdca_regmap_deferrable - return if a given SDCA Control is deferrable + * @function: Pointer to the Function information. + * @reg: Register address/Control to be processed. + * + * Return: Returns true if the register is deferrable. + */ +bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_control *control; + + if (!SDW_SDCA_VALID_CTL(reg)) + return false; + + control = function_find_control(function, reg); + if (!control) + return false; + + return control->deferrable; +} +EXPORT_SYMBOL_NS(sdca_regmap_deferrable, "SND_SOC_SDCA"); + +/** + * sdca_regmap_mbq_size - return size in bytes of a given SDCA Control + * @function: Pointer to the Function information. + * @reg: Register address/Control to be processed. + * + * Return: Returns the size in bytes of the Control. + */ +int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg) +{ + struct sdca_control *control; + + if (!SDW_SDCA_VALID_CTL(reg)) + return -EINVAL; + + control = function_find_control(function, reg); + if (!control) + return false; + + return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32)); +} +EXPORT_SYMBOL_NS(sdca_regmap_mbq_size, "SND_SOC_SDCA"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SDCA library"); From 28c12866c22c2826ccbd8c82dc353f02ab2deea5 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 17 Feb 2025 14:01:58 +0000 Subject: [PATCH 0293/1090] ASoC: SDCA: Add regmap helpers for parsing for DisCo Constant values Add helpers to parse the DisCo Constant values from ACPI and populate an array of reg_defaults with these. This will allow drivers to access these ACPI specified values through the same interface as other registers that are physically present on the device, using the regmap cache. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250217140159.2288784-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_regmap.h | 6 +++ sound/soc/sdca/sdca_regmap.c | 80 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/include/sound/sdca_regmap.h b/include/sound/sdca_regmap.h index 11826f4f0726..850533e83f3b 100644 --- a/include/sound/sdca_regmap.h +++ b/include/sound/sdca_regmap.h @@ -10,7 +10,9 @@ #ifndef __SDCA_REGMAP_H__ #define __SDCA_REGMAP_H__ +struct device; struct sdca_function_data; +struct reg_default; bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg); bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg); @@ -18,4 +20,8 @@ bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg) bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg); int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg); +int sdca_regmap_count_constants(struct device *dev, struct sdca_function_data *function); +int sdca_regmap_populate_constants(struct device *dev, struct sdca_function_data *function, + struct reg_default *consts); + #endif // __SDCA_REGMAP_H__ diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c index ae6358f0fc26..dba4188620f9 100644 --- a/sound/soc/sdca/sdca_regmap.c +++ b/sound/soc/sdca/sdca_regmap.c @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -188,5 +190,83 @@ int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg) } EXPORT_SYMBOL_NS(sdca_regmap_mbq_size, "SND_SOC_SDCA"); +/** + * sdca_regmap_count_constants - count the number of DisCo constant Controls + * @dev: Pointer to the device. + * @function: Pointer to the Function information, to be parsed. + * + * This function returns the number of DisCo constant Controls present + * in a function. Typically this information will be used to populate + * the regmap defaults array, allowing drivers to access the values of + * DisCo constants as any other physical register. + * + * Return: Returns number of DisCo constant controls, or a negative error + * code on failure. + */ +int sdca_regmap_count_constants(struct device *dev, + struct sdca_function_data *function) +{ + int nconsts = 0; + int i, j; + + for (i = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + + for (j = 0; j < entity->num_controls; j++) { + if (entity->controls[j].mode == SDCA_ACCESS_MODE_DC) + nconsts += hweight64(entity->controls[j].cn_list); + } + } + + return nconsts; +} +EXPORT_SYMBOL_NS(sdca_regmap_count_constants, "SND_SOC_SDCA"); + +/** + * sdca_regmap_populate_constants - fill an array with DisCo constant values + * @dev: Pointer to the device. + * @function: Pointer to the Function information, to be parsed. + * @consts: Pointer to the array which should be filled with the DisCo + * constant values. + * + * This function will populate a regmap struct reg_default array with + * the values of the DisCo constants for a given Function. This + * allows to access the values of DisCo constants the same as any + * other physical register. + * + * Return: Returns the number of constants populated on success, a negative + * error code on failure. + */ +int sdca_regmap_populate_constants(struct device *dev, + struct sdca_function_data *function, + struct reg_default *consts) +{ + int i, j, k; + + for (i = 0, k = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + + for (j = 0; j < entity->num_controls; j++) { + struct sdca_control *control = &entity->controls[j]; + int cn; + + if (control->mode != SDCA_ACCESS_MODE_DC) + continue; + + for_each_set_bit(cn, (unsigned long *)&control->cn_list, + BITS_PER_TYPE(control->cn_list)) { + consts[k].reg = SDW_SDCA_CTL(function->desc->adr, + entity->id, + control->sel, cn); + consts[k].def = control->value; + k++; + } + } + } + + return k; +} +EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA"); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SDCA library"); From c143755d8cce31e770234732ff23134993b0550f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 17 Feb 2025 14:01:59 +0000 Subject: [PATCH 0294/1090] ASoC: SDCA: Add helper to write out defaults and fixed values The concept of an SDCA default value differs slightly from the regmap usage of the term. An SDCA default is a value that is parsed from DisCo and then written out to the hardware if no user value has superceded it. Add a helper function that will iterate through all the SDCA Controls and write out any default values. After these have been written out once they will exist in the cache and that will take care of any user values superceeding them. The code here also writes out any Controls with a fixed value as there is only one available value for these Controls there is no point in allowing the user to select them, simply treat them similarly to a default. Signed-off-by: Charles Keepax Reviewed-by: Pierre-Louis Bossart Link: https://patch.msgid.link/20250217140159.2288784-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_regmap.h | 4 +++ sound/soc/sdca/sdca_regmap.c | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/sound/sdca_regmap.h b/include/sound/sdca_regmap.h index 850533e83f3b..b2e3c2ad2bb8 100644 --- a/include/sound/sdca_regmap.h +++ b/include/sound/sdca_regmap.h @@ -12,6 +12,7 @@ struct device; struct sdca_function_data; +struct regmap; struct reg_default; bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg); @@ -24,4 +25,7 @@ int sdca_regmap_count_constants(struct device *dev, struct sdca_function_data *f int sdca_regmap_populate_constants(struct device *dev, struct sdca_function_data *function, struct reg_default *consts); +int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function); + #endif // __SDCA_REGMAP_H__ diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c index dba4188620f9..4b78188cfceb 100644 --- a/sound/soc/sdca/sdca_regmap.c +++ b/sound/soc/sdca/sdca_regmap.c @@ -268,5 +268,54 @@ int sdca_regmap_populate_constants(struct device *dev, } EXPORT_SYMBOL_NS(sdca_regmap_populate_constants, "SND_SOC_SDCA"); +/** + * sdca_regmap_write_defaults - write out DisCo defaults to device + * @dev: Pointer to the device. + * @regmap: Pointer to the Function register map. + * @function: Pointer to the Function information, to be parsed. + * + * This function will write out to the hardware all the DisCo default and + * fixed value controls. This will cause them to be populated into the cache, + * and subsequent handling can be done through a cache sync. + * + * Return: Returns zero on success, and a negative error code on failure. + */ +int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function) +{ + int i, j; + int ret; + + for (i = 0; i < function->num_entities; i++) { + struct sdca_entity *entity = &function->entities[i]; + + for (j = 0; j < entity->num_controls; j++) { + struct sdca_control *control = &entity->controls[j]; + int cn; + + if (control->mode == SDCA_ACCESS_MODE_DC) + continue; + + if (!control->has_default && !control->has_fixed) + continue; + + for_each_set_bit(cn, (unsigned long *)&control->cn_list, + BITS_PER_TYPE(control->cn_list)) { + unsigned int reg; + + reg = SDW_SDCA_CTL(function->desc->adr, entity->id, + control->sel, cn); + + ret = regmap_write(regmap, reg, control->value); + if (ret) + return ret; + } + } + } + + return 0; +} +EXPORT_SYMBOL_NS(sdca_regmap_write_defaults, "SND_SOC_SDCA"); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SDCA library"); From 79ed408b2402e8113aa5a298f3bb9088ede58f6c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 27 Feb 2025 14:19:01 +0100 Subject: [PATCH 0295/1090] ASoC: mediatek: mt8188: avoid uninitialized variable use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'msk' variable has no initialization: sound/soc/mediatek/mt8188/mt8188-dai-dmic.c:311:4: error: variable 'msk' is uninitialized when used here [-Werror,-Wuninitialized] 311 | msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i); | ^~~ Set it to zero before the loop. Fixes: c1e42ec04197 ("ASoC: mediatek: mt8188: Add support for DMIC") Signed-off-by: Arnd Bergmann Reviewed-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250227131939.1040168-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-dai-dmic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c b/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c index 4cfbcb71d2d9..adcea7818be2 100644 --- a/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c +++ b/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c @@ -307,6 +307,7 @@ static int mtk_dmic_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: /* request fifo soft rst */ + msk = 0; for (i = dmic_num; i >= DMIC0; i--) msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i); From 6b481ab0e6855fb30e2923c51f62f1662d1cda7e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Feb 2025 11:25:31 +1000 Subject: [PATCH 0296/1090] drm/nouveau: select FW caching nouveau tries to load some firmware during suspend that it loaded earlier, but with fw caching disabled it hangs suspend, so just rely on FW cache enabling instead of working around it in the driver. Fixes: 176fdcbddfd2 ("drm/nouveau/gsp/r535: add support for booting GSP-RM") Signed-off-by: Dave Airlie Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20250207012531.621369-1-airlied@gmail.com --- drivers/gpu/drm/nouveau/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ce840300578d..1050a4617fc1 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -4,6 +4,7 @@ config DRM_NOUVEAU depends on DRM && PCI && MMU select IOMMU_API select FW_LOADER + select FW_CACHE if PM_SLEEP select DRM_CLIENT_SELECTION select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDMI_HELPER From c133ec0e5717868c9967fa3df92a55e537b1aead Mon Sep 17 00:00:00 2001 From: Michal Pecio Date: Tue, 25 Feb 2025 11:59:27 +0200 Subject: [PATCH 0297/1090] usb: xhci: Enable the TRB overfetch quirk on VIA VL805 Raspberry Pi is a major user of those chips and they discovered a bug - when the end of a transfer ring segment is reached, up to four TRBs can be prefetched from the next page even if the segment ends with link TRB and on page boundary (the chip claims to support standard 4KB pages). It also appears that if the prefetched TRBs belong to a different ring whose doorbell is later rung, they may be used without refreshing from system RAM and the endpoint will stay idle if their cycle bit is stale. Other users complain about IOMMU faults on x86 systems, unsurprisingly. Deal with it by using existing quirk which allocates a dummy page after each transfer ring segment. This was seen to resolve both problems. RPi came up with a more efficient solution, shortening each segment by four TRBs, but it complicated the driver and they ditched it for this quirk. Also rename the quirk and add VL805 device ID macro. Signed-off-by: Michal Pecio Link: https://github.com/raspberrypi/linux/issues/4685 Closes: https://bugzilla.kernel.org/show_bug.cgi?id=215906 CC: stable@vger.kernel.org Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20250225095927.2512358-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 3 ++- drivers/usb/host/xhci-pci.c | 10 +++++++--- drivers/usb/host/xhci.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 92703efda1f7..fdf0c1008225 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2437,7 +2437,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) * and our use of dma addresses in the trb_address_map radix tree needs * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need. */ - if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH) + if (xhci->quirks & XHCI_TRB_OVERFETCH) + /* Buggy HC prefetches beyond segment bounds - allocate dummy space at the end */ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2); else diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ad0ff356f6fa..54460d11f7ee 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -38,6 +38,8 @@ #define PCI_DEVICE_ID_ETRON_EJ168 0x7023 #define PCI_DEVICE_ID_ETRON_EJ188 0x7052 +#define PCI_DEVICE_ID_VIA_VL805 0x3483 + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1 @@ -418,8 +420,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == 0x3432) xhci->quirks |= XHCI_BROKEN_STREAMS; - if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) + if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) { xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_TRB_OVERFETCH; + } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) { @@ -467,11 +471,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->device == 0x9202) { xhci->quirks |= XHCI_RESET_ON_RESUME; - xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + xhci->quirks |= XHCI_TRB_OVERFETCH; } if (pdev->device == 0x9203) - xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH; + xhci->quirks |= XHCI_TRB_OVERFETCH; } if (pdev->vendor == PCI_VENDOR_ID_CDNS && diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8c164340a2c3..779b01dee068 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1632,7 +1632,7 @@ struct xhci_hcd { #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) -#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) +#define XHCI_TRB_OVERFETCH BIT_ULL(45) #define XHCI_ZHAOXIN_HOST BIT_ULL(46) #define XHCI_WRITE_64_HI_LO BIT_ULL(47) #define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48) From 2397d61ee45cddb8f3bd3a3a9840ef0f0b5aa843 Mon Sep 17 00:00:00 2001 From: Christian Heusel Date: Mon, 24 Feb 2025 09:32:59 +0100 Subject: [PATCH 0298/1090] Revert "drivers/card_reader/rtsx_usb: Restore interrupt based detection" This reverts commit 235b630eda072d7e7b102ab346d6b8a2c028a772. This commit was found responsible for issues with SD card recognition, as users had to re-insert their cards in the readers and wait for a while. As for some people the SD card was involved in the boot process it also caused boot failures. Cc: stable@vger.kernel.org Link: https://bbs.archlinux.org/viewtopic.php?id=303321 Fixes: 235b630eda07 ("drivers/card_reader/rtsx_usb: Restore interrupt based detection") Reported-by: qf Closes: https://lore.kernel.org/all/1de87dfa-1e81-45b7-8dcb-ad86c21d5352@heusel.eu Signed-off-by: Christian Heusel Link: https://lore.kernel.org/r/20250224-revert-sdcard-patch-v1-1-d1a457fbb796@heusel.eu Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cardreader/rtsx_usb.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c index e0174da5e9fc..77b0490a1b38 100644 --- a/drivers/misc/cardreader/rtsx_usb.c +++ b/drivers/misc/cardreader/rtsx_usb.c @@ -286,7 +286,6 @@ static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status) int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status) { int ret; - u8 interrupt_val = 0; u16 *buf; if (!status) @@ -309,20 +308,6 @@ int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status) ret = rtsx_usb_get_status_with_bulk(ucr, status); } - rtsx_usb_read_register(ucr, CARD_INT_PEND, &interrupt_val); - /* Cross check presence with interrupts */ - if (*status & XD_CD) - if (!(interrupt_val & XD_INT)) - *status &= ~XD_CD; - - if (*status & SD_CD) - if (!(interrupt_val & SD_INT)) - *status &= ~SD_CD; - - if (*status & MS_CD) - if (!(interrupt_val & MS_INT)) - *status &= ~MS_CD; - /* usb_control_msg may return positive when success */ if (ret < 0) return ret; From cbf85b9cb80bec6345ffe0368dfff98386f4714f Mon Sep 17 00:00:00 2001 From: Salah Triki Date: Fri, 21 Feb 2025 22:32:59 +0100 Subject: [PATCH 0299/1090] bluetooth: btusb: Initialize .owner field of force_poll_sync_fops Initialize .owner field of force_poll_sync_fops to THIS_MODULE in order to prevent btusb from being unloaded while its operations are in use. Fixes: 800fe5ec302e ("Bluetooth: btusb: Add support for queuing during polling interval") Signed-off-by: Salah Triki Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 8149e53fd0a7..2a8d91963c63 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3644,6 +3644,7 @@ static ssize_t force_poll_sync_write(struct file *file, } static const struct file_operations force_poll_sync_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_poll_sync_read, .write = force_poll_sync_write, From f2176a07e7b19f73e05c805cf3d130a2999154cb Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 21 Feb 2025 16:49:47 +0800 Subject: [PATCH 0300/1090] Bluetooth: Add check for mgmt_alloc_skb() in mgmt_remote_name() Add check for the return value of mgmt_alloc_skb() in mgmt_remote_name() to prevent null pointer dereference. Fixes: ba17bb62ce41 ("Bluetooth: Fix skb allocation in mgmt_remote_name() & mgmt_device_connected()") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f53304cb09db..3e0f88cd975c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -10413,6 +10413,8 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_FOUND, sizeof(*ev) + (name ? eir_precalc_len(name_len) : 0)); + if (!skb) + return; ev = skb_put(skb, sizeof(*ev)); bacpy(&ev->addr.bdaddr, bdaddr); From d8df010f72b8a32aaea393e36121738bb53ed905 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 21 Feb 2025 16:58:01 +0800 Subject: [PATCH 0301/1090] Bluetooth: Add check for mgmt_alloc_skb() in mgmt_device_connected() Add check for the return value of mgmt_alloc_skb() in mgmt_device_connected() to prevent null pointer dereference. Fixes: e96741437ef0 ("Bluetooth: mgmt: Make use of mgmt_send_event_skb in MGMT_EV_DEVICE_CONNECTED") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 3e0f88cd975c..621c555f639b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -9660,6 +9660,9 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn, sizeof(*ev) + (name ? eir_precalc_len(name_len) : 0) + eir_precalc_len(sizeof(conn->dev_class))); + if (!skb) + return; + ev = skb_put(skb, sizeof(*ev)); bacpy(&ev->addr.bdaddr, &conn->dst); ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type); From 0979ff3676b1b4e6a20970bc265491d23c2da42b Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Thu, 27 Feb 2025 20:00:05 +0100 Subject: [PATCH 0302/1090] nvmet: remove old function prototype nvmet_subsys_nsid_exists() doesn't exist anymore Fixes: 74d16965d7ac ("nvmet-loop: avoid using mutex in IO hotpath") Signed-off-by: Maurizio Lombardi Signed-off-by: Keith Busch --- drivers/nvme/target/nvmet.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index d2c1233981e1..fcf4f460dc9a 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -647,7 +647,6 @@ void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys, struct nvmet_host *host); void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type, u8 event_info, u8 log_page); -bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid); #define NVMET_MIN_QUEUE_SIZE 16 #define NVMET_MAX_QUEUE_SIZE 1024 From afb41b08c44e5386f2f52fa859010ac4afd2b66f Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Mon, 24 Feb 2025 15:40:58 +0100 Subject: [PATCH 0303/1090] nvme-tcp: Fix a C2HTermReq error message In H2CTermReq, a FES with value 0x05 means "R2T Limit Exceeded"; but in C2HTermReq the same value has a different meaning (Data Transfer Limit Exceeded). Fixes: 84e009042d0f ("nvme-tcp: add basic support for the C2HTermReq PDU") Signed-off-by: Maurizio Lombardi Reviewed-by: Sagi Grimberg Signed-off-by: Keith Busch --- drivers/nvme/host/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 8c14018201db..1094cbbec169 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -775,7 +775,7 @@ static void nvme_tcp_handle_c2h_term(struct nvme_tcp_queue *queue, [NVME_TCP_FES_PDU_SEQ_ERR] = "PDU Sequence Error", [NVME_TCP_FES_HDR_DIGEST_ERR] = "Header Digest Error", [NVME_TCP_FES_DATA_OUT_OF_RANGE] = "Data Transfer Out Of Range", - [NVME_TCP_FES_R2T_LIMIT_EXCEEDED] = "R2T Limit Exceeded", + [NVME_TCP_FES_DATA_LIMIT_EXCEEDED] = "Data Transfer Limit Exceeded", [NVME_TCP_FES_UNSUPPORTED_PARAM] = "Unsupported Parameter", }; From ada9ce437a4da8e27243251bd7a9ecec32ebd72a Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 27 Feb 2025 02:21:26 +0100 Subject: [PATCH 0304/1090] mailmap: remove unwanted entry for Antonio Quartulli antonio@openvpn.net is still used for sending patches under the OpenVPN Inc. umbrella, therefore this address should not be re-mapped. Signed-off-by: Antonio Quartulli Link: https://patch.msgid.link/20250227-b4-ovpn-v20-1-93f363310834@openvpn.net Signed-off-by: Jakub Kicinski --- .mailmap | 1 - 1 file changed, 1 deletion(-) diff --git a/.mailmap b/.mailmap index a897c16d3bae..598f31c4b498 100644 --- a/.mailmap +++ b/.mailmap @@ -88,7 +88,6 @@ Antonio Quartulli Antonio Quartulli Antonio Quartulli Antonio Quartulli -Antonio Quartulli Antonio Quartulli Anup Patel Archit Taneja From ad95bab0cd28ed77c2c0d0b6e76e03e031391064 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Wed, 26 Feb 2025 14:42:18 +0100 Subject: [PATCH 0305/1090] nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu() nvme_tcp_recv_pdu() doesn't check the validity of the header length. When header digests are enabled, a target might send a packet with an invalid header length (e.g. 255), causing nvme_tcp_verify_hdgst() to access memory outside the allocated area and cause memory corruptions by overwriting it with the calculated digest. Fix this by rejecting packets with an unexpected header length. Fixes: 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver") Signed-off-by: Maurizio Lombardi Reviewed-by: Sagi Grimberg Signed-off-by: Keith Busch --- drivers/nvme/host/tcp.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 1094cbbec169..23f11527d29d 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -217,6 +217,19 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue) return queue - queue->ctrl->queues; } +static inline bool nvme_tcp_recv_pdu_supported(enum nvme_tcp_pdu_type type) +{ + switch (type) { + case nvme_tcp_c2h_term: + case nvme_tcp_c2h_data: + case nvme_tcp_r2t: + case nvme_tcp_rsp: + return true; + default: + return false; + } +} + /* * Check if the queue is TLS encrypted */ @@ -818,6 +831,16 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb, return 0; hdr = queue->pdu; + if (unlikely(hdr->hlen != sizeof(struct nvme_tcp_rsp_pdu))) { + if (!nvme_tcp_recv_pdu_supported(hdr->type)) + goto unsupported_pdu; + + dev_err(queue->ctrl->ctrl.device, + "pdu type %d has unexpected header length (%d)\n", + hdr->type, hdr->hlen); + return -EPROTO; + } + if (unlikely(hdr->type == nvme_tcp_c2h_term)) { /* * C2HTermReq never includes Header or Data digests. @@ -850,10 +873,13 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb, nvme_tcp_init_recv_ctx(queue); return nvme_tcp_handle_r2t(queue, (void *)queue->pdu); default: - dev_err(queue->ctrl->ctrl.device, - "unsupported pdu type (%d)\n", hdr->type); - return -EINVAL; + goto unsupported_pdu; } + +unsupported_pdu: + dev_err(queue->ctrl->ctrl.device, + "unsupported pdu type (%d)\n", hdr->type); + return -EINVAL; } static inline void nvme_tcp_end_request(struct request *rq, u16 status) From a16f88964c647103dad7743a484b216d488a6352 Mon Sep 17 00:00:00 2001 From: Meir Elisha Date: Wed, 26 Feb 2025 09:28:12 +0200 Subject: [PATCH 0306/1090] nvmet-tcp: Fix a possible sporadic response drops in weakly ordered arch The order in which queue->cmd and rcv_state are updated is crucial. If these assignments are reordered by the compiler, the worker might not get queued in nvmet_tcp_queue_response(), hanging the IO. to enforce the the correct reordering, set rcv_state using smp_store_release(). Fixes: bdaf13279192 ("nvmet-tcp: fix a segmentation fault during io parsing error") Signed-off-by: Meir Elisha Reviewed-by: Sagi Grimberg Signed-off-by: Keith Busch --- drivers/nvme/target/tcp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 7c51c2a8c109..4f9cac8a5abe 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -571,10 +571,16 @@ static void nvmet_tcp_queue_response(struct nvmet_req *req) struct nvmet_tcp_cmd *cmd = container_of(req, struct nvmet_tcp_cmd, req); struct nvmet_tcp_queue *queue = cmd->queue; + enum nvmet_tcp_recv_state queue_state; + struct nvmet_tcp_cmd *queue_cmd; struct nvme_sgl_desc *sgl; u32 len; - if (unlikely(cmd == queue->cmd)) { + /* Pairs with store_release in nvmet_prepare_receive_pdu() */ + queue_state = smp_load_acquire(&queue->rcv_state); + queue_cmd = READ_ONCE(queue->cmd); + + if (unlikely(cmd == queue_cmd)) { sgl = &cmd->req.cmd->common.dptr.sgl; len = le32_to_cpu(sgl->length); @@ -583,7 +589,7 @@ static void nvmet_tcp_queue_response(struct nvmet_req *req) * Avoid using helpers, this might happen before * nvmet_req_init is completed. */ - if (queue->rcv_state == NVMET_TCP_RECV_PDU && + if (queue_state == NVMET_TCP_RECV_PDU && len && len <= cmd->req.port->inline_data_size && nvme_is_write(cmd->req.cmd)) return; @@ -847,8 +853,9 @@ static void nvmet_prepare_receive_pdu(struct nvmet_tcp_queue *queue) { queue->offset = 0; queue->left = sizeof(struct nvme_tcp_hdr); - queue->cmd = NULL; - queue->rcv_state = NVMET_TCP_RECV_PDU; + WRITE_ONCE(queue->cmd, NULL); + /* Ensure rcv_state is visible only after queue->cmd is set */ + smp_store_release(&queue->rcv_state, NVMET_TCP_RECV_PDU); } static void nvmet_tcp_free_crypto(struct nvmet_tcp_queue *queue) From 00371a3f48775967950c2fe3ec97b7c786ca956d Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Wed, 26 Feb 2025 09:52:05 +0100 Subject: [PATCH 0307/1090] stmmac: loongson: Pass correct arg to PCI function pcim_iomap_regions() should receive the driver's name as its third parameter, not the PCI device's name. Define the driver name with a macro and use it at the appropriate places, including pcim_iomap_regions(). Cc: stable@vger.kernel.org # v5.14+ Fixes: 30bba69d7db4 ("stmmac: pci: Add dwmac support for Loongson") Signed-off-by: Philipp Stanner Reviewed-by: Andrew Lunn Reviewed-by: Yanteng Si Tested-by: Henry Chen Link: https://patch.msgid.link/20250226085208.97891-2-phasta@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index f5acfb7d4ff6..ab7c2750c104 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -11,6 +11,8 @@ #include "dwmac_dma.h" #include "dwmac1000.h" +#define DRIVER_NAME "dwmac-loongson-pci" + /* Normal Loongson Tx Summary */ #define DMA_INTR_ENA_NIE_TX_LOONGSON 0x00040000 /* Normal Loongson Rx Summary */ @@ -568,7 +570,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id for (i = 0; i < PCI_STD_NUM_BARS; i++) { if (pci_resource_len(pdev, i) == 0) continue; - ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); + ret = pcim_iomap_regions(pdev, BIT(0), DRIVER_NAME); if (ret) goto err_disable_device; break; @@ -687,7 +689,7 @@ static const struct pci_device_id loongson_dwmac_id_table[] = { MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table); static struct pci_driver loongson_dwmac_driver = { - .name = "dwmac-loongson-pci", + .name = DRIVER_NAME, .id_table = loongson_dwmac_id_table, .probe = loongson_dwmac_probe, .remove = loongson_dwmac_remove, From c72e455b89f216b43cd0dbb518036ec4c98f5c46 Mon Sep 17 00:00:00 2001 From: Manuel Fombuena Date: Tue, 25 Feb 2025 22:01:02 +0000 Subject: [PATCH 0308/1090] leds: leds-st1202: Fix NULL pointer access on race condition st1202_dt_init() calls devm_led_classdev_register_ext() before the internal data structures are properly set up, so the LEDs become visible to user space while being partially initialized, leading to a window where trying to access them causes a NULL pointer access. Move devm_led_classdev_register_ext() from DT initialization to the end of the probe function when DT and hardware are fully initialized and ready to interact with user space. Fixes: 259230378c65 ("leds: Add LED1202 I2C driver") Signed-off-by: Manuel Fombuena Link: https://lore.kernel.org/r/CWLP123MB54732771AC0CE5491B3C84DCC5C32@CWLP123MB5473.GBRP123.PROD.OUTLOOK.COM Signed-off-by: Lee Jones --- drivers/leds/leds-st1202.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c index b691c4886993..e894b3f9a0f4 100644 --- a/drivers/leds/leds-st1202.c +++ b/drivers/leds/leds-st1202.c @@ -261,8 +261,6 @@ static int st1202_dt_init(struct st1202_chip *chip) int err, reg; for_each_available_child_of_node_scoped(dev_of_node(dev), child) { - struct led_init_data init_data = {}; - err = of_property_read_u32(child, "reg", ®); if (err) return dev_err_probe(dev, err, "Invalid register\n"); @@ -276,15 +274,6 @@ static int st1202_dt_init(struct st1202_chip *chip) led->led_cdev.pattern_set = st1202_led_pattern_set; led->led_cdev.pattern_clear = st1202_led_pattern_clear; led->led_cdev.default_trigger = "pattern"; - - init_data.fwnode = led->fwnode; - init_data.devicename = "st1202"; - init_data.default_label = ":"; - - err = devm_led_classdev_register_ext(dev, &led->led_cdev, &init_data); - if (err < 0) - return dev_err_probe(dev, err, "Failed to register LED class device\n"); - led->led_cdev.brightness_set = st1202_brightness_set; led->led_cdev.brightness_get = st1202_brightness_get; } @@ -368,6 +357,7 @@ static int st1202_probe(struct i2c_client *client) return ret; for (int i = 0; i < ST1202_MAX_LEDS; i++) { + struct led_init_data init_data = {}; led = &chip->leds[i]; led->chip = chip; led->led_num = i; @@ -384,6 +374,15 @@ static int st1202_probe(struct i2c_client *client) if (ret < 0) return dev_err_probe(&client->dev, ret, "Failed to clear LED pattern\n"); + + init_data.fwnode = led->fwnode; + init_data.devicename = "st1202"; + init_data.default_label = ":"; + + ret = devm_led_classdev_register_ext(&client->dev, &led->led_cdev, &init_data); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to register LED class device\n"); } return 0; From 0bd862846e7f89910252cbef8718a757950f1683 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:07 +0530 Subject: [PATCH 0309/1090] ASoC: Intel: avs: use devm_kmemdup_array() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert to use devm_kmemdup_array() and while at it, use source size instead of destination. Signed-off-by: Raag Jadav Acked-by: Mark Brown Reviewed-by: Amadeusz SÅ‚awiÅ„ski Reviewed-by: Linus Walleij Link: https://patch.msgid.link/20250228062812.150004-2-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/da7219.c | 3 ++- sound/soc/intel/avs/boards/es8336.c | 3 ++- sound/soc/intel/avs/boards/nau8825.c | 3 ++- sound/soc/intel/avs/boards/rt274.c | 3 ++- sound/soc/intel/avs/boards/rt286.c | 3 ++- sound/soc/intel/avs/boards/rt298.c | 3 ++- sound/soc/intel/avs/boards/rt5663.c | 3 ++- sound/soc/intel/avs/boards/rt5682.c | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 76078a7005b0..9507a96f26ac 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -113,7 +113,8 @@ static int avs_da7219_codec_init(struct snd_soc_pcm_runtime *runtime) } num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 426ce37105ae..6f3c4f6c9302 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -109,7 +109,8 @@ static int avs_es8336_codec_init(struct snd_soc_pcm_runtime *runtime) data = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index bf902540744c..6833eebd82d6 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -88,7 +88,8 @@ static int avs_nau8825_codec_init(struct snd_soc_pcm_runtime *runtime) jack = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index 4b6c02a40204..f5caafc21861 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -98,7 +98,8 @@ static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) jack = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index e40563ca99fd..1eb0399c0fae 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -59,7 +59,8 @@ static int avs_rt286_codec_init(struct snd_soc_pcm_runtime *runtime) jack = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 94fce07c83f9..85269a3be981 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -70,7 +70,8 @@ static int avs_rt298_codec_init(struct snd_soc_pcm_runtime *runtime) jack = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index b456b9d14665..e3310b3268ba 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -65,7 +65,8 @@ static int avs_rt5663_codec_init(struct snd_soc_pcm_runtime *runtime) jack = &priv->jack; num_pins = ARRAY_SIZE(card_headset_pins); - pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_headset_pins, num_pins, + sizeof(card_headset_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 335960cfd7ba..339df0b944c1 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -102,7 +102,8 @@ static int avs_rt5682_codec_init(struct snd_soc_pcm_runtime *runtime) jack = snd_soc_card_get_drvdata(card); num_pins = ARRAY_SIZE(card_jack_pins); - pins = devm_kmemdup(card->dev, card_jack_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + pins = devm_kmemdup_array(card->dev, card_jack_pins, num_pins, + sizeof(card_jack_pins[0]), GFP_KERNEL); if (!pins) return -ENOMEM; From 3e706be02befae55b50b240d4360b5993f9879a8 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:08 +0530 Subject: [PATCH 0310/1090] ASoC: hdac_hdmi: use devm_kmemdup_array() Convert to use devm_kmemdup_array() and while at it, make the size robust against type changes. Signed-off-by: Raag Jadav Link: https://patch.msgid.link/20250228062812.150004-3-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index e1a7f0b0c0f3..3bea5d09219a 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1017,8 +1017,7 @@ static int hdac_hdmi_create_pin_port_muxs(struct hdac_device *hdev, return -ENOMEM; } - se->texts = devm_kmemdup(&hdev->dev, items, - (num_items * sizeof(char *)), GFP_KERNEL); + se->texts = devm_kmemdup_array(&hdev->dev, items, num_items, sizeof(items[0]), GFP_KERNEL); if (!se->texts) return -ENOMEM; From 69aaab0e65e9bd7601740c1e14cc6de86dafb621 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:09 +0530 Subject: [PATCH 0311/1090] ASoC: tlv320dac33: use devm_kmemdup_array() Convert to use devm_kmemdup_array() and while at it, make the size robust against type changes. Signed-off-by: Raag Jadav Link: https://patch.msgid.link/20250228062812.150004-4-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index fa46f51d4341..423b9264a205 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1477,10 +1477,8 @@ static int dac33_i2c_probe(struct i2c_client *client) if (dac33 == NULL) return -ENOMEM; - dac33->reg_cache = devm_kmemdup(&client->dev, - dac33_reg, - ARRAY_SIZE(dac33_reg) * sizeof(u8), - GFP_KERNEL); + dac33->reg_cache = devm_kmemdup_array(&client->dev, dac33_reg, ARRAY_SIZE(dac33_reg), + sizeof(dac33_reg[0]), GFP_KERNEL); if (!dac33->reg_cache) return -ENOMEM; From d9d71a6e2d19a2f3ccebea0092b8ddc1e935886f Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:10 +0530 Subject: [PATCH 0312/1090] ASoC: uda1380: use devm_kmemdup_array() Convert to use devm_kmemdup_array() and while at it, make the size robust against type changes. Signed-off-by: Raag Jadav Link: https://patch.msgid.link/20250228062812.150004-5-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 4f8fdd574585..c179d865b938 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -766,10 +766,8 @@ static int uda1380_i2c_probe(struct i2c_client *i2c) return ret; } - uda1380->reg_cache = devm_kmemdup(&i2c->dev, - uda1380_reg, - ARRAY_SIZE(uda1380_reg) * sizeof(u16), - GFP_KERNEL); + uda1380->reg_cache = devm_kmemdup_array(&i2c->dev, uda1380_reg, ARRAY_SIZE(uda1380_reg), + sizeof(uda1380_reg[0]), GFP_KERNEL); if (!uda1380->reg_cache) return -ENOMEM; From b26205e172ca035e327e49edb0c2611e5d2ede8d Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:11 +0530 Subject: [PATCH 0313/1090] ASoC: meson: axg-tdm-interface: use devm_kmemdup_array() Convert to use devm_kmemdup_array() which is more robust. Signed-off-by: Raag Jadav Link: https://patch.msgid.link/20250228062812.150004-6-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdm-interface.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 09103eef2a97..421b5d719fb3 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -529,7 +529,6 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_dai_driver *dai_drv; struct axg_tdm_iface *iface; - int i; iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); if (!iface) @@ -541,15 +540,11 @@ static int axg_tdm_iface_probe(struct platform_device *pdev) * We'll change the number of channel provided by DAI stream, so dpcm * channel merge can be done properly */ - dai_drv = devm_kcalloc(dev, ARRAY_SIZE(axg_tdm_iface_dai_drv), - sizeof(*dai_drv), GFP_KERNEL); + dai_drv = devm_kmemdup_array(dev, axg_tdm_iface_dai_drv, ARRAY_SIZE(axg_tdm_iface_dai_drv), + sizeof(axg_tdm_iface_dai_drv[0]), GFP_KERNEL); if (!dai_drv) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(axg_tdm_iface_dai_drv); i++) - memcpy(&dai_drv[i], &axg_tdm_iface_dai_drv[i], - sizeof(*dai_drv)); - /* Bit clock provided on the pad */ iface->sclk = devm_clk_get(dev, "sclk"); if (IS_ERR(iface->sclk)) From c173b5ee81a25e8aafb21ccdb7ab457da7783bf1 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Fri, 28 Feb 2025 11:58:12 +0530 Subject: [PATCH 0314/1090] ASoC: uniphier: use devm_kmemdup_array() Convert to use devm_kmemdup_array() and while at it, make the size robust against type changes. Signed-off-by: Raag Jadav Link: https://patch.msgid.link/20250228062812.150004-7-raag.jadav@intel.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-cpu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c index 470f129166a4..3224c11a527f 100644 --- a/sound/soc/uniphier/aio-cpu.c +++ b/sound/soc/uniphier/aio-cpu.c @@ -762,14 +762,10 @@ int uniphier_aio_probe(struct platform_device *pdev) return -ENOMEM; chip->num_plls = chip->chip_spec->num_plls; - chip->plls = devm_kcalloc(dev, - chip->num_plls, - sizeof(struct uniphier_aio_pll), - GFP_KERNEL); + chip->plls = devm_kmemdup_array(dev, chip->chip_spec->plls, chip->num_plls, + sizeof(*chip->chip_spec->plls), GFP_KERNEL); if (!chip->plls) return -ENOMEM; - memcpy(chip->plls, chip->chip_spec->plls, - sizeof(struct uniphier_aio_pll) * chip->num_plls); for (i = 0; i < chip->num_aios; i++) { struct uniphier_aio *aio = &chip->aios[i]; From be45bc4eff33d9a7dae84a2150f242a91a617402 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 24 Feb 2025 08:54:41 -0800 Subject: [PATCH 0315/1090] KVM: SVM: Set RFLAGS.IF=1 in C code, to get VMRUN out of the STI shadow Enable/disable local IRQs, i.e. set/clear RFLAGS.IF, in the common svm_vcpu_enter_exit() just after/before guest_state_{enter,exit}_irqoff() so that VMRUN is not executed in an STI shadow. AMD CPUs have a quirk (some would say "bug"), where the STI shadow bleeds into the guest's intr_state field if a #VMEXIT occurs during injection of an event, i.e. if the VMRUN doesn't complete before the subsequent #VMEXIT. The spurious "interrupts masked" state is relatively benign, as it only occurs during event injection and is transient. Because KVM is already injecting an event, the guest can't be in HLT, and if KVM is querying IRQ blocking for injection, then KVM would need to force an immediate exit anyways since injecting multiple events is impossible. However, because KVM copies int_state verbatim from vmcb02 to vmcb12, the spurious STI shadow is visible to L1 when running a nested VM, which can trip sanity checks, e.g. in VMware's VMM. Hoist the STI+CLI all the way to C code, as the aforementioned calls to guest_state_{enter,exit}_irqoff() already inform lockdep that IRQs are enabled/disabled, and taking a fault on VMRUN with RFLAGS.IF=1 is already possible. I.e. if there's kernel code that is confused by running with RFLAGS.IF=1, then it's already a problem. In practice, since GIF=0 also blocks NMIs, the only change in exposure to non-KVM code (relative to surrounding VMRUN with STI+CLI) is exception handling code, and except for the kvm_rebooting=1 case, all exception in the core VM-Enter/VM-Exit path are fatal. Use the "raw" variants to enable/disable IRQs to avoid tracing in the "no instrumentation" code; the guest state helpers also take care of tracing IRQ state. Oppurtunstically document why KVM needs to do STI in the first place. Reported-by: Doug Covelli Closes: https://lore.kernel.org/all/CADH9ctBs1YPmE4aCfGPNBwA10cA8RuAk2gO7542DjMZgs4uzJQ@mail.gmail.com Fixes: f14eec0a3203 ("KVM: SVM: move more vmentry code to assembly") Cc: stable@vger.kernel.org Reviewed-by: Jim Mattson Link: https://lore.kernel.org/r/20250224165442.2338294-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 14 ++++++++++++++ arch/x86/kvm/svm/vmenter.S | 10 +--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index a713c803a3a3..0d299f3f921e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4189,6 +4189,18 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in guest_state_enter_irqoff(); + /* + * Set RFLAGS.IF prior to VMRUN, as the host's RFLAGS.IF at the time of + * VMRUN controls whether or not physical IRQs are masked (KVM always + * runs with V_INTR_MASKING_MASK). Toggle RFLAGS.IF here to avoid the + * temptation to do STI+VMRUN+CLI, as AMD CPUs bleed the STI shadow + * into guest state if delivery of an event during VMRUN triggers a + * #VMEXIT, and the guest_state transitions already tell lockdep that + * IRQs are being enabled/disabled. Note! GIF=0 for the entirety of + * this path, so IRQs aren't actually unmasked while running host code. + */ + raw_local_irq_enable(); + amd_clear_divider(); if (sev_es_guest(vcpu->kvm)) @@ -4197,6 +4209,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in else __svm_vcpu_run(svm, spec_ctrl_intercepted); + raw_local_irq_disable(); + guest_state_exit_irqoff(); } diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 2ed80aea3bb1..0c61153b275f 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -170,12 +170,8 @@ SYM_FUNC_START(__svm_vcpu_run) mov VCPU_RDI(%_ASM_DI), %_ASM_DI /* Enter guest mode */ - sti - 3: vmrun %_ASM_AX 4: - cli - /* Pop @svm to RAX while it's the only available register. */ pop %_ASM_AX @@ -340,12 +336,8 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) mov KVM_VMCB_pa(%rax), %rax /* Enter guest mode */ - sti - 1: vmrun %rax - -2: cli - +2: /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT From f3513a335e71296a1851167b4e3b0e2bf09fc5f1 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 24 Feb 2025 08:54:42 -0800 Subject: [PATCH 0316/1090] KVM: selftests: Assert that STI blocking isn't set after event injection Add an L1 (guest) assert to the nested exceptions test to verify that KVM doesn't put VMRUN in an STI shadow (AMD CPUs bleed the shadow into the guest's int_state if a #VMEXIT occurs before VMRUN fully completes). Add a similar assert to the VMX side as well, because why not. Reviewed-by: Jim Mattson Link: https://lore.kernel.org/r/20250224165442.2338294-3-seanjc@google.com Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/x86/nested_exceptions_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c index 3eb0313ffa39..3641a42934ac 100644 --- a/tools/testing/selftests/kvm/x86/nested_exceptions_test.c +++ b/tools/testing/selftests/kvm/x86/nested_exceptions_test.c @@ -85,6 +85,7 @@ static void svm_run_l2(struct svm_test_data *svm, void *l2_code, int vector, GUEST_ASSERT_EQ(ctrl->exit_code, (SVM_EXIT_EXCP_BASE + vector)); GUEST_ASSERT_EQ(ctrl->exit_info_1, error_code); + GUEST_ASSERT(!ctrl->int_state); } static void l1_svm_code(struct svm_test_data *svm) @@ -122,6 +123,7 @@ static void vmx_run_l2(void *l2_code, int vector, uint32_t error_code) GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_EXCEPTION_NMI); GUEST_ASSERT_EQ((vmreadz(VM_EXIT_INTR_INFO) & 0xff), vector); GUEST_ASSERT_EQ(vmreadz(VM_EXIT_INTR_ERROR_CODE), error_code); + GUEST_ASSERT(!vmreadz(GUEST_INTERRUPTIBILITY_INFO)); } static void l1_vmx_code(struct vmx_pages *vmx) From ee89e8013383d50a27ea9bf3c8a69eed6799856f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 27 Feb 2025 14:24:06 -0800 Subject: [PATCH 0317/1090] KVM: SVM: Drop DEBUGCTL[5:2] from guest's effective value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop bits 5:2 from the guest's effective DEBUGCTL value, as AMD changed the architectural behavior of the bits and broke backwards compatibility. On CPUs without BusLockTrap (or at least, in APMs from before ~2023), bits 5:2 controlled the behavior of external pins: Performance-Monitoring/Breakpoint Pin-Control (PBi)—Bits 5:2, read/write. Software uses thesebits to control the type of information reported by the four external performance-monitoring/breakpoint pins on the processor. When a PBi bit is cleared to 0, the corresponding external pin (BPi) reports performance-monitor information. When a PBi bit is set to 1, the corresponding external pin (BPi) reports breakpoint information. With the introduction of BusLockTrap, presumably to be compatible with Intel CPUs, AMD redefined bit 2 to be BLCKDB: Bus Lock #DB Trap (BLCKDB)—Bit 2, read/write. Software sets this bit to enable generation of a #DB trap following successful execution of a bus lock when CPL is > 0. and redefined bits 5:3 (and bit 6) as "6:3 Reserved MBZ". Ideally, KVM would treat bits 5:2 as reserved. Defer that change to a feature cleanup to avoid breaking existing guest in LTS kernels. For now, drop the bits to retain backwards compatibility (of a sort). Note, dropping bits 5:2 is still a guest-visible change, e.g. if the guest is enabling LBRs *and* the legacy PBi bits, then the state of the PBi bits is visible to the guest, whereas now the guest will always see '0'. Reported-by: Ravi Bangoria Cc: stable@vger.kernel.org Reviewed-and-tested-by: Ravi Bangoria Link: https://lore.kernel.org/r/20250227222411.3490595-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 12 ++++++++++++ arch/x86/kvm/svm/svm.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 0d299f3f921e..bdafbde1f211 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3165,6 +3165,18 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) kvm_pr_unimpl_wrmsr(vcpu, ecx, data); break; } + + /* + * AMD changed the architectural behavior of bits 5:2. On CPUs + * without BusLockTrap, bits 5:2 control "external pins", but + * on CPUs that support BusLockDetect, bit 2 enables BusLockTrap + * and bits 5:3 are reserved-to-zero. Sadly, old KVM allowed + * the guest to set bits 5:2 despite not actually virtualizing + * Performance-Monitoring/Breakpoint external pins. Drop bits + * 5:2 for backwards compatibility. + */ + data &= ~GENMASK(5, 2); + if (data & DEBUGCTL_RESERVED_BITS) return 1; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 9d7cdb8fbf87..3a931d3885e7 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -584,7 +584,7 @@ static inline bool is_vnmi_enabled(struct vcpu_svm *svm) /* svm.c */ #define MSR_INVALID 0xffffffffU -#define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) +#define DEBUGCTL_RESERVED_BITS (~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) extern bool dump_invalid_vmcb; From d0eac42f5cecce009d315655bee341304fbe075e Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 27 Feb 2025 14:24:07 -0800 Subject: [PATCH 0318/1090] KVM: SVM: Suppress DEBUGCTL.BTF on AMD Mark BTF as reserved in DEBUGCTL on AMD, as KVM doesn't actually support BTF, and fully enabling BTF virtualization is non-trivial due to interactions with the emulator, guest_debug, #DB interception, nested SVM, etc. Don't inject #GP if the guest attempts to set BTF, as there's no way to communicate lack of support to the guest, and instead suppress the flag and treat the WRMSR as (partially) unsupported. In short, make KVM behave the same on AMD and Intel (VMX already squashes BTF). Note, due to other bugs in KVM's handling of DEBUGCTL, the only way BTF has "worked" in any capacity is if the guest simultaneously enables LBRs. Reported-by: Ravi Bangoria Cc: stable@vger.kernel.org Reviewed-and-tested-by: Ravi Bangoria Link: https://lore.kernel.org/r/20250227222411.3490595-3-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 9 +++++++++ arch/x86/kvm/svm/svm.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index bdafbde1f211..ed4846518696 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3177,6 +3177,15 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) */ data &= ~GENMASK(5, 2); + /* + * Suppress BTF as KVM doesn't virtualize BTF, but there's no + * way to communicate lack of support to the guest. + */ + if (data & DEBUGCTLMSR_BTF) { + kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data); + data &= ~DEBUGCTLMSR_BTF; + } + if (data & DEBUGCTL_RESERVED_BITS) return 1; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 3a931d3885e7..ea44c1da5a7c 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -584,7 +584,7 @@ static inline bool is_vnmi_enabled(struct vcpu_svm *svm) /* svm.c */ #define MSR_INVALID 0xffffffffU -#define DEBUGCTL_RESERVED_BITS (~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) +#define DEBUGCTL_RESERVED_BITS (~DEBUGCTLMSR_LBR) extern bool dump_invalid_vmcb; From fb71c795935652fa20eaf9517ca9547f5af99a76 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 27 Feb 2025 14:24:08 -0800 Subject: [PATCH 0319/1090] KVM: x86: Snapshot the host's DEBUGCTL in common x86 Move KVM's snapshot of DEBUGCTL to kvm_vcpu_arch and take the snapshot in common x86, so that SVM can also use the snapshot. Opportunistically change the field to a u64. While bits 63:32 are reserved on AMD, not mentioned at all in Intel's SDM, and managed as an "unsigned long" by the kernel, DEBUGCTL is an MSR and therefore a 64-bit value. Reviewed-by: Xiaoyao Li Cc: stable@vger.kernel.org Reviewed-and-tested-by: Ravi Bangoria Link: https://lore.kernel.org/r/20250227222411.3490595-4-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/vmx/vmx.c | 8 ++------ arch/x86/kvm/vmx/vmx.h | 2 -- arch/x86/kvm/x86.c | 1 + 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0b7af5902ff7..32ae3aa50c7e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -780,6 +780,7 @@ struct kvm_vcpu_arch { u32 pkru; u32 hflags; u64 efer; + u64 host_debugctl; u64 apic_base; struct kvm_lapic *apic; /* kernel irqchip context */ bool load_eoi_exitmap_pending; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 6c56d5235f0f..3b92f893b239 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1514,16 +1514,12 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu, */ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { - struct vcpu_vmx *vmx = to_vmx(vcpu); - if (vcpu->scheduled_out && !kvm_pause_in_guest(vcpu->kvm)) shrink_ple_window(vcpu); vmx_vcpu_load_vmcs(vcpu, cpu, NULL); vmx_vcpu_pi_load(vcpu, cpu); - - vmx->host_debugctlmsr = get_debugctlmsr(); } void vmx_vcpu_put(struct kvm_vcpu *vcpu) @@ -7458,8 +7454,8 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) } /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */ - if (vmx->host_debugctlmsr) - update_debugctlmsr(vmx->host_debugctlmsr); + if (vcpu->arch.host_debugctl) + update_debugctlmsr(vcpu->arch.host_debugctl); #ifndef CONFIG_X86_64 /* diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 8b111ce1087c..951e44dc9d0e 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -340,8 +340,6 @@ struct vcpu_vmx { /* apic deadline value in host tsc */ u64 hv_deadline_tsc; - unsigned long host_debugctlmsr; - /* * Only bits masked by msr_ia32_feature_control_valid_bits can be set in * msr_ia32_feature_control. FEAT_CTL_LOCKED is always included diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 02159c967d29..5c6fd0edc41f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4968,6 +4968,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) /* Save host pkru register if supported */ vcpu->arch.host_pkru = read_pkru(); + vcpu->arch.host_debugctl = get_debugctlmsr(); /* Apply any externally detected TSC adjustments (due to suspend) */ if (unlikely(vcpu->arch.tsc_offset_adjustment)) { From 433265870ab3455b418885bff48fa5fd02f7e448 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 27 Feb 2025 14:24:09 -0800 Subject: [PATCH 0320/1090] KVM: SVM: Manually context switch DEBUGCTL if LBR virtualization is disabled Manually load the guest's DEBUGCTL prior to VMRUN (and restore the host's value on #VMEXIT) if it diverges from the host's value and LBR virtualization is disabled, as hardware only context switches DEBUGCTL if LBR virtualization is fully enabled. Running the guest with the host's value has likely been mildly problematic for quite some time, e.g. it will result in undesirable behavior if BTF diverges (with the caveat that KVM now suppresses guest BTF due to lack of support). But the bug became fatal with the introduction of Bus Lock Trap ("Detect" in kernel paralance) support for AMD (commit 408eb7417a92 ("x86/bus_lock: Add support for AMD")), as a bus lock in the guest will trigger an unexpected #DB. Note, suppressing the bus lock #DB, i.e. simply resuming the guest without injecting a #DB, is not an option. It wouldn't address the general issue with DEBUGCTL, e.g. for things like BTF, and there are other guest-visible side effects if BusLockTrap is left enabled. If BusLockTrap is disabled, then DR6.BLD is reserved-to-1; any attempts to clear it by software are ignored. But if BusLockTrap is enabled, software can clear DR6.BLD: Software enables bus lock trap by setting DebugCtl MSR[BLCKDB] (bit 2) to 1. When bus lock trap is enabled, ... The processor indicates that this #DB was caused by a bus lock by clearing DR6[BLD] (bit 11). DR6[11] previously had been defined to be always 1. and clearing DR6.BLD is "sticky" in that it's not set (i.e. lowered) by other #DBs: All other #DB exceptions leave DR6[BLD] unmodified E.g. leaving BusLockTrap enable can confuse a legacy guest that writes '0' to reset DR6. Reported-by: rangemachine@gmail.com Reported-by: whanos@sergal.fun Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219787 Closes: https://lore.kernel.org/all/bug-219787-28872@https.bugzilla.kernel.org%2F Cc: Ravi Bangoria Cc: stable@vger.kernel.org Reviewed-and-tested-by: Ravi Bangoria Link: https://lore.kernel.org/r/20250227222411.3490595-5-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ed4846518696..e67de787fc71 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4288,6 +4288,16 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, clgi(); kvm_load_guest_xsave_state(vcpu); + /* + * Hardware only context switches DEBUGCTL if LBR virtualization is + * enabled. Manually load DEBUGCTL if necessary (and restore it after + * VM-Exit), as running with the host's DEBUGCTL can negatively affect + * guest state and can even be fatal, e.g. due to Bus Lock Detect. + */ + if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) && + vcpu->arch.host_debugctl != svm->vmcb->save.dbgctl) + update_debugctlmsr(svm->vmcb->save.dbgctl); + kvm_wait_lapic_expire(vcpu); /* @@ -4315,6 +4325,10 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) kvm_before_interrupt(vcpu, KVM_HANDLING_NMI); + if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) && + vcpu->arch.host_debugctl != svm->vmcb->save.dbgctl) + update_debugctlmsr(vcpu->arch.host_debugctl); + kvm_load_host_xsave_state(vcpu); stgi(); From 189ecdb3e112da703ac0699f4ec76aa78122f911 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 27 Feb 2025 14:24:10 -0800 Subject: [PATCH 0321/1090] KVM: x86: Snapshot the host's DEBUGCTL after disabling IRQs Snapshot the host's DEBUGCTL after disabling IRQs, as perf can toggle debugctl bits from IRQ context, e.g. when enabling/disabling events via smp_call_function_single(). Taking the snapshot (long) before IRQs are disabled could result in KVM effectively clobbering DEBUGCTL due to using a stale snapshot. Cc: stable@vger.kernel.org Reviewed-and-tested-by: Ravi Bangoria Link: https://lore.kernel.org/r/20250227222411.3490595-6-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/x86.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5c6fd0edc41f..12d5f47c1bbe 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4968,7 +4968,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) /* Save host pkru register if supported */ vcpu->arch.host_pkru = read_pkru(); - vcpu->arch.host_debugctl = get_debugctlmsr(); /* Apply any externally detected TSC adjustments (due to suspend) */ if (unlikely(vcpu->arch.tsc_offset_adjustment)) { @@ -10969,6 +10968,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) set_debugreg(0, 7); } + vcpu->arch.host_debugctl = get_debugctlmsr(); + guest_timing_enter_irqoff(); for (;;) { From 4a4f9b5c7c13601c4f1b3d8c607d7439e39f40d2 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 28 Feb 2025 15:58:30 -0500 Subject: [PATCH 0322/1090] bcachefs: Don't set BCH_FEATURE_incompat_version_field unless requested We shouldn't be setting incompatible bits or the incompatible version field unless explicitly request or allowed - otherwise we break mounting with old kernels or userspace. Reported-by: Dave Hansen Signed-off-by: Kent Overstreet --- fs/bcachefs/super-io.c | 24 ++++++++++++++++-------- fs/bcachefs/super-io.h | 11 ++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index 8037ccbacf6a..a81a7b6c0989 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -69,14 +69,20 @@ enum bcachefs_metadata_version bch2_latest_compatible_version(enum bcachefs_meta return v; } -void bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version version) +bool bch2_set_version_incompat(struct bch_fs *c, enum bcachefs_metadata_version version) { - mutex_lock(&c->sb_lock); - SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb, - max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version)); - c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_FEATURE_incompat_version_field); - bch2_write_super(c); - mutex_unlock(&c->sb_lock); + bool ret = (c->sb.features & BIT_ULL(BCH_FEATURE_incompat_version_field)) && + version <= c->sb.version_incompat_allowed; + + if (ret) { + mutex_lock(&c->sb_lock); + SET_BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb, + max(BCH_SB_VERSION_INCOMPAT(c->disk_sb.sb), version)); + bch2_write_super(c); + mutex_unlock(&c->sb_lock); + } + + return ret; } const char * const bch2_sb_fields[] = { @@ -1219,9 +1225,11 @@ void bch2_sb_upgrade(struct bch_fs *c, unsigned new_version, bool incompat) c->disk_sb.sb->version = cpu_to_le16(new_version); c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_SB_FEATURES_ALL); - if (incompat) + if (incompat) { SET_BCH_SB_VERSION_INCOMPAT_ALLOWED(c->disk_sb.sb, max(BCH_SB_VERSION_INCOMPAT_ALLOWED(c->disk_sb.sb), new_version)); + c->disk_sb.sb->features[0] |= cpu_to_le64(BCH_FEATURE_incompat_version_field); + } } static int bch2_sb_ext_validate(struct bch_sb *sb, struct bch_sb_field *f, diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h index f1ab4f943720..b4cff9ebdebb 100644 --- a/fs/bcachefs/super-io.h +++ b/fs/bcachefs/super-io.h @@ -21,17 +21,14 @@ static inline bool bch2_version_compatible(u16 version) void bch2_version_to_text(struct printbuf *, enum bcachefs_metadata_version); enum bcachefs_metadata_version bch2_latest_compatible_version(enum bcachefs_metadata_version); -void bch2_set_version_incompat(struct bch_fs *, enum bcachefs_metadata_version); +bool bch2_set_version_incompat(struct bch_fs *, enum bcachefs_metadata_version); static inline bool bch2_request_incompat_feature(struct bch_fs *c, enum bcachefs_metadata_version version) { - if (unlikely(version > c->sb.version_incompat)) { - if (version > c->sb.version_incompat_allowed) - return false; - bch2_set_version_incompat(c, version); - } - return true; + return likely(version <= c->sb.version_incompat) + ? true + : bch2_set_version_incompat(c, version); } static inline size_t bch2_sb_field_bytes(struct bch_sb_field *f) From ee01b2f2d7d0010787c2343463965bbc283a497f Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Wed, 26 Feb 2025 18:13:42 +0100 Subject: [PATCH 0323/1090] net: gso: fix ownership in __udp_gso_segment In __udp_gso_segment the skb destructor is removed before segmenting the skb but the socket reference is kept as-is. This is an issue if the original skb is later orphaned as we can hit the following bug: kernel BUG at ./include/linux/skbuff.h:3312! (skb_orphan) RIP: 0010:ip_rcv_core+0x8b2/0xca0 Call Trace: ip_rcv+0xab/0x6e0 __netif_receive_skb_one_core+0x168/0x1b0 process_backlog+0x384/0x1100 __napi_poll.constprop.0+0xa1/0x370 net_rx_action+0x925/0xe50 The above can happen following a sequence of events when using OpenVSwitch, when an OVS_ACTION_ATTR_USERSPACE action precedes an OVS_ACTION_ATTR_OUTPUT action: 1. OVS_ACTION_ATTR_USERSPACE is handled (in do_execute_actions): the skb goes through queue_gso_packets and then __udp_gso_segment, where its destructor is removed. 2. The segments' data are copied and sent to userspace. 3. OVS_ACTION_ATTR_OUTPUT is handled (in do_execute_actions) and the same original skb is sent to its path. 4. If it later hits skb_orphan, we hit the bug. Fix this by also removing the reference to the socket in __udp_gso_segment. Fixes: ad405857b174 ("udp: better wmem accounting on gso") Signed-off-by: Antoine Tenart Link: https://patch.msgid.link/20250226171352.258045-1-atenart@kernel.org Signed-off-by: Jakub Kicinski --- net/ipv4/udp_offload.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index a5be6e4ed326..ecfca59f31f1 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -321,13 +321,17 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, /* clear destructor to avoid skb_segment assigning it to tail */ copy_dtor = gso_skb->destructor == sock_wfree; - if (copy_dtor) + if (copy_dtor) { gso_skb->destructor = NULL; + gso_skb->sk = NULL; + } segs = skb_segment(gso_skb, features); if (IS_ERR_OR_NULL(segs)) { - if (copy_dtor) + if (copy_dtor) { gso_skb->destructor = sock_wfree; + gso_skb->sk = sk; + } return segs; } From a466fd7e9fafd975949e5945e2f70c33a94b1a70 Mon Sep 17 00:00:00 2001 From: Vitaliy Shevtsov Date: Thu, 27 Feb 2025 23:46:27 +0500 Subject: [PATCH 0324/1090] caif_virtio: fix wrong pointer check in cfv_probe() del_vqs() frees virtqueues, therefore cfv->vq_tx pointer should be checked for NULL before calling it, not cfv->vdev. Also the current implementation is redundant because the pointer cfv->vdev is dereferenced before it is checked for NULL. Fix this by checking cfv->vq_tx for NULL instead of cfv->vdev before calling del_vqs(). Fixes: 0d2e1a2926b1 ("caif_virtio: Introduce caif over virtio") Signed-off-by: Vitaliy Shevtsov Reviewed-by: Gerhard Engleder Link: https://patch.msgid.link/20250227184716.4715-1-v.shevtsov@mt-integration.ru Signed-off-by: Jakub Kicinski --- drivers/net/caif/caif_virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index 7fea00c7ca8a..c60386bf2d1a 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c @@ -745,7 +745,7 @@ err: if (cfv->vr_rx) vdev->vringh_config->del_vrhs(cfv->vdev); - if (cfv->vdev) + if (cfv->vq_tx) vdev->config->del_vqs(cfv->vdev); free_netdev(netdev); return err; From 2565e42539b120b81a68a58da961ce5d1e34eac8 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 4 Nov 2024 14:39:11 +0100 Subject: [PATCH 0325/1090] perf/core: Fix pmus_lock vs. pmus_srcu ordering Commit a63fbed776c7 ("perf/tracing/cpuhotplug: Fix locking order") placed pmus_lock inside pmus_srcu, this makes perf_pmu_unregister() trip lockdep. Move the locking about such that only pmu_idr and pmus (list) are modified while holding pmus_lock. This avoids doing synchronize_srcu() while holding pmus_lock and all is well again. Fixes: a63fbed776c7 ("perf/tracing/cpuhotplug: Fix locking order") Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20241104135517.679556858@infradead.org --- kernel/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 6364319e2f88..11793d690cbb 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -11939,6 +11939,8 @@ void perf_pmu_unregister(struct pmu *pmu) { mutex_lock(&pmus_lock); list_del_rcu(&pmu->entry); + idr_remove(&pmu_idr, pmu->type); + mutex_unlock(&pmus_lock); /* * We dereference the pmu list under both SRCU and regular RCU, so @@ -11948,7 +11950,6 @@ void perf_pmu_unregister(struct pmu *pmu) synchronize_rcu(); free_percpu(pmu->pmu_disable_count); - idr_remove(&pmu_idr, pmu->type); if (pmu_bus_running && pmu->dev && pmu->dev != PMU_NULL_DEV) { if (pmu->nr_addr_filters) device_remove_file(pmu->dev, &dev_attr_nr_addr_filters); @@ -11956,7 +11957,6 @@ void perf_pmu_unregister(struct pmu *pmu) put_device(pmu->dev); } free_pmu_context(pmu); - mutex_unlock(&pmus_lock); } EXPORT_SYMBOL_GPL(perf_pmu_unregister); From 003659fec9f6d8c04738cb74b5384398ae8a7e88 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 4 Nov 2024 14:39:12 +0100 Subject: [PATCH 0326/1090] perf/core: Fix perf_pmu_register() vs. perf_init_event() There is a fairly obvious race between perf_init_event() doing idr_find() and perf_pmu_register() doing idr_alloc() with an incompletely initialized PMU pointer. Avoid by doing idr_alloc() on a NULL pointer to register the id, and swizzling the real struct pmu pointer at the end using idr_replace(). Also making sure to not set struct pmu members after publishing the struct pmu, duh. [ introduce idr_cmpxchg() in order to better handle the idr_replace() error case -- if it were to return an unexpected pointer, it will already have replaced the value and there is no going back. ] Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20241104135517.858805880@infradead.org --- kernel/events/core.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 11793d690cbb..823aa0824916 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -11830,6 +11830,21 @@ free_dev: static struct lock_class_key cpuctx_mutex; static struct lock_class_key cpuctx_lock; +static bool idr_cmpxchg(struct idr *idr, unsigned long id, void *old, void *new) +{ + void *tmp, *val = idr_find(idr, id); + + if (val != old) + return false; + + tmp = idr_replace(idr, new, id); + if (IS_ERR(tmp)) + return false; + + WARN_ON_ONCE(tmp != val); + return true; +} + int perf_pmu_register(struct pmu *pmu, const char *name, int type) { int cpu, ret, max = PERF_TYPE_MAX; @@ -11856,7 +11871,7 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type) if (type >= 0) max = type; - ret = idr_alloc(&pmu_idr, pmu, max, 0, GFP_KERNEL); + ret = idr_alloc(&pmu_idr, NULL, max, 0, GFP_KERNEL); if (ret < 0) goto free_pdc; @@ -11864,6 +11879,7 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type) type = ret; pmu->type = type; + atomic_set(&pmu->exclusive_cnt, 0); if (pmu_bus_running && !pmu->dev) { ret = pmu_dev_alloc(pmu); @@ -11912,14 +11928,22 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type) if (!pmu->event_idx) pmu->event_idx = perf_event_idx_default; + /* + * Now that the PMU is complete, make it visible to perf_try_init_event(). + */ + if (!idr_cmpxchg(&pmu_idr, pmu->type, NULL, pmu)) + goto free_context; list_add_rcu(&pmu->entry, &pmus); - atomic_set(&pmu->exclusive_cnt, 0); + ret = 0; unlock: mutex_unlock(&pmus_lock); return ret; +free_context: + free_percpu(pmu->cpu_pmu_context); + free_dev: if (pmu->dev && pmu->dev != PMU_NULL_DEV) { device_del(pmu->dev); From 7a68b55ff39b0a1638acb1694c185d49f6077a0d Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Thu, 27 Feb 2025 18:05:25 +0000 Subject: [PATCH 0327/1090] KVM: arm64: Initialize HCR_EL2.E2H early On CPUs without FEAT_E2H0, HCR_EL2.E2H is RES1, but may reset to an UNKNOWN value out of reset and consequently may not read as 1 unless it has been explicitly initialized. We handled this for the head.S boot code in commits: 3944382fa6f22b54 ("arm64: Treat HCR_EL2.E2H as RES1 when ID_AA64MMFR4_EL1.E2H0 is negative") b3320142f3db9b3f ("arm64: Fix early handling of FEAT_E2H0 not being implemented") Unfortunately, we forgot to apply a similar fix to the KVM PSCI entry points used when relaying CPU_ON, CPU_SUSPEND, and SYSTEM SUSPEND. When KVM is entered via these entry points, the value of HCR_EL2.E2H may be consumed before it has been initialized (e.g. by the 'init_el2_state' macro). Initialize HCR_EL2.E2H early in these paths such that it can be consumed reliably. The existing code in head.S is factored out into a new 'init_el2_hcr' macro, and this is used in the __kvm_hyp_init_cpu() function common to all the relevant PSCI entry points. For clarity, I've tweaked the assembly used to check whether ID_AA64MMFR4_EL1.E2H0 is negative. The bitfield is extracted as a signed value, and this is checked with a signed-greater-or-equal (GE) comparison. As the hyp code will reconfigure HCR_EL2 later in ___kvm_hyp_init(), all bits other than E2H are initialized to zero in __kvm_hyp_init_cpu(). Fixes: 3944382fa6f22b54 ("arm64: Treat HCR_EL2.E2H as RES1 when ID_AA64MMFR4_EL1.E2H0 is negative") Fixes: b3320142f3db9b3f ("arm64: Fix early handling of FEAT_E2H0 not being implemented") Signed-off-by: Mark Rutland Cc: Ahmed Genidi Cc: Ben Horgan Cc: Catalin Marinas Cc: Leo Yan Cc: Marc Zyngier Cc: Oliver Upton Cc: Will Deacon Link: https://lore.kernel.org/r/20250227180526.1204723-2-mark.rutland@arm.com [maz: fixed LT->GE thinko] Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/el2_setup.h | 26 ++++++++++++++++++++++++++ arch/arm64/kernel/head.S | 19 +------------------ arch/arm64/kvm/hyp/nvhe/hyp-init.S | 8 +++++++- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index 25e162651750..56034a394b43 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -16,6 +16,32 @@ #include #include +.macro init_el2_hcr val + mov_q x0, \val + + /* + * Compliant CPUs advertise their VHE-onlyness with + * ID_AA64MMFR4_EL1.E2H0 < 0. On such CPUs HCR_EL2.E2H is RES1, but it + * can reset into an UNKNOWN state and might not read as 1 until it has + * been initialized explicitly. + * + * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but + * don't advertise it (they predate this relaxation). + * + * Initalize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H + * indicating whether the CPU is running in E2H mode. + */ + mrs_s x1, SYS_ID_AA64MMFR4_EL1 + sbfx x1, x1, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH + cmp x1, #0 + b.ge .LnVHE_\@ + + orr x0, x0, #HCR_E2H +.LnVHE_\@: + msr hcr_el2, x0 + isb +.endm + .macro __init_el2_sctlr mov_q x0, INIT_SCTLR_EL2_MMU_OFF msr sctlr_el2, x0 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 5ab1970ee543..2d56459d6c94 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -298,25 +298,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) msr sctlr_el2, x0 isb 0: - mov_q x0, HCR_HOST_NVHE_FLAGS - - /* - * Compliant CPUs advertise their VHE-onlyness with - * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be - * RES1 in that case. Publish the E2H bit early so that - * it can be picked up by the init_el2_state macro. - * - * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but - * don't advertise it (they predate this relaxation). - */ - mrs_s x1, SYS_ID_AA64MMFR4_EL1 - tbz x1, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f - - orr x0, x0, #HCR_E2H -1: - msr hcr_el2, x0 - isb + init_el2_hcr HCR_HOST_NVHE_FLAGS init_el2_state /* Hypervisor stub */ diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S index fc1866226067..3fb5504a7d7f 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-init.S +++ b/arch/arm64/kvm/hyp/nvhe/hyp-init.S @@ -73,8 +73,12 @@ __do_hyp_init: eret SYM_CODE_END(__kvm_hyp_init) +/* + * Initialize EL2 CPU state to sane values. + * + * HCR_EL2.E2H must have been initialized already. + */ SYM_CODE_START_LOCAL(__kvm_init_el2_state) - /* Initialize EL2 CPU state to sane values. */ init_el2_state // Clobbers x0..x2 finalise_el2_state ret @@ -206,6 +210,8 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu) 2: msr SPsel, #1 // We want to use SP_EL{1,2} + init_el2_hcr 0 + bl __kvm_init_el2_state __init_el2_nvhe_prepare_eret From 3855a7b91d42ebf3513b7ccffc44807274978b3d Mon Sep 17 00:00:00 2001 From: Ahmed Genidi Date: Thu, 27 Feb 2025 18:05:26 +0000 Subject: [PATCH 0328/1090] KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu() When KVM is in protected mode, host calls to PSCI are proxied via EL2, and cold entries from CPU_ON, CPU_SUSPEND, and SYSTEM_SUSPEND bounce through __kvm_hyp_init_cpu() at EL2 before entering the host kernel's entry point at EL1. While __kvm_hyp_init_cpu() initializes SPSR_EL2 for the exception return to EL1, it does not initialize SCTLR_EL1. Due to this, it's possible to enter EL1 with SCTLR_EL1 in an UNKNOWN state. In practice this has been seen to result in kernel crashes after CPU_ON as a result of SCTLR_EL1.M being 1 in violation of the initial core configuration specified by PSCI. Fix this by initializing SCTLR_EL1 for cold entry to the host kernel. As it's necessary to write to SCTLR_EL12 in VHE mode, this initialization is moved into __kvm_host_psci_cpu_entry() where we can use write_sysreg_el1(). The remnants of the '__init_el2_nvhe_prepare_eret' macro are folded into its only caller, as this is clearer than having the macro. Fixes: cdf367192766ad11 ("KVM: arm64: Intercept host's CPU_ON SMCs") Reported-by: Leo Yan Signed-off-by: Ahmed Genidi [ Mark: clarify commit message, handle E2H, move to C, remove macro ] Signed-off-by: Mark Rutland Cc: Ahmed Genidi Cc: Ben Horgan Cc: Catalin Marinas Cc: Leo Yan Cc: Marc Zyngier Cc: Oliver Upton Cc: Will Deacon Reviewed-by: Leo Yan Link: https://lore.kernel.org/r/20250227180526.1204723-3-mark.rutland@arm.com Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/el2_setup.h | 5 ----- arch/arm64/kernel/head.S | 3 ++- arch/arm64/kvm/hyp/nvhe/hyp-init.S | 2 -- arch/arm64/kvm/hyp/nvhe/psci-relay.c | 3 +++ 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index 56034a394b43..555c613fd232 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -270,11 +270,6 @@ .Lskip_gcs_\@: .endm -.macro __init_el2_nvhe_prepare_eret - mov x0, #INIT_PSTATE_EL1 - msr spsr_el2, x0 -.endm - .macro __init_el2_mpam /* Memory Partitioning And Monitoring: disable EL2 traps */ mrs x1, id_aa64pfr0_el1 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 2d56459d6c94..2ce73525de2c 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -322,7 +322,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) msr sctlr_el1, x1 mov x2, xzr 3: - __init_el2_nvhe_prepare_eret + mov x0, #INIT_PSTATE_EL1 + msr spsr_el2, x0 mov w0, #BOOT_CPU_MODE_EL2 orr x0, x0, x2 diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-init.S b/arch/arm64/kvm/hyp/nvhe/hyp-init.S index 3fb5504a7d7f..f8af11189572 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-init.S +++ b/arch/arm64/kvm/hyp/nvhe/hyp-init.S @@ -214,8 +214,6 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu) bl __kvm_init_el2_state - __init_el2_nvhe_prepare_eret - /* Enable MMU, set vectors and stack. */ mov x0, x28 bl ___kvm_hyp_init // Clobbers x0..x2 diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c index 9c2ce1e0e99a..c3e196fb8b18 100644 --- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c +++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c @@ -218,6 +218,9 @@ asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on) if (is_cpu_on) release_boot_args(boot_args); + write_sysreg_el1(INIT_SCTLR_EL1_MMU_OFF, SYS_SCTLR); + write_sysreg(INIT_PSTATE_EL1, SPSR_EL2); + __host_enter(host_ctxt); } From e04918dc594669068f5d59d567d08db531167188 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 2 Mar 2025 15:18:24 +0800 Subject: [PATCH 0329/1090] cred: Fix RCU warnings in override/revert_creds Fix RCU warnings in override_creds and revert_creds by turning the RCU pointer into a normal pointer using rcu_replace_pointer. These warnings were previously private to the cred code, but due to the move into the header file they are now polluting unrelated subsystems. Fixes: 49dffdfde462 ("cred: Add a light version of override/revert_creds()") Signed-off-by: Herbert Xu Link: https://lore.kernel.org/r/Z8QGQGW0IaSklKG7@gondor.apana.org.au Signed-off-by: Christian Brauner --- include/linux/cred.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/include/linux/cred.h b/include/linux/cred.h index 0c3c4b16b469..5658a3bfe803 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -172,18 +172,12 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred) static inline const struct cred *override_creds(const struct cred *override_cred) { - const struct cred *old = current->cred; - - rcu_assign_pointer(current->cred, override_cred); - return old; + return rcu_replace_pointer(current->cred, override_cred, 1); } static inline const struct cred *revert_creds(const struct cred *revert_cred) { - const struct cred *override_cred = current->cred; - - rcu_assign_pointer(current->cred, revert_cred); - return override_cred; + return rcu_replace_pointer(current->cred, revert_cred, 1); } /** From 6b6e2e8fd0de3fa7c6f4f8fe6841b01770b2e7bc Mon Sep 17 00:00:00 2001 From: Titus Rwantare Date: Thu, 27 Feb 2025 22:24:55 +0000 Subject: [PATCH 0330/1090] hwmon: (pmbus) Initialise page count in pmbus_identify() The `pmbus_identify()` function fails to correctly determine the number of supported pages on PMBus devices. This occurs because `info->pages` is implicitly zero-initialised, and `pmbus_set_page()` does not perform writes to the page register if `info->pages` is not yet initialised. Without this patch, `info->pages` is always set to the maximum after scanning. This patch initialises `info->pages` to `PMBUS_PAGES` before the probing loop, enabling `pmbus_set_page()` writes to make it out onto the bus correctly identifying the number of pages. `PMBUS_PAGES` seemed like a reasonable non-zero number because that's the current result of the identification process. Testing was done with a PMBus device in QEMU. Signed-off-by: Titus Rwantare Fixes: 442aba78728e7 ("hwmon: PMBus device driver") Link: https://lore.kernel.org/r/20250227222455.2583468-1-titusr@google.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/pmbus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 77cf268e7d2d..920cd5408141 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -103,6 +103,8 @@ static int pmbus_identify(struct i2c_client *client, if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { int page; + info->pages = PMBUS_PAGES; + for (page = 1; page < PMBUS_PAGES; page++) { if (pmbus_set_page(client, page, 0xff) < 0) break; From 1c7932d5ae0f5c22fa52ac811b4c427bbca5aff5 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Thu, 27 Feb 2025 13:57:53 +0100 Subject: [PATCH 0331/1090] hwmon: (ntc_thermistor) Fix the ncpXXxh103 sensor table I could not find a single table that has the values currently present in the table, change it to the actual values that can be found in [1]/[2] and [3] (page 15 column 2) [1]: https://www.murata.com/products/productdetail?partno=NCP15XH103F03RC [2]: https://www.murata.com/products/productdata/8796836626462/NTHCG83.txt?1437969843000 [3]: https://nl.mouser.com/datasheet/2/281/r44e-522712.pdf Fixes: 54ce3a0d8011 ("hwmon: (ntc_thermistor) Add support for ncpXXxh103") Signed-off-by: Maud Spierings Link: https://lore.kernel.org/r/20250227-ntc_thermistor_fixes-v1-3-70fa73200b52@gocontroll.com Reviewed-by: Linus Walleij Signed-off-by: Guenter Roeck --- drivers/hwmon/ntc_thermistor.c | 66 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index b5352900463f..0d29c8f97ba7 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -181,40 +181,40 @@ static const struct ntc_compensation ncpXXwf104[] = { }; static const struct ntc_compensation ncpXXxh103[] = { - { .temp_c = -40, .ohm = 247565 }, - { .temp_c = -35, .ohm = 181742 }, - { .temp_c = -30, .ohm = 135128 }, - { .temp_c = -25, .ohm = 101678 }, - { .temp_c = -20, .ohm = 77373 }, - { .temp_c = -15, .ohm = 59504 }, - { .temp_c = -10, .ohm = 46222 }, - { .temp_c = -5, .ohm = 36244 }, - { .temp_c = 0, .ohm = 28674 }, - { .temp_c = 5, .ohm = 22878 }, - { .temp_c = 10, .ohm = 18399 }, - { .temp_c = 15, .ohm = 14910 }, - { .temp_c = 20, .ohm = 12169 }, + { .temp_c = -40, .ohm = 195652 }, + { .temp_c = -35, .ohm = 148171 }, + { .temp_c = -30, .ohm = 113347 }, + { .temp_c = -25, .ohm = 87559 }, + { .temp_c = -20, .ohm = 68237 }, + { .temp_c = -15, .ohm = 53650 }, + { .temp_c = -10, .ohm = 42506 }, + { .temp_c = -5, .ohm = 33892 }, + { .temp_c = 0, .ohm = 27219 }, + { .temp_c = 5, .ohm = 22021 }, + { .temp_c = 10, .ohm = 17926 }, + { .temp_c = 15, .ohm = 14674 }, + { .temp_c = 20, .ohm = 12081 }, { .temp_c = 25, .ohm = 10000 }, - { .temp_c = 30, .ohm = 8271 }, - { .temp_c = 35, .ohm = 6883 }, - { .temp_c = 40, .ohm = 5762 }, - { .temp_c = 45, .ohm = 4851 }, - { .temp_c = 50, .ohm = 4105 }, - { .temp_c = 55, .ohm = 3492 }, - { .temp_c = 60, .ohm = 2985 }, - { .temp_c = 65, .ohm = 2563 }, - { .temp_c = 70, .ohm = 2211 }, - { .temp_c = 75, .ohm = 1915 }, - { .temp_c = 80, .ohm = 1666 }, - { .temp_c = 85, .ohm = 1454 }, - { .temp_c = 90, .ohm = 1275 }, - { .temp_c = 95, .ohm = 1121 }, - { .temp_c = 100, .ohm = 990 }, - { .temp_c = 105, .ohm = 876 }, - { .temp_c = 110, .ohm = 779 }, - { .temp_c = 115, .ohm = 694 }, - { .temp_c = 120, .ohm = 620 }, - { .temp_c = 125, .ohm = 556 }, + { .temp_c = 30, .ohm = 8315 }, + { .temp_c = 35, .ohm = 6948 }, + { .temp_c = 40, .ohm = 5834 }, + { .temp_c = 45, .ohm = 4917 }, + { .temp_c = 50, .ohm = 4161 }, + { .temp_c = 55, .ohm = 3535 }, + { .temp_c = 60, .ohm = 3014 }, + { .temp_c = 65, .ohm = 2586 }, + { .temp_c = 70, .ohm = 2228 }, + { .temp_c = 75, .ohm = 1925 }, + { .temp_c = 80, .ohm = 1669 }, + { .temp_c = 85, .ohm = 1452 }, + { .temp_c = 90, .ohm = 1268 }, + { .temp_c = 95, .ohm = 1110 }, + { .temp_c = 100, .ohm = 974 }, + { .temp_c = 105, .ohm = 858 }, + { .temp_c = 110, .ohm = 758 }, + { .temp_c = 115, .ohm = 672 }, + { .temp_c = 120, .ohm = 596 }, + { .temp_c = 125, .ohm = 531 }, }; /* From e278d5e8aef4c0a1d9a9fa8b8910d713a89aa800 Mon Sep 17 00:00:00 2001 From: Erik Schumacher Date: Mon, 24 Feb 2025 09:19:04 +0000 Subject: [PATCH 0332/1090] hwmon: (ad7314) Validate leading zero bits and return error Leading zero bits are sent on the bus before the temperature value is transmitted. If any of these bits are high, the connection might be unstable or there could be no AD7314 / ADT730x (or compatible) at all. Return -EIO in that case. Signed-off-by: Erik Schumacher Fixes: 4f3a659581cab ("hwmon: AD7314 driver (ported from IIO)") Link: https://lore.kernel.org/r/24a50c2981a318580aca8f50d23be7987b69ea00.camel@iris-sensing.com Signed-off-by: Guenter Roeck --- drivers/hwmon/ad7314.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index 7802bbf5f958..59424103f634 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -22,11 +22,13 @@ */ #define AD7314_TEMP_MASK 0x7FE0 #define AD7314_TEMP_SHIFT 5 +#define AD7314_LEADING_ZEROS_MASK BIT(15) /* * ADT7301 and ADT7302 temperature masks */ #define ADT7301_TEMP_MASK 0x3FFF +#define ADT7301_LEADING_ZEROS_MASK (BIT(15) | BIT(14)) enum ad7314_variant { adt7301, @@ -65,12 +67,20 @@ static ssize_t ad7314_temperature_show(struct device *dev, return ret; switch (spi_get_device_id(chip->spi_dev)->driver_data) { case ad7314: + if (ret & AD7314_LEADING_ZEROS_MASK) { + /* Invalid read-out, leading zero part is missing */ + return -EIO; + } data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_SHIFT; data = sign_extend32(data, 9); return sprintf(buf, "%d\n", 250 * data); case adt7301: case adt7302: + if (ret & ADT7301_LEADING_ZEROS_MASK) { + /* Invalid read-out, leading zero part is missing */ + return -EIO; + } /* * Documented as a 13 bit twos complement register * with a sign bit - which is a 14 bit 2's complement From fd5ba38390c59e1c147480ae49b6133c4ac24001 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 26 Feb 2025 15:19:18 +0900 Subject: [PATCH 0333/1090] tracing: probe-events: Remove unused MAX_ARG_BUF_LEN macro Commit 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args") introduced MAX_ARG_BUF_LEN but it is not used. Remove it. Link: https://lore.kernel.org/all/174055075876.4079315.8805416872155957588.stgit@mhiramat.tok.corp.google.com/ Fixes: 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args") Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Steven Rostedt (Google) --- kernel/trace/trace_probe.h | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index c47ca002347a..96792bc4b092 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -36,7 +36,6 @@ #define MAX_BTF_ARGS_LEN 128 #define MAX_DENTRY_ARGS_LEN 256 #define MAX_STRING_SIZE PATH_MAX -#define MAX_ARG_BUF_LEN (MAX_TRACE_ARGS * MAX_ARG_NAME_LEN) /* Reserved field names */ #define FIELD_STRING_IP "__probe_ip" From 4dd541f9d9e4d8cdfa9797e68d893b0c27e4c46c Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Sat, 15 Feb 2025 11:01:49 +0900 Subject: [PATCH 0334/1090] MAINTAINERS: update email address in cifs and ksmbd entry Steve mainly checks his email through his gmail address. I also check issues through another email address. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8e0736dc2ee0..ca11a553d412 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5775,6 +5775,7 @@ X: drivers/clk/clkdev.c COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3) M: Steve French +M: Steve French R: Paulo Alcantara (DFS, global name space) R: Ronnie Sahlberg (directory leases, sparse files) R: Shyam Prasad N (multichannel) @@ -12655,7 +12656,9 @@ F: tools/testing/selftests/ KERNEL SMB3 SERVER (KSMBD) M: Namjae Jeon +M: Namjae Jeon M: Steve French +M: Steve French R: Sergey Senozhatsky R: Tom Talpey L: linux-cifs@vger.kernel.org From d6e13e19063db24f94b690159d0633aaf72a0f03 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 18 Feb 2025 22:49:50 +0900 Subject: [PATCH 0335/1090] ksmbd: fix out-of-bounds in parse_sec_desc() If osidoffset, gsidoffset and dacloffset could be greater than smb_ntsd struct size. If it is smaller, It could cause slab-out-of-bounds. And when validating sid, It need to check it included subauth array size. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smbacl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index d39d3e553366..89415b02dd64 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -807,6 +807,13 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl) return -EINVAL; } + if (!psid->num_subauth) + return 0; + + if (psid->num_subauth > SID_MAX_SUB_AUTHORITIES || + end_of_acl < (char *)psid + 8 + sizeof(__le32) * psid->num_subauth) + return -EINVAL; + return 0; } @@ -848,6 +855,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd, pntsd->type = cpu_to_le16(DACL_PRESENT); if (pntsd->osidoffset) { + if (le32_to_cpu(pntsd->osidoffset) < sizeof(struct smb_ntsd)) + return -EINVAL; + rc = parse_sid(owner_sid_ptr, end_of_acl); if (rc) { pr_err("%s: Error %d parsing Owner SID\n", __func__, rc); @@ -863,6 +873,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd, } if (pntsd->gsidoffset) { + if (le32_to_cpu(pntsd->gsidoffset) < sizeof(struct smb_ntsd)) + return -EINVAL; + rc = parse_sid(group_sid_ptr, end_of_acl); if (rc) { pr_err("%s: Error %d mapping Owner SID to gid\n", @@ -884,6 +897,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd, pntsd->type |= cpu_to_le16(DACL_PROTECTED); if (dacloffset) { + if (dacloffset < sizeof(struct smb_ntsd)) + return -EINVAL; + parse_dacl(idmap, dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr); } From e2ff19f0b7a30e03516e6eb73b948e27a55bc9d2 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 21 Feb 2025 14:16:23 +0900 Subject: [PATCH 0336/1090] ksmbd: fix type confusion via race condition when using ipc_msg_send_request req->handle is allocated using ksmbd_acquire_id(&ipc_ida), based on ida_alloc. req->handle from ksmbd_ipc_login_request and FSCTL_PIPE_TRANSCEIVE ioctl can be same and it could lead to type confusion between messages, resulting in access to unexpected parts of memory after an incorrect delivery. ksmbd check type of ipc response but missing add continue to check next ipc reponse. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/transport_ipc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c index 0460ebea6ff0..3f185ae60dc5 100644 --- a/fs/smb/server/transport_ipc.c +++ b/fs/smb/server/transport_ipc.c @@ -281,6 +281,7 @@ static int handle_response(int type, void *payload, size_t sz) if (entry->type + 1 != type) { pr_err("Waiting for IPC type %d, got %d. Ignore.\n", entry->type + 1, type); + continue; } entry->response = kvzalloc(sz, KSMBD_DEFAULT_GFP); From 84d2d1641b71dec326e8736a749b7ee76a9599fc Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 26 Feb 2025 15:44:02 +0900 Subject: [PATCH 0337/1090] ksmbd: fix use-after-free in smb2_lock If smb_lock->zero_len has value, ->llist of smb_lock is not delete and flock is old one. It will cause use-after-free on error handling routine. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smb2pdu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index f1efcd027475..35bed8fc1b97 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -7458,13 +7458,13 @@ out_check_cl: } no_check_cl: + flock = smb_lock->fl; + list_del(&smb_lock->llist); + if (smb_lock->zero_len) { err = 0; goto skip; } - - flock = smb_lock->fl; - list_del(&smb_lock->llist); retry: rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL); skip: From e26e2d2e15daf1ab33e0135caf2304a0cfa2744b Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 27 Feb 2025 15:49:10 +0900 Subject: [PATCH 0338/1090] ksmbd: fix bug on trap in smb2_lock If lock count is greater than 1, flags could be old value. It should be checked with flags of smb_lock, not flags. It will cause bug-on trap from locks_free_lock in error handling routine. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smb2pdu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 35bed8fc1b97..c53121538990 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -7468,7 +7468,7 @@ no_check_cl: retry: rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL); skip: - if (flags & SMB2_LOCKFLAG_UNLOCK) { + if (smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) { if (!rc) { ksmbd_debug(SMB, "File unlocked\n"); } else if (rc == -ENOENT) { From 62e7dd0a39c2d0d7ff03274c36df971f1b3d2d0d Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 12 Feb 2025 23:26:09 +0900 Subject: [PATCH 0339/1090] smb: common: change the data type of num_aces to le16 2.4.5 in [MS-DTYP].pdf describe the data type of num_aces as le16. AceCount (2 bytes): An unsigned 16-bit integer that specifies the count of the number of ACE records in the ACL. Change it to le16 and add reserved field to smb_acl struct. Reported-by: Igor Leite Ladessa Tested-by: Igor Leite Ladessa Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/client/cifsacl.c | 26 +++++++++++++------------- fs/smb/common/smbacl.h | 3 ++- fs/smb/server/smbacl.c | 31 ++++++++++++++++--------------- fs/smb/server/smbacl.h | 2 +- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c index 699a3f76d083..7d953208046a 100644 --- a/fs/smb/client/cifsacl.c +++ b/fs/smb/client/cifsacl.c @@ -763,7 +763,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, struct cifs_fattr *fattr, bool mode_from_special_sid) { int i; - int num_aces = 0; + u16 num_aces = 0; int acl_size; char *acl_base; struct smb_ace **ppace; @@ -785,7 +785,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n", le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), - le32_to_cpu(pdacl->num_aces)); + le16_to_cpu(pdacl->num_aces)); /* reset rwx permissions for user/group/other. Also, if num_aces is 0 i.e. DACL has no ACEs, @@ -795,7 +795,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, acl_base = (char *)pdacl; acl_size = sizeof(struct smb_acl); - num_aces = le32_to_cpu(pdacl->num_aces); + num_aces = le16_to_cpu(pdacl->num_aces); if (num_aces > 0) { umode_t denied_mode = 0; @@ -937,12 +937,12 @@ unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace) static void populate_new_aces(char *nacl_base, struct smb_sid *pownersid, struct smb_sid *pgrpsid, - __u64 *pnmode, u32 *pnum_aces, u16 *pnsize, + __u64 *pnmode, u16 *pnum_aces, u16 *pnsize, bool modefromsid, bool posix) { __u64 nmode; - u32 num_aces = 0; + u16 num_aces = 0; u16 nsize = 0; __u64 user_mode; __u64 group_mode; @@ -1050,7 +1050,7 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p u16 size = 0; struct smb_ace *pntace = NULL; char *acl_base = NULL; - u32 src_num_aces = 0; + u16 src_num_aces = 0; u16 nsize = 0; struct smb_ace *pnntace = NULL; char *nacl_base = NULL; @@ -1058,7 +1058,7 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p acl_base = (char *)pdacl; size = sizeof(struct smb_acl); - src_num_aces = le32_to_cpu(pdacl->num_aces); + src_num_aces = le16_to_cpu(pdacl->num_aces); nacl_base = (char *)pndacl; nsize = sizeof(struct smb_acl); @@ -1090,11 +1090,11 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl, u16 size = 0; struct smb_ace *pntace = NULL; char *acl_base = NULL; - u32 src_num_aces = 0; + u16 src_num_aces = 0; u16 nsize = 0; struct smb_ace *pnntace = NULL; char *nacl_base = NULL; - u32 num_aces = 0; + u16 num_aces = 0; bool new_aces_set = false; /* Assuming that pndacl and pnmode are never NULL */ @@ -1112,7 +1112,7 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl, acl_base = (char *)pdacl; size = sizeof(struct smb_acl); - src_num_aces = le32_to_cpu(pdacl->num_aces); + src_num_aces = le16_to_cpu(pdacl->num_aces); /* Retain old ACEs which we can retain */ for (i = 0; i < src_num_aces; ++i) { @@ -1158,7 +1158,7 @@ next_ace: } finalize_dacl: - pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->num_aces = cpu_to_le16(num_aces); pndacl->size = cpu_to_le16(nsize); return 0; @@ -1293,7 +1293,7 @@ static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd, dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION); ndacl_ptr->size = cpu_to_le16(0); - ndacl_ptr->num_aces = cpu_to_le32(0); + ndacl_ptr->num_aces = cpu_to_le16(0); rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr, pnmode, mode_from_sid, posix); @@ -1653,7 +1653,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); if (mode_from_sid) nsecdesclen += - le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace); + le16_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace); else /* cifsacl */ nsecdesclen += le16_to_cpu(dacl_ptr->size); } diff --git a/fs/smb/common/smbacl.h b/fs/smb/common/smbacl.h index 6a60698fc6f0..a624ec9e4a14 100644 --- a/fs/smb/common/smbacl.h +++ b/fs/smb/common/smbacl.h @@ -107,7 +107,8 @@ struct smb_sid { struct smb_acl { __le16 revision; /* revision level */ __le16 size; - __le32 num_aces; + __le16 num_aces; + __le16 reserved; } __attribute__((packed)); struct smb_ace { diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index 89415b02dd64..561f80d3f953 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -333,7 +333,7 @@ void posix_state_to_acl(struct posix_acl_state *state, pace->e_perm = state->other.allow; } -int init_acl_state(struct posix_acl_state *state, int cnt) +int init_acl_state(struct posix_acl_state *state, u16 cnt) { int alloc; @@ -368,7 +368,7 @@ static void parse_dacl(struct mnt_idmap *idmap, struct smb_fattr *fattr) { int i, ret; - int num_aces = 0; + u16 num_aces = 0; unsigned int acl_size; char *acl_base; struct smb_ace **ppace; @@ -389,12 +389,12 @@ static void parse_dacl(struct mnt_idmap *idmap, ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n", le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), - le32_to_cpu(pdacl->num_aces)); + le16_to_cpu(pdacl->num_aces)); acl_base = (char *)pdacl; acl_size = sizeof(struct smb_acl); - num_aces = le32_to_cpu(pdacl->num_aces); + num_aces = le16_to_cpu(pdacl->num_aces); if (num_aces <= 0) return; @@ -580,7 +580,7 @@ static void parse_dacl(struct mnt_idmap *idmap, static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap, struct smb_ace *pndace, - struct smb_fattr *fattr, u32 *num_aces, + struct smb_fattr *fattr, u16 *num_aces, u16 *size, u32 nt_aces_num) { struct posix_acl_entry *pace; @@ -701,7 +701,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap, struct smb_fattr *fattr) { struct smb_ace *ntace, *pndace; - int nt_num_aces = le32_to_cpu(nt_dacl->num_aces), num_aces = 0; + u16 nt_num_aces = le16_to_cpu(nt_dacl->num_aces), num_aces = 0; unsigned short size = 0; int i; @@ -728,7 +728,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap, set_posix_acl_entries_dacl(idmap, pndace, fattr, &num_aces, &size, nt_num_aces); - pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->num_aces = cpu_to_le16(num_aces); pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size); } @@ -736,7 +736,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap, struct smb_acl *pndacl, struct smb_fattr *fattr) { struct smb_ace *pace, *pndace; - u32 num_aces = 0; + u16 num_aces = 0; u16 size = 0, ace_size = 0; uid_t uid; const struct smb_sid *sid; @@ -792,7 +792,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap, fattr->cf_mode, 0007); out: - pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->num_aces = cpu_to_le16(num_aces); pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size); } @@ -1022,8 +1022,9 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, struct smb_sid owner_sid, group_sid; struct dentry *parent = path->dentry->d_parent; struct mnt_idmap *idmap = mnt_idmap(path->mnt); - int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size; - int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size; + int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size; + int rc = 0, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size; + u16 num_aces, ace_cnt = 0; char *aces_base; bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode); @@ -1039,7 +1040,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset); acl_len = pntsd_size - dacloffset; - num_aces = le32_to_cpu(parent_pdacl->num_aces); + num_aces = le16_to_cpu(parent_pdacl->num_aces); pntsd_type = le16_to_cpu(parent_pntsd->type); pdacl_size = le16_to_cpu(parent_pdacl->size); @@ -1199,7 +1200,7 @@ pass: pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset)); pdacl->revision = cpu_to_le16(2); pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size); - pdacl->num_aces = cpu_to_le32(ace_cnt); + pdacl->num_aces = cpu_to_le16(ace_cnt); pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); memcpy(pace, aces_base, nt_size); pntsd_size += sizeof(struct smb_acl) + nt_size; @@ -1280,7 +1281,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); aces_size = acl_size - sizeof(struct smb_acl); - for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) { + for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (offsetof(struct smb_ace, access_req) > aces_size) break; ace_size = le16_to_cpu(ace->size); @@ -1301,7 +1302,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); aces_size = acl_size - sizeof(struct smb_acl); - for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) { + for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (offsetof(struct smb_ace, access_req) > aces_size) break; ace_size = le16_to_cpu(ace->size); diff --git a/fs/smb/server/smbacl.h b/fs/smb/server/smbacl.h index 24ce576fc292..355adaee39b8 100644 --- a/fs/smb/server/smbacl.h +++ b/fs/smb/server/smbacl.h @@ -86,7 +86,7 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd, int build_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info, __u32 *secdesclen, struct smb_fattr *fattr); -int init_acl_state(struct posix_acl_state *state, int cnt); +int init_acl_state(struct posix_acl_state *state, u16 cnt); void free_acl_state(struct posix_acl_state *state); void posix_state_to_acl(struct posix_acl_state *state, struct posix_acl_entry *pace); From 1b8b67f3c5e5169535e26efedd3e422172e2db64 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 12 Feb 2025 09:32:11 +0900 Subject: [PATCH 0340/1090] ksmbd: fix incorrect validation for num_aces field of smb_acl parse_dcal() validate num_aces to allocate posix_ace_state_array. if (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) It is an incorrect validation that we can create an array of size ULONG_MAX. smb_acl has ->size field to calculate actual number of aces in request buffer size. Use this to check invalid num_aces. Reported-by: Igor Leite Ladessa Tested-by: Igor Leite Ladessa Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smbacl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c index 561f80d3f953..49b128698670 100644 --- a/fs/smb/server/smbacl.c +++ b/fs/smb/server/smbacl.c @@ -398,7 +398,9 @@ static void parse_dacl(struct mnt_idmap *idmap, if (num_aces <= 0) return; - if (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) + if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) / + (offsetof(struct smb_ace, sid) + + offsetof(struct smb_sid, sub_auth) + sizeof(__le16))) return; ret = init_acl_state(&acl_state, num_aces); @@ -432,6 +434,7 @@ static void parse_dacl(struct mnt_idmap *idmap, offsetof(struct smb_sid, sub_auth); if (end_of_acl - acl_base < acl_size || + ppace[i]->sid.num_subauth == 0 || ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || (end_of_acl - acl_base < acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || From aa2a739a75ab6f24ef72fb3fdb9192c081eacf06 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 12 Feb 2025 09:37:57 +0900 Subject: [PATCH 0341/1090] cifs: fix incorrect validation for num_aces field of smb_acl parse_dcal() validate num_aces to allocate ace array. f (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) It is an incorrect validation that we can create an array of size ULONG_MAX. smb_acl has ->size field to calculate actual number of aces in response buffer size. Use this to check invalid num_aces. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/client/cifsacl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c index 7d953208046a..64bd68f750f8 100644 --- a/fs/smb/client/cifsacl.c +++ b/fs/smb/client/cifsacl.c @@ -778,7 +778,8 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, } /* validate that we do not go past end of acl */ - if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { + if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) || + end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { cifs_dbg(VFS, "ACL too small to parse DACL\n"); return; } @@ -799,8 +800,11 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, if (num_aces > 0) { umode_t denied_mode = 0; - if (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) + if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) / + (offsetof(struct smb_ace, sid) + + offsetof(struct smb_sid, sub_auth) + sizeof(__le16))) return; + ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL); if (!ppace) From 59b348be7597c4a9903cb003c69e37df20c04a30 Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Fri, 28 Feb 2025 16:46:57 +0300 Subject: [PATCH 0342/1090] wifi: cfg80211: regulatory: improve invalid hints checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Syzbot keeps reporting an issue [1] that occurs when erroneous symbols sent from userspace get through into user_alpha2[] via regulatory_hint_user() call. Such invalid regulatory hints should be rejected. While a sanity check from commit 47caf685a685 ("cfg80211: regulatory: reject invalid hints") looks to be enough to deter these very cases, there is a way to get around it due to 2 reasons. 1) The way isalpha() works, symbols other than latin lower and upper letters may be used to determine a country/domain. For instance, greek letters will also be considered upper/lower letters and for such characters isalpha() will return true as well. However, ISO-3166-1 alpha2 codes should only hold latin characters. 2) While processing a user regulatory request, between reg_process_hint_user() and regulatory_hint_user() there happens to be a call to queue_regulatory_request() which modifies letters in request->alpha2[] with toupper(). This works fine for latin symbols, less so for weird letter characters from the second part of _ctype[]. Syzbot triggers a warning in is_user_regdom_saved() by first sending over an unexpected non-latin letter that gets malformed by toupper() into a character that ends up failing isalpha() check. Prevent this by enhancing is_an_alpha2() to ensure that incoming symbols are latin letters and nothing else. [1] Syzbot report: ------------[ cut here ]------------ Unexpected user alpha2: A� WARNING: CPU: 1 PID: 964 at net/wireless/reg.c:442 is_user_regdom_saved net/wireless/reg.c:440 [inline] WARNING: CPU: 1 PID: 964 at net/wireless/reg.c:442 restore_alpha2 net/wireless/reg.c:3424 [inline] WARNING: CPU: 1 PID: 964 at net/wireless/reg.c:442 restore_regulatory_settings+0x3c0/0x1e50 net/wireless/reg.c:3516 Modules linked in: CPU: 1 UID: 0 PID: 964 Comm: kworker/1:2 Not tainted 6.12.0-rc5-syzkaller-00044-gc1e939a21eb1 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Workqueue: events_power_efficient crda_timeout_work RIP: 0010:is_user_regdom_saved net/wireless/reg.c:440 [inline] RIP: 0010:restore_alpha2 net/wireless/reg.c:3424 [inline] RIP: 0010:restore_regulatory_settings+0x3c0/0x1e50 net/wireless/reg.c:3516 ... Call Trace: crda_timeout_work+0x27/0x50 net/wireless/reg.c:542 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa65/0x1850 kernel/workqueue.c:3310 worker_thread+0x870/0xd30 kernel/workqueue.c:3391 kthread+0x2f2/0x390 kernel/kthread.c:389 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 Reported-by: syzbot+e10709ac3c44f3d4e800@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e10709ac3c44f3d4e800 Fixes: 09d989d179d0 ("cfg80211: add regulatory hint disconnect support") Cc: stable@kernel.org Signed-off-by: Nikita Zhandarovich Link: https://patch.msgid.link/20250228134659.1577656-1-n.zhandarovich@fintech.ru Signed-off-by: Johannes Berg --- net/wireless/reg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2dd0533e7660..212e9561aae7 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -407,7 +407,8 @@ static bool is_an_alpha2(const char *alpha2) { if (!alpha2) return false; - return isalpha(alpha2[0]) && isalpha(alpha2[1]); + return isascii(alpha2[0]) && isalpha(alpha2[0]) && + isascii(alpha2[1]) && isalpha(alpha2[1]); } static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) From 487cfd4a8e3dc42d34a759017978a4edaf85fce0 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 27 Feb 2025 19:45:29 +0000 Subject: [PATCH 0343/1090] xhci: Restrict USB4 tunnel detection for USB3 devices to Intel hosts When adding support for USB3-over-USB4 tunnelling detection, a check for an Intel-specific capability was added. This capability, which goes by ID 206, is used without any check that we are actually dealing with an Intel host. As it turns out, the Cadence XHCI controller *also* exposes an extended capability numbered 206 (for unknown purposes), but of course doesn't have the Intel-specific registers that the tunnelling code is trying to access. Fun follows. The core of the problems is that the tunnelling code blindly uses vendor-specific capabilities without any check (the Intel-provided documentation I have at hand indicates that 192-255 are indeed vendor-specific). Restrict the detection code to Intel HW for real, preventing any further explosion on my (non-Intel) HW. Cc: stable Fixes: 948ce83fbb7df ("xhci: Add USB4 tunnel detection for USB3 devices on Intel hosts") Signed-off-by: Marc Zyngier Acked-by: Mathias Nyman Link: https://lore.kernel.org/r/20250227194529.2288718-1-maz@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 9693464c0520..69c278b64084 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -770,9 +771,16 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci) enum usb_link_tunnel_mode xhci_port_is_tunneled(struct xhci_hcd *xhci, struct xhci_port *port) { + struct usb_hcd *hcd; void __iomem *base; u32 offset; + /* Don't try and probe this capability for non-Intel hosts */ + hcd = xhci_to_hcd(xhci); + if (!dev_is_pci(hcd->self.controller) || + to_pci_dev(hcd->self.controller)->vendor != PCI_VENDOR_ID_INTEL) + return USB_LINK_UNKNOWN; + base = &xhci->cap_regs->hc_capbase; offset = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_INTEL_SPR_SHADOW); From 8e812e9355a6f14dffd54a33d951ca403b9732f5 Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Mon, 24 Feb 2025 14:26:04 +0530 Subject: [PATCH 0344/1090] usb: gadget: Check bmAttributes only if configuration is valid If the USB configuration is not valid, then avoid checking for bmAttributes to prevent null pointer deference. Cc: stable Fixes: 40e89ff5750f ("usb: gadget: Set self-powered based on MaxPower and bmAttributes") Signed-off-by: Prashanth K Link: https://lore.kernel.org/r/20250224085604.417327-1-prashanth.k@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4bcf73bae761..869ad99afb48 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1051,7 +1051,7 @@ static int set_config(struct usb_composite_dev *cdev, usb_gadget_set_remote_wakeup(gadget, 0); done: if (power > USB_SELF_POWER_VBUS_MAX_DRAW || - !(c->bmAttributes & USB_CONFIG_ATT_SELFPOWER)) + (c && !(c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))) usb_gadget_clear_selfpowered(gadget); else usb_gadget_set_selfpowered(gadget); From 69c58deec19628c8a686030102176484eb94fed4 Mon Sep 17 00:00:00 2001 From: Badhri Jagan Sridharan Date: Sun, 16 Feb 2025 22:30:02 +0000 Subject: [PATCH 0345/1090] usb: dwc3: gadget: Prevent irq storm when TH re-executes While commit d325a1de49d6 ("usb: dwc3: gadget: Prevent losing events in event cache") makes sure that top half(TH) does not end up overwriting the cached events before processing them when the TH gets invoked more than one time, returning IRQ_HANDLED results in occasional irq storm where the TH hogs the CPU. The irq storm can be prevented by the flag before event handler busy is cleared. Default enable interrupt moderation in all versions which support them. ftrace event stub during dwc3 irq storm: irq/504_dwc3-1111 ( 1111) [000] .... 70.000866: irq_handler_exit: irq=14 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000872: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000874: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000881: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000883: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000889: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000892: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000898: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000901: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000907: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000909: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000915: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000918: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000924: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000927: irq_handler_exit: irq=504 ret=handled irq/504_dwc3-1111 ( 1111) [000] .... 70.000933: irq_handler_entry: irq=504 name=dwc3 irq/504_dwc3-1111 ( 1111) [000] .... 70.000935: irq_handler_exit: irq=504 ret=handled .... Cc: stable Suggested-by: Thinh Nguyen Fixes: d325a1de49d6 ("usb: dwc3: gadget: Prevent losing events in event cache") Signed-off-by: Badhri Jagan Sridharan Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20250216223003.3568039-1-badhri@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 16 ++++++---------- drivers/usb/dwc3/gadget.c | 10 +++++++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index dfa1b5fe48dc..2c472cb97f6c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1835,8 +1835,6 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd; dwc->tx_max_burst_prd = tx_max_burst_prd; - dwc->imod_interval = 0; - dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num; } @@ -1854,21 +1852,19 @@ static void dwc3_check_params(struct dwc3 *dwc) unsigned int hwparam_gen = DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3); - /* Check for proper value of imod_interval */ - if (dwc->imod_interval && !dwc3_has_imod(dwc)) { - dev_warn(dwc->dev, "Interrupt moderation not supported\n"); - dwc->imod_interval = 0; - } - /* + * Enable IMOD for all supporting controllers. + * + * Particularly, DWC_usb3 v3.00a must enable this feature for + * the following reason: + * * Workaround for STAR 9000961433 which affects only version * 3.00a of the DWC_usb3 core. This prevents the controller * interrupt from being masked while handling events. IMOD * allows us to work around this issue. Enable it for the * affected version. */ - if (!dwc->imod_interval && - DWC3_VER_IS(DWC3, 300A)) + if (dwc3_has_imod((dwc))) dwc->imod_interval = 1; /* Check the maximum_speed parameter */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index ddd6b2ce5710..89a4dc8ebf94 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4501,14 +4501,18 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_SIZE(evt->length)); + evt->flags &= ~DWC3_EVENT_PENDING; + /* + * Add an explicit write memory barrier to make sure that the update of + * clearing DWC3_EVENT_PENDING is observed in dwc3_check_event_buf() + */ + wmb(); + if (dwc->imod_interval) { dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval); } - /* Keep the clearing of DWC3_EVENT_PENDING at the end */ - evt->flags &= ~DWC3_EVENT_PENDING; - return ret; } From b5ea08aa883da05106fcc683d12489a4292d1122 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 25 Feb 2025 13:02:46 +0200 Subject: [PATCH 0346/1090] usb: renesas_usbhs: Call clk_put() Clocks acquired with of_clk_get() need to be freed with clk_put(). Call clk_put() on priv->clks[0] on error path. Fixes: 3df0e240caba ("usb: renesas_usbhs: Add multiple clocks management") Cc: stable Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20250225110248.870417-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 935fc496fe94..6c7857b66a21 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -312,8 +312,10 @@ static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv) priv->clks[1] = of_clk_get(dev_of_node(dev), 1); if (PTR_ERR(priv->clks[1]) == -ENOENT) priv->clks[1] = NULL; - else if (IS_ERR(priv->clks[1])) + else if (IS_ERR(priv->clks[1])) { + clk_put(priv->clks[0]); return PTR_ERR(priv->clks[1]); + } return 0; } From e0c92440938930e7fa7aa6362780d39cdea34449 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 25 Feb 2025 13:02:47 +0200 Subject: [PATCH 0347/1090] usb: renesas_usbhs: Use devm_usb_get_phy() The gpriv->transceiver is retrieved in probe() through usb_get_phy() but never released. Use devm_usb_get_phy() to handle this scenario. This issue was identified through code investigation. No issue was found without this change. Fixes: b5a2875605ca ("usb: renesas_usbhs: Allow an OTG PHY driver to provide VBUS") Cc: stable Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20250225110248.870417-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 105132ae87ac..e8e5723f5412 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -1094,7 +1094,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) goto usbhs_mod_gadget_probe_err_gpriv; } - gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); + gpriv->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_UNDEFINED); dev_info(dev, "%stransceiver found\n", !IS_ERR(gpriv->transceiver) ? "" : "no "); From 552ca6b87e3778f3dd5b87842f95138162e16c82 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 25 Feb 2025 13:02:48 +0200 Subject: [PATCH 0348/1090] usb: renesas_usbhs: Flush the notify_hotplug_work When performing continuous unbind/bind operations on the USB drivers available on the Renesas RZ/G2L SoC, a kernel crash with the message "Unable to handle kernel NULL pointer dereference at virtual address" may occur. This issue points to the usbhsc_notify_hotplug() function. Flush the delayed work to avoid its execution when driver resources are unavailable. Fixes: bc57381e6347 ("usb: renesas_usbhs: use delayed_work instead of work_struct") Cc: stable Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20250225110248.870417-4-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 6c7857b66a21..4b35ef216125 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -781,6 +781,8 @@ static void usbhs_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "usb remove\n"); + flush_delayed_work(&priv->notify_hotplug_work); + /* power off */ if (!usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, 0); From 2b66ef84d0d2a0ea955b40bd306f5e3abbc5cf9c Mon Sep 17 00:00:00 2001 From: Pawel Laszczak Date: Fri, 28 Feb 2025 07:50:25 +0000 Subject: [PATCH 0349/1090] usb: hub: lack of clearing xHC resources The xHC resources allocated for USB devices are not released in correct order after resuming in case when while suspend device was reconnected. This issue has been detected during the fallowing scenario: - connect hub HS to root port - connect LS/FS device to hub port - wait for enumeration to finish - force host to suspend - reconnect hub attached to root port - wake host For this scenario during enumeration of USB LS/FS device the Cadence xHC reports completion error code for xHC commands because the xHC resources used for devices has not been properly released. XHCI specification doesn't mention that device can be reset in any order so, we should not treat this issue as Cadence xHC controller bug. Similar as during disconnecting in this case the device resources should be cleared starting form the last usb device in tree toward the root hub. To fix this issue usbcore driver should call hcd->driver->reset_device for all USB devices connected to hub which was reconnected while suspending. Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Cc: stable Signed-off-by: Pawel Laszczak Reviewed-by: Alan Stern Link: https://lore.kernel.org/r/PH7PR07MB953841E38C088678ACDCF6EEDDCC2@PH7PR07MB9538.namprd07.prod.outlook.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a76bb50b6202..dcba4281ea48 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -6065,6 +6065,36 @@ void usb_hub_cleanup(void) usb_deregister(&hub_driver); } /* usb_hub_cleanup() */ +/** + * hub_hc_release_resources - clear resources used by host controller + * @udev: pointer to device being released + * + * Context: task context, might sleep + * + * Function releases the host controller resources in correct order before + * making any operation on resuming usb device. The host controller resources + * allocated for devices in tree should be released starting from the last + * usb device in tree toward the root hub. This function is used only during + * resuming device when usb device require reinitialization – that is, when + * flag udev->reset_resume is set. + * + * This call is synchronous, and may not be used in an interrupt context. + */ +static void hub_hc_release_resources(struct usb_device *udev) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(udev); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + int i; + + /* Release up resources for all children before this device */ + for (i = 0; i < udev->maxchild; i++) + if (hub->ports[i]->child) + hub_hc_release_resources(hub->ports[i]->child); + + if (hcd->driver->reset_device) + hcd->driver->reset_device(hcd, udev); +} + /** * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) @@ -6129,6 +6159,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev) bos = udev->bos; udev->bos = NULL; + if (udev->reset_resume) + hub_hc_release_resources(udev); + mutex_lock(hcd->address0_mutex); for (i = 0; i < PORT_INIT_TRIES; ++i) { From 1be4e29e94a6be77de3bc210820b74f40814f17a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 27 Feb 2025 11:03:06 -0600 Subject: [PATCH 0350/1090] platform/x86/amd/pmf: Initialize and clean up `cb_mutex` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cb_mutex` was introduced in commit 9e0894d07072e ("platform/x86/amd/pmf: Enable Custom BIOS Inputs for PMF-TA") to prevent conccurrent access for BIOS inputs. It however isn't initialized and so on use it may lead to a NULL pointer dereference. Add code to initialize on probe and clean up on destroy. Reported-by: Yijun Shen Cc: Richard Gong Fixes: 9e0894d07072e ("platform/x86/amd/pmf: Enable Custom BIOS Inputs for PMF-TA") Signed-off-by: Mario Limonciello Tested-By: Yijun Shen Acked-by: Shyam Sundar S K Link: https://lore.kernel.org/r/20250227170308.435862-1-superm1@kernel.org Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index 764cc1fe90ae..a2cb2d5544f5 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -452,6 +452,7 @@ static int amd_pmf_probe(struct platform_device *pdev) mutex_init(&dev->lock); mutex_init(&dev->update_mutex); + mutex_init(&dev->cb_mutex); apmf_acpi_init(dev); platform_set_drvdata(pdev, dev); @@ -477,6 +478,7 @@ static void amd_pmf_remove(struct platform_device *pdev) amd_pmf_dbgfs_unregister(dev); mutex_destroy(&dev->lock); mutex_destroy(&dev->update_mutex); + mutex_destroy(&dev->cb_mutex); kfree(dev->buf); } From 010c4a461c1dbf3fa75ddea8df018a6128b700c6 Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Fri, 28 Feb 2025 18:35:43 -0800 Subject: [PATCH 0351/1090] x86/speculation: Simplify and make CALL_NOSPEC consistent CALL_NOSPEC macro is used to generate Spectre-v2 mitigation friendly indirect branches. At compile time the macro defaults to indirect branch, and at runtime those can be patched to thunk based mitigations. This approach is opposite of what is done for the rest of the kernel, where the compile time default is to replace indirect calls with retpoline thunk calls. Make CALL_NOSPEC consistent with the rest of the kernel, default to retpoline thunk at compile time when CONFIG_MITIGATION_RETPOLINE is enabled. Signed-off-by: Pawan Gupta Signed-off-by: Ingo Molnar Cc: Andrew Cooper Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20250228-call-nospec-v3-1-96599fed0f33@linux.intel.com --- arch/x86/include/asm/nospec-branch.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 7e8bf78c03d5..1e6b915ce956 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -424,16 +424,11 @@ static inline void call_depth_return_thunk(void) {} * Inline asm uses the %V modifier which is only in newer GCC * which is ensured when CONFIG_MITIGATION_RETPOLINE is defined. */ -# define CALL_NOSPEC \ - ALTERNATIVE_2( \ - ANNOTATE_RETPOLINE_SAFE \ - "call *%[thunk_target]\n", \ - "call __x86_indirect_thunk_%V[thunk_target]\n", \ - X86_FEATURE_RETPOLINE, \ - "lfence;\n" \ - ANNOTATE_RETPOLINE_SAFE \ - "call *%[thunk_target]\n", \ - X86_FEATURE_RETPOLINE_LFENCE) +#ifdef CONFIG_MITIGATION_RETPOLINE +#define CALL_NOSPEC "call __x86_indirect_thunk_%V[thunk_target]\n" +#else +#define CALL_NOSPEC "call *%[thunk_target]\n" +#endif # define THUNK_TARGET(addr) [thunk_target] "r" (addr) From 9af9ad85ac44cb754e526d468c3006b48db5dfd8 Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Fri, 28 Feb 2025 18:35:58 -0800 Subject: [PATCH 0352/1090] x86/speculation: Add a conditional CS prefix to CALL_NOSPEC Retpoline mitigation for spectre-v2 uses thunks for indirect branches. To support this mitigation compilers add a CS prefix with -mindirect-branch-cs-prefix. For an indirect branch in asm, this needs to be added manually. CS prefix is already being added to indirect branches in asm files, but not in inline asm. Add CS prefix to CALL_NOSPEC for inline asm as well. There is no JMP_NOSPEC for inline asm. Reported-by: Josh Poimboeuf Signed-off-by: Pawan Gupta Signed-off-by: Ingo Molnar Cc: Andrew Cooper Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20250228-call-nospec-v3-2-96599fed0f33@linux.intel.com --- arch/x86/include/asm/nospec-branch.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 1e6b915ce956..aee26bb8230f 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -198,9 +198,8 @@ .endm /* - * Equivalent to -mindirect-branch-cs-prefix; emit the 5 byte jmp/call - * to the retpoline thunk with a CS prefix when the register requires - * a RAX prefix byte to encode. Also see apply_retpolines(). + * Emits a conditional CS prefix that is compatible with + * -mindirect-branch-cs-prefix. */ .macro __CS_PREFIX reg:req .irp rs,r8,r9,r10,r11,r12,r13,r14,r15 @@ -420,12 +419,24 @@ static inline void call_depth_return_thunk(void) {} #ifdef CONFIG_X86_64 +/* + * Emits a conditional CS prefix that is compatible with + * -mindirect-branch-cs-prefix. + */ +#define __CS_PREFIX(reg) \ + ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" \ + ".ifc \\rs," reg "\n" \ + ".byte 0x2e\n" \ + ".endif\n" \ + ".endr\n" + /* * Inline asm uses the %V modifier which is only in newer GCC * which is ensured when CONFIG_MITIGATION_RETPOLINE is defined. */ #ifdef CONFIG_MITIGATION_RETPOLINE -#define CALL_NOSPEC "call __x86_indirect_thunk_%V[thunk_target]\n" +#define CALL_NOSPEC __CS_PREFIX("%V[thunk_target]") \ + "call __x86_indirect_thunk_%V[thunk_target]\n" #else #define CALL_NOSPEC "call *%[thunk_target]\n" #endif From df1a1ed5e1bdd9cc13148e0e5549f5ebcf76cf13 Mon Sep 17 00:00:00 2001 From: Brendan King Date: Wed, 26 Feb 2025 15:42:19 +0000 Subject: [PATCH 0353/1090] drm/imagination: avoid deadlock on fence release Do scheduler queue fence release processing on a workqueue, rather than in the release function itself. Fixes deadlock issues such as the following: [ 607.400437] ============================================ [ 607.405755] WARNING: possible recursive locking detected [ 607.415500] -------------------------------------------- [ 607.420817] weston:zfq0/24149 is trying to acquire lock: [ 607.426131] ffff000017d041a0 (reservation_ww_class_mutex){+.+.}-{3:3}, at: pvr_gem_object_vunmap+0x40/0xc0 [powervr] [ 607.436728] but task is already holding lock: [ 607.442554] ffff000017d105a0 (reservation_ww_class_mutex){+.+.}-{3:3}, at: dma_buf_ioctl+0x250/0x554 [ 607.451727] other info that might help us debug this: [ 607.458245] Possible unsafe locking scenario: [ 607.464155] CPU0 [ 607.466601] ---- [ 607.469044] lock(reservation_ww_class_mutex); [ 607.473584] lock(reservation_ww_class_mutex); [ 607.478114] *** DEADLOCK *** Cc: stable@vger.kernel.org Fixes: eaf01ee5ba28 ("drm/imagination: Implement job submission and scheduling") Signed-off-by: Brendan King Reviewed-by: Matt Coster Link: https://patchwork.freedesktop.org/patch/msgid/20250226-fence-release-deadlock-v2-1-6fed2fc1fe88@imgtec.com Signed-off-by: Matt Coster --- drivers/gpu/drm/imagination/pvr_queue.c | 13 +++++++++++-- drivers/gpu/drm/imagination/pvr_queue.h | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c index c4f08432882b..f3f1c5212df7 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.c +++ b/drivers/gpu/drm/imagination/pvr_queue.c @@ -109,12 +109,20 @@ pvr_queue_fence_get_driver_name(struct dma_fence *f) return PVR_DRIVER_NAME; } +static void pvr_queue_fence_release_work(struct work_struct *w) +{ + struct pvr_queue_fence *fence = container_of(w, struct pvr_queue_fence, release_work); + + pvr_context_put(fence->queue->ctx); + dma_fence_free(&fence->base); +} + static void pvr_queue_fence_release(struct dma_fence *f) { struct pvr_queue_fence *fence = container_of(f, struct pvr_queue_fence, base); + struct pvr_device *pvr_dev = fence->queue->ctx->pvr_dev; - pvr_context_put(fence->queue->ctx); - dma_fence_free(f); + queue_work(pvr_dev->sched_wq, &fence->release_work); } static const char * @@ -268,6 +276,7 @@ pvr_queue_fence_init(struct dma_fence *f, pvr_context_get(queue->ctx); fence->queue = queue; + INIT_WORK(&fence->release_work, pvr_queue_fence_release_work); dma_fence_init(&fence->base, fence_ops, &fence_ctx->lock, fence_ctx->id, atomic_inc_return(&fence_ctx->seqno)); diff --git a/drivers/gpu/drm/imagination/pvr_queue.h b/drivers/gpu/drm/imagination/pvr_queue.h index e06ced69302f..93fe9ac9f58c 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.h +++ b/drivers/gpu/drm/imagination/pvr_queue.h @@ -5,6 +5,7 @@ #define PVR_QUEUE_H #include +#include #include "pvr_cccb.h" #include "pvr_device.h" @@ -63,6 +64,9 @@ struct pvr_queue_fence { /** @queue: Queue that created this fence. */ struct pvr_queue *queue; + + /** @release_work: Fence release work structure. */ + struct work_struct release_work; }; /** From a5c4c3ba95a52d66315acdfbaba9bd82ed39c250 Mon Sep 17 00:00:00 2001 From: Brendan King Date: Wed, 26 Feb 2025 15:43:06 +0000 Subject: [PATCH 0354/1090] drm/imagination: Hold drm_gem_gpuva lock for unmap Avoid a warning from drm_gem_gpuva_assert_lock_held in drm_gpuva_unlink. The Imagination driver uses the GEM object reservation lock to protect the gpuva list, but the GEM object was not always known in the code paths that ended up calling drm_gpuva_unlink. When the GEM object isn't known, it is found by calling drm_gpuva_find to lookup the object associated with a given virtual address range, or by calling drm_gpuva_find_first when removing all mappings. Cc: stable@vger.kernel.org Fixes: 4bc736f890ce ("drm/imagination: vm: make use of GPUVM's drm_exec helper") Signed-off-by: Brendan King Reviewed-by: Matt Coster Link: https://patchwork.freedesktop.org/patch/msgid/20250226-hold-drm_gem_gpuva-lock-for-unmap-v2-1-3fdacded227f@imgtec.com Signed-off-by: Matt Coster --- drivers/gpu/drm/imagination/pvr_fw_meta.c | 6 +- drivers/gpu/drm/imagination/pvr_vm.c | 134 +++++++++++++++++----- drivers/gpu/drm/imagination/pvr_vm.h | 3 + 3 files changed, 115 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c index c39beb70c317..6d13864851fc 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_meta.c +++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c @@ -527,8 +527,10 @@ pvr_meta_vm_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj) static void pvr_meta_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj) { - pvr_vm_unmap(pvr_dev->kernel_vm_ctx, fw_obj->fw_mm_node.start, - fw_obj->fw_mm_node.size); + struct pvr_gem_object *pvr_obj = fw_obj->gem; + + pvr_vm_unmap_obj(pvr_dev->kernel_vm_ctx, pvr_obj, + fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size); } static bool diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c index 363f885a7098..2896fa7501b1 100644 --- a/drivers/gpu/drm/imagination/pvr_vm.c +++ b/drivers/gpu/drm/imagination/pvr_vm.c @@ -293,8 +293,9 @@ err_bind_op_fini: static int pvr_vm_bind_op_unmap_init(struct pvr_vm_bind_op *bind_op, - struct pvr_vm_context *vm_ctx, u64 device_addr, - u64 size) + struct pvr_vm_context *vm_ctx, + struct pvr_gem_object *pvr_obj, + u64 device_addr, u64 size) { int err; @@ -318,6 +319,7 @@ pvr_vm_bind_op_unmap_init(struct pvr_vm_bind_op *bind_op, goto err_bind_op_fini; } + bind_op->pvr_obj = pvr_obj; bind_op->vm_ctx = vm_ctx; bind_op->device_addr = device_addr; bind_op->size = size; @@ -597,20 +599,6 @@ err_free: return ERR_PTR(err); } -/** - * pvr_vm_unmap_all() - Unmap all mappings associated with a VM context. - * @vm_ctx: Target VM context. - * - * This function ensures that no mappings are left dangling by unmapping them - * all in order of ascending device-virtual address. - */ -void -pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx) -{ - WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start, - vm_ctx->gpuvm_mgr.mm_range)); -} - /** * pvr_vm_context_release() - Teardown a VM context. * @ref_count: Pointer to reference counter of the VM context. @@ -703,11 +691,7 @@ pvr_vm_lock_extra(struct drm_gpuvm_exec *vm_exec) struct pvr_vm_bind_op *bind_op = vm_exec->extra.priv; struct pvr_gem_object *pvr_obj = bind_op->pvr_obj; - /* Unmap operations don't have an object to lock. */ - if (!pvr_obj) - return 0; - - /* Acquire lock on the GEM being mapped. */ + /* Acquire lock on the GEM object being mapped/unmapped. */ return drm_exec_lock_obj(&vm_exec->exec, gem_from_pvr_gem(pvr_obj)); } @@ -772,8 +756,10 @@ err_cleanup: } /** - * pvr_vm_unmap() - Unmap an already mapped section of device-virtual memory. + * pvr_vm_unmap_obj_locked() - Unmap an already mapped section of device-virtual + * memory. * @vm_ctx: Target VM context. + * @pvr_obj: Target PowerVR memory object. * @device_addr: Virtual device address at the start of the target mapping. * @size: Size of the target mapping. * @@ -784,9 +770,13 @@ err_cleanup: * * Any error encountered while performing internal operations required to * destroy the mapping (returned from pvr_vm_gpuva_unmap or * pvr_vm_gpuva_remap). + * + * The vm_ctx->lock must be held when calling this function. */ -int -pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size) +static int +pvr_vm_unmap_obj_locked(struct pvr_vm_context *vm_ctx, + struct pvr_gem_object *pvr_obj, + u64 device_addr, u64 size) { struct pvr_vm_bind_op bind_op = {0}; struct drm_gpuvm_exec vm_exec = { @@ -799,11 +789,13 @@ pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size) }, }; - int err = pvr_vm_bind_op_unmap_init(&bind_op, vm_ctx, device_addr, - size); + int err = pvr_vm_bind_op_unmap_init(&bind_op, vm_ctx, pvr_obj, + device_addr, size); if (err) return err; + pvr_gem_object_get(pvr_obj); + err = drm_gpuvm_exec_lock(&vm_exec); if (err) goto err_cleanup; @@ -818,6 +810,96 @@ err_cleanup: return err; } +/** + * pvr_vm_unmap_obj() - Unmap an already mapped section of device-virtual + * memory. + * @vm_ctx: Target VM context. + * @pvr_obj: Target PowerVR memory object. + * @device_addr: Virtual device address at the start of the target mapping. + * @size: Size of the target mapping. + * + * Return: + * * 0 on success, + * * Any error encountered by pvr_vm_unmap_obj_locked. + */ +int +pvr_vm_unmap_obj(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj, + u64 device_addr, u64 size) +{ + int err; + + mutex_lock(&vm_ctx->lock); + err = pvr_vm_unmap_obj_locked(vm_ctx, pvr_obj, device_addr, size); + mutex_unlock(&vm_ctx->lock); + + return err; +} + +/** + * pvr_vm_unmap() - Unmap an already mapped section of device-virtual memory. + * @vm_ctx: Target VM context. + * @device_addr: Virtual device address at the start of the target mapping. + * @size: Size of the target mapping. + * + * Return: + * * 0 on success, + * * Any error encountered by drm_gpuva_find, + * * Any error encountered by pvr_vm_unmap_obj_locked. + */ +int +pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size) +{ + struct pvr_gem_object *pvr_obj; + struct drm_gpuva *va; + int err; + + mutex_lock(&vm_ctx->lock); + + va = drm_gpuva_find(&vm_ctx->gpuvm_mgr, device_addr, size); + if (va) { + pvr_obj = gem_to_pvr_gem(va->gem.obj); + err = pvr_vm_unmap_obj_locked(vm_ctx, pvr_obj, + va->va.addr, va->va.range); + } else { + err = -ENOENT; + } + + mutex_unlock(&vm_ctx->lock); + + return err; +} + +/** + * pvr_vm_unmap_all() - Unmap all mappings associated with a VM context. + * @vm_ctx: Target VM context. + * + * This function ensures that no mappings are left dangling by unmapping them + * all in order of ascending device-virtual address. + */ +void +pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx) +{ + mutex_lock(&vm_ctx->lock); + + for (;;) { + struct pvr_gem_object *pvr_obj; + struct drm_gpuva *va; + + va = drm_gpuva_find_first(&vm_ctx->gpuvm_mgr, + vm_ctx->gpuvm_mgr.mm_start, + vm_ctx->gpuvm_mgr.mm_range); + if (!va) + break; + + pvr_obj = gem_to_pvr_gem(va->gem.obj); + + WARN_ON(pvr_vm_unmap_obj_locked(vm_ctx, pvr_obj, + va->va.addr, va->va.range)); + } + + mutex_unlock(&vm_ctx->lock); +} + /* Static data areas are determined by firmware. */ static const struct drm_pvr_static_data_area static_data_areas[] = { { diff --git a/drivers/gpu/drm/imagination/pvr_vm.h b/drivers/gpu/drm/imagination/pvr_vm.h index 79406243617c..b0528dffa7f1 100644 --- a/drivers/gpu/drm/imagination/pvr_vm.h +++ b/drivers/gpu/drm/imagination/pvr_vm.h @@ -38,6 +38,9 @@ struct pvr_vm_context *pvr_vm_create_context(struct pvr_device *pvr_dev, int pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj, u64 pvr_obj_offset, u64 device_addr, u64 size); +int pvr_vm_unmap_obj(struct pvr_vm_context *vm_ctx, + struct pvr_gem_object *pvr_obj, + u64 device_addr, u64 size); int pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size); void pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx); From 91cf42c63f2d8a9c1bcdfe923218e079b32e1a69 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Mon, 3 Mar 2025 10:47:40 +0000 Subject: [PATCH 0355/1090] spi: microchip-core: prevent RX overflows when transmit size > FIFO size When the size of a transfer exceeds the size of the FIFO (32 bytes), RX overflows will be generated and receive data will be corrupted and warnings will be produced. For example, here's an error generated by a transfer of 36 bytes: spi_master spi0: mchp_corespi_interrupt: RX OVERFLOW: rxlen: 4, txlen: 0 The driver is currently split between handling receiving in the interrupt handler, and sending outside of it. Move all handling out of the interrupt handling, and explicitly link the number of bytes read of of the RX FIFO to the number written into the TX one. This both resolves the overflow problems as well as simplifying the flow of the driver. CC: stable@vger.kernel.org Fixes: 9ac8d17694b6 ("spi: add support for microchip fpga spi controllers") Signed-off-by: Conor Dooley Link: https://patch.msgid.link/20250303-veal-snooper-712c1dfad336@wendy Signed-off-by: Mark Brown --- drivers/spi/spi-microchip-core.c | 41 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c index 5b6af55855ef..62ba0bd9cbb7 100644 --- a/drivers/spi/spi-microchip-core.c +++ b/drivers/spi/spi-microchip-core.c @@ -70,8 +70,7 @@ #define INT_RX_CHANNEL_OVERFLOW BIT(2) #define INT_TX_CHANNEL_UNDERRUN BIT(3) -#define INT_ENABLE_MASK (CONTROL_RX_DATA_INT | CONTROL_TX_DATA_INT | \ - CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT) +#define INT_ENABLE_MASK (CONTROL_RX_OVER_INT | CONTROL_TX_UNDER_INT) #define REG_CONTROL (0x00) #define REG_FRAME_SIZE (0x04) @@ -133,10 +132,15 @@ static inline void mchp_corespi_disable(struct mchp_corespi *spi) mchp_corespi_write(spi, REG_CONTROL, control); } -static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi) +static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi, int fifo_max) { - while (spi->rx_len >= spi->n_bytes && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) { - u32 data = mchp_corespi_read(spi, REG_RX_DATA); + for (int i = 0; i < fifo_max; i++) { + u32 data; + + while (mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY) + ; + + data = mchp_corespi_read(spi, REG_RX_DATA); spi->rx_len -= spi->n_bytes; @@ -211,11 +215,10 @@ static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) mchp_corespi_write(spi, REG_FRAMESUP, len); } -static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi) +static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi, int fifo_max) { - int fifo_max, i = 0; + int i = 0; - fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes); mchp_corespi_set_xfer_size(spi, fifo_max); while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { @@ -413,19 +416,6 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id) if (intfield == 0) return IRQ_NONE; - if (intfield & INT_TXDONE) - mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE); - - if (intfield & INT_RXRDY) { - mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY); - - if (spi->rx_len) - mchp_corespi_read_fifo(spi); - } - - if (!spi->rx_len && !spi->tx_len) - finalise = true; - if (intfield & INT_RX_CHANNEL_OVERFLOW) { mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); finalise = true; @@ -512,9 +502,14 @@ static int mchp_corespi_transfer_one(struct spi_controller *host, mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); - while (spi->tx_len) - mchp_corespi_write_fifo(spi); + while (spi->tx_len) { + int fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes); + mchp_corespi_write_fifo(spi, fifo_max); + mchp_corespi_read_fifo(spi, fifo_max); + } + + spi_finalize_current_transfer(host); return 1; } From 68c3de7f707e8a70e0a6d8087cf0fe4a3d5dbfb0 Mon Sep 17 00:00:00 2001 From: Brendan King Date: Wed, 26 Feb 2025 15:43:54 +0000 Subject: [PATCH 0356/1090] drm/imagination: only init job done fences once Ensure job done fences are only initialised once. This fixes a memory manager not clean warning from drm_mm_takedown on module unload. Cc: stable@vger.kernel.org Fixes: eaf01ee5ba28 ("drm/imagination: Implement job submission and scheduling") Signed-off-by: Brendan King Reviewed-by: Matt Coster Link: https://patchwork.freedesktop.org/patch/msgid/20250226-init-done-fences-once-v2-1-c1b2f556b329@imgtec.com Signed-off-by: Matt Coster --- drivers/gpu/drm/imagination/pvr_queue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c index f3f1c5212df7..43411be930a2 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.c +++ b/drivers/gpu/drm/imagination/pvr_queue.c @@ -313,8 +313,9 @@ pvr_queue_cccb_fence_init(struct dma_fence *fence, struct pvr_queue *queue) static void pvr_queue_job_fence_init(struct dma_fence *fence, struct pvr_queue *queue) { - pvr_queue_fence_init(fence, queue, &pvr_queue_job_fence_ops, - &queue->job_fence_ctx); + if (!fence->ops) + pvr_queue_fence_init(fence, queue, &pvr_queue_job_fence_ops, + &queue->job_fence_ctx); } /** From 1d2eabb6616433ccaa13927811bdfa205e91ba60 Mon Sep 17 00:00:00 2001 From: Alessio Belle Date: Fri, 21 Feb 2025 10:49:35 +0000 Subject: [PATCH 0357/1090] drm/imagination: Fix timestamps in firmware traces When firmware traces are enabled, the firmware dumps 48-bit timestamps for each trace as two 32-bit values, highest 32 bits (of which only 16 useful) first. The driver was reassembling them the other way round i.e. interpreting the first value in memory as the lowest 32 bits, and the second value as the highest 32 bits (then truncated to 16 bits). Due to this, firmware trace dumps showed very large timestamps even for traces recorded shortly after GPU boot. The timestamps in these dumps would also sometimes jump backwards because of the truncation. Example trace dumped after loading the powervr module and enabling firmware traces, where each line is commented with the timestamp value in hexadecimal to better show both issues: [93540092739584] : Host Sync Partition marker: 1 // 0x551300000000 [28419798597632] : GPU units deinit // 0x19d900000000 [28548647616512] : GPU deinit // 0x19f700000000 Update logic to reassemble the timestamps halves in the correct order. Fixes: cb56cd610866 ("drm/imagination: Add firmware trace to debugfs") Signed-off-by: Alessio Belle Reviewed-by: Matt Coster Link: https://patchwork.freedesktop.org/patch/msgid/20250221-fix-fw-trace-timestamps-v1-1-dba4aeb030ca@imgtec.com Signed-off-by: Matt Coster --- drivers/gpu/drm/imagination/pvr_fw_trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_fw_trace.c b/drivers/gpu/drm/imagination/pvr_fw_trace.c index 73707daa4e52..5dbb636d7d4f 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_trace.c +++ b/drivers/gpu/drm/imagination/pvr_fw_trace.c @@ -333,8 +333,8 @@ static int fw_trace_seq_show(struct seq_file *s, void *v) if (sf_id == ROGUE_FW_SF_LAST) return -EINVAL; - timestamp = read_fw_trace(trace_seq_data, 1) | - ((u64)read_fw_trace(trace_seq_data, 2) << 32); + timestamp = ((u64)read_fw_trace(trace_seq_data, 1) << 32) | + read_fw_trace(trace_seq_data, 2); timestamp = (timestamp & ~ROGUE_FWT_TIMESTAMP_TIME_CLRMSK) >> ROGUE_FWT_TIMESTAMP_TIME_SHIFT; From 2738d06fb4f01145b24c542fb06de538ffc56430 Mon Sep 17 00:00:00 2001 From: Dmitry Panchenko Date: Thu, 20 Feb 2025 17:39:31 +0200 Subject: [PATCH 0358/1090] platform/x86: intel-hid: fix volume buttons on Microsoft Surface Go 4 tablet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Volume buttons on Microsoft Surface Go 4 tablet didn't send any events. Add Surface Go 4 DMI match to button_array_table to fix this. Signed-off-by: Dmitry Panchenko Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20250220154016.3620917-1-dmitry@d-systems.ee Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/hid.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index 927a2993f616..88a1a9ff2f34 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -139,6 +139,13 @@ static const struct dmi_system_id button_array_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), }, }, + { + .ident = "Microsoft Surface Go 4", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 4"), + }, + }, { } }; From d0d10eaedcb53740883d7e5d53c5e15c879b48fb Mon Sep 17 00:00:00 2001 From: Mingcong Bai Date: Sat, 22 Feb 2025 00:48:24 +0800 Subject: [PATCH 0359/1090] platform/x86: thinkpad_acpi: Add battery quirk for ThinkPad X131e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the dmesg messages from the original reporter: [ 4.964073] ACPI: \_SB_.PCI0.LPCB.EC__.HKEY: BCTG evaluated but flagged as error [ 4.964083] thinkpad_acpi: Error probing battery 2 Lenovo ThinkPad X131e also needs this battery quirk. Reported-by: Fan Yang <804284660@qq.com> Tested-by: Fan Yang <804284660@qq.com> Co-developed-by: Xi Ruoyao Signed-off-by: Xi Ruoyao Signed-off-by: Mingcong Bai Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250221164825.77315-1-jeffbai@aosc.io Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/thinkpad_acpi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 72a10ed2017c..1cc91173e012 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -9972,6 +9972,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = { * Individual addressing is broken on models that expose the * primary battery as BAT1. */ + TPACPI_Q_LNV('G', '8', true), /* ThinkPad X131e */ TPACPI_Q_LNV('8', 'F', true), /* Thinkpad X120e */ TPACPI_Q_LNV('J', '7', true), /* B5400 */ TPACPI_Q_LNV('J', 'I', true), /* Thinkpad 11e */ From f317f38e7fbb15a0d8329289fef8cf034938fb4f Mon Sep 17 00:00:00 2001 From: "David E. Box" Date: Wed, 26 Feb 2025 13:47:27 -0800 Subject: [PATCH 0360/1090] platform/x86/intel/vsec: Add Diamond Rapids support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PCI ID for the Diamond Rapids Platforms Signed-off-by: David E. Box Link: https://lore.kernel.org/r/20250226214728.1256747-1-david.e.box@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/vsec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c index 8272f1dd0fbc..db3c031d1757 100644 --- a/drivers/platform/x86/intel/vsec.c +++ b/drivers/platform/x86/intel/vsec.c @@ -404,6 +404,11 @@ static const struct intel_vsec_platform_info oobmsm_info = { .caps = VSEC_CAP_TELEMETRY | VSEC_CAP_SDSI | VSEC_CAP_TPMI, }; +/* DMR OOBMSM info */ +static const struct intel_vsec_platform_info dmr_oobmsm_info = { + .caps = VSEC_CAP_TELEMETRY | VSEC_CAP_TPMI, +}; + /* TGL info */ static const struct intel_vsec_platform_info tgl_info = { .caps = VSEC_CAP_TELEMETRY, @@ -420,6 +425,7 @@ static const struct intel_vsec_platform_info lnl_info = { #define PCI_DEVICE_ID_INTEL_VSEC_MTL_M 0x7d0d #define PCI_DEVICE_ID_INTEL_VSEC_MTL_S 0xad0d #define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM 0x09a7 +#define PCI_DEVICE_ID_INTEL_VSEC_OOBMSM_DMR 0x09a1 #define PCI_DEVICE_ID_INTEL_VSEC_RPL 0xa77d #define PCI_DEVICE_ID_INTEL_VSEC_TGL 0x9a0d #define PCI_DEVICE_ID_INTEL_VSEC_LNL_M 0x647d @@ -430,6 +436,7 @@ static const struct pci_device_id intel_vsec_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, VSEC_MTL_M, &mtl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_MTL_S, &mtl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM, &oobmsm_info) }, + { PCI_DEVICE_DATA(INTEL, VSEC_OOBMSM_DMR, &dmr_oobmsm_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) }, { PCI_DEVICE_DATA(INTEL, VSEC_LNL_M, &lnl_info) }, From 5cfe5612ca9590db69b9be29dc83041dbf001108 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 17 Feb 2025 17:02:42 +0100 Subject: [PATCH 0361/1090] netfilter: nft_ct: Use __refcount_inc() for per-CPU nft_ct_pcpu_template. nft_ct_pcpu_template is a per-CPU variable and relies on disabled BH for its locking. The refcounter is read and if its value is set to one then the refcounter is incremented and variable is used - otherwise it is already in use and left untouched. Without per-CPU locking in local_bh_disable() on PREEMPT_RT the read-then-increment operation is not atomic and therefore racy. This can be avoided by using unconditionally __refcount_inc() which will increment counter and return the old value as an atomic operation. In case the returned counter is not one, the variable is in use and we need to decrement counter. Otherwise we can use it. Use __refcount_inc() instead of read and a conditional increment. Fixes: edee4f1e9245 ("netfilter: nft_ct: add zone id set support") Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_ct.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 2e59aba681a1..d526e69a2a2b 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -230,6 +230,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr, enum ip_conntrack_info ctinfo; u16 value = nft_reg_load16(®s->data[priv->sreg]); struct nf_conn *ct; + int oldcnt; ct = nf_ct_get(skb, &ctinfo); if (ct) /* already tracked */ @@ -250,10 +251,11 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr, ct = this_cpu_read(nft_ct_pcpu_template); - if (likely(refcount_read(&ct->ct_general.use) == 1)) { - refcount_inc(&ct->ct_general.use); + __refcount_inc(&ct->ct_general.use, &oldcnt); + if (likely(oldcnt == 1)) { nf_ct_zone_add(ct, &zone); } else { + refcount_dec(&ct->ct_general.use); /* previous skb got queued to userspace, allocate temporary * one until percpu template can be reused. */ From b686559772d1baa28e2ad346d5a9932863d9523c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:51 +0100 Subject: [PATCH 0362/1090] ASoC: codecs: rt1011: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index a0e75b03e9dc..fb76f9e020ff 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -2192,15 +2192,15 @@ static const struct regmap_config rt1011_regmap = { #if defined(CONFIG_OF) static const struct of_device_id rt1011_of_match[] = { { .compatible = "realtek,rt1011", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1011_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt1011_acpi_match[] = { - {"10EC1011", 0,}, - {}, + { "10EC1011" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match); #endif From a859d2383f66002a442218bf5083faaa674bc4e4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:52 +0100 Subject: [PATCH 0363/1090] ASoC: codecs: rt1015: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 0f806dde9c39..ea8037117d42 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1105,15 +1105,15 @@ MODULE_DEVICE_TABLE(i2c, rt1015_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id rt1015_of_match[] = { { .compatible = "realtek,rt1015", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1015_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt1015_acpi_match[] = { - {"10EC1015", 0,}, - {}, + { "10EC1015" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1015_acpi_match); #endif From e7795c17b82684afb9390b8788f781c07be1a368 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:53 +0100 Subject: [PATCH 0364/1090] ASoC: codecs: rt1016: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1016.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index fed4da23cba2..132c102983bf 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -616,15 +616,15 @@ MODULE_DEVICE_TABLE(i2c, rt1016_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id rt1016_of_match[] = { { .compatible = "realtek,rt1016", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1016_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt1016_acpi_match[] = { - {"10EC1016", 0,}, - {}, + { "10EC1016" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1016_acpi_match); #endif From 689e4d5fd8a76c676f04bc8916d78ca5db3130db Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:54 +0100 Subject: [PATCH 0365/1090] ASoC: codecs: rt1019: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index d989d06a2614..86539c6f6cc1 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -547,14 +547,14 @@ MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); static const struct of_device_id rt1019_of_match[] __maybe_unused = { { .compatible = "realtek,rt1019", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1019_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id rt1019_acpi_match[] = { - { "10EC1019", 0}, - { }, + { "10EC1019" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1019_acpi_match); #endif From 0440f938aacf54a3e7dc67cd898f76bbd371da49 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:55 +0100 Subject: [PATCH 0366/1090] ASoC: codecs: rt1305: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1305.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index c2b55be8d165..59ddc4b21803 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -966,16 +966,16 @@ static const struct regmap_config rt1305_regmap = { static const struct of_device_id rt1305_of_match[] = { { .compatible = "realtek,rt1305", }, { .compatible = "realtek,rt1306", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1305_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt1305_acpi_match[] = { - {"10EC1305", 0,}, - {"10EC1306", 0,}, - {}, + { "10EC1305" }, + { "10EC1306" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1305_acpi_match); #endif From 30e03871146129acb75adac48405c203f5bdb3c2 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:56 +0100 Subject: [PATCH 0367/1090] ASoC: codecs: rt1308: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index b366338cea71..90d14e2d62f1 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -781,15 +781,15 @@ static const struct regmap_config rt1308_regmap = { #ifdef CONFIG_OF static const struct of_device_id rt1308_of_match[] = { { .compatible = "realtek,rt1308", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, rt1308_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt1308_acpi_match[] = { - { "10EC1308", 0, }, - { }, + { "10EC1308" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match); #endif From acac29fa62a8b738569a99da2f6458bc21aa55ae Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:57 +0100 Subject: [PATCH 0368/1090] ASoC: codecs: rt1318: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1318.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c index e12b1e96a53a..ae01b2ce630b 100644 --- a/sound/soc/codecs/rt1318.c +++ b/sound/soc/codecs/rt1318.c @@ -1147,14 +1147,14 @@ MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id); static const struct of_device_id rt1318_of_match[] = { { .compatible = "realtek,rt1318", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt1318_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id rt1318_acpi_match[] = { - { "10EC1318", 0}, - { }, + { "10EC1318" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt1318_acpi_match); #endif From 5a84cbb03094fd903ed79ca6c06e558821a69be4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:58 +0100 Subject: [PATCH 0369/1090] ASoC: codecs: rt274: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt274.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index bd61a257d7b5..b27e9d06e32d 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1091,7 +1091,7 @@ static const struct regmap_config rt274_regmap = { #ifdef CONFIG_OF static const struct of_device_id rt274_of_match[] = { {.compatible = "realtek,rt274"}, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt274_of_match); #endif @@ -1104,9 +1104,9 @@ MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt274_acpi_match[] = { - { "10EC0274", 0 }, - { "INT34C2", 0 }, - {}, + { "10EC0274" }, + { "INT34C2" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt274_acpi_match); #endif From 1c418cf146380031b13b6fde02f944830e5b9155 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:25:59 +0100 Subject: [PATCH 0370/1090] ASoC: codecs: rt5514: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 9cb74962161a..a7f984b5d80f 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -1206,15 +1206,15 @@ MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id rt5514_of_match[] = { { .compatible = "realtek,rt5514", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5514_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5514_acpi_match[] = { - { "10EC5514", 0}, - {}, + { "10EC5514" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); #endif From dfc6b8ccb1bb8d591cd26571e554208fc4af7d0c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:00 +0100 Subject: [PATCH 0371/1090] ASoC: codecs: rt5640: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-11-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 855139348edb..391df62491fa 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2963,19 +2963,19 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); static const struct of_device_id rt5640_of_match[] = { { .compatible = "realtek,rt5639", }, { .compatible = "realtek,rt5640", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5640_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5640_acpi_match[] = { - { "INT33CA", 0 }, - { "10EC3276", 0 }, - { "10EC5640", 0 }, - { "10EC5642", 0 }, - { "INTCCFFD", 0 }, - { }, + { "10EC3276" }, + { "10EC5640" }, + { "10EC5642" }, + { "INT33CA" }, + { "INTCCFFD" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match); #endif From d3a37a664ebe57471bd7ab2486dd3072a9c07378 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:01 +0100 Subject: [PATCH 0372/1090] ASoC: codecs: rt5645: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-12-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 51187b1e0ed2..56cf410926e3 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3660,12 +3660,12 @@ MODULE_DEVICE_TABLE(of, rt5645_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id rt5645_acpi_match[] = { - { "10EC5645", 0 }, - { "10EC5648", 0 }, - { "10EC5650", 0 }, - { "10EC5640", 0 }, - { "10EC3270", 0 }, - {}, + { "10EC3270" }, + { "10EC5640" }, + { "10EC5645" }, + { "10EC5648" }, + { "10EC5650" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); #endif From 85188e3bd7cb4141181f24a59f9057c38ffa37bf Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:02 +0100 Subject: [PATCH 0373/1090] ASoC: codecs: rt5651: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-13-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 00421a1f54bf..2c1fad3ee690 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -2184,16 +2184,16 @@ static const struct regmap_config rt5651_regmap = { #if defined(CONFIG_OF) static const struct of_device_id rt5651_of_match[] = { { .compatible = "realtek,rt5651", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5651_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5651_acpi_match[] = { - { "10EC5651", 0 }, - { "10EC5640", 0 }, - { }, + { "10EC5640" }, + { "10EC5651" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match); #endif From 24a4302478118ff1caf39fb48809c0127f608664 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:03 +0100 Subject: [PATCH 0374/1090] ASoC: codecs: rt5659: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-14-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index a2652fa6e1d7..e5e8ccc604eb 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -4315,16 +4315,16 @@ static void rt5659_i2c_shutdown(struct i2c_client *client) static const struct of_device_id rt5659_of_match[] = { { .compatible = "realtek,rt5658", }, { .compatible = "realtek,rt5659", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, rt5659_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5659_acpi_match[] = { - { "10EC5658", 0, }, - { "10EC5659", 0, }, - { }, + { "10EC5658" }, + { "10EC5659" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5659_acpi_match); #endif From 4d34ea6709894243d55ae6a6b63834851f9c5d6f Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:04 +0100 Subject: [PATCH 0375/1090] ASoC: codecs: rt5660: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-15-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5660.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 3ac41d2c279b..7e8ac735b82c 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -1232,16 +1232,16 @@ MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id); #ifdef CONFIG_OF static const struct of_device_id rt5660_of_match[] = { { .compatible = "realtek,rt5660", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5660_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5660_acpi_match[] = { - { "10EC5660", 0 }, - { "10EC3277", 0 }, - { }, + { "10EC3277" }, + { "10EC5660" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match); #endif From e9d9a43e3f00b9313013b78d915a1f97dd215bf5 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:05 +0100 Subject: [PATCH 0376/1090] ASoC: codecs: rt5663: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-16-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 9d32debd3689..874c5ea3efb5 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3315,15 +3315,15 @@ MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id rt5663_of_match[] = { { .compatible = "realtek,rt5663", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5663_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5663_acpi_match[] = { - { "10EC5663", 0}, - {}, + { "10EC5663" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5663_acpi_match); #endif From b89d9d26fb6cbc9f6e0aae72a2a76b5d8e5f1023 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:06 +0100 Subject: [PATCH 0377/1090] ASoC: codecs: rt5665: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-17-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 47df14ba5278..be5ddb4be6df 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4949,16 +4949,16 @@ static void rt5665_i2c_shutdown(struct i2c_client *client) static const struct of_device_id rt5665_of_match[] = { {.compatible = "realtek,rt5665"}, {.compatible = "realtek,rt5666"}, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5665_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5665_acpi_match[] = { - {"10EC5665", 0,}, - {"10EC5666", 0,}, - {}, + { "10EC5665" }, + { "10EC5666" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5665_acpi_match); #endif From a06ef7754b8e6f45d78c0015c3edb2117945adfb Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:07 +0100 Subject: [PATCH 0378/1090] ASoC: codecs: rt5668: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-18-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5668.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 494ca3ce9b96..51be7b1f900b 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -2598,15 +2598,15 @@ static void rt5668_i2c_shutdown(struct i2c_client *client) #ifdef CONFIG_OF static const struct of_device_id rt5668_of_match[] = { {.compatible = "realtek,rt5668b"}, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5668_of_match); #endif #ifdef CONFIG_ACPI static const struct acpi_device_id rt5668_acpi_match[] = { - {"10EC5668", 0,}, - {}, + { "10EC5668" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5668_acpi_match); #endif From 9aa85f433bb1f51b599278b29b3d6224ca5147cf Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:08 +0100 Subject: [PATCH 0379/1090] ASoC: codecs: rt5670: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. While at it, sort the IDs alphabetically. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-19-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 30bf96c35b58..c18fc86a2513 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2880,10 +2880,10 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt5670_acpi_match[] = { - { "10EC5670", 0}, - { "10EC5672", 0}, - { "10EC5640", 0}, /* quirk */ - { }, + { "10EC5640" }, /* quirk */ + { "10EC5670" }, + { "10EC5672" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); #endif From 6de7c4def7a6bf967d6603f7e1abda5231ccc312 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:09 +0100 Subject: [PATCH 0380/1090] ASoC: codecs: rt5682: Fix definition of device_id tables There shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-20-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index a8820435d1e0..bba987308e15 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -313,13 +313,13 @@ static void rt5682_i2c_remove(struct i2c_client *client) static const struct of_device_id rt5682_of_match[] = { {.compatible = "realtek,rt5682i"}, - {}, + { } }; MODULE_DEVICE_TABLE(of, rt5682_of_match); static const struct acpi_device_id rt5682_acpi_match[] = { - {"10EC5682", 0,}, - {}, + { "10EC5682" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); From 7f15da9a55d3ba9f8c3af545246a4588102a38db Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:10 +0100 Subject: [PATCH 0381/1090] ASoC: codecs: rt286: Update definition of device_id tables Follow PCI-based format (10ECxxxx) for ACPI IDs by adding relevant entries to the existing table. While at it, there shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-21-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index d0f533120c33..5ad1b9311d11 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1083,8 +1083,9 @@ MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt286_acpi_match[] = { - { "INT343A", 0 }, - {}, + { "10EC0286" }, + { "INT343A" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt286_acpi_match); #endif From ed4bef1d52ce0d6c96a86b6a470d6777034c564c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:11 +0100 Subject: [PATCH 0382/1090] ASoC: codecs: rt298: Update definition of device_id tables Follow PCI-based format (10ECxxxx) for ACPI IDs by adding relevant entries to the existing table. While at it, there shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-22-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt298.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 13aef6c5e91c..dd2d27515e7e 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1144,8 +1144,9 @@ MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt298_acpi_match[] = { - { "INT343A", 0 }, - {}, + { "10EC0298" }, + { "INT343A" }, + { } }; MODULE_DEVICE_TABLE(acpi, rt298_acpi_match); #endif From 739db0529c2a3ac5a0dc3e5a76a46ce80735dcfa Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 26 Feb 2025 12:26:12 +0100 Subject: [PATCH 0383/1090] ASoC: codecs: rt5677: Update definition of device_id tables Follow PCI-based format (10ECxxxx) for ACPI IDs by adding relevant entries to the existing table. While at it, there shall be no comma after the terminator entry and initializing fields with 0 for statically defined structs is redundant. Signed-off-by: Cezary Rojewski Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250226112612.166989-23-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677-spi.c | 3 ++- sound/soc/codecs/rt5677.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index d91a2184f67c..abe0a5a95770 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -617,7 +617,8 @@ static int rt5677_spi_probe(struct spi_device *spi) #ifdef CONFIG_ACPI static const struct acpi_device_id rt5677_spi_acpi_id[] = { - { "RT5677AA", 0 }, + { "10EC5677" }, + { "RT5677AA" }, { } }; MODULE_DEVICE_TABLE(acpi, rt5677_spi_acpi_id); diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 0e70a3ab42b5..d1e0b93d6ee6 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5201,6 +5201,7 @@ static const struct of_device_id rt5677_of_match[] = { MODULE_DEVICE_TABLE(of, rt5677_of_match); static const struct acpi_device_id rt5677_acpi_match[] = { + { "10EC5677", RT5677 }, { "RT5677CE", RT5677 }, { } }; From 8450fa6b16e2f46f5b880e0b80d55ab9fc4524ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:29:45 +0000 Subject: [PATCH 0384/1090] ASoC: Documentation: Codec to Codec: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczlh4s7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- Documentation/sound/soc/codec-to-codec.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/soc/codec-to-codec.rst b/Documentation/sound/soc/codec-to-codec.rst index 0418521b6e03..973c147d9d82 100644 --- a/Documentation/sound/soc/codec-to-codec.rst +++ b/Documentation/sound/soc/codec-to-codec.rst @@ -68,7 +68,7 @@ file: .codec_dai_name = "codec-2-dai_name", .platform_name = "samsung-i2s.0", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &dsp_codec_params, .num_c2c_params = 1, @@ -80,7 +80,7 @@ file: .codec_name = "codec-3, .codec_dai_name = "codec-3-dai_name", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &dsp_codec_params, .num_c2c_params = 1, From 231bf041d425a086ec08231c98cf02b6fb16b169 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:29:51 +0000 Subject: [PATCH 0385/1090] ASoC: ti: n810: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5h4s0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/n810.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index 50a8ec97cf20..345c98765380 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -258,7 +258,7 @@ static struct snd_soc_dai_link n810_dai = { .name = "TLV320AIC33", .stream_name = "AIC33", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ops = &n810_ops, SND_SOC_DAILINK_REG(aic33), }; From dfdc0debf1b82354e301843f8cbd16eaf05a01c6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:29:55 +0000 Subject: [PATCH 0386/1090] ASoC: ti: osk5912: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjuph4rw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/osk5912.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c index 98714c593496..fa5ef7814dab 100644 --- a/sound/soc/ti/osk5912.c +++ b/sound/soc/ti/osk5912.c @@ -86,7 +86,7 @@ static struct snd_soc_dai_link osk_dai = { .name = "TLV320AIC23", .stream_name = "AIC23", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ops = &osk_ops, SND_SOC_DAILINK_REG(aic23), }; From 48d5e50e4fe78bf9cc5b4eca72798d4507da62fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:00 +0000 Subject: [PATCH 0387/1090] ASoC: ti: ams-delta: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9h4rr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/ams-delta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index 94645f275495..8a4423646aea 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -532,7 +532,7 @@ static struct snd_soc_dai_link ams_delta_dai_link = { .init = ams_delta_cx20442_init, .ops = &ams_delta_ops, .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(cx20442), }; From 5cfb2f62242b41e2b60cadf21b28ee43cf615ec2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:09 +0000 Subject: [PATCH 0388/1090] ASoC: ti: j721e-evm: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qpth4ri.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/j721e-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c index d9d1e021f5b2..c0fa72e626ff 100644 --- a/sound/soc/ti/j721e-evm.c +++ b/sound/soc/ti/j721e-evm.c @@ -37,7 +37,7 @@ enum j721e_audio_domain_id { #define J721E_DAI_FMT (SND_SOC_DAIFMT_RIGHT_J | \ SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBS_CFS) + SND_SOC_DAIFMT_CBC_CFC) enum j721e_board_type { J721E_BOARD_CPB = 1, From bc17eaf1b925595fb9f945ced5d70fe82ce11e78 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:13 +0000 Subject: [PATCH 0389/1090] ASoC: ti: davinci-evm: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5dh4re.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c index 1bf333d2740d..2a2f5bc95576 100644 --- a/sound/soc/ti/davinci-evm.c +++ b/sound/soc/ti/davinci-evm.c @@ -152,7 +152,7 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = { .stream_name = "AIC3X", .ops = &evm_ops, .init = evm_aic3x_init, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | + .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_IB_NF, SND_SOC_DAILINK_REG(evm), }; From 9fde82ea39a7f52c23de366c8592d4805634f45c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:17 +0000 Subject: [PATCH 0390/1090] ASoC: ti: omap-twl4030: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxh4ra.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-twl4030.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ti/omap-twl4030.c b/sound/soc/ti/omap-twl4030.c index a402d66e4f4d..3548b58002c4 100644 --- a/sound/soc/ti/omap-twl4030.c +++ b/sound/soc/ti/omap-twl4030.c @@ -42,12 +42,12 @@ static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, case 2: /* Stereo I2S mode */ fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; + SND_SOC_DAIFMT_CBP_CFP; break; case 4: /* Four channel TDM mode */ fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM; + SND_SOC_DAIFMT_CBP_CFP; break; default: return -EINVAL; @@ -218,7 +218,7 @@ static struct snd_soc_dai_link omap_twl4030_dai_links[] = { .name = "TWL4030 Voice", .stream_name = "TWL4030 Voice", .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(voice), }, }; From 941abe67e176a3ddbe59cd4323b13f69515f6628 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:22 +0000 Subject: [PATCH 0391/1090] ASoC: ti: omap3pandora: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0hh4r5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ti/omap3pandora.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c index be69476e59d6..808fb6765c05 100644 --- a/sound/soc/ti/omap3pandora.c +++ b/sound/soc/ti/omap3pandora.c @@ -189,7 +189,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .name = "PCM1773", .stream_name = "HiFi Out", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &omap3pandora_ops, .init = omap3pandora_out_init, SND_SOC_DAILINK_REG(out), @@ -197,7 +197,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = { .name = "TWL4030", .stream_name = "Line/Mic In", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &omap3pandora_ops, .init = omap3pandora_in_init, SND_SOC_DAILINK_REG(in), From df95f0157ba1ea7b73b3f1db4abfdb4b05e0bfd9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:27 +0000 Subject: [PATCH 0392/1090] ASoC: amd: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1h4r0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-mach-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index f7602c1769bf..a0dab85088ec 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -919,7 +919,7 @@ static int acp_max98388_hw_params(struct snd_pcm_substream *substream, int ret; ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF); if (ret < 0) return ret; From 2920be2fabcb8010fefdf101d84fe0867730d925 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:35 +0000 Subject: [PATCH 0393/1090] ASoC: fsl: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvlh4qs.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 2bad9cb1daaf..ab583b432c60 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -759,7 +759,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) { codec_dai_name[0] = "tlv320dac31xx-hifi"; - priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; priv->dai_link[1].playback_only = 1; priv->dai_link[2].playback_only = 1; priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT; @@ -818,7 +818,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->codec_priv[0].mclk_id = NAU8822_CLK_MCLK; priv->codec_priv[0].fll_id = NAU8822_CLK_PLL; priv->codec_priv[0].pll_id = NAU8822_CLK_PLL; - priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; + priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; if (codec_dev[0]) priv->codec_priv[0].mclk = devm_clk_get(codec_dev[0], NULL); } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8904")) { From 74f6e045d879414ae4c352dc7f4e8d438ea9d55d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:40 +0000 Subject: [PATCH 0394/1090] ASoC: mxs: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi9fq68.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index a41a13ae38a5..245f17411638 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -59,7 +59,7 @@ static const struct snd_soc_ops mxs_sgtl5000_hifi_ops = { }; #define MXS_SGTL5000_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBS_CFS) + SND_SOC_DAIFMT_CBC_CFC) SND_SOC_DAILINK_DEFS(hifi_tx, From e42ec97657fa5ee40fd2358c973d273edd7999bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:44 +0000 Subject: [PATCH 0395/1090] ASoC: pxa: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xtfq64.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/pxa/spitz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 8caa1aa99bdc..6ca0a6bcd34c 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -260,7 +260,7 @@ static struct snd_soc_dai_link spitz_dai = { .name = "wm8750", .stream_name = "WM8750", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &spitz_ops, SND_SOC_DAILINK_REG(wm8750), }; From a1cadae42c9bc52cff24b22b0c4986be8d82ae16 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:48 +0000 Subject: [PATCH 0396/1090] ASoC: qcom: sc7180: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmddfq5z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/sc7180.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c index d95710b1ea4e..84b6ac5d2a20 100644 --- a/sound/soc/qcom/sc7180.c +++ b/sound/soc/qcom/sc7180.c @@ -397,7 +397,7 @@ static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream) switch (cpu_dai->id) { case MI2S_PRIMARY: snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S); runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; From f8ca280bf5c2a3fb08890bdd212a3f3c00589f87 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:53 +0000 Subject: [PATCH 0397/1090] ASoC: qcom: sc7280: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sxfq5v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/qcom/sc7280.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c index 230af8d7b205..af412bd0c89f 100644 --- a/sound/soc/qcom/sc7280.c +++ b/sound/soc/qcom/sc7280.c @@ -342,8 +342,8 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) static int sc7280_snd_startup(struct snd_pcm_substream *substream) { - unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; - unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; + unsigned int fmt = SND_SOC_DAIFMT_CBC_CFC; + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBC_CFC; struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); From 3c2e63a3a0efa8c52f9fd67f58a71af48957ca7a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:30:56 +0000 Subject: [PATCH 0398/1090] ASoC: codec: cs4234: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8hfq5r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4234.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c index 69287ba7e955..df160db5bbb5 100644 --- a/sound/soc/codecs/cs4234.c +++ b/sound/soc/codecs/cs4234.c @@ -307,9 +307,9 @@ static int cs4234_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int format } switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: if (cs4234->format == SND_SOC_DAIFMT_DSP_A) { dev_err(component->dev, "Unsupported DSP A format in master mode\n"); return -EINVAL; From c974655b0c7f82a760bd22d9ef9db281e765a9a2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:00 +0000 Subject: [PATCH 0399/1090] ASoC: codec: cs4265: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo1fq5n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4265.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 78ffb7fa7fc5..3f759c13d6d1 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -344,12 +344,12 @@ static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 iface = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: snd_soc_component_update_bits(component, CS4265_ADC_CTL, CS4265_ADC_MASTER, CS4265_ADC_MASTER); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: snd_soc_component_update_bits(component, CS4265_ADC_CTL, CS4265_ADC_MASTER, 0); From 46dbe25747fca3d82e98dca488fa9be6b809d522 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:04 +0000 Subject: [PATCH 0400/1090] ASoC: codec: cs4270: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03lfq5j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 67e92bfecb56..9f9dc8b017a3 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -287,10 +287,10 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs4270->slave_mode = 1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs4270->slave_mode = 0; break; default: From e9ab4b38205a34fffe537b4db721458b5d07066e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:09 +0000 Subject: [PATCH 0401/1090] ASoC: codec: cs4271: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj5fq5e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index e864188ae5eb..6a3cca3d26c7 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -209,10 +209,10 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, int ret; switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs4271->master = false; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs4271->master = true; val |= CS4271_MODE1_MASTER; break; From 0d41068ca151a6368ab4591c13e9a7a9fb92a56f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:13 +0000 Subject: [PATCH 0402/1090] ASoC: codec: cs4341: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6ypfq5a.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4341.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index d87aae31c516..b726e22ef57d 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -49,7 +49,7 @@ static int cs4341_set_fmt(struct snd_soc_dai *dai, unsigned int format) struct cs4341_priv *cs4341 = snd_soc_component_get_drvdata(component); switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 0c57e55719681412e87db7bb81b8255b43d6162f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:17 +0000 Subject: [PATCH 0403/1090] ASoC: codec: cs530x: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse9fq56.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs530x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c index 252e66c8449e..b9eff240b929 100644 --- a/sound/soc/codecs/cs530x.c +++ b/sound/soc/codecs/cs530x.c @@ -557,9 +557,9 @@ static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int asp_fmt, asp_cfg = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: asp_cfg = CS530X_ASP_PRIMARY; break; default: From b26c604a0dcef62e7c61bd1d560c63547c9bbfe8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:25 +0000 Subject: [PATCH 0404/1090] ASoC: codec: cs35l32: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldttfq4y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 96555263e10b..6d78fa953c89 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -153,12 +153,12 @@ static int cs35l32_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct snd_soc_component *component = codec_dai->component; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: snd_soc_component_update_bits(component, CS35L32_ADSP_CTL, CS35L32_ADSP_MASTER_MASK, CS35L32_ADSP_MASTER_MASK); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: snd_soc_component_update_bits(component, CS35L32_ADSP_CTL, CS35L32_ADSP_MASTER_MASK, 0); break; From ea38f63c4afdd5531fbd8f0f881594a94c4bd413 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:29 +0000 Subject: [PATCH 0405/1090] ASoC: codec: cs35l33: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9dfq4u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l33.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index b03aab147530..02a420659a33 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -438,12 +438,12 @@ static int cs35l33_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct cs35l33_private *priv = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, CS35L33_MS_MASK, CS35L33_MS_MASK); dev_dbg(component->dev, "Audio port in master mode\n"); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: regmap_update_bits(priv->regmap, CS35L33_ADSP_CTL, CS35L33_MS_MASK, 0); dev_dbg(component->dev, "Audio port in slave mode\n"); From d21e3b442ff6401511831ae1b8be11d530f063de Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:33 +0000 Subject: [PATCH 0406/1090] ASoC: codec: cs35l34: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikoxfq4r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l34.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index 287b27476a10..6d098bfd38f6 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -523,11 +523,11 @@ static int cs35l34_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct cs35l34_private *priv = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL, 0x80, 0x80); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL, 0x80, 0x00); break; From 952b334dcfcf641a6290b876bdc226c23772287e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:36 +0000 Subject: [PATCH 0407/1090] ASoC: codec: cs42l42: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64hfq4n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 501c951cc327..56668c392063 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -830,11 +830,11 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u32 asp_cfg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: asp_cfg_val |= CS42L42_ASP_MASTER_MODE << CS42L42_ASP_MODE_SHIFT; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: asp_cfg_val |= CS42L42_ASP_SLAVE_MODE << CS42L42_ASP_MODE_SHIFT; break; From fad200733e5026b103ec2504ad3dfc2843216cc8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:40 +0000 Subject: [PATCH 0408/1090] ASoC: codec: cs42l51: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk1fq4j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e51954bdb1e..0602d03095d6 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -322,10 +322,10 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, } switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs42l51->func = MODE_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs42l51->func = MODE_SLAVE_AUTO; break; default: From 1ef8b1c830a0b5a6600d803a8bbeb7179d3ca4da Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:44 +0000 Subject: [PATCH 0409/1090] ASoC: codec: cs42l52: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczlfq4f.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 7128d4c62f50..cd3f92c19045 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -733,10 +733,10 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 iface = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface = CS42L52_IFACE_CTL1_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: iface = CS42L52_IFACE_CTL1_SLAVE; break; default: From b9dde447dd27f1b3ca21e07da1d885fd342cfa62 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:48 +0000 Subject: [PATCH 0410/1090] ASoC: codec: cs42l56: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5fq4b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l56.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index aaa10c459b52..aaf90c8b7339 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -757,10 +757,10 @@ static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs42l56->iface = CS42L56_MASTER_MODE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs42l56->iface = CS42L56_SLAVE_MODE; break; default: From 8f5ae83953335d9c4c8d1cb698b87cea1ac8aeca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:51 +0000 Subject: [PATCH 0411/1090] ASoC: codec: cs42l73: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjupfq48.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 21ba796a5cd9..ddf36001100e 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -943,11 +943,11 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) mmcc = snd_soc_component_read(component, CS42L73_MMCC(id)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: mmcc |= CS42L73_MS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: mmcc &= ~CS42L73_MS_MASTER; break; From 90fd7bb1af1733685f0aece12dd7264d4ef68422 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:31:56 +0000 Subject: [PATCH 0412/1090] ASoC: codec: cs42xx8: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9fq43.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 9c44b6283b8f..8887db653dbf 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -242,10 +242,10 @@ static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Set master/slave audio interface */ switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: cs42xx8->slave_mode = true; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: cs42xx8->slave_mode = false; break; default: From dc946ef548aeeea258b040087b88c9b7fae5cb6d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:00 +0000 Subject: [PATCH 0413/1090] ASoC: codec: cs43130: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qptfq3z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs43130.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index f8e2fb69ada2..cd535be0b4ba 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -640,10 +640,10 @@ static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk, } switch (cs43130->dais[dai_id].dai_mode) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: dai_mode_val = 0; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: dai_mode_val = 1; break; default: @@ -851,7 +851,7 @@ static int cs43130_dsd_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if (cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM) + if (cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBP_CFP) regmap_update_bits(cs43130->regmap, CS43130_DSD_INT_CFG, CS43130_DSD_MASTER, CS43130_DSD_MASTER); else @@ -951,7 +951,7 @@ static int cs43130_hw_params(struct snd_pcm_substream *substream, break; } - if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM) + if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBP_CFP) /* Calculate SCLK in master mode if unassigned */ sclk = params_rate(params) * bitwidth_dai * params_channels(params); @@ -1516,11 +1516,11 @@ static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS; + case SND_SOC_DAIFMT_CBC_CFC: + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBC_CFC; break; - case SND_SOC_DAIFMT_CBM_CFM: - cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM; + case SND_SOC_DAIFMT_CBP_CFP: + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBP_CFP; break; default: dev_err(cs43130->dev, "unsupported mode\n"); @@ -1579,11 +1579,11 @@ static int cs43130_dsd_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS; + case SND_SOC_DAIFMT_CBC_CFC: + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBC_CFC; break; - case SND_SOC_DAIFMT_CBM_CFM: - cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM; + case SND_SOC_DAIFMT_CBP_CFP: + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBP_CFP; break; default: dev_err(cs43130->dev, "Unsupported DAI format.\n"); From e759aeeb1d09147891e08682df3a70dfbd15724a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:04 +0000 Subject: [PATCH 0414/1090] ASoC: codec: cs53l30: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5dfq3v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs53l30.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 28f4be37dec1..aea4244fb275 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -572,10 +572,10 @@ static int cs53l30_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) u8 aspcfg = 0, aspctl1 = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aspcfg |= CS53L30_ASP_MS; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From b50e5b9694e2a4355f2abeaa711dae5190661c27 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:08 +0000 Subject: [PATCH 0415/1090] ASoC: codec: da7210: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxfq3r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7210.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index da2d0242019e..a889f05119f8 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -882,11 +882,11 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: da7210->master = 1; dai_cfg1 |= DA7210_DAI_MODE_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: da7210->master = 0; dai_cfg1 |= DA7210_DAI_MODE_SLAVE; break; From 7177a7a8e10d7722d0b9d4be4eea7dde014527b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:12 +0000 Subject: [PATCH 0416/1090] ASoC: codec: da7218: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0hfq3n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7218.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 8aacd7350798..5f2f67e3bd29 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -1935,10 +1935,10 @@ static int da7218_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 dai_clk_mode = 0, dai_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: da7218->master = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: da7218->master = false; break; default: From fc0a8ee9921f50ac23b3264846720d1d15be539e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:16 +0000 Subject: [PATCH 0417/1090] ASoC: codec: da7219: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1fq3k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index e2da3e317b5a..3958e88a2445 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1312,10 +1312,10 @@ static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 dai_clk_mode = 0, dai_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: da7219->master = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: da7219->master = false; break; default: From e5f0c2ad987b494ab94bcb1331667d189249f234 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:19 +0000 Subject: [PATCH 0418/1090] ASoC: codec: da732x: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvlfq3g.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index b747f6fa12e4..016c9be3ebda 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1034,11 +1034,11 @@ static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: aif1 = DA732X_AIF_SLAVE; aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif1 = DA732X_AIF_CLK_FROM_SRC; aif_mclk = DA732X_CLK_GENERATION_AIF_A; break; From 6f8ac982806a104e4e816e12279d85440b6f703f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:24 +0000 Subject: [PATCH 0419/1090] ASoC: codec: da9055: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi9ebiw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/da9055.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 8bb8fef2a1d1..eb795abe9acd 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1160,12 +1160,12 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 aif_clk_mode, aif_ctrl, mode; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: /* DA9055 in I2S Master Mode */ mode = 1; aif_clk_mode = DA9055_AIF_CLK_EN_MASTER_MODE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: /* DA9055 in I2S Slave Mode */ mode = 0; aif_clk_mode = DA9055_AIF_CLK_EN_SLAVE_MODE; From 739f4f44dc42b866090297adc1f007ffcdefb602 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:27 +0000 Subject: [PATCH 0420/1090] ASoC: codec: nau8540: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xtebis.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8540.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c index 7e59448e7ac6..caf2edb23088 100644 --- a/sound/soc/codecs/nau8540.c +++ b/sound/soc/codecs/nau8540.c @@ -482,10 +482,10 @@ static int nau8540_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int ctrl1_val = 0, ctrl2_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl2_val |= NAU8540_I2S_MS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From a3c86259f8a402aa050fc5f3039f94c7872e4657 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:31 +0000 Subject: [PATCH 0421/1090] ASoC: codec: nau8810: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmddebio.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8810.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index dc3aaca89919..6f432b992941 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -613,10 +613,10 @@ static int nau8810_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 ctrl1_val = 0, ctrl2_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl2_val |= NAU8810_CLKIO_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 1fca457c22a277ba47ae1bdd2a09d42926a5beed Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:35 +0000 Subject: [PATCH 0422/1090] ASoC: codec: nau8822: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sxebik.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index fd4a96a12060..15d6f8d01f78 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -806,10 +806,10 @@ static int nau8822_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_dbg(component->dev, "%s\n", __func__); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl2_val |= 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: ctrl2_val &= ~1; break; default: From e23d68d7d3b35a44eb83d834b65cd28ca08844ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:39 +0000 Subject: [PATCH 0423/1090] ASoC: codec: nau8824: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8hebig.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8824.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 5aaf8c496300..542bd22e6180 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -1159,10 +1159,10 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int ctrl1_val = 0, ctrl2_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl2_val |= NAU8824_I2S_MS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 2f120ee8026ab9630dc7f93dd4bafdcd56c82056 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:43 +0000 Subject: [PATCH 0424/1090] ASoC: codec: nau8825: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo1ebic.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index bde25bc6909d..25b8b19e27ec 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -1356,10 +1356,10 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) unsigned int ctrl1_val = 0, ctrl2_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl2_val |= NAU8825_I2S_MS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 5f2d29942c82d229dbdafe4bd21585d1b67f31ee Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:46 +0000 Subject: [PATCH 0425/1090] ASoC: codec: rk817: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03lebi9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rk817_codec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 3c5b66357661..3c9957b00881 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -303,10 +303,10 @@ static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int i2s_mst = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: i2s_mst |= RK817_I2S_MODE_SLV; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: i2s_mst |= RK817_I2S_MODE_MST; break; default: From 9c7cf29bdb11cfdd1b59d1ea1eb852245b26e93a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:51 +0000 Subject: [PATCH 0426/1090] ASoC: codec: rt274: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj5ebi4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt274.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index bd61a257d7b5..92ff78aa536b 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -706,12 +706,12 @@ static int rt274_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct rt274_priv *rt274 = snd_soc_component_get_drvdata(component); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: snd_soc_component_update_bits(component, RT274_I2S_CTRL1, RT274_I2S_MODE_MASK, RT274_I2S_MODE_M); rt274->master = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: snd_soc_component_update_bits(component, RT274_I2S_CTRL1, RT274_I2S_MODE_MASK, RT274_I2S_MODE_S); rt274->master = false; From a212edb16ca0698c488c6adfa6854224666c8cc1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:55 +0000 Subject: [PATCH 0427/1090] ASoC: codec: rt286: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6ypebi0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index d0f533120c33..8a4bd8d5ee39 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -765,11 +765,11 @@ static int rt286_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct snd_soc_component *component = dai->component; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: snd_soc_component_update_bits(component, RT286_I2S_CTRL1, 0x800, 0x800); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: snd_soc_component_update_bits(component, RT286_I2S_CTRL1, 0x800, 0x0); break; From 84f32702f3efe02c2622b9151d4e08c436249a8c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:32:59 +0000 Subject: [PATCH 0428/1090] ASoC: codec: rt298: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse9ebhx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt298.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 13aef6c5e91c..b1fb8f365fc2 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -829,11 +829,11 @@ static int rt298_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct snd_soc_component *component = dai->component; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: snd_soc_component_update_bits(component, RT298_I2S_CTRL1, 0x800, 0x800); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: snd_soc_component_update_bits(component, RT298_I2S_CTRL1, 0x800, 0x0); break; From b865e0823cbffb747173b7dd4f4c8d82491d111f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:03 +0000 Subject: [PATCH 0429/1090] ASoC: codec: rt1011: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldttebhs.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index a0e75b03e9dc..93ad078cdd25 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1671,7 +1671,7 @@ static int rt1011_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) snd_soc_dapm_mutex_lock(dapm); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT1011_I2S_TDM_MS_S; break; default: From 2281565db79b5fd6b539e73a28e73fc960ee34d4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:07 +0000 Subject: [PATCH 0430/1090] ASoC: codec: rt1015: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9debho.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 0f806dde9c39..a85dd0bcf438 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -753,10 +753,10 @@ static int rt1015_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, reg_val2 = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: reg_val |= RT1015_TCON_TDM_MS_M; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT1015_TCON_TDM_MS_S; break; default: From f9ef0947ba848467e4dcca6b5ab3a4ff2e218df6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:11 +0000 Subject: [PATCH 0431/1090] ASoC: codec: rt1016: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikoxebhl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1016.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index fed4da23cba2..2f38a35f0768 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -367,11 +367,11 @@ static int rt1016_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: reg_val |= RT1016_I2S_MS_M; rt1016->master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT1016_I2S_MS_S; break; default: From 9261d67d8bd2d9e787ceee8ff593f105bb3f5176 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:15 +0000 Subject: [PATCH 0432/1090] ASoC: codec: rt1305: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64hebhh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index c2b55be8d165..311a974654ff 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -697,11 +697,11 @@ static int rt1305_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, reg1_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: reg_val |= RT1305_SEL_I2S_OUT_MODE_M; rt1305->master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT1305_SEL_I2S_OUT_MODE_S; rt1305->master = 0; break; From 668db717850296122fa0e2aff471cd20a722e0c5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:18 +0000 Subject: [PATCH 0433/1090] ASoC: codec: rt1308: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk1ebhd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index b366338cea71..871391f8ffe1 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -523,7 +523,7 @@ static int rt1308_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, reg1_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: rt1308->master = 0; break; default: From 2d5e9d40998b441485376b8729c69073d8f2ab9d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:23 +0000 Subject: [PATCH 0434/1090] ASoC: codec: rt5616: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczlebh9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5616.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 34461c462009..1ec486707ff9 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1015,10 +1015,10 @@ static int rt5616_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5616->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5616_I2S_MS_S; rt5616->master[dai->id] = 0; break; From 1b16920e651d11811ca4b3a5d92cfb3d817b1a14 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:26 +0000 Subject: [PATCH 0435/1090] ASoC: codec: rt5631: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5ebh5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 12df0c4f2097..d523477c5102 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1411,10 +1411,10 @@ static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, dev_dbg(component->dev, "enter %s\n", __func__); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5631->master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: iface |= RT5631_SDP_MODE_SEL_SLAVE; rt5631->master = 0; break; From 60143172c63daa49fef6eb9daa066fb7f1360bbe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:30 +0000 Subject: [PATCH 0436/1090] ASoC: codec: rt5640: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjupebh1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 855139348edb..bf5dfcdd36d9 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1773,10 +1773,10 @@ static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) int dai_sel; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5640->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5640_I2S_MS_S; rt5640->master[dai->id] = 0; break; From 3165df2f130d567e6cf05d789ecc28810519e5f7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:34 +0000 Subject: [PATCH 0437/1090] ASoC: codec: rt5645: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9ebgx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 51187b1e0ed2..2d4ad416c186 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2841,10 +2841,10 @@ static int rt5645_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5645->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5645_I2S_MS_S; rt5645->master[dai->id] = 0; break; From e41ebb0a1f8bff63c8e333eec34ff64e748227d0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:38 +0000 Subject: [PATCH 0438/1090] ASoC: codec: rt5651: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qptebgt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 00421a1f54bf..7be9f9f0f34f 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1352,10 +1352,10 @@ static int rt5651_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5651->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5651_I2S_MS_S; rt5651->master[dai->id] = 0; break; From f1205656ef2334e860ced588e76dd88119394166 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:41 +0000 Subject: [PATCH 0439/1090] ASoC: codec: rt5659: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5debgq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index a2652fa6e1d7..1083e7bffcfa 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3363,10 +3363,10 @@ static int rt5659_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5659->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5659_I2S_MS_S; rt5659->master[dai->id] = 0; break; From 67f2243f2b1f1936c4dc22897289f5815a0e224a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:45 +0000 Subject: [PATCH 0440/1090] ASoC: codec: rt5660: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxebgm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5660.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 3ac41d2c279b..e335fec9fc56 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -905,11 +905,11 @@ static int rt5660_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5660->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5660_I2S_MS_S; rt5660->master[dai->id] = 0; break; From 0ad3a7d311f0e93f2e838b4e47a7da57c501d737 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:49 +0000 Subject: [PATCH 0441/1090] ASoC: codec: rt5663: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0hebgj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 9d32debd3689..b86bc0285266 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -2814,9 +2814,9 @@ static int rt5663_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5663_I2S_MS_S; break; default: From 0b74ed5533c87db1abe3967e3a370bc3046892c7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:52 +0000 Subject: [PATCH 0442/1090] ASoC: codec: rt5665: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1ebgf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 47df14ba5278..7c5a03b0e918 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4219,10 +4219,10 @@ static int rt5665_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5665->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5665_I2S_MS_S; rt5665->master[dai->id] = 0; break; From 4869417f4a2b010e9ee00f611265f551a47e4f1a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:56 +0000 Subject: [PATCH 0443/1090] ASoC: codec: rt5668: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvlebgc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5668.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 494ca3ce9b96..dbb5912e5e2c 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -2010,10 +2010,10 @@ static int rt5668_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, tdm_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5668->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: rt5668->master[dai->id] = 0; break; default: From b3a3eda6cb30f21b818f40795468ff0a9f629990 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:33:59 +0000 Subject: [PATCH 0444/1090] ASoC: codec: rt5670: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi9cwvs.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 30bf96c35b58..4129071f6b83 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2439,10 +2439,10 @@ static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5670->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5670_I2S_MS_S; rt5670->master[dai->id] = 0; break; From 40213f8d5b498f5eb2f3297ee0f9c84d98737ee9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:03 +0000 Subject: [PATCH 0445/1090] ASoC: codec: rt5677: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xtcwvp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 0e70a3ab42b5..753dc3c85630 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4377,10 +4377,10 @@ static int rt5677_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5677->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg_val |= RT5677_I2S_MS_S; rt5677->master[dai->id] = 0; break; From f61c11db0f598eed6dd35a2d700ca54c6c74af4a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:06 +0000 Subject: [PATCH 0446/1090] ASoC: codec: rt5682: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmddcwvl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index b4d72fc4a44d..7c88370e2dee 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2225,10 +2225,10 @@ static int rt5682_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, tdm_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5682->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: rt5682->master[dai->id] = 0; break; default: From bd178280c7d967e87e217b51c0647a2bfdf5deec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:10 +0000 Subject: [PATCH 0447/1090] ASoC: codec: rt5682s: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sxcwvh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index ce2e88e066f3..73c4b3c31f8c 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -2132,10 +2132,10 @@ static int rt5682s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int reg_val = 0, tdm_ctrl = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: rt5682s->master[dai->id] = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: rt5682s->master[dai->id] = 0; break; default: From 461deb4911f39e455756cbc42928b12b04e82851 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:14 +0000 Subject: [PATCH 0448/1090] ASoC: codec: wm2200: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8hcwvd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 841247173d98..7ed4ac5cce3c 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1576,15 +1576,15 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk |= WM2200_AIF1TX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= WM2200_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: lrclk |= WM2200_AIF1TX_LRCLK_MSTR; bclk |= WM2200_AIF1_BCLK_MSTR; break; From 4042bb6e973aded1de6ce83436804a90181d6357 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:17 +0000 Subject: [PATCH 0449/1090] ASoC: codec: wm5100: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo1cwva.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 11bbc94a282c..dfeec55159a6 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1303,15 +1303,15 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk |= WM5100_AIF1TX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= WM5100_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: lrclk |= WM5100_AIF1TX_LRCLK_MSTR; bclk |= WM5100_AIF1_BCLK_MSTR; break; From 474cd6355413b264087ddc66b1dbc6c7e59fb76f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:21 +0000 Subject: [PATCH 0450/1090] ASoC: codec: wm8350: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03lcwv6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8350.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 66bd281095e1..b1fe6f4e0c10 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -846,12 +846,12 @@ static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master |= WM8350_BCLK_MSTR; dac_lrc |= WM8350_DACLRC_ENA; adc_lrc |= WM8350_ADCLRC_ENA; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 24684cc2060150afd7a1ea47c586f9c09330633c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:24 +0000 Subject: [PATCH 0451/1090] ASoC: codec: wm8400: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj5cwv3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8400.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 19ce839f6ef7..5ad6d5b63ffc 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -986,10 +986,10 @@ static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: audio3 &= ~WM8400_AIF_MSTR1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: audio3 |= WM8400_AIF_MSTR1; break; default: From 420663ae8fa2d70d2b824848763ca15bb5b2b585 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:28 +0000 Subject: [PATCH 0452/1090] ASoC: codec: wm8510: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6ypcwv0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8510.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 4a31d6f89502..79adbcc90d4a 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -389,10 +389,10 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: clk |= 0x0001; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From e2bcc61a4481c3de4747014895cef45d701956bf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:31 +0000 Subject: [PATCH 0453/1090] ASoC: codec: wm8523: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse9cwuw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 138eba7e577a..6671e13c320c 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -264,10 +264,10 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aifctrl1 |= WM8523_AIF_MSTR; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From dee14c5b6d29886255c4a54599590d49fc1754be Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:35 +0000 Subject: [PATCH 0454/1090] ASoC: codec: wm8524: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldttcwut.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index fa9942a08927..403e513f3fa8 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -139,7 +139,7 @@ static int wm8524_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) SND_SOC_DAIFMT_MASTER_MASK); if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS)) { + SND_SOC_DAIFMT_CBC_CFC)) { dev_err(codec_dai->dev, "Invalid DAI format\n"); return -EINVAL; } From 1b94f3874d61b34febd5ddf3482a90107dc80082 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:38 +0000 Subject: [PATCH 0455/1090] ASoC: codec: wm8580: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9dcwup.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8580.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 73a8edc797fb..ba4a08456e78 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -614,10 +614,10 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: aifa &= ~WM8580_AIF_MS; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aifa |= WM8580_AIF_MS; break; default: From 042ecb2ab2361f77b34a7d3c642bd378f6ecc73a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:41 +0000 Subject: [PATCH 0456/1090] ASoC: codec: wm8711: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikoxcwum.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8711.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index a1c99bbf5aa1..481088987742 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -243,10 +243,10 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface |= 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 4d20a35acef6fb8c42eff953a11759e94710ba8b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:45 +0000 Subject: [PATCH 0457/1090] ASoC: codec: wm8728: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64hcwui.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8728.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 2cbd6b189416..ea0a588da40f 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -128,7 +128,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, /* The hardware only support full slave mode */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From bb0b8a07192d86b291c5b13fb64ef984930f8ea6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:49 +0000 Subject: [PATCH 0458/1090] ASoC: codec: wm8737: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk1cwuf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index efdc242c2ede..f7e48f27649d 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -404,10 +404,10 @@ static int wm8737_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 af = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: af |= WM8737_MS; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From a018b6601c47e7d989f1fe5c175325f85dceb264 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:53 +0000 Subject: [PATCH 0459/1090] ASoC: codec: wm8741: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczlcwub.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 4863d6ac461b..4dfbb33edb09 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -308,7 +308,7 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, /* check master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 4be54b6bdafad7656fd85c1fa6b7bebb7700a3d2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:56 +0000 Subject: [PATCH 0460/1090] ASoC: codec: wm8750: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5cwu7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8750.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index cae97fa3bcb0..312be0721b5d 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -522,10 +522,10 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface = 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 92acd9f7409d2939e5fef8bde5ad527b9e525229 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:34:59 +0000 Subject: [PATCH 0461/1090] ASoC: codec: wm8753: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjupcwu4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8753.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 38b76b7275e5..43cc368cf3f3 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -963,12 +963,12 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_component *component, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ioctl |= 0x2; fallthrough; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: voice |= 0x0040; break; default: @@ -1089,12 +1089,12 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_component *component, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ioctl |= 0x1; fallthrough; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: hifi |= 0x0040; break; default: From d17b39f6d3e635b039314726fbc66dcef286ed79 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:03 +0000 Subject: [PATCH 0462/1090] ASoC: codec: wm8770: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9cwu0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8770.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 38376b605201..5685c3bb5555 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -349,10 +349,10 @@ static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) component = dai->component; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master = 0x100; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: master = 0; break; default: From 9b9cbc6b4fa312d963f4373e88b6e27106f2051a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:06 +0000 Subject: [PATCH 0463/1090] ASoC: codec: wm8776: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qptcwtx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8776.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 166e00fcd11d..7b73c825aed4 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -182,9 +182,9 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) iface = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: master = 0; break; default: From ad3993c449637fcec1e05bd2b63c24d34cb82243 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:10 +0000 Subject: [PATCH 0464/1090] ASoC: codec: wm8804: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5dcwtu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8804.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index cfa78e4d8b73..0a879c29eb04 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -243,10 +243,10 @@ static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) snd_soc_component_update_bits(component, WM8804_AIFRX, 0x3, format); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: master = 0; break; default: From 2f8b07842e9e95122b848727ea73504a035e7c12 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:14 +0000 Subject: [PATCH 0465/1090] ASoC: codec: wm8900: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxcwtp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8900.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index e44fdf97796f..6fb25588ca81 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -867,22 +867,22 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; From 1a126668ab0946ebb7d1450742cd14775aa298fa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:18 +0000 Subject: [PATCH 0466/1090] ASoC: codec: wm8903: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0hcwtl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index c643b5377d3a..03902909f27e 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1229,15 +1229,15 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: aif1 |= WM8903_LRCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif1 |= WM8903_LRCLK_DIR | WM8903_BCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aif1 |= WM8903_BCLK_DIR; break; default: From 25baeacd9c6307830e2ed9f586f81fc23d4d1002 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:21 +0000 Subject: [PATCH 0467/1090] ASoC: codec: wm8904: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1cwti.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index aef82532f8cf..207d3bd2e729 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1424,15 +1424,15 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int aif3 = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: aif3 |= WM8904_LRCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aif1 |= WM8904_BCLK_DIR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif1 |= WM8904_BCLK_DIR; aif3 |= WM8904_LRCLK_DIR; break; From 2d2223d742d968fec77ed056db9f158e7cb3ca94 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:25 +0000 Subject: [PATCH 0468/1090] ASoC: codec: wm8940: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvlcwte.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8940.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 8a532f7d750c..401ee20897b1 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -343,10 +343,10 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clk = snd_soc_component_read(component, WM8940_CLOCK) & 0x1fe; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: clk |= 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From fb44bd4902cd5df526ad432015edcfaf163999e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:28 +0000 Subject: [PATCH 0469/1090] ASoC: codec: wm8955: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi9bi8v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index bae52a8a2e11..bca83410b432 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -671,9 +671,9 @@ static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) u16 aif = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif |= WM8955_MS; break; default: From 541e0b4947a92f4bf1d60ef7e55f0a254d9c41a0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:32 +0000 Subject: [PATCH 0470/1090] ASoC: codec: wm8960: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xtbi8r.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 00858b9c9568..e6525b4cedfb 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -540,10 +540,10 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface |= 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From b99c850bd41e8f6f142bb24c3c2485043b552621 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:36 +0000 Subject: [PATCH 0471/1090] ASoC: codec: wm8961: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmddbi8o.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index d1c731e25777..1ec7c5e8fd69 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -627,10 +627,10 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM8961_MS | WM8961_FORMAT_MASK); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif |= WM8961_MS; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From c6472392301fc15a09d5435f1f89421270aed81c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:41 +0000 Subject: [PATCH 0472/1090] ASoC: codec: wm8962: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sxbi8j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 08d164ce3e49..0aaac24eeb5a 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2762,10 +2762,10 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif0 |= WM8962_MSTR; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From ed86f7b7e5f676c24ba0ddd86de6614a4b69a9e4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:44 +0000 Subject: [PATCH 0473/1090] ASoC: codec: wm8971: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8hbi8f.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8971.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index b97c7d5bd4e7..62dcddeb78b3 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -452,10 +452,10 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface = 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From 68084db5e7a5eb1e4901e2158565cfc59873756d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:48 +0000 Subject: [PATCH 0474/1090] ASoC: codec: wm8974: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo1bi8b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 0ee3655cad01..bdf437a5403f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -454,10 +454,10 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: clk |= 0x0001; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From f0bd6cb02505eca6adbe2e3ad3445a2420637c19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:51 +0000 Subject: [PATCH 0475/1090] ASoC: codec: wm8978: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03lbi88.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 40d22b36b7a9..8c45ba6fc4c3 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -660,10 +660,10 @@ static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: clk |= 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: clk &= ~1; break; default: From 93b1fefd8b1a004c6c8f8c92085e7bfb694dfe98 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:54 +0000 Subject: [PATCH 0476/1090] ASoC: codec: wm8983: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj5bi85.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 252b4a6cac04..6a83afe6400b 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -594,10 +594,10 @@ static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM8983_FMT_MASK, format << WM8983_FMT_SHIFT); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: master = 0; break; default: From 7f3ed7ea52f21d5b8ecc01a17fb8f7209d337cbe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:35:58 +0000 Subject: [PATCH 0477/1090] ASoC: codec: wm8985: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6ypbi82.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8985.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index da00db5b0172..2e2d07193c41 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -688,10 +688,10 @@ static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM8985_FMT_MASK, format << WM8985_FMT_SHIFT); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: master = 0; break; default: From 2725c018785d52286dd5b4ff7e087d2ff455a1a8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:01 +0000 Subject: [PATCH 0478/1090] ASoC: codec: wm8988: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse9bi7y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8988.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index f0e9d6e38dc0..cf6d642b7bfe 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -589,10 +589,10 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: iface = 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; From d542f5bfa3e4e16aac6141abdd44bb8a2a6f0761 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:04 +0000 Subject: [PATCH 0479/1090] ASoC: codec: wm8990: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldttbi7v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 573bd3d487ba..89df406bf552 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -897,10 +897,10 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: audio3 &= ~WM8990_AIF_MSTR1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: audio3 |= WM8990_AIF_MSTR1; break; default: From 0d4291fa3a8945d97d26a6bac8a4068f116f2885 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:08 +0000 Subject: [PATCH 0480/1090] ASoC: codec: wm8991: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9dbi7s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 3bd9b362051b..c3dd44c1dd0c 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -958,10 +958,10 @@ static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: audio3 &= ~WM8991_AIF_MSTR1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: audio3 |= WM8991_AIF_MSTR1; break; default: From 291b4eb984792fcc0bd3dec9ad9a69c3c6988951 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:11 +0000 Subject: [PATCH 0481/1090] ASoC: codec: wm8993: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikoxbi7o.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8993.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index f257980f9b56..9be4f6cadba3 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1098,18 +1098,18 @@ static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, aif4 &= ~WM8993_LRCLK_DIR; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: wm8993->master = 0; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: aif4 |= WM8993_LRCLK_DIR; wm8993->master = 1; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aif1 |= WM8993_BCLK_DIR; wm8993->master = 1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif1 |= WM8993_BCLK_DIR; aif4 |= WM8993_LRCLK_DIR; wm8993->master = 1; From 35492f84fbd6d790ad7f93bffaaa6823890c103a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:15 +0000 Subject: [PATCH 0482/1090] ASoC: codec: wm8994: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64hbi7l.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a4abe6e53bfc..69a22992c281 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2783,9 +2783,9 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ms = WM8994_AIF1_MSTR; break; default: From c417a7cf976eb8ecd8ebca439ec0cb0fe9ddc7ec Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:18 +0000 Subject: [PATCH 0483/1090] ASoC: codec: wm8995: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk1bi7h.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 1f9a9b636935..a88170a3ed91 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -1448,9 +1448,9 @@ static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) master = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: master = WM8995_AIF1_MSTR; break; default: From cc49a35ab19565c5eaef070755b6fba235f9d05a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:22 +0000 Subject: [PATCH 0484/1090] ASoC: codec: wm8996: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczlbi7e.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 5c06cea09bd1..c2af8d7ecdd8 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1672,16 +1672,16 @@ static int wm8996_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR; lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= WM8996_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: bclk |= WM8996_AIF1_BCLK_MSTR; lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR; lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR; From cfb91be8f9c8e54e517a9a539012309101abcac5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:26 +0000 Subject: [PATCH 0485/1090] ASoC: codec: wm9081: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5bi7a.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index cb9d040b34d6..94d8571360c4 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -907,18 +907,18 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: wm9081->master = 0; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: aif2 |= WM9081_LRCLK_DIR; wm9081->master = 1; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aif2 |= WM9081_BCLK_DIR; wm9081->master = 1; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR; wm9081->master = 1; break; From 9c914ef3b876a6f6c0059b4f4323fc1b76fa05e4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:29 +0000 Subject: [PATCH 0486/1090] ASoC: codec: wm9713: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjupbi76.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm9713.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 64b69316e4c7..5b0fa1b20d76 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -944,19 +944,19 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai, /* clock masters */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: reg |= 0x4000; gpio |= 0x0010; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: reg |= 0x6000; gpio |= 0x0018; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg |= 0x2000; gpio |= 0x001a; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: gpio |= 0x0012; break; } From 74da545ec6a8b41de96b4c350bb59dfe45c0d822 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:32 +0000 Subject: [PATCH 0487/1090] ASoC: codec: madera: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9bi73.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/madera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index a840a2eb92b9..b0b5973509e4 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -2776,7 +2776,7 @@ static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_DAIFMT_DSP_B: if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != - SND_SOC_DAIFMT_CBM_CFM) { + SND_SOC_DAIFMT_CBP_CFP) { madera_aif_err(dai, "DSP_B not valid in slave mode\n"); return -EINVAL; } @@ -2787,7 +2787,7 @@ static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_DAIFMT_LEFT_J: if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != - SND_SOC_DAIFMT_CBM_CFM) { + SND_SOC_DAIFMT_CBP_CFP) { madera_aif_err(dai, "LEFT_J not valid in slave mode\n"); return -EINVAL; } @@ -2800,15 +2800,15 @@ static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk |= MADERA_AIF1TX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= MADERA_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: bclk |= MADERA_AIF1_BCLK_MSTR; lrclk |= MADERA_AIF1TX_LRCLK_MSTR; break; From 1af0148c3f871e55a6c4adf544af77a19fd17671 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:36 +0000 Subject: [PATCH 0488/1090] ASoC: codec: arizona: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qptbi6z.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 402b9a2ff024..6bb1e8698d41 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1457,7 +1457,7 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_DAIFMT_DSP_B: if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) - != SND_SOC_DAIFMT_CBM_CFM) { + != SND_SOC_DAIFMT_CBP_CFP) { arizona_aif_err(dai, "DSP_B not valid in slave mode\n"); return -EINVAL; } @@ -1468,7 +1468,7 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; case SND_SOC_DAIFMT_LEFT_J: if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) - != SND_SOC_DAIFMT_CBM_CFM) { + != SND_SOC_DAIFMT_CBP_CFP) { arizona_aif_err(dai, "LEFT_J not valid in slave mode\n"); return -EINVAL; } @@ -1481,15 +1481,15 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: bclk |= ARIZONA_AIF1_BCLK_MSTR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: bclk |= ARIZONA_AIF1_BCLK_MSTR; lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR; break; From c80956630fa077646f971ff5d3e9452339742def Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:40 +0000 Subject: [PATCH 0489/1090] ASoC: codec: twl4030: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5dbi6v.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index e3782762139f..609886461805 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -2049,7 +2049,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_CBP_CFP: format &= ~(TWL4030_VIF_SLAVE_EN); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: format |= TWL4030_VIF_SLAVE_EN; break; default: From 27f5e88fdc8ab577dbff389085ae6ad41e994ae7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:43 +0000 Subject: [PATCH 0490/1090] ASoC: codec: src4xxx: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxbi6s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/src4xxx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/src4xxx.c b/sound/soc/codecs/src4xxx.c index db4e280dd055..5a3489475225 100644 --- a/sound/soc/codecs/src4xxx.c +++ b/sound/soc/codecs/src4xxx.c @@ -158,11 +158,11 @@ static int src4xxx_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int ctrl; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: ctrl = SRC4XXX_BUS_MASTER; src4xxx->master[dai->id] = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: ctrl = 0; src4xxx->master[dai->id] = false; break; From 6575dd53217ee5686d48a35f48415b113518d2a9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:48 +0000 Subject: [PATCH 0491/1090] ASoC: codec: sgtl5000: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0hbi6n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 7aa89e34657e..2cc8efe3d896 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -806,9 +806,9 @@ static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) * - clock and frame master */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: i2sctl |= SGTL5000_I2S_MASTER; sgtl5000->master = 1; break; From 6dd61011a67e35b8d5f3b94193ed66d0c19ba425 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:51 +0000 Subject: [PATCH 0492/1090] ASoC: codec: lochnagar-sc: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1bi6k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/lochnagar-sc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/lochnagar-sc.c b/sound/soc/codecs/lochnagar-sc.c index 5e0bd0d24ed3..a3d6318c9050 100644 --- a/sound/soc/codecs/lochnagar-sc.c +++ b/sound/soc/codecs/lochnagar-sc.c @@ -129,12 +129,12 @@ static int lochnagar_sc_check_fmt(struct snd_soc_dai *dai, unsigned int fmt, static int lochnagar_sc_set_line_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBS_CFS); + return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBC_CFC); } static int lochnagar_sc_set_usb_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBM_CFM); + return lochnagar_sc_check_fmt(dai, fmt, SND_SOC_DAIFMT_CBP_CFP); } static const struct snd_soc_dai_ops lochnagar_sc_line_ops = { From 521c04c6e32ac110d942fa0e11bea4b91cc3241d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:55 +0000 Subject: [PATCH 0493/1090] ASoC: ux500: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvlbi6h.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/ux500/mop500_ab8500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 710b6744e013..5246f73ef12e 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c @@ -275,12 +275,12 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, if (driver_mode == DRIVERMODE_NORMAL) { fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_CBM_CFM | + SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CONT; } else { fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_CBM_CFM | + SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_GATED; } From 6cc4d2c11537d66e9d4a7356a576f1bea6f4009f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:36:58 +0000 Subject: [PATCH 0494/1090] ASoC: meson: t9015: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi9a3lx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/t9015.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c index 571f65788c59..a80e9c9d6288 100644 --- a/sound/soc/meson/t9015.c +++ b/sound/soc/meson/t9015.c @@ -57,11 +57,11 @@ static int t9015_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int val; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: val = I2S_MODE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: val = 0; break; From 4586b056956995754e95456312b2a9ce36c8de21 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:02 +0000 Subject: [PATCH 0495/1090] ASoC: meson: meson-card-utils: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xta3lt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/meson/meson-card-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index 1a4ef124e4e2..cfc7f6e41ab5 100644 --- a/sound/soc/meson/meson-card-utils.c +++ b/sound/soc/meson/meson-card-utils.c @@ -119,10 +119,10 @@ unsigned int meson_card_parse_daifmt(struct device_node *node, /* If no master is provided, default to cpu master */ if (!bitclkmaster || bitclkmaster == cpu_node) { daifmt |= (!framemaster || framemaster == cpu_node) ? - SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM; + SND_SOC_DAIFMT_CBC_CFC : SND_SOC_DAIFMT_CBC_CFP; } else { daifmt |= (!framemaster || framemaster == cpu_node) ? - SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM; + SND_SOC_DAIFMT_CBP_CFC : SND_SOC_DAIFMT_CBP_CFP; } of_node_put(bitclkmaster); From 04ea3e0d2e10642f0a0199081e9aa8fd5e1bbea6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:06 +0000 Subject: [PATCH 0496/1090] ASoC: tegra: tegra_asoc_machine: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmdda3lp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 775ce433fdbf..62f896772731 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -637,7 +637,7 @@ static struct snd_soc_dai_link tegra_wm8753_dai = { .stream_name = "WM8753 PCM", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(wm8753_hifi), }; @@ -701,7 +701,7 @@ static struct snd_soc_dai_link tegra_max98090_dai = { .init = tegra_asoc_machine_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(max98090_hifi), }; @@ -736,7 +736,7 @@ static struct snd_soc_dai_link tegra_max98088_dai = { .init = tegra_asoc_machine_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(max98088_hifi), }; @@ -769,7 +769,7 @@ static struct snd_soc_dai_link tegra_sgtl5000_dai = { .stream_name = "HiFi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(sgtl5000_hifi), }; @@ -812,7 +812,7 @@ static struct snd_soc_dai_link tegra_tlv320aic23_dai = { .stream_name = "AIC23", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(tlv320aic23_hifi), }; @@ -861,7 +861,7 @@ static struct snd_soc_dai_link tegra_rt5677_dai = { .init = tegra_rt5677_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(rt5677_aif1), }; @@ -895,7 +895,7 @@ static struct snd_soc_dai_link tegra_rt5640_dai = { .init = tegra_asoc_machine_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(rt5640_aif1), }; @@ -928,7 +928,7 @@ static struct snd_soc_dai_link tegra_rt5632_dai = { .init = tegra_rt5677_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(rt5632_hifi), }; @@ -961,7 +961,7 @@ static struct snd_soc_dai_link tegra_rt5631_dai = { .init = tegra_asoc_machine_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(rt5631_hifi), }; From b15ea10972a1b4db23f7495003fccc6fe59e44bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:09 +0000 Subject: [PATCH 0497/1090] ASoC: tegra: tegra_wm8903: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sxa3lm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_wm8903.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 6116d2e30fca..78b02c64d95c 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -124,7 +124,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { .init = tegra_wm8903_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(hifi), }; From 836d2924c05edb06e32eeede8bc12c4c96da0b3d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:13 +0000 Subject: [PATCH 0498/1090] ASoC: intel: rt274: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8ha3li.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt274.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index f5caafc21861..29977aee2153 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -179,7 +179,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_rt274_codec_init; dl->exit = avs_rt274_codec_exit; dl->be_hw_params_fixup = avs_rt274_be_fixup; From ccf2a77a5d1504ca95c1ae5f37ed184e62dcd2f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:16 +0000 Subject: [PATCH 0499/1090] ASoC: intel: rt286: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo1a3lf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt286.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index 1eb0399c0fae..6a27c6a9f394 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -147,7 +147,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_rt286_codec_init; dl->exit = avs_rt286_codec_exit; dl->be_hw_params_fixup = avs_rt286_be_fixup; From f5617b647c8597e2437b3899f520fdf65e0f277a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:20 +0000 Subject: [PATCH 0500/1090] ASoC: intel: rt298: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03la3lb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt298.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 85269a3be981..a7a463d6f852 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -165,9 +165,9 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->num_platforms = 1; dl->id = 0; if (dmi_first_match(kblr_dmi_table)) - dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; else - dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_rt298_codec_init; dl->exit = avs_rt298_codec_exit; dl->be_hw_params_fixup = avs_rt298_be_fixup; From 6d41096d7df609992479d6a3a43bc60e21b8e165 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:27 +0000 Subject: [PATCH 0501/1090] ASoC: intel: rt5514: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj5a3l4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt5514.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c index 30588d9e9ba3..d1c3e29a28ff 100644 --- a/sound/soc/intel/avs/boards/rt5514.c +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -116,7 +116,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_rt5514_codec_init; dl->be_hw_params_fixup = avs_rt5514_be_fixup; dl->nonatomic = 1; From e15abfa60107f97fd8297faad8cc3dc4eae0b5cc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:31 +0000 Subject: [PATCH 0502/1090] ASoC: intel: da7219: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6ypa3l1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/da7219.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index 9507a96f26ac..7217ae51e89c 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -198,7 +198,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->be_hw_params_fixup = avs_da7219_be_fixup; dl->init = avs_da7219_codec_init; dl->exit = avs_da7219_codec_exit; From 0808c1ab8d1a1222194d830870f6b2b47220b1d7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:35 +0000 Subject: [PATCH 0503/1090] ASoC: intel: ssm4567: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse9a3kx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/ssm4567.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index cfef00462f66..c9d89bfe7178 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -116,7 +116,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_ssm4567_codec_init; dl->be_hw_params_fixup = avs_ssm4567_be_fixup; dl->nonatomic = 1; From 4994da5c7fea1ede9b71ae66e3b906ea56b9a929 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:38 +0000 Subject: [PATCH 0504/1090] ASoC: intel: nau8825: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldtta3kt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 6833eebd82d6..e203ceb83b87 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -204,7 +204,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->init = avs_nau8825_codec_init; dl->exit = avs_nau8825_codec_exit; dl->be_hw_params_fixup = avs_nau8825_be_fixup; From bcb896a69864aec4dd0251732a380bcdbeff8c51 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:42 +0000 Subject: [PATCH 0505/1090] ASoC: intel: max98927: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9da3kq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/max98927.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index ad18c4e9a670..e8e5d1c717cd 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -127,7 +127,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->be_hw_params_fixup = avs_max98927_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; From d2f277bf8aaed8c5307ab998b2de4346bed6e884 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:46 +0000 Subject: [PATCH 0506/1090] ASoC: intel: max98357a: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikoxa3km.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/max98357a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index 6570209c1a63..c55c1d60b777 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -78,7 +78,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->platforms = platform; dl->num_platforms = 1; dl->id = 0; - dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; dl->be_hw_params_fixup = avs_max98357a_be_fixup; dl->nonatomic = 1; dl->no_pcm = 1; From 69e35d9bfd6ba2837fe18bebf97ea747ceb110d5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:49 +0000 Subject: [PATCH 0507/1090] ASoC: samsung: snow: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64ha3ki.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 4bbe7bcdb845..66ef49dff1ba 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -137,7 +137,7 @@ static int snow_probe(struct platform_device *pdev) link = &priv->dai_link; link->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; + SND_SOC_DAIFMT_CBC_CFC; link->name = "Primary"; link->stream_name = link->name; From 5dc6b4a351de9804932c4475a2c73c22c0b59369 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:52 +0000 Subject: [PATCH 0508/1090] ASoC: samsung: bells: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk1a3kf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/bells.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 365b1aca4855..ba9b0b1fba03 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -256,14 +256,14 @@ static struct snd_soc_dai_link bells_dai_wm2200[] = { .name = "CPU-DSP", .stream_name = "CPU-DSP", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(wm2200_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .c2c_params = &sub_params, .num_c2c_params = 1, .ignore_suspend = 1, @@ -293,14 +293,14 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .name = "CPU-DSP", .stream_name = "CPU-DSP", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(wm5102_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .c2c_params = &sub_params, .num_c2c_params = 1, .ignore_suspend = 1, @@ -310,7 +310,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .name = "Baseband", .stream_name = "Baseband", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &baseband_params, .num_c2c_params = 1, @@ -320,7 +320,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = { .name = "Sub", .stream_name = "Sub", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, + | SND_SOC_DAIFMT_CBC_CFC, .ignore_suspend = 1, .c2c_params = &sub_params, .num_c2c_params = 1, @@ -351,14 +351,14 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .name = "CPU-DSP", .stream_name = "CPU-DSP", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(wm5110_cpu_dsp), }, { .name = "DSP-CODEC", .stream_name = "DSP-CODEC", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .c2c_params = &sub_params, .num_c2c_params = 1, .ignore_suspend = 1, @@ -368,7 +368,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .name = "Baseband", .stream_name = "Baseband", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &baseband_params, .num_c2c_params = 1, @@ -378,7 +378,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { .name = "Sub", .stream_name = "Sub", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, + | SND_SOC_DAIFMT_CBC_CFC, .ignore_suspend = 1, .c2c_params = &sub_params, .num_c2c_params = 1, From 06d07a4f5b98c71c696fa8f8718050b656ab99ba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:37:57 +0000 Subject: [PATCH 0509/1090] ASoC: samsung: odroid: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczla3ka.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/odroid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index 40ac12c07145..ab3398f39f4a 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -180,7 +180,7 @@ static struct snd_soc_dai_link odroid_card_dais[] = { .no_pcm = 1, .playback_only = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(mixer), }, { /* Secondary FE <-> BE link */ From 3f97e52562dd1ad041f63c910a746eab695f40c1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:00 +0000 Subject: [PATCH 0510/1090] ASoC: samsung: arndale: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf5a3k7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/arndale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index 9619f550608c..172943bb3b24 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -95,7 +95,7 @@ static struct snd_soc_dai_link arndale_rt5631_dai[] = { .stream_name = "Primary", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBS_CFS, + | SND_SOC_DAIFMT_CBC_CFC, .ops = &arndale_rt5631_ops, SND_SOC_DAILINK_REG(rt5631_hifi), }, @@ -112,7 +112,7 @@ static struct snd_soc_dai_link arndale_wm1811_dai[] = { .stream_name = "Primary", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ops = &arndale_wm1811_ops, SND_SOC_DAILINK_REG(wm1811_hifi), }, From 9ef6a439bc987753b7e5af5a926f05debe82bd1c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:04 +0000 Subject: [PATCH 0511/1090] ASoC: samsung: lowland: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjupa3k3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/lowland.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 702cb4cc1ce9..2cb19f4b9dad 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -105,7 +105,7 @@ static struct snd_soc_dai_link lowland_dai[] = { .name = "CPU", .stream_name = "CPU", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .init = lowland_wm5100_init, SND_SOC_DAILINK_REG(cpu), }, @@ -113,7 +113,7 @@ static struct snd_soc_dai_link lowland_dai[] = { .name = "Baseband", .stream_name = "Baseband", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, SND_SOC_DAILINK_REG(baseband), }, @@ -121,7 +121,7 @@ static struct snd_soc_dai_link lowland_dai[] = { .name = "Sub Speaker", .stream_name = "Sub Speaker", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &sub_params, .num_c2c_params = 1, From 3d5f026256d985e8b81e7657a5430a9ff14e651c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:07 +0000 Subject: [PATCH 0512/1090] ASoC: samsung: speyside: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a9a3k0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 79476e8eb680..64d3e4ea66b0 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -210,7 +210,7 @@ static struct snd_soc_dai_link speyside_dai[] = { .stream_name = "CPU-DSP", .init = speyside_wm0010_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(cpu_dsp), }, { @@ -218,7 +218,7 @@ static struct snd_soc_dai_link speyside_dai[] = { .stream_name = "DSP-CODEC", .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .c2c_params = &dsp_codec_params, .num_c2c_params = 1, .ignore_suspend = 1, @@ -228,7 +228,7 @@ static struct snd_soc_dai_link speyside_dai[] = { .name = "Baseband", .stream_name = "Baseband", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, SND_SOC_DAILINK_REG(baseband), }, From 29664312a75e47f989ad32e43682746d8681a02b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:11 +0000 Subject: [PATCH 0513/1090] ASoC: samsung: tobermory: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qpta3jx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/tobermory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index 2bdd81bf821a..39a8c129dfdb 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -119,7 +119,7 @@ static struct snd_soc_dai_link tobermory_dai[] = { .name = "CPU", .stream_name = "CPU", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ops = &tobermory_ops, SND_SOC_DAILINK_REG(cpu), }, From 1455b3857ca2d05966005f7172210f6bd00048c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:14 +0000 Subject: [PATCH 0514/1090] ASoC: samsung: tm2_wm5110: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5da3jt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 2417b91a328f..db853833f0d4 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -451,21 +451,21 @@ static struct snd_soc_dai_link tm2_dai_links[] = { .stream_name = "HiFi Primary", .ops = &tm2_aif1_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(aif1), }, { .name = "WM5110 Voice", .stream_name = "Voice call", .ops = &tm2_aif2_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, SND_SOC_DAILINK_REG(voice), }, { .name = "WM5110 BT", .stream_name = "Bluetooth", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, SND_SOC_DAILINK_REG(bt), }, { @@ -473,7 +473,7 @@ static struct snd_soc_dai_link tm2_dai_links[] = { .stream_name = "i2s1", .ops = &tm2_hdmi_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(hdmi), } }; From 2c4a2b5d084b06e1a9fd2e85866b51f6118dd254 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:18 +0000 Subject: [PATCH 0515/1090] ASoC: samsung: littlemill: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkxa3jq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/littlemill.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index c5260e101c2a..b32ce027be8e 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -157,7 +157,7 @@ static struct snd_soc_dai_link littlemill_dai[] = { .name = "CPU", .stream_name = "CPU", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ops = &littlemill_ops, SND_SOC_DAILINK_REG(cpu), }, @@ -165,7 +165,7 @@ static struct snd_soc_dai_link littlemill_dai[] = { .name = "Baseband", .stream_name = "Baseband", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBM_CFM, + | SND_SOC_DAIFMT_CBP_CFP, .ignore_suspend = 1, .c2c_params = &baseband_params, .num_c2c_params = 1, From 795aad6b179de4c3f68b18132bd183931d09c462 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:21 +0000 Subject: [PATCH 0516/1090] ASoC: samsung: smdk_wm8994: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/874j0ha3jn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index def92cc09f9c..acb29cd785a9 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -106,14 +106,14 @@ static struct snd_soc_dai_link smdk_dai[] = { .stream_name = "Pri_Dai", .init = smdk_wm8994_init_paiftx, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ops = &smdk_ops, SND_SOC_DAILINK_REG(aif1), }, { /* Sec_Fifo Playback i/f */ .name = "Sec_FIFO TX", .stream_name = "Sec_Dai", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ops = &smdk_ops, SND_SOC_DAILINK_REG(fifo_tx), }, From 697c58941c0a0d1a5ea3f323cf0231018d3ec4b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:24 +0000 Subject: [PATCH 0517/1090] ASoC: samsung: aries_wm8994: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/8734g1a3jj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/aries_wm8994.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c index 01716df0c842..3723329b266d 100644 --- a/sound/soc/samsung/aries_wm8994.c +++ b/sound/soc/samsung/aries_wm8994.c @@ -474,7 +474,7 @@ static struct snd_soc_dai_link aries_dai[] = { .name = "WM8994 AIF1", .stream_name = "HiFi", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .ops = &aries_ops, SND_SOC_DAILINK_REG(aif1), }, @@ -510,13 +510,13 @@ static struct snd_soc_card aries_card = { }; static const struct aries_wm8994_variant fascinate4g_variant = { - .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_IB_NF, .has_fm_radio = false, }; static const struct aries_wm8994_variant aries_variant = { - .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM + .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_IB_NF, .has_fm_radio = true, }; From 22bbcab0a2a100827a26833b7cab16ae8b1a3f9e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:27 +0000 Subject: [PATCH 0518/1090] ASoC: samsung: midas_wm1811: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pvla3jg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/midas_wm1811.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index bbfe5fef59af..239e958b88d3 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -537,7 +537,7 @@ static struct snd_soc_dai_link midas_dai[] = { .stream_name = "HiFi Primary", .ops = &midas_aif1_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(wm1811_hifi), }, { .name = "WM1811 Voice", From cc8e22b6b1622f44654a9ce70c1285c15c1b8414 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:31 +0000 Subject: [PATCH 0519/1090] ASoC: samsung: smdk_wm8994pcm: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87zfi98oyx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 5802f92ab8ba..a3f539fbde5f 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -99,7 +99,7 @@ static struct snd_soc_dai_link smdk_dai[] = { .name = "WM8994 PAIF PCM", .stream_name = "Primary PCM", .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &smdk_wm8994_pcm_ops, SND_SOC_DAILINK_REG(paif_pcm), }, From 862123a0a41647bd130a2d0edefc76a52dc8b8f8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:34 +0000 Subject: [PATCH 0520/1090] ASoC: mediatek: mt2701-wm8960: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xt8oyt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-wm8960.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c index 2814f0570928..84b3d6cd77a5 100644 --- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c +++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c @@ -83,7 +83,7 @@ static struct snd_soc_dai_link mt2701_wm8960_dai_links[] = { { .name = "wm8960-codec", .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, .ops = &mt2701_wm8960_be_ops, SND_SOC_DAILINK_REG(codec), From b1f5886cca25a6957b5541031376e2c06c5bd621 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:38 +0000 Subject: [PATCH 0521/1090] ASoC: mediatek: mt2701-cs42448: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmdd8oyp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-cs42448.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index 00a79867235d..778a9dccfcaa 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c @@ -266,7 +266,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = { [DAI_LINK_BE_I2S0] = { .name = "mt2701-cs42448-I2S0", .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, SND_SOC_DAILINK_REG(be_i2s0), @@ -274,7 +274,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = { [DAI_LINK_BE_I2S1] = { .name = "mt2701-cs42448-I2S1", .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, SND_SOC_DAILINK_REG(be_i2s1), @@ -282,7 +282,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = { [DAI_LINK_BE_I2S2] = { .name = "mt2701-cs42448-I2S2", .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, SND_SOC_DAILINK_REG(be_i2s2), @@ -290,7 +290,7 @@ static struct snd_soc_dai_link mt2701_cs42448_dai_links[] = { [DAI_LINK_BE_I2S3] = { .name = "mt2701-cs42448-I2S3", .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, .ops = &mt2701_cs42448_be_ops, SND_SOC_DAILINK_REG(be_i2s3), From c709a876b7de676d49b00b624b37d208e452cc7e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:42 +0000 Subject: [PATCH 0522/1090] ASoC: mediatek: mt7986-wm8960: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7sx8oyl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt7986/mt7986-wm8960.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt7986/mt7986-wm8960.c b/sound/soc/mediatek/mt7986/mt7986-wm8960.c index c3d1e2eeb0e5..f1dc18222be7 100644 --- a/sound/soc/mediatek/mt7986/mt7986-wm8960.c +++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c @@ -63,7 +63,7 @@ static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_GATED, SND_SOC_DAILINK_REG(codec), }, From d8c808af2a9bf731f72fcb772cf22886c6d00d99 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:46 +0000 Subject: [PATCH 0523/1090] ASoC: mediatek: mt7986-dai-etdm: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8h8oyh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt7986/mt7986-dai-etdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c index d57971413a04..fc55ff47b7bc 100644 --- a/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c +++ b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c @@ -348,10 +348,10 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: etdm_data->slave_mode = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: etdm_data->slave_mode = false; break; default: From eeb25b3ca1ef57d57906295d829febbd30cf4d8d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:50 +0000 Subject: [PATCH 0524/1090] ASoC: mediatek: mt8173-rt5650: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87seo18oyd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 59c19fdd8675..7d6a3586cdd5 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -235,7 +235,7 @@ static struct snd_soc_dai_link mt8173_rt5650_dais[] = { .no_pcm = 1, .init = mt8173_rt5650_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &mt8173_rt5650_ops, .ignore_pmdown_time = 1, SND_SOC_DAILINK_REG(codec), From 47c59833c42a99bd27826f4f369bf4bb433c7ff9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:38:55 +0000 Subject: [PATCH 0525/1090] ASoC: mediatek: mt8173-max98090: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87r03l8oy8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-max98090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 0724564cee6a..49ebb67c818a 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -122,7 +122,7 @@ static struct snd_soc_dai_link mt8173_max98090_dais[] = { .init = mt8173_max98090_init, .ops = &mt8173_max98090_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(hifi), }, }; From b73c2719c951868efc15181269a3caeb99157f29 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:01 +0000 Subject: [PATCH 0526/1090] ASoC: mediatek: mt8173-rt5650-rt5676: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plj58oy2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index 488f2314dbf7..a1ba5df87e1e 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -197,7 +197,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { .no_pcm = 1, .init = mt8173_rt5650_rt5676_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &mt8173_rt5650_rt5676_ops, .ignore_pmdown_time = 1, SND_SOC_DAILINK_REG(codec), @@ -214,7 +214,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { .stream_name = "rt5650_rt5676 intercodec", .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, SND_SOC_DAILINK_REG(intercodec), }, }; From 522f5021cfb5a74e9b7aa3cbf365471f7a564c0a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:05 +0000 Subject: [PATCH 0527/1090] ASoC: mediatek: mt8173-rt5650-rt5514: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6yp8oxy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index d8e4e70d834c..dc063d85e62f 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c @@ -156,7 +156,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = { .no_pcm = 1, .init = mt8173_rt5650_rt5514_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .ops = &mt8173_rt5650_rt5514_ops, .ignore_pmdown_time = 1, SND_SOC_DAILINK_REG(codec), From 711035c043b3a5116860b3a25d808572f70e1dc1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:08 +0000 Subject: [PATCH 0528/1090] ASoC: mediatek: mt8183-da7219-max98357: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87mse98oxv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 1d8881e0a361..3388e076ccc9 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -563,7 +563,7 @@ static struct snd_soc_dai_link mt8183_da7219_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .playback_only = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, From e33d0569d7a1d041e37fb93094e70807856531c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:12 +0000 Subject: [PATCH 0529/1090] ASoC: mediatek: mt8183-mt6358-ts3a227-max98357: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ldtt8oxs.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 6267c8554c15..497a9043be7b 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -575,7 +575,7 @@ static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .playback_only = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, @@ -783,7 +783,7 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) strcmp(dai_link->name, "I2S3") == 0) dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; + SND_SOC_DAIFMT_CBP_CFP; } if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { From 38cc5b0bed6c57367dca3725d01857fa0876899a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:15 +0000 Subject: [PATCH 0530/1090] ASoC: mediatek: mt8186-mt6366: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87jz9d8oxo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-mt6366.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c index a5ef913743d4..43546012cf61 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c @@ -875,7 +875,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .playback_only = 1, .ignore_suspend = 1, .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init, From d4ee06219f2fffb71e2a23fc5060fdd3c7bb2cf7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:19 +0000 Subject: [PATCH 0531/1090] ASoC: mediatek: mt8192-mt6359-rt1015-rt5682: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87ikox8oxk.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index b1598cc5587e..bf483a8fb34a 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -920,7 +920,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM, + SND_SOC_DAIFMT_CBP_CFP, .playback_only = 1, .ignore_suspend = 1, .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, From cb1ebf6e20371208c49d59615bf4b46d92991fc4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:22 +0000 Subject: [PATCH 0532/1090] ASoC: mediatek: mt8195-mt6359: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87h64h8oxh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index 2b9cb3248795..df29a9fa5aee 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -1114,7 +1114,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .capture_only = 1, SND_SOC_DAILINK_REG(ETDM1_IN_BE), }, @@ -1123,7 +1123,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .capture_only = 1, .be_hw_params_fixup = mt8195_etdm_hw_params_fixup, SND_SOC_DAILINK_REG(ETDM2_IN_BE), @@ -1133,7 +1133,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .playback_only = 1, .be_hw_params_fixup = mt8195_etdm_hw_params_fixup, SND_SOC_DAILINK_REG(ETDM1_OUT_BE), @@ -1143,7 +1143,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .playback_only = 1, SND_SOC_DAILINK_REG(ETDM2_OUT_BE), }, @@ -1152,7 +1152,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, .playback_only = 1, SND_SOC_DAILINK_REG(ETDM3_OUT_BE), }, @@ -1161,7 +1161,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { .no_pcm = 1, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(PCM1_BE), }, [DAI_LINK_UL_SRC1_BE] = { From db9912ce99c346c948c8fa774c0afc7d80d0ec20 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:26 +0000 Subject: [PATCH 0533/1090] ASoC: mediatek: mt8365-mt6357: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87frk18oxe.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8365/mt8365-mt6357.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c index 9f28d6bf0323..a998fba82bfe 100644 --- a/sound/soc/mediatek/mt8365/mt8365-mt6357.c +++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c @@ -225,7 +225,7 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = { .id = DAI_LINK_2ND_I2S_INTF, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(i2s3), }, [DAI_LINK_DMIC] = { From 9002421ebb1409e2f47062722aad598b561cf9eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:29 +0000 Subject: [PATCH 0534/1090] ASoC: mediatek: mt8365-dai-i2s: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87eczl8oxa.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8365/mt8365-dai-i2s.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c index 11b9a5bc7163..cae51756cead 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c @@ -313,7 +313,7 @@ static int mt8365_dai_set_config(struct mtk_base_afe *afe, } if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) == - SND_SOC_DAIFMT_CBM_CFM) { + SND_SOC_DAIFMT_CBP_CFP) { val |= AFE_I2S_CON_SRC_SLAVE; val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys } @@ -523,7 +523,7 @@ static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream, bool i2s_in_slave = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) && ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) == - SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_CBP_CFP); mt8365_afe_enable_main_clk(afe); @@ -551,7 +551,7 @@ static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream, bool i2s_in_slave = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) && ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) == - SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_CBP_CFP); if (be->prepared[substream->stream]) { if (reset_i2s_out_change) @@ -613,7 +613,7 @@ static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream, if (apply_i2s_in_change) { if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) - == SND_SOC_DAIFMT_CBM_CFM) { + == SND_SOC_DAIFMT_CBP_CFP) { ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate, (unsigned int)bit_width, 0, 0, 1); @@ -659,7 +659,7 @@ static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream, mt8365_dai_set_enable(afe, i2s_data, true, true); if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) - == SND_SOC_DAIFMT_CBM_CFM) + == SND_SOC_DAIFMT_CBP_CFP) mt8365_afe_set_2nd_i2s_asrc_enable(afe, true); be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true; @@ -712,7 +712,7 @@ static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK); - if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)) + if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBP_CFP)) be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK); return 0; From 0526b0b88c3092e38ba2d05f480b66bd5a1e1004 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:33 +0000 Subject: [PATCH 0535/1090] ASoC: mediatek: mt8365-dai-pcm: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87cyf58ox6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8365/mt8365-dai-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c index 3373b88da28e..0ec114a566ad 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-pcm.c @@ -189,10 +189,10 @@ static int mt8365_dai_pcm1_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: pcm_priv->slave_mode = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: pcm_priv->slave_mode = false; break; default: From 99239dc5147ea4678e871e5c9d068a36f154558b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:37 +0000 Subject: [PATCH 0536/1090] ASoC: rockchip: rk3288_hdmi_analog: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87bjup8ox3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3288_hdmi_analog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index a65d923d94dc..ffbc5a39b493 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -148,7 +148,7 @@ static struct snd_soc_dai_link rk_dailink = { .ops = &rk_ops, /* Set codecs as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(audio), }; From 8410a099c88d1d720c9780b0ed716e544ea5a6d2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:40 +0000 Subject: [PATCH 0537/1090] ASoC: rockchip: rk3399_gru_sound: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87a5a98owz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3399_gru_sound.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index 6c89c7331229..c8137e8883c4 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -338,7 +338,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .stream_name = "DP PCM", .init = rockchip_sound_cdndp_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(cdndp), }, [DAILINK_DA7219] = { @@ -348,7 +348,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .ops = &rockchip_sound_da7219_ops, /* set da7219 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(da7219), }, [DAILINK_DMIC] = { @@ -356,7 +356,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .stream_name = "DMIC PCM", .ops = &rockchip_sound_dmic_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(dmic), }, [DAILINK_MAX98357A] = { @@ -365,7 +365,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .ops = &rockchip_sound_max98357a_ops, /* set max98357a as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(max98357a), }, [DAILINK_RT5514] = { @@ -374,7 +374,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = { .ops = &rockchip_sound_rt5514_ops, /* set rt5514 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(rt5514), }, /* RT5514 DSP for voice wakeup via spi bus */ From edca7ad57c50483ec81ab5b74ff1d71dca62e5cb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:44 +0000 Subject: [PATCH 0538/1090] ASoC: rockchip: rockchip_max98090: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/878qpt8owv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_max98090.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index 783956dc83b5..b8326e9143b6 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -247,7 +247,7 @@ static struct snd_soc_dai_link rk_max98090_dailinks[] = { .ops = &rk_aif1_ops, /* set max98090 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(analog), }, }; @@ -260,7 +260,7 @@ static struct snd_soc_dai_link rk_hdmi_dailinks[] = { .init = rk_hdmi_init, .ops = &rk_aif1_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(hdmi), } }; @@ -274,7 +274,7 @@ static struct snd_soc_dai_link rk_max98090_hdmi_dailinks[] = { .ops = &rk_aif1_ops, /* set max98090 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(analog), }, [DAILINK_HDMI] = { @@ -283,7 +283,7 @@ static struct snd_soc_dai_link rk_max98090_hdmi_dailinks[] = { .init = rk_hdmi_init, .ops = &rk_aif1_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(hdmi), } }; From 7370a8fe5bd211042610ec200dcc83de5ccc50cd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:47 +0000 Subject: [PATCH 0539/1090] ASoC: rockchip: rockchip_rt5645: use inclusive language for SND_SOC_DAIFMT_CBx_CFx In SND_SOC_DAIFMT_CBx_CFx, M/S are no longer used. use P/C. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/877c5d8ows.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_rt5645.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_rt5645.c b/sound/soc/rockchip/rockchip_rt5645.c index b085d80ea2e4..590b64b362f6 100644 --- a/sound/soc/rockchip/rockchip_rt5645.c +++ b/sound/soc/rockchip/rockchip_rt5645.c @@ -145,7 +145,7 @@ static struct snd_soc_dai_link rk_dailink = { .ops = &rk_aif1_ops, /* set rt5645 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAIFMT_CBC_CFC, SND_SOC_DAILINK_REG(pcm), }; From 0f68f56ab7be101fc949177774107769e63f13e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 26 Feb 2025 01:39:54 +0000 Subject: [PATCH 0540/1090] ASoC: soc-dai: remove SND_SOC_DAIFMT_CB{MS}_CF{MS} No drivers are using SND_SOC_DAIFMT_CB{MS}_CF{MS}. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/875xkx8owm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index a11501752637..c3a3ba4b0bb7 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -118,12 +118,6 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_CBP_CFC (3 << 12) /* codec clk provider & frame consumer */ #define SND_SOC_DAIFMT_CBC_CFC (4 << 12) /* codec clk consumer & frame consumer */ -/* previous definitions kept for backwards-compatibility, do not use in new contributions */ -#define SND_SOC_DAIFMT_CBM_CFM SND_SOC_DAIFMT_CBP_CFP -#define SND_SOC_DAIFMT_CBS_CFM SND_SOC_DAIFMT_CBC_CFP -#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC -#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC - /* when passed to set_fmt directly indicate if the device is provider or consumer */ #define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP #define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP From 22e5c40fda71d0b6cdf83af9418403808d5d06bd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 18 Feb 2025 01:14:47 +0000 Subject: [PATCH 0541/1090] ASoC: audio-graph-card2-custom-sample1.dtsi: Separate Sample DT audio-graph-card2-custom-sample has many sample connections, but because ALSA card has number limition for links, it is impossible to have all samples into 1 ASoC card. Separate it and took the normal connection part. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87wmdo9hq0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../audio-graph-card2-custom-sample1.dtsi | 396 ++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 sound/soc/generic/audio-graph-card2-custom-sample1.dtsi diff --git a/sound/soc/generic/audio-graph-card2-custom-sample1.dtsi b/sound/soc/generic/audio-graph-card2-custom-sample1.dtsi new file mode 100644 index 000000000000..12d40e05de46 --- /dev/null +++ b/sound/soc/generic/audio-graph-card2-custom-sample1.dtsi @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * audio-graph-card2-custom-sample1.dtsi + * + * Copyright (C) 2020 Renesas Electronics Corp. + * Copyright (C) 2020 Kuninori Morimoto + * + * This sample indicates how to use audio-graph-card2 and its + * custom driver. "audio-graph-card2-custom-sample" is the custome driver + * which is using audio-graph-card2. + * + * You can easily use this sample by adding below line on your DT file, + * and add new CONFIG to your .config. + * + * #include "../../../../../sound/soc/generic/audio-graph-card2-custom-sample1.dtsi" + * + * CONFIG_SND_AUDIO_GRAPH_CARD2 + * CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE + * CONFIG_SND_TEST_COMPONENT + * + * + * You can indicate more detail each device behavior as debug if you modify + * "compatible" on each test-component. see below + * + * test_cpu { + * - compatible = "test-cpu"; + * + compatible = "test-cpu-verbose"; + * ... + * }; + * + * test_codec { + * - compatible = "test-codec"; + * + compatible = "test-codec-verbose"; + * ... + * }; + * + * + * Below sample doesn't use "format" property, + * because test-component driver (test-cpu/test-codec) is supporting + * snd_soc_dai_ops :: .auto_selectable_formats. + * see + * snd_soc_runtime_get_dai_fmt() + * linux/sound/soc/generic/test-component.c :: test_dai_formats + */ +/ { + audio-graph-card2-custom-sample-1 { + /* + * You can use audio-graph-card2 directly by using + * + * compatible = "audio-graph-card2"; + */ + compatible = "audio-graph-card2-custom-sample"; + label = "card2-custom-sample-1"; + + /* + * @ : used at links + */ + links = < + /* + * + * [Normal] + * + * + * cpu1_0 <-@-----> codec1_0 + */ + &cpu1_0 /* CPU side only */ + + /* + * [Semi-Multi] + * + * CPU:Codec = 1:N + * + * +-+ + * cpu1_1 <--@---->| |-> codec1_1 + * | |-> codec1_2 + * +-+ + */ + &sm /* CPU side only */ + + /* + * [Multi-CPU/Codec-A] + * + * +-+ +-+ + * cpu1_2 <-| |<---@------>| |-> codec1_3 + * cpu1_3 <-| | | |-> codec1_4 + * +-+ +-+ + */ + &mcpuA /* CPU side only */ + + /* + * [Multi-CPU/Codec-B] + * + * +-+ +-+ + * | |<---@------>| | + * | | | | + * cpu1_4 <-| |<---------->| |-> codec1_5 + * cpu1_5 <-| |<---+------>| |-> codec1_6 + * +-+ \----->| |-> codec1_7 + * +-+ + */ + &mcpuB /* CPU side only */ + + /* + * [Multi-CPU/Codec-C] + * + * +-+ +-+ + * | |<---@------>| | + * | | | | + * cpu1_6 <-| |<---------->| |-> codec1_8 + * cpu1_7 <-| |<-----+---->| |-> codec1_9 + * cpu1_8 <-| |<----/ +-+ + * +-+ + */ + &mcpuC /* CPU side only */ + >; + + multi { + #address-cells = <1>; + #size-cells = <0>; + + /* + * [Semi-Multi] + * + * +---+ + * cpu1_1 <---@--->|X A|-> codec1_1 + * | B|-> codec1_2 + * +---+ + */ + ports@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; smcodec_ep: endpoint { remote-endpoint = <&cpu1_1_ep>; };};/* (X) to pair */ + port@1 { reg = <1>; smcodec_A_ep: endpoint { remote-endpoint = <&codec1_1_ep>; };};/* (A) Multi Element */ + port@2 { reg = <2>; smcodec_B_ep: endpoint { remote-endpoint = <&codec1_2_ep>; };};/* (B) Multi Element */ + }; + + /* + * [Multi-CPU-A] + * + * +---+ +---+ + * cpu1_2 <-|A X|<---@---->|x a|-> codec1_3 + * cpu1_3 <-|B | | b|-> codec1_4 + * +---+ +---+ + */ + ports@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mcpuA: port@0 { reg = <0>; mcpu_A_ep: endpoint { remote-endpoint = <&mcodec_A_ep>; };}; /* (X) to pair */ + port@1 { reg = <1>; mcpu_AA_ep: endpoint { remote-endpoint = <&cpu1_2_ep>; };}; /* (A) Multi Element */ + port@2 { reg = <2>; mcpu_AB_ep: endpoint { remote-endpoint = <&cpu1_3_ep>; };}; /* (B) Multi Element */ + }; + + /* + * [Multi-Codec-A] + * + * +---+ +---+ + * cpu1_2 <-|A X|<-@------>|x a|-> codec1_3 + * cpu1_3 <-|B | | b|-> codec1_4 + * +---+ +---+ + */ + ports@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; mcodec_A_ep: endpoint { remote-endpoint = <&mcpu_A_ep>; };}; /* (x) to pair */ + port@1 { reg = <1>; mcodec_Aa_ep: endpoint { remote-endpoint = <&codec1_3_ep>; };}; /* (a) Multi Element */ + port@2 { reg = <2>; mcodec_Ab_ep: endpoint { remote-endpoint = <&codec1_4_ep>; };}; /* (b) Multi Element */ + }; + + /* + * [Multi-CPU-B] + * + * +---+ +---+ + * | X|<---@---->|x | + * | | | | + * cpu1_4 <-|A 1|<-------->|3 a|-> codec1_5 + * cpu1_5 <-|B 2|<---+---->|4 b|-> codec1_6 + * +---+ \--->|5 c|-> codec1_7 + * +---+ + */ + ports@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + mcpuB: port@0 { + reg = <0>; + mcpu_BX_ep: endpoint { remote-endpoint = <&mcodec_Bx_ep>; }; /* (X) to pair */ + }; + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + mcpu_BA_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu1_4_ep>; }; /* (A) Multi Element */ + mcpu_B1_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec_B3_ep>; }; /* (1) connected Codec */ + }; + port@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + mcpu_BB_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu1_5_ep>; }; /* (B) Multi Element */ + mcpu_B2_0_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec_B4_ep>; }; /* (2) connected Codec */ + mcpu_B2_1_ep: endpoint@2 { reg = <2>; remote-endpoint = <&mcodec_B5_ep>; }; /* (2) connected Codec */ + }; + }; + + /* + * [Multi-Codec-B] + * + * +---+ +---+ + * | X|<-@------>|x | + * | | | | + * cpu1_4 <-|A 1|<-------->|3 a|-> codec1_5 + * cpu1_5 <-|B 2|<---+---->|4 b|-> codec1_6 + * +---+ \--->|5 c|-> codec1_7 + * +---+ + */ + ports@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + mcodec_Bx_ep: endpoint { remote-endpoint = <&mcpu_BX_ep>; }; /* (x) to pair */ + }; + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + mcodec_Ba_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec1_5_ep>;}; /* (a) Multi Element */ + mcodec_B3_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu_B1_ep>; }; /* (3) connected CPU */ + }; + port@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + mcodec_Bb_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec1_6_ep>; }; /* (b) Multi Element */ + mcodec_B4_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu_B2_0_ep>;}; /* (4) connected CPU */ + }; + port@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + mcodec_Bc_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec1_7_ep>; }; /* (c) Multi Element */ + mcodec_B5_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu_B2_1_ep>;}; /* (5) connected CPU */ + }; + }; + + /* + * [Multi-CPU-C] + * + * +---+ +---+ + * | X|<-@------>|x | + * | | | | + * cpu1_6 <-|A 1|<-------->|4 a|-> codec1_8 + * cpu1_7 <-|B 2|<-----+-->|5 b|-> codec1_9 + * cpu1_8 <-|C 3|<----/ +---+ + * +---+ + */ + ports@5 { + reg = <5>; + #address-cells = <1>; + #size-cells = <0>; + mcpuC: port@0 { + reg = <0>; + mcpu_CX_ep: endpoint { remote-endpoint = <&mcodec_Cx_ep>; }; /* (X) to pair */ + }; + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + mcpu_CA_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu1_6_ep>; }; /* (A) Multi Element */ + mcpu_C1_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec_C4_ep>; }; /* (1) connected Codec */ + }; + port@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + mcpu_CB_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu1_7_ep>; }; /* (B) Multi Element */ + mcpu_C2_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec_C5_0_ep>; }; /* (2) connected Codec */ + }; + port@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + mcpu_CC_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu1_8_ep>; }; /* (C) Multi Element */ + mcpu_C3_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec_C5_1_ep>; }; /* (3) connected Codec */ + }; + }; + + /* + * [Multi-Codec-C] + * + * +---+ +---+ + * | X|<-@------>|x | + * | | | | + * cpu1_6 <-|A 1|<-------->|4 a|-> codec1_8 + * cpu1_7 <-|B 2|<-----+-->|5 b|-> codec1_9 + * cpu1_8 <-|C 3|<----/ +---+ + * +---+ + */ + ports@6 { + reg = <6>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + mcodec_Cx_ep: endpoint { remote-endpoint = <&mcpu_CX_ep>; }; /* (x) to pair */ + }; + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + mcodec_Ca_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec1_8_ep>;}; /* (a) Multi Element */ + mcodec_C4_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu_C1_ep>; }; /* (4) connected CPU */ + }; + port@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + mcodec_Cb_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec1_9_ep>;}; /* (b) Multi Element */ + mcodec_C5_0_ep: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu_C2_ep>; }; /* (5) connected CPU */ + mcodec_C5_1_ep: endpoint@2 { reg = <2>; remote-endpoint = <&mcpu_C3_ep>; }; /* (5) connected CPU */ + }; + }; + }; + }; + + test_cpu_1 { + /* + * update compatible to indicate more detail behaviour + * if you want. see test-compatible for more detail. + * + * ex) + * - compatible = "test-cpu"; + * + compatible = "test-cpu-verbose"; + */ + compatible = "test-cpu"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + bitclock-master; + frame-master; + + /* [Normal] */ + cpu1_0: port@0 { reg = <0>; cpu1_0_ep: endpoint { remote-endpoint = <&codec1_0_ep>;}; }; + /* [Semi-Multi] */ + sm: port@1 { reg = <1>; cpu1_1_ep: endpoint { remote-endpoint = <&smcodec_ep>; }; }; + /* [Multi-CPU-A] */ + port@2 { reg = <2>; cpu1_2_ep: endpoint { remote-endpoint = <&mcpu_AA_ep>; }; }; + port@3 { reg = <3>; cpu1_3_ep: endpoint { remote-endpoint = <&mcpu_AB_ep>; }; }; + /* [Multi-CPU-B] */ + port@4 { reg = <4>; cpu1_4_ep: endpoint { remote-endpoint = <&mcpu_BA_ep>; }; }; + port@5 { reg = <5>; cpu1_5_ep: endpoint { remote-endpoint = <&mcpu_BB_ep>; }; }; + /* [Multi-CPU-C] */ + port@6 { reg = <6>; cpu1_6_ep: endpoint { remote-endpoint = <&mcpu_CA_ep>; }; }; + port@7 { reg = <7>; cpu1_7_ep: endpoint { remote-endpoint = <&mcpu_CB_ep>; }; }; + port@8 { reg = <8>; cpu1_8_ep: endpoint { remote-endpoint = <&mcpu_CC_ep>; }; }; + }; + }; + + test_codec_1 { + /* + * update compatible to indicate more detail behaviour + * if you want. see test-compatible for more detail. + * + * ex) + * - compatible = "test-codec"; + * + compatible = "test-codec-verbose"; + */ + compatible = "test-codec"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* [Normal] */ + port@0 { reg = <0>; codec1_0_ep: endpoint { remote-endpoint = <&cpu1_0_ep>; }; }; + /* [Semi-Multi] */ + port@1 { reg = <1>; codec1_1_ep: endpoint { remote-endpoint = <&smcodec_A_ep>; }; }; + port@2 { reg = <2>; codec1_2_ep: endpoint { remote-endpoint = <&smcodec_B_ep>; }; }; + /* [Multi-Codec-0] */ + port@3 { reg = <3>; codec1_3_ep: endpoint { remote-endpoint = <&mcodec_Aa_ep>; }; }; + port@4 { reg = <4>; codec1_4_ep: endpoint { remote-endpoint = <&mcodec_Ab_ep>; }; }; + /* [Multi-Codec-1] */ + port@5 { reg = <5>; codec1_5_ep: endpoint { remote-endpoint = <&mcodec_Ba_ep>; }; }; + port@6 { reg = <6>; codec1_6_ep: endpoint { remote-endpoint = <&mcodec_Bb_ep>; }; }; + port@7 { reg = <7>; codec1_7_ep: endpoint { remote-endpoint = <&mcodec_Bc_ep>; }; }; + /* [Multi-Codec-2] */ + port@8 { reg = <8>; codec1_8_ep: endpoint { remote-endpoint = <&mcodec_Ca_ep>; }; }; + port@9 { reg = <9>; codec1_9_ep: endpoint { remote-endpoint = <&mcodec_Cb_ep>; }; }; + }; + }; +}; From 7c0572197faf3b6d6b27271455e76ac8ba84c43f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 18 Feb 2025 01:14:54 +0000 Subject: [PATCH 0542/1090] ASoC: audio-graph-card2-custom-sample2.dtsi: Separate Sample DT audio-graph-card2-custom-sample has many sample connections, but because ALSA card has number limition for links, it is impossible to have all samples into 1 ASoC card. Separate it and took DPCM / Codec2Codec connection part. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87v7t89hpt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../audio-graph-card2-custom-sample2.dtsi | 382 ++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 sound/soc/generic/audio-graph-card2-custom-sample2.dtsi diff --git a/sound/soc/generic/audio-graph-card2-custom-sample2.dtsi b/sound/soc/generic/audio-graph-card2-custom-sample2.dtsi new file mode 100644 index 000000000000..1fb061a10ab1 --- /dev/null +++ b/sound/soc/generic/audio-graph-card2-custom-sample2.dtsi @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * audio-graph-card2-custom-sample2.dtsi + * + * Copyright (C) 2020 Renesas Electronics Corp. + * Copyright (C) 2020 Kuninori Morimoto + * + * This sample indicates how to use audio-graph-card2 and its + * custom driver. "audio-graph-card2-custom-sample" is the custome driver + * which is using audio-graph-card2. + * + * You can easily use this sample by adding below line on your DT file, + * and add new CONFIG to your .config. + * + * #include "../../../../../sound/soc/generic/audio-graph-card2-custom-sample2.dtsi" + * + * CONFIG_SND_AUDIO_GRAPH_CARD2 + * CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE + * CONFIG_SND_TEST_COMPONENT + * + * + * You can indicate more detail each device behavior as debug if you modify + * "compatible" on each test-component. see below + * + * test_cpu { + * - compatible = "test-cpu"; + * + compatible = "test-cpu-verbose"; + * ... + * }; + * + * test_codec { + * - compatible = "test-codec"; + * + compatible = "test-codec-verbose"; + * ... + * }; + * + * + * Below sample doesn't use "format" property, + * because test-component driver (test-cpu/test-codec) is supporting + * snd_soc_dai_ops :: .auto_selectable_formats. + * see + * snd_soc_runtime_get_dai_fmt() + * linux/sound/soc/generic/test-component.c :: test_dai_formats + */ +/ { + audio-graph-card2-custom-sample-2 { + /* + * You can use audio-graph-card2 directly by using + * + * compatible = "audio-graph-card2"; + */ + compatible = "audio-graph-card2-custom-sample"; + label = "card2-custom-sample-2"; + + /* for [DPCM] */ + /* BE FE */ + routing = "TC DAI0 Playback", "DAI0 Playback", + "TC DAI0 Playback", "DAI1 Playback", + "DAI0 Capture", "TC DAI0 Capture", + "DAI1 Capture", "TC DAI0 Capture", + /* for [DPCM-Multi] */ + /* BE FE */ + "TC DAI1 Playback", "DAI2 Playback", + "TC DAI2 Playback", "DAI2 Playback", + "TC DAI1 Playback", "DAI3 Playback", + "TC DAI2 Playback", "DAI3 Playback", + "DAI2 Capture", "TC DAI1 Capture", + "DAI2 Capture", "TC DAI2 Capture", + "DAI3 Capture", "TC DAI1 Capture", + "DAI3 Capture", "TC DAI2 Capture", + /* for [Codec2Codec] */ + "TC OUT", "TC DAI4 Playback", + "TC DAI3 Capture", "TC IN", + /* for [Codec2Codec-Multi] */ + "TC OUT", "TC DAI7 Playback", + "TC DAI5 Capture", "TC IN", + "TC OUT", "TC DAI8 Playback", + "TC DAI6 Capture", "TC IN"; + + /* + * @ : used at links + */ + links = < + /* + * [DPCM] + * + * cpu20/cpu21 are converting rate to 44.1kHz + * + * FE BE + * **** + * cpu2_0 <----@---* *------@---> codec2_0 (44.1kHz) + * cpu2_1 <----@---* * + * **** + */ + &feA &feB &beA /* both FE / BE */ + + /* + * [DPCM-Multi] + * + * FE BE + * **** +-+ + * cpu2_2 <----@---* *------@---> | | -> codec2_1 + * cpu2_3 <----@---* * | | -> codec2_2 + * **** +-+ + */ + &feC &feD &beB /* both FE / BE*/ + + /* + * [Codec2Codec] + * + * + * +-@-> codec2_3 + * | + * +---> codec2_4 + */ + &c2c /* CPU side only */ + + /* + * [Codec2Codec-Multi] + * + * --NOTE-- + * Multi connect N:M is not supported by ASoC. + * + * +-+ + * +---@-->| |-> codec2_5 + * | | |-> codec2_6 + * | +-+ + * | +-+ + * +------>| |-> codec2_7 + * | |-> codec2_8 + * +-+ + */ + &c2c_m /* CPU side only */ + >; + + multi { + #address-cells = <1>; + #size-cells = <0>; + + /* + * [DPCM-Multi]::BE + * + * FE BE + * **** +---+ + * cpu2_2 <----@---* *------@---> |x a| -> codec2_1 + * cpu2_3 <----@---* * | b| -> codec2_2 + * **** +---+ + */ + ports@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; mbe_x_ep: endpoint { remote-endpoint = <&beB_ep>; };};/* (x) to pair */ + port@1 { reg = <1>; mbe_a_ep: endpoint { remote-endpoint = <&codec2_1_ep>; };};/* (a) Multi Element */ + port@2 { reg = <2>; mbe_b_ep: endpoint { remote-endpoint = <&codec2_2_ep>; };};/* (b) Multi Element */ + }; + + /* + * [Codec2Codec-Multi]::CPU + * + * c2cmf +---+ + * +---@---------->|X A|-> codec2_5 + * | | B|-> codec2_6 + * | +---+ + * | c2cmb +---+ + * +-------------->|x a|-> codec2_7 + * | b|-> codec2_8 + * +---+ + */ + ports@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; mc2c0X_ep: endpoint { remote-endpoint = <&c2cmf_ep>; };};/* (X) to pair */ + port@1 { reg = <1>; mc2c0A_ep: endpoint { remote-endpoint = <&codec2_5_ep>; };};/* (A) Multi Element */ + port@2 { reg = <2>; mc2c0B_ep: endpoint { remote-endpoint = <&codec2_6_ep>; };};/* (B) Multi Element */ + }; + + /* + * [Codec2Codec-Multi]::Codec + * + * c2cmf +---+ + * +---@---------->|X A|-> codec2_5 + * | | B|-> codec2_6 + * | +---+ + * | c2cmb +---+ + * +-------------->|x a|-> codec2_7 + * | b|-> codec2_8 + * +---+ + */ + ports@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + port@0 { reg = <0>; mc2c1x_ep: endpoint { remote-endpoint = <&c2cmb_ep>; };};/* (x) to pair */ + port@1 { reg = <1>; mc2c1a_ep: endpoint { remote-endpoint = <&codec2_7_ep>; };};/* (a) Multi Element */ + port@2 { reg = <2>; mc2c1b_ep: endpoint { remote-endpoint = <&codec2_8_ep>; };};/* (b) Multi Element */ + }; + }; + + dpcm { + #address-cells = <1>; + #size-cells = <0>; + + /* FE part */ + ports@0 { + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + /* + * [DPCM]::FE + * + * FE BE + * **** + * cpu2_0 <----@---* *------@---> codec2_0 (44.1kHz) + * cpu2_1 <----@---* * + * **** + */ + feA: port@0 { reg = <0>; feA_ep: endpoint { remote-endpoint = <&cpu2_0_ep>; }; }; + feB: port@1 { reg = <1>; feB_ep: endpoint { remote-endpoint = <&cpu2_1_ep>; }; }; + + /* + * [DPCM-Multi]::FE + * + * FE BE + * **** +-+ + * cpu2_2 <----@---* *------@---> | | -> codec2_1 + * cpu2_3 <----@---* * | | -> codec2_2 + * **** +-+ + */ + feC: port@2 { reg = <2>; feC_ep: endpoint { remote-endpoint = <&cpu2_2_ep>; }; }; + feD: port@3 { reg = <3>; feD_ep: endpoint { remote-endpoint = <&cpu2_3_ep>; }; }; + }; + + /* BE part */ + ports@1 { + reg = <1>; + + #address-cells = <1>; + #size-cells = <0>; + /* + * [DPCM]::BE + * + * FE BE + * **** + * cpu2_0 <----@---* *------@---> codec2_0 (44.1kHz) + * cpu2_1 <----@---* * + * **** + */ + beA: port@0 { reg = <0>; beA_ep: endpoint { remote-endpoint = <&codec2_0_ep>; }; }; + + /* + * [DPCM-Multi]::BE + * + * FE BE + * **** +-------+ + * cpu2_2 <----@---* *------@---> |mbe_x | -> codec2_1 + * cpu2_3 <----@---* * | | -> codec2_2 + * **** +-------+ + */ + beB: port@1 { reg = <1>; beB_ep: endpoint { remote-endpoint = <&mbe_x_ep>; }; }; + }; + }; + + codec2codec { + #address-cells = <1>; + #size-cells = <0>; + /* + * [Codec2Codec] + * + * + * +-@--> codec2_3 + * | + * +----> codec2_4 + */ + ports@0 { + reg = <0>; + + #address-cells = <1>; + #size-cells = <0>; + + /* use default settings */ + c2c: port@0 { reg = <0>; c2cf_ep: endpoint { remote-endpoint = <&codec2_3_ep>; }; }; + port@1 { reg = <1>; c2cb_ep: endpoint { remote-endpoint = <&codec2_4_ep>; }; }; + }; + + /* + * [Codec2Codec-Multi] + * + * c2cmf +--------+ + * +---@---------->|mc2c0X |-> codec2_5 + * | | |-> codec2_6 + * | +--------+ + * | c2cmb +--------+ + * +-------------->|mc2c1x |-> codec2_7 + * | |-> codec2_8 + * +--------+ + */ + ports@1 { + reg = <1>; + + #address-cells = <1>; + #size-cells = <0>; + + /* use original settings */ + rate = <48000>; + c2c_m: port@0 { reg = <0>; c2cmf_ep: endpoint { remote-endpoint = <&mc2c0X_ep>; }; }; + port@1 { reg = <1>; c2cmb_ep: endpoint { remote-endpoint = <&mc2c1x_ep>; }; }; + }; + }; + }; + + test_cpu_2 { + /* + * update compatible to indicate more detail behaviour + * if you want. see test-compatible for more detail. + * + * ex) + * - compatible = "test-cpu"; + * + compatible = "test-cpu-verbose"; + */ + compatible = "test-cpu"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + bitclock-master; + frame-master; + + /* [DPCM]::FE */ + port@0 { reg = <0>; cpu2_0_ep: endpoint { remote-endpoint = <&feA_ep>; };}; + port@1 { reg = <1>; cpu2_1_ep: endpoint { remote-endpoint = <&feB_ep>; };}; + /* [DPCM-Multi]::FE */ + port@2 { reg = <2>; cpu2_2_ep: endpoint { remote-endpoint = <&feC_ep>; };}; + port@3 { reg = <3>; cpu2_3_ep: endpoint { remote-endpoint = <&feD_ep>; };}; + }; + }; + + test_codec_2 { + /* + * update compatible to indicate more detail behaviour + * if you want. see test-compatible for more detail. + * + * ex) + * - compatible = "test-codec"; + * + compatible = "test-codec-verbose"; + */ + compatible = "test-codec"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* + * prefix can be added to *component*, + * see audio-graph-card2::routing + */ + prefix = "TC"; + + /* [DPCM]::BE */ + port@0 { + convert-rate = <44100>; + reg = <0>; codec2_0_ep: endpoint { remote-endpoint = <&beA_ep>; }; + }; + /* [DPCM-Multi]::BE */ + port@1 { reg = <1>; codec2_1_ep: endpoint { remote-endpoint = <&mbe_a_ep>; };}; + port@2 { reg = <2>; codec2_2_ep: endpoint { remote-endpoint = <&mbe_b_ep>; };}; + /* [Codec2Codec] */ + port@3 { bitclock-master; + frame-master; + reg = <3>; codec2_3_ep: endpoint { remote-endpoint = <&c2cf_ep>; };}; + port@4 { reg = <4>; codec2_4_ep: endpoint { remote-endpoint = <&c2cb_ep>; };}; + /* [Codec2Codec-Multi] */ + port@5 { bitclock-master; + frame-master; + reg = <5>; codec2_5_ep: endpoint { remote-endpoint = <&mc2c0A_ep>; };}; + port@6 { reg = <6>; codec2_6_ep: endpoint { remote-endpoint = <&mc2c0B_ep>; };}; + port@7 { reg = <7>; codec2_7_ep: endpoint { remote-endpoint = <&mc2c1a_ep>; };}; + port@8 { reg = <8>; codec2_8_ep: endpoint { remote-endpoint = <&mc2c1b_ep>; };}; + }; + }; +}; From 7d73a1beaa9428ed4da7786725fcb1a20fd371ab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 18 Feb 2025 01:14:58 +0000 Subject: [PATCH 0543/1090] ASoC: audio-graph-card2-custom-sample.dtsi: remove original sample audio-graph-card2-custom-sample has many sample connections, but because ALSA card has number limition for links, it is impossible to have all samples into 1 ASoC card. The sample is separated into 2 samples. Remove original sample. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt8s9hpp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- .../audio-graph-card2-custom-sample.dtsi | 702 ------------------ 1 file changed, 702 deletions(-) delete mode 100644 sound/soc/generic/audio-graph-card2-custom-sample.dtsi diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi b/sound/soc/generic/audio-graph-card2-custom-sample.dtsi deleted file mode 100644 index 9efd31206c9b..000000000000 --- a/sound/soc/generic/audio-graph-card2-custom-sample.dtsi +++ /dev/null @@ -1,702 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * audio-graph-card2-custom-sample.dtsi - * - * Copyright (C) 2020 Renesas Electronics Corp. - * Copyright (C) 2020 Kuninori Morimoto - * - * This sample indicates how to use audio-graph-card2 and its - * custom driver. "audio-graph-card2-custom-sample" is the custome driver - * which is using audio-graph-card2. - * - * You can easily use this sample by adding below line on your DT file, - * and add new CONFIG to your .config. - * - * #include "../../../../../sound/soc/generic/audio-graph-card2-custom-sample.dtsi" - * - * CONFIG_SND_AUDIO_GRAPH_CARD2 - * CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE - * CONFIG_SND_TEST_COMPONENT - * - * - * You can indicate more detail each device behavior as debug if you modify - * "compatible" on each test-component. see below - * - * test_cpu { - * - compatible = "test-cpu"; - * + compatible = "test-cpu-verbose"; - * ... - * }; - * - * test_codec { - * - compatible = "test-codec"; - * + compatible = "test-codec-verbose"; - * ... - * }; - * - * - * Below sample doesn't use "format" property, - * because test-component driver (test-cpu/test-codec) is supporting - * snd_soc_dai_ops :: .auto_selectable_formats. - * see - * snd_soc_runtime_get_dai_fmt() - * linux/sound/soc/generic/test-component.c :: test_dai_formats - */ -/ { - /* - * @ : used at links - * - * [Normal] - * cpu0 <-@-----------------> codec0 - * - * [Semi-Multi] - * - * CPU:Codec = 1:N - * - * +-+ - * cpu7 <-@------->| |-> codec12 - * | |-> codec13 - * +-+ - * - * [Multi-CPU/Codec-0] - * +-+ +-+ - * cpu1 <--| |<-@--------->| |-> codec1 - * cpu2 <--| | | |-> codec2 - * +-+ +-+ - * - * [Multi-CPU/Codec-1] - * - * +-+ +-+ - * | |<-@--------->| | - * | | | | - * cpu8 <--| |<----------->| |-> codec14 - * cpu9 <--| |<---+------->| |-> codec15 - * +-+ \------>| |-> codec16 - * +-+ - * - * [Multi-CPU/Codec-2] - * - * +-+ +-+ - * | |<-@--------->| | - * | | | | - * cpu10 <-| |<----------->| |-> codec17 - * cpu11 <-| |<-----+----->| |-> codec18 - * cpu12 <-| |<----/ +-+ - * +-+ - * - * [DPCM] - * - * CPU3/CPU4 are converting rate to 44100 - * - * FE BE - * **** - * cpu3 <-@--* *--@-> codec3 - * cpu4 <-@--* * (44.1kHz) - * **** - * - * [DPCM-Multi] - * - * --NOTE-- - * Multi-FE is not supported by ASoC. - * - * FE BE - * **** +-+ - * cpu5 <-@--* *--@-> | | -> codec4 - * cpu6 <-@--* * | | -> codec5 - * **** +-+ - * - * [Codec2Codec] - * +-@-> codec6 - * | - * +---> codec7 - * - * [Codec2Codec-Multi] - * - * --NOTE-- - * Multi connect N:M is not supported by ASoC. - * - * +-+ - * +-@->| |-> codec8 - * | | |-> codec9 - * | +-+ - * | +-+ - * +--->| |-> codec10 - * | |-> codec11 - * +-+ - */ - audio-graph-card2-custom-sample { - /* - * You can use audio-graph-card2 directly by using - * - * compatible = "audio-graph-card2"; - */ - compatible = "audio-graph-card2-custom-sample"; - - /* for [DPCM] */ - /* BE FE */ - routing = "TC DAI3 Playback", "DAI3 Playback", - "TC DAI3 Playback", "DAI4 Playback", - "DAI3 Capture", "TC DAI3 Capture", - "DAI4 Capture", "TC DAI3 Capture", - /* for [DPCM-Multi] */ - /* BE FE */ - "TC DAI4 Playback", "DAI5 Playback", - "TC DAI5 Playback", "DAI5 Playback", - "TC DAI4 Playback", "DAI6 Playback", - "TC DAI5 Playback", "DAI6 Playback", - "DAI5 Capture", "TC DAI4 Capture", - "DAI5 Capture", "TC DAI5 Capture", - "DAI6 Capture", "TC DAI4 Capture", - "DAI6 Capture", "TC DAI5 Capture", - /* for [Codec2Codec] */ - "TC OUT", "TC DAI7 Playback", - "TC DAI6 Capture", "TC IN", - /* for [Codec2Codec-Multi] */ - "TC OUT", "TC DAI10 Playback", - "TC DAI8 Capture", "TC IN", - "TC OUT", "TC DAI11 Playback", - "TC DAI9 Capture", "TC IN"; - - links = < - /* - * [Normal]: cpu side only - * cpu0/codec0 - */ - &cpu0 - - /* - * [Semi-Multi] - * cpu7/codec12/codec13 - */ - &sm0 - - /* - * [Multi-CPU/Codec-0]: cpu side only - * cpu1/cpu2/codec1/codec2 - */ - &mcpu0 - - /* - * [Multi-CPU/Codec-1]: cpu side only - * cpu8/cpu9/codec14/codec15/codec16 - * - * Because it will reach to the maximum of sound minor number, - * disable it so far. - * If you want to try it, please disable some other one instead. - */ - //&mcpu1 - - /* - * [Multi-CPU/Codec-2]: cpu side only - * cpu10/cpu11/cpu12/codec17/codec18 - * - * Because it will reach to the maximum of sound minor number, - * disable it so far. - * If you want to try it, please disable some other one instead. - */ - //&mcpu2 - - /* - * [DPCM]: both FE / BE - * cpu3/cpu4/codec3 - */ - &fe00 &fe01 &be0 - - /* - * [DPCM-Multi]: both FE / BE - * cpu5/cpu6/codec4/codec5 - */ - &fe10 &fe11 &be1 - - /* - * [Codec2Codec]: cpu side only - * codec6/codec7 - */ - &c2c - - /* - * [Codec2Codec-Multi]: cpu side only - * codec8/codec9/codec10/codec11 - */ - &c2c_m - >; - - multi { - #address-cells = <1>; - #size-cells = <0>; - - /* - * [Multi-CPU-0] - * - * +---+ +---+ - * cpu1 <--|A X|<-@------->|x a|-> codec1 - * cpu2 <--|B | | b|-> codec2 - * +---+ +---+ - */ - ports@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - mcpu0: port@0 { reg = <0>; mcpu00_ep: endpoint { remote-endpoint = <&mcodec00_ep>; };};/* (X) to pair */ - port@1 { reg = <1>; mcpu01_ep: endpoint { remote-endpoint = <&cpu1_ep>; };};/* (A) Multi Element */ - port@2 { reg = <2>; mcpu02_ep: endpoint { remote-endpoint = <&cpu2_ep>; };};/* (B) Multi Element */ - }; - - /* - * [Multi-Codec-0] - * - * +---+ +---+ - * cpu1 <--|A X|<-@------->|x a|-> codec1 - * cpu2 <--|B | | b|-> codec2 - * +---+ +---+ - */ - ports@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mcodec00_ep: endpoint { remote-endpoint = <&mcpu00_ep>; };};/* (x) to pair */ - port@1 { reg = <1>; mcodec01_ep: endpoint { remote-endpoint = <&codec1_ep>; };};/* (a) Multi Element */ - port@2 { reg = <2>; mcodec02_ep: endpoint { remote-endpoint = <&codec2_ep>; };};/* (b) Multi Element */ - }; - - /* - * [DPCM-Multi]::BE - * - * FE BE - * **** +---+ - * cpu5 <-@--* *-----@--->|x a|-> codec4 - * cpu6 <-@--* * | b|-> codec5 - * **** +---+ - */ - ports@2 { - reg = <2>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mbe_ep: endpoint { remote-endpoint = <&be10_ep>; };};/* (x) to pair */ - port@1 { reg = <1>; mbe1_ep: endpoint { remote-endpoint = <&codec4_ep>; };};/* (a) Multi Element */ - port@2 { reg = <2>; mbe2_ep: endpoint { remote-endpoint = <&codec5_ep>; };};/* (b) Multi Element */ - }; - - /* - * [Codec2Codec-Multi]::CPU - * - * +---+ - * +-@->|X A|-> codec8 - * | | B|-> codec9 - * | +---+ - * | +---+ - * +--->|x a|-> codec10 - * | b|-> codec11 - * +---+ - */ - ports@3 { - reg = <3>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mc2c0_ep: endpoint { remote-endpoint = <&c2cmf_ep>; };};/* (X) to pair */ - port@1 { reg = <1>; mc2c00_ep: endpoint { remote-endpoint = <&codec8_ep>; };};/* (A) Multi Element */ - port@2 { reg = <2>; mc2c01_ep: endpoint { remote-endpoint = <&codec9_ep>; };};/* (B) Multi Element */ - }; - - /* - * [Codec2Codec-Multi]::Codec - * - * +---+ - * +-@->|X A|-> codec8 - * | | B|-> codec9 - * | +---+ - * | +---+ - * +--->|x a|-> codec10 - * | b|-> codec11 - * +---+ - */ - ports@4 { - reg = <4>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mc2c1_ep: endpoint { remote-endpoint = <&c2cmb_ep>; };};/* (x) to pair */ - port@1 { reg = <1>; mc2c10_ep: endpoint { remote-endpoint = <&codec10_ep>; };};/* (a) Multi Element */ - port@2 { reg = <2>; mc2c11_ep: endpoint { remote-endpoint = <&codec11_ep>; };};/* (b) Multi Element */ - }; - - /* - * [Semi-Multi] - * - * +---+ - * cpu7 <-@------->|X A|-> codec12 - * | B|-> codec13 - * +---+ - */ - ports@5 { - reg = <5>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; smcodec0_ep: endpoint { remote-endpoint = <&cpu7_ep>; };};/* (X) to pair */ - port@1 { reg = <1>; smcodec1_ep: endpoint { remote-endpoint = <&codec12_ep>; };};/* (A) Multi Element */ - port@2 { reg = <2>; smcodec2_ep: endpoint { remote-endpoint = <&codec13_ep>; };};/* (B) Multi Element */ - }; - - /* - * [Multi-CPU-1] - * - * +---+ +---+ - * | X|<-@------->|x | - * | | | | - * cpu8 <--|A 1|<--------->|3 a|-> codec14 - * cpu9 <--|B 2|<---+----->|4 b|-> codec15 - * +---+ \---->|5 c|-> codec16 - * +---+ - */ - ports@6 { - reg = <6>; - #address-cells = <1>; - #size-cells = <0>; - mcpu1: port@0 { reg = <0>; mcpu10_ep: endpoint { remote-endpoint = <&mcodec10_ep>; };}; /* (X) to pair */ - port@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mcpu11_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu8_ep>; }; /* (A) Multi Element */ - mcpu11_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec11_ep_0>; }; /* (1) connected Codec */ - }; - port@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - mcpu12_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu9_ep>; }; /* (B) Multi Element */ - mcpu12_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec12_ep_0>; }; /* (2) connected Codec */ - mcpu12_ep_1: endpoint@2 { reg = <2>; remote-endpoint = <&mcodec13_ep_0>; }; /* (2) connected Codec */ - }; - }; - - /* - * [Multi-Codec-1] - * - * +---+ +---+ - * | X|<-@------->|x | - * | | | | - * cpu8 <--|A 1|<--------->|3 a|-> codec14 - * cpu9 <--|B 2|<---+----->|4 b|-> codec15 - * +---+ \---->|5 c|-> codec16 - * +---+ - */ - ports@7 { - reg = <7>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mcodec10_ep: endpoint { remote-endpoint = <&mcpu10_ep>; };}; /* (x) to pair */ - port@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mcodec11_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec14_ep>; }; /* (a) Multi Element */ - mcodec11_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu11_ep_0>; }; /* (3) connected CPU */ - }; - port@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - mcodec12_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec15_ep>; }; /* (b) Multi Element */ - mcodec12_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu12_ep_0>; }; /* (4) connected CPU */ - }; - port@3 { - #address-cells = <1>; - #size-cells = <0>; - reg = <3>; - mcodec13_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec16_ep>; }; /* (c) Multi Element */ - mcodec13_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu12_ep_1>; }; /* (5) connected CPU */ - }; - }; - - /* - * [Multi-CPU-2] - * - * +---+ +---+ - * | X|<-@------->|x | - * | | | | - * cpu10 <-|A 1|<--------->|4 a|-> codec17 - * cpu11 <-|B 2|<-----+--->|5 b|-> codec18 - * cpu12 <-|C 3|<----/ +---+ - * +---+ - */ - ports@8 { - reg = <8>; - #address-cells = <1>; - #size-cells = <0>; - mcpu2: port@0 { reg = <0>; mcpu20_ep: endpoint { remote-endpoint = <&mcodec20_ep>; };}; /* (X) to pair */ - port@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mcpu21_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu10_ep>; }; /* (A) Multi Element */ - mcpu21_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec21_ep_0>; }; /* (1) connected Codec */ - }; - port@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - mcpu22_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu11_ep>; }; /* (B) Multi Element */ - mcpu22_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec22_ep_0>; }; /* (2) connected Codec */ - }; - port@3 { - #address-cells = <1>; - #size-cells = <0>; - reg = <3>; - mcpu23_ep: endpoint@0 { reg = <0>; remote-endpoint = <&cpu12_ep>; }; /* (C) Multi Element */ - mcpu23_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcodec22_ep_1>; }; /* (3) connected Codec */ - }; - }; - - /* - * [Multi-Codec-2] - * - * +---+ +---+ - * | X|<-@------->|x | - * | | | | - * cpu10 <-|A 1|<--------->|4 a|-> codec17 - * cpu11 <-|B 2|<-----+--->|5 b|-> codec18 - * cpu12 <-|C 3|<----/ +---+ - * +---+ - */ - ports@9 { - reg = <9>; - #address-cells = <1>; - #size-cells = <0>; - port@0 { reg = <0>; mcodec20_ep: endpoint { remote-endpoint = <&mcpu20_ep>; };}; /* (x) to pair */ - port@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - mcodec21_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec17_ep>; }; /* (a) Multi Element */ - mcodec21_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu21_ep_0>; }; /* (4) connected CPU */ - }; - port@2 { - #address-cells = <1>; - #size-cells = <0>; - reg = <2>; - mcodec22_ep: endpoint@0 { reg = <0>; remote-endpoint = <&codec18_ep>; }; /* (b) Multi Element */ - mcodec22_ep_0: endpoint@1 { reg = <1>; remote-endpoint = <&mcpu22_ep_0>; }; /* (5) connected CPU */ - mcodec22_ep_1: endpoint@2 { reg = <2>; remote-endpoint = <&mcpu23_ep_0>; }; /* (5) connected CPU */ - }; - }; - }; - - dpcm { - #address-cells = <1>; - #size-cells = <0>; - - ports@0 { - reg = <0>; - - #address-cells = <1>; - #size-cells = <0>; - /* - * [DPCM]::FE - * - * FE BE - * **** - * cpu3 <-@(fe00)--* *--(be0)@--> codec3 - * cpu4 <-@(fe01)--* * (44.1kHz) - * **** - */ - fe00: port@0 { reg = <0>; fe00_ep: endpoint { remote-endpoint = <&cpu3_ep>; }; }; - fe01: port@1 { reg = <1>; fe01_ep: endpoint { remote-endpoint = <&cpu4_ep>; }; }; - - /* - * [DPCM-Multi]::FE - * - * FE BE - * **** +-+ - * cpu5 <-@(fe10)--* *---(be1)@-->| |-> codec4 - * cpu6 <-@(fe11)--* * | |-> codec5 - * **** +-+ - */ - fe10: port@2 { reg = <2>; fe10_ep: endpoint { remote-endpoint = <&cpu5_ep>; }; }; - fe11: port@3 { reg = <3>; fe11_ep: endpoint { remote-endpoint = <&cpu6_ep>; }; }; - }; - - ports@1 { - reg = <1>; - - #address-cells = <1>; - #size-cells = <0>; - /* - * [DPCM]::BE - * - * FE BE - * **** - * cpu3 <-@(fe00)--* *--(be0)@--> codec3 - * cpu4 <-@(fe01)--* * (44.1kHz) - * **** - */ - be0: port@0 { reg = <0>; be00_ep: endpoint { remote-endpoint = <&codec3_ep>; }; }; - - /* - * [DPCM-Multi]::BE - * - * FE BE - * **** +-+ - * cpu5 <-@(fe10)--* *---(be1)@-->| |-> codec4 - * cpu6 <-@(fe11)--* * | |-> codec5 - * **** +-+ - */ - be1: port@1 { reg = <1>; be10_ep: endpoint { remote-endpoint = <&mbe_ep>; }; }; - }; - }; - - codec2codec { - #address-cells = <1>; - #size-cells = <0>; - /* - * [Codec2Codec] - * - * +-@(c2c)-> codec6 - * | - * +--------> codec7 - */ - ports@0 { - reg = <0>; - - #address-cells = <1>; - #size-cells = <0>; - - /* use default settings */ - c2c: port@0 { reg = <0>; c2cf_ep: endpoint { remote-endpoint = <&codec6_ep>; }; }; - port@1 { reg = <1>; c2cb_ep: endpoint { remote-endpoint = <&codec7_ep>; }; }; - }; - - /* - * [Codec2Codec-Multi] - * - * +-+ - * +-@(c2c_m)-->| |-> codec8 - * | | |-> codec9 - * | +-+ - * | +-+ - * +----------->| |-> codec10 - * | |-> codec11 - * +-+ - */ - ports@1 { - reg = <1>; - - #address-cells = <1>; - #size-cells = <0>; - - /* use original settings */ - rate = <48000>; - c2c_m: port@0 { reg = <0>; c2cmf_ep: endpoint { remote-endpoint = <&mc2c0_ep>; }; }; - port@1 { reg = <1>; c2cmb_ep: endpoint { remote-endpoint = <&mc2c1_ep>; }; }; - }; - }; - }; - - test_cpu { - /* - * update compatible to indicate more detail behaviour - * if you want. see test-compatible for more detail. - * - * ex) - * - compatible = "test-cpu"; - * + compatible = "test-cpu-verbose"; - */ - compatible = "test-cpu"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - bitclock-master; - frame-master; - /* [Normal] */ - cpu0: port@0 { reg = <0>; cpu0_ep: endpoint { remote-endpoint = <&codec0_ep>; }; }; - - /* [Multi-CPU-0] */ - port@1 { reg = <1>; cpu1_ep: endpoint { remote-endpoint = <&mcpu01_ep>; }; }; - port@2 { reg = <2>; cpu2_ep: endpoint { remote-endpoint = <&mcpu02_ep>; }; }; - - /* [DPCM]::FE */ - port@3 { reg = <3>; cpu3_ep: endpoint { remote-endpoint = <&fe00_ep>; }; }; - port@4 { reg = <4>; cpu4_ep: endpoint { remote-endpoint = <&fe01_ep>; }; }; - - /* [DPCM-Multi]::FE */ - port@5 { reg = <5>; cpu5_ep: endpoint { remote-endpoint = <&fe10_ep>; }; }; - port@6 { reg = <6>; cpu6_ep: endpoint { remote-endpoint = <&fe11_ep>; }; }; - - /* [Semi-Multi] */ - sm0: port@7 { reg = <7>; cpu7_ep: endpoint { remote-endpoint = <&smcodec0_ep>; }; }; - - /* [Multi-CPU-1] */ - port@8 { reg = <8>; cpu8_ep: endpoint { remote-endpoint = <&mcpu11_ep>; }; }; - port@9 { reg = <9>; cpu9_ep: endpoint { remote-endpoint = <&mcpu12_ep>; }; }; - /* [Multi-CPU-2] */ - port@a { reg = <10>; cpu10_ep: endpoint { remote-endpoint = <&mcpu21_ep>; }; }; - port@b { reg = <11>; cpu11_ep: endpoint { remote-endpoint = <&mcpu22_ep>; }; }; - port@c { reg = <12>; cpu12_ep: endpoint { remote-endpoint = <&mcpu23_ep>; }; }; - }; - }; - - test_codec { - /* - * update compatible to indicate more detail behaviour - * if you want. see test-compatible for more detail. - * - * ex) - * - compatible = "test-codec"; - * + compatible = "test-codec-verbose"; - */ - compatible = "test-codec"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - /* - * prefix can be added to *component*, - * see audio-graph-card2::routing - */ - prefix = "TC"; - - /* [Normal] */ - port@0 { reg = <0>; codec0_ep: endpoint { remote-endpoint = <&cpu0_ep>; }; }; - - /* [Multi-Codec-0] */ - port@1 { reg = <1>; codec1_ep: endpoint { remote-endpoint = <&mcodec01_ep>; }; }; - port@2 { reg = <2>; codec2_ep: endpoint { remote-endpoint = <&mcodec02_ep>; }; }; - - /* [DPCM]::BE */ - port@3 { - convert-rate = <44100>; - reg = <3>; codec3_ep: endpoint { remote-endpoint = <&be00_ep>; }; - }; - - /* [DPCM-Multi]::BE */ - port@4 { reg = <4>; codec4_ep: endpoint { remote-endpoint = <&mbe1_ep>; }; }; - port@5 { reg = <5>; codec5_ep: endpoint { remote-endpoint = <&mbe2_ep>; }; }; - - /* [Codec2Codec] */ - port@6 { bitclock-master; - frame-master; - reg = <6>; codec6_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; }; - port@7 { reg = <7>; codec7_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; }; - - /* [Codec2Codec-Multi] */ - port@8 { bitclock-master; - frame-master; - reg = <8>; codec8_ep: endpoint { remote-endpoint = <&mc2c00_ep>; }; }; - port@9 { reg = <9>; codec9_ep: endpoint { remote-endpoint = <&mc2c01_ep>; }; }; - port@a { reg = <10>; codec10_ep: endpoint { remote-endpoint = <&mc2c10_ep>; }; }; - port@b { reg = <11>; codec11_ep: endpoint { remote-endpoint = <&mc2c11_ep>; }; }; - - /* [Semi-Multi] */ - port@c { reg = <12>; codec12_ep: endpoint { remote-endpoint = <&smcodec1_ep>; }; }; - port@d { reg = <13>; codec13_ep: endpoint { remote-endpoint = <&smcodec2_ep>; }; }; - - /* [Multi-Codec-1] */ - port@e { reg = <14>; codec14_ep: endpoint { remote-endpoint = <&mcodec11_ep>; }; }; - port@f { reg = <15>; codec15_ep: endpoint { remote-endpoint = <&mcodec12_ep>; }; }; - port@10 { reg = <16>; codec16_ep: endpoint { remote-endpoint = <&mcodec13_ep>; }; }; - /* [Multi-Codec-2] */ - port@11 { reg = <17>; codec17_ep: endpoint { remote-endpoint = <&mcodec21_ep>; }; }; - port@12 { reg = <18>; codec18_ep: endpoint { remote-endpoint = <&mcodec22_ep>; }; }; - }; - }; -}; From feb849404a8b677aa6760d1539acf597e4574337 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 23 Feb 2025 21:25:45 +0100 Subject: [PATCH 0544/1090] ASoC: SOF: Intel: hda-dai: Remove unnecessary bool conversion Remove the unnecessary bool conversion and simplify the code. Signed-off-by: Thorsten Blum Link: https://patch.msgid.link/20250223202547.1795-2-thorsten.blum@linux.dev Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index da12aabc1bb8..883d0d3bae9e 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -318,7 +318,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: ret = hda_link_dma_cleanup(substream, hext_stream, dai, - cmd == SNDRV_PCM_TRIGGER_STOP ? false : true); + cmd != SNDRV_PCM_TRIGGER_STOP); if (ret < 0) { dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); return ret; From a02c42d41af7d66db71ca43c52531c3253ebe35e Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Fri, 21 Feb 2025 03:21:41 +0000 Subject: [PATCH 0545/1090] ASoC: codecs: wsa883x: Implement temperature reading and hwmon Read temperature of the amplifier and expose it via hwmon interface, which will be later used during calibration of speaker protection algorithms. The method is the same as for wsa884x and therefore this is based on Krzysztof Kozlowski's approach implemented in commit 6b99dc62d940 ("ASoC: codecs: wsa884x: Implement temperature reading and hwmon"). Cc: Krzysztof Kozlowski Cc: Srinivas Kandagatla Cc: Steev Klimaszewski Signed-off-by: Alexey Klimov Tested-by: Steev Klimaszewski #Thinkpad X13s Link: https://patch.msgid.link/20250221032141.1206902-1-alexey.klimov@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wsa883x.c | 194 +++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index 47da5674d7c9..a5a6cb90bb43 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -156,8 +157,28 @@ #define WSA883X_PA_FSM_ERR_COND (WSA883X_DIG_CTRL_BASE + 0x0014) #define WSA883X_PA_FSM_MSK (WSA883X_DIG_CTRL_BASE + 0x0015) #define WSA883X_PA_FSM_BYP (WSA883X_DIG_CTRL_BASE + 0x0016) +#define WSA883X_PA_FSM_BYP_DC_CAL_EN_MASK 0x01 +#define WSA883X_PA_FSM_BYP_DC_CAL_EN_SHIFT 0 +#define WSA883X_PA_FSM_BYP_CLK_WD_EN_MASK 0x02 +#define WSA883X_PA_FSM_BYP_CLK_WD_EN_SHIFT 1 +#define WSA883X_PA_FSM_BYP_BG_EN_MASK 0x04 +#define WSA883X_PA_FSM_BYP_BG_EN_SHIFT 2 +#define WSA883X_PA_FSM_BYP_BOOST_EN_MASK 0x08 +#define WSA883X_PA_FSM_BYP_BOOST_EN_SHIFT 3 +#define WSA883X_PA_FSM_BYP_PA_EN_MASK 0x10 +#define WSA883X_PA_FSM_BYP_PA_EN_SHIFT 4 +#define WSA883X_PA_FSM_BYP_D_UNMUTE_MASK 0x20 +#define WSA883X_PA_FSM_BYP_D_UNMUTE_SHIFT 5 +#define WSA883X_PA_FSM_BYP_SPKR_PROT_EN_MASK 0x40 +#define WSA883X_PA_FSM_BYP_SPKR_PROT_EN_SHIFT 6 +#define WSA883X_PA_FSM_BYP_TSADC_EN_MASK 0x80 +#define WSA883X_PA_FSM_BYP_TSADC_EN_SHIFT 7 #define WSA883X_PA_FSM_DBG (WSA883X_DIG_CTRL_BASE + 0x0017) #define WSA883X_TADC_VALUE_CTL (WSA883X_DIG_CTRL_BASE + 0x0020) +#define WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK 0x01 +#define WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_SHIFT 0 +#define WSA883X_TADC_VALUE_CTL_VBAT_VALUE_RD_EN_MASK 0x02 +#define WSA883X_TADC_VALUE_CTL_VBAT_VALUE_RD_EN_SHIFT 1 #define WSA883X_TEMP_DETECT_CTL (WSA883X_DIG_CTRL_BASE + 0x0021) #define WSA883X_TEMP_MSB (WSA883X_DIG_CTRL_BASE + 0x0022) #define WSA883X_TEMP_LSB (WSA883X_DIG_CTRL_BASE + 0x0023) @@ -427,6 +448,17 @@ SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) +/* Two-point trimming for temperature calibration */ +#define WSA883X_T1_TEMP -10L +#define WSA883X_T2_TEMP 150L + +/* + * Device will report senseless data in many cases, so discard any measurements + * outside of valid range. + */ +#define WSA883X_LOW_TEMP_THRESHOLD 5 +#define WSA883X_HIGH_TEMP_THRESHOLD 45 + struct wsa883x_priv { struct regmap *regmap; struct device *dev; @@ -441,6 +473,13 @@ struct wsa883x_priv { int active_ports; int dev_mode; int comp_offset; + /* + * Protects temperature reading code (related to speaker protection) and + * fields: temperature and pa_on. + */ + struct mutex sp_lock; + unsigned int temperature; + bool pa_on; }; enum { @@ -1186,6 +1225,10 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: + mutex_lock(&wsa883x->sp_lock); + wsa883x->pa_on = true; + mutex_unlock(&wsa883x->sp_lock); + switch (wsa883x->dev_mode) { case RECEIVER: snd_soc_component_write_field(component, WSA883X_CDC_PATH_MODE, @@ -1235,6 +1278,9 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, WSA883X_GLOBAL_PA_EN_MASK, 0); snd_soc_component_write_field(component, WSA883X_PDM_WD_CTL, WSA883X_PDM_EN_MASK, 0); + mutex_lock(&wsa883x->sp_lock); + wsa883x->pa_on = false; + mutex_unlock(&wsa883x->sp_lock); break; } return 0; @@ -1367,6 +1413,140 @@ static struct snd_soc_dai_driver wsa883x_dais[] = { }, }; +static int wsa883x_get_temp(struct wsa883x_priv *wsa883x, long *temp) +{ + unsigned int d1_msb = 0, d1_lsb = 0, d2_msb = 0, d2_lsb = 0; + unsigned int dmeas_msb = 0, dmeas_lsb = 0; + int d1, d2, dmeas; + unsigned int mask; + int ret, range; + long val; + + guard(mutex)(&wsa883x->sp_lock); + + if (wsa883x->pa_on) { + /* + * Reading temperature is possible only when Power Amplifier is + * off. Report last cached data. + */ + *temp = wsa883x->temperature * 1000; + return 0; + } + + ret = pm_runtime_resume_and_get(wsa883x->dev); + if (ret < 0) + return ret; + + mask = WSA883X_PA_FSM_BYP_DC_CAL_EN_MASK | + WSA883X_PA_FSM_BYP_CLK_WD_EN_MASK | + WSA883X_PA_FSM_BYP_BG_EN_MASK | + WSA883X_PA_FSM_BYP_D_UNMUTE_MASK | + WSA883X_PA_FSM_BYP_SPKR_PROT_EN_MASK | + WSA883X_PA_FSM_BYP_TSADC_EN_MASK; + + /* + * Here and further do not care about read or update failures. + * For example, before turning the amplifier on for the first + * time, reading WSA883X_TEMP_DIN_MSB will always return 0. + * Instead, check if returned value is within reasonable + * thresholds. + */ + regmap_update_bits(wsa883x->regmap, WSA883X_PA_FSM_BYP, mask, mask); + + regmap_update_bits(wsa883x->regmap, WSA883X_TADC_VALUE_CTL, + WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, + FIELD_PREP(WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, 0x0)); + + regmap_read(wsa883x->regmap, WSA883X_TEMP_MSB, &dmeas_msb); + regmap_read(wsa883x->regmap, WSA883X_TEMP_LSB, &dmeas_lsb); + + regmap_update_bits(wsa883x->regmap, WSA883X_TADC_VALUE_CTL, + WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, + FIELD_PREP(WSA883X_TADC_VALUE_CTL_TEMP_VALUE_RD_EN_MASK, 0x1)); + + regmap_read(wsa883x->regmap, WSA883X_OTP_REG_1, &d1_msb); + regmap_read(wsa883x->regmap, WSA883X_OTP_REG_2, &d1_lsb); + regmap_read(wsa883x->regmap, WSA883X_OTP_REG_3, &d2_msb); + regmap_read(wsa883x->regmap, WSA883X_OTP_REG_4, &d2_lsb); + + regmap_update_bits(wsa883x->regmap, WSA883X_PA_FSM_BYP, mask, 0x0); + + dmeas = (((dmeas_msb & 0xff) << 0x8) | (dmeas_lsb & 0xff)) >> 0x6; + d1 = (((d1_msb & 0xff) << 0x8) | (d1_lsb & 0xff)) >> 0x6; + d2 = (((d2_msb & 0xff) << 0x8) | (d2_lsb & 0xff)) >> 0x6; + + if (d1 == d2) { + /* Incorrect data in OTP? */ + ret = -EINVAL; + goto out; + } + + val = WSA883X_T1_TEMP + (((dmeas - d1) * (WSA883X_T2_TEMP - WSA883X_T1_TEMP)) / (d2 - d1)); + range = WSA883X_HIGH_TEMP_THRESHOLD - WSA883X_LOW_TEMP_THRESHOLD; + if (in_range(val, WSA883X_LOW_TEMP_THRESHOLD, range)) { + wsa883x->temperature = val; + *temp = val * 1000; + ret = 0; + } else { + ret = -EAGAIN; + } +out: + pm_runtime_mark_last_busy(wsa883x->dev); + pm_runtime_put_autosuspend(wsa883x->dev); + + return ret; +} + +static umode_t wsa883x_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + return 0444; + default: + break; + } + + return 0; +} + +static int wsa883x_hwmon_read(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, long *temp) +{ + int ret; + + switch (attr) { + case hwmon_temp_input: + ret = wsa883x_get_temp(dev_get_drvdata(dev), temp); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static const struct hwmon_channel_info *const wsa883x_hwmon_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), + NULL +}; + +static const struct hwmon_ops wsa883x_hwmon_ops = { + .is_visible = wsa883x_hwmon_is_visible, + .read = wsa883x_hwmon_read, +}; + +static const struct hwmon_chip_info wsa883x_hwmon_chip_info = { + .ops = &wsa883x_hwmon_ops, + .info = wsa883x_hwmon_info, +}; + static int wsa883x_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) { @@ -1402,6 +1582,7 @@ static int wsa883x_probe(struct sdw_slave *pdev, wsa883x->sconfig.bps = 1; wsa883x->sconfig.direction = SDW_DATA_DIR_RX; wsa883x->sconfig.type = SDW_STREAM_PDM; + mutex_init(&wsa883x->sp_lock); /** * Port map index starts with 0, however the data port for this codec @@ -1424,6 +1605,19 @@ static int wsa883x_probe(struct sdw_slave *pdev, "regmap_init failed\n"); goto err; } + + if (IS_REACHABLE(CONFIG_HWMON)) { + struct device *hwmon; + + hwmon = devm_hwmon_device_register_with_info(dev, "wsa883x", + wsa883x, + &wsa883x_hwmon_chip_info, + NULL); + if (IS_ERR(hwmon)) + return dev_err_probe(dev, PTR_ERR(hwmon), + "Failed to register hwmon sensor\n"); + } + pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); pm_runtime_mark_last_busy(dev); From abcb9a1fd89144536f3ef604f700e94424867366 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 26 Feb 2025 18:05:05 +0800 Subject: [PATCH 0546/1090] ASoC: dt-bindings: fsl,sai: Document audio graph port This device can be used in conjunction with audio-graph-card to provide an endpoint for binding with the other side of the audio link. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250226100508.2352568-2-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,sai.yaml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml index a5d9c246cc47..5c95508ee707 100644 --- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml @@ -93,6 +93,24 @@ properties: items: - description: receive and transmit interrupt + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: port for TX and RX + + port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: port for TX only + + port@2: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: port for RX only + big-endian: description: | required if all the SAI registers are big-endian rather than little-endian. @@ -204,4 +222,37 @@ examples: dma-names = "rx", "tx"; fsl,dataline = <1 0xff 0xff 2 0xff 0x11>; #sound-dai-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + playback-only; + + sai1_endpoint0: endpoint { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-width-map = <32 8 32>; + dai-format = "dsp_a"; + bitclock-master; + frame-master; + remote-endpoint = <&mcodec01_ep>; + }; + }; + + port@2 { + reg = <2>; + capture-only; + + sai1_endpoint1: endpoint { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-width-map = <32 8 32>; + dai-format = "dsp_a"; + remote-endpoint = <&fe02_ep>; + }; + }; + }; }; From 5fee78e517ce0765def9387659fc56a1d5532c60 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 26 Feb 2025 18:05:06 +0800 Subject: [PATCH 0547/1090] ASoC: dt-bindings: fsl,audmix: Document audio graph port This device can be used in conjunction with audio-graph-card to provide an endpoint for binding with the other side of the audio link. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250226100508.2352568-3-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,audmix.yaml | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,audmix.yaml b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml index 9413b901cf77..d3b93407b4f0 100644 --- a/Documentation/devicetree/bindings/sound/fsl,audmix.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml @@ -61,6 +61,20 @@ properties: - description: serial audio input 2 maxItems: 1 + ports: + $ref: /schemas/graph.yaml#/properties/ports + patternProperties: + '^port@[0-1]': + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: Input port from SAI TX + + properties: + port@2: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: Output port to SAI RX + required: - compatible - reg @@ -80,4 +94,50 @@ examples: clock-names = "ipg"; power-domains = <&pd_audmix>; dais = <&sai4>, <&sai5>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + playback-only; + + amix_endpoint0: endpoint { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-width-map = <32 8 32>; + dai-format = "dsp_a"; + remote-endpoint = <&be00_ep>; + }; + }; + + port@1 { + reg = <1>; + playback-only; + + amix_endpoint1: endpoint { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-width-map = <32 8 32>; + dai-format = "dsp_a"; + remote-endpoint = <&be01_ep>; + }; + }; + + port@2 { + reg = <2>; + capture-only; + + amix_endpoint2: endpoint { + dai-tdm-slot-num = <8>; + dai-tdm-slot-width = <32>; + dai-tdm-slot-width-map = <32 8 32>; + dai-format = "dsp_a"; + bitclock-master; + frame-master; + remote-endpoint = <&be02_ep>; + }; + }; + }; }; From 597acf1a04bede55e3ad8a7922bba286c11112d3 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 26 Feb 2025 18:05:07 +0800 Subject: [PATCH 0548/1090] ASoC: dt-bindings: fsl,audmix: make 'dais' property to be optional Make 'dais' property to be optional. When there is no 'dais' property, driver won't register the card, dts should have audio graph card node for linking this device. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250226100508.2352568-4-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,audmix.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,audmix.yaml b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml index d3b93407b4f0..3ad197b3c82c 100644 --- a/Documentation/devicetree/bindings/sound/fsl,audmix.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml @@ -81,7 +81,6 @@ required: - clocks - clock-names - power-domains - - dais unevaluatedProperties: false From 294a60e5e9830045c161181286d44ce669f88833 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 26 Feb 2025 18:05:08 +0800 Subject: [PATCH 0549/1090] ASoC: fsl_audmix: register card device depends on 'dais' property In order to make the audmix device linked by audio graph card, make 'dais' property to be optional. If 'dais' property exists, then register the imx-audmix card driver. otherwise, it should be linked by audio graph card. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20250226100508.2352568-5-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 3cd9a66b70a1..7981d598ba13 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -488,11 +488,17 @@ static int fsl_audmix_probe(struct platform_device *pdev) goto err_disable_pm; } - priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0); - if (IS_ERR(priv->pdev)) { - ret = PTR_ERR(priv->pdev); - dev_err(dev, "failed to register platform: %d\n", ret); - goto err_disable_pm; + /* + * If dais property exist, then register the imx-audmix card driver. + * otherwise, it should be linked by audio graph card. + */ + if (of_find_property(pdev->dev.of_node, "dais", NULL)) { + priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0); + if (IS_ERR(priv->pdev)) { + ret = PTR_ERR(priv->pdev); + dev_err(dev, "failed to register platform: %d\n", ret); + goto err_disable_pm; + } } return 0; From 64e6a754d33d31aa844b3ee66fb93ac84ca1565e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 27 Feb 2025 08:26:42 +0000 Subject: [PATCH 0550/1090] llc: do not use skb_get() before dev_queue_xmit() syzbot is able to crash hosts [1], using llc and devices not supporting IFF_TX_SKB_SHARING. In this case, e1000 driver calls eth_skb_pad(), while the skb is shared. Simply replace skb_get() by skb_clone() in net/llc/llc_s_ac.c Note that e1000 driver might have an issue with pktgen, because it does not clear IFF_TX_SKB_SHARING, this is an orthogonal change. We need to audit other skb_get() uses in net/llc. [1] kernel BUG at net/core/skbuff.c:2178 ! Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI CPU: 0 UID: 0 PID: 16371 Comm: syz.2.2764 Not tainted 6.14.0-rc4-syzkaller-00052-gac9c34d1e45a #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:pskb_expand_head+0x6ce/0x1240 net/core/skbuff.c:2178 Call Trace: __skb_pad+0x18a/0x610 net/core/skbuff.c:2466 __skb_put_padto include/linux/skbuff.h:3843 [inline] skb_put_padto include/linux/skbuff.h:3862 [inline] eth_skb_pad include/linux/etherdevice.h:656 [inline] e1000_xmit_frame+0x2d99/0x5800 drivers/net/ethernet/intel/e1000/e1000_main.c:3128 __netdev_start_xmit include/linux/netdevice.h:5151 [inline] netdev_start_xmit include/linux/netdevice.h:5160 [inline] xmit_one net/core/dev.c:3806 [inline] dev_hard_start_xmit+0x9a/0x7b0 net/core/dev.c:3822 sch_direct_xmit+0x1ae/0xc30 net/sched/sch_generic.c:343 __dev_xmit_skb net/core/dev.c:4045 [inline] __dev_queue_xmit+0x13d4/0x43e0 net/core/dev.c:4621 dev_queue_xmit include/linux/netdevice.h:3313 [inline] llc_sap_action_send_test_c+0x268/0x320 net/llc/llc_s_ac.c:144 llc_exec_sap_trans_actions net/llc/llc_sap.c:153 [inline] llc_sap_next_state net/llc/llc_sap.c:182 [inline] llc_sap_state_process+0x239/0x510 net/llc/llc_sap.c:209 llc_ui_sendmsg+0xd0d/0x14e0 net/llc/af_llc.c:993 sock_sendmsg_nosec net/socket.c:718 [inline] Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot+da65c993ae113742a25f@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/67c020c0.050a0220.222324.0011.GAE@google.com/T/#u Signed-off-by: Eric Dumazet Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- net/llc/llc_s_ac.c | 49 +++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index 06fb8e6944b0..7a0cae9a8111 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -24,7 +24,7 @@ #include #include #include - +#include /** * llc_sap_action_unitdata_ind - forward UI PDU to network layer @@ -40,6 +40,26 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb) return 0; } +static int llc_prepare_and_xmit(struct sk_buff *skb) +{ + struct llc_sap_state_ev *ev = llc_sap_ev(skb); + struct sk_buff *nskb; + int rc; + + rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); + if (rc) + return rc; + + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) + return -ENOMEM; + + if (skb->sk) + skb_set_owner_w(nskb, skb->sk); + + return dev_queue_xmit(nskb); +} + /** * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer * @sap: SAP @@ -52,17 +72,12 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) { struct llc_sap_state_ev *ev = llc_sap_ev(skb); - int rc; llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap, ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_ui_cmd(skb); - rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) { - skb_get(skb); - rc = dev_queue_xmit(skb); - } - return rc; + + return llc_prepare_and_xmit(skb); } /** @@ -77,17 +92,12 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) { struct llc_sap_state_ev *ev = llc_sap_ev(skb); - int rc; llc_pdu_header_init(skb, LLC_PDU_TYPE_U_XID, ev->saddr.lsap, ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); - rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) { - skb_get(skb); - rc = dev_queue_xmit(skb); - } - return rc; + + return llc_prepare_and_xmit(skb); } /** @@ -133,17 +143,12 @@ out: int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) { struct llc_sap_state_ev *ev = llc_sap_ev(skb); - int rc; llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap, ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_test_cmd(skb); - rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (likely(!rc)) { - skb_get(skb); - rc = dev_queue_xmit(skb); - } - return rc; + + return llc_prepare_and_xmit(skb); } int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) From 10fce7ebe888fa8c97eee7e317a47e7603e5e78d Mon Sep 17 00:00:00 2001 From: Xinghuo Chen Date: Mon, 3 Mar 2025 07:57:33 -0500 Subject: [PATCH 0551/1090] hwmon: fix a NULL vs IS_ERR_OR_NULL() check in xgene_hwmon_probe() The devm_memremap() function returns error pointers on error, it doesn't return NULL. Fixes: c7cefce03e69 ("hwmon: (xgene) access mailbox as RAM") Signed-off-by: Xinghuo Chen Link: https://lore.kernel.org/r/tencent_9AD8E7683EC29CAC97496B44F3F865BA070A@qq.com Signed-off-by: Guenter Roeck --- drivers/hwmon/xgene-hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index 1e3bd129a922..7087197383c9 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -706,7 +706,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev) goto out; } - if (!ctx->pcc_comm_addr) { + if (IS_ERR_OR_NULL(ctx->pcc_comm_addr)) { dev_err(&pdev->dev, "Failed to ioremap PCC comm region\n"); rc = -ENOMEM; From 23e0832d6d7be2d3c713f9390c060b6f1c48bf36 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Tue, 18 Feb 2025 13:41:50 +0100 Subject: [PATCH 0552/1090] drm/sched: Fix preprocessor guard When writing the header guard for gpu_scheduler_trace.h, a typo, apparently, occurred. Fix the typo and document the scope of the guard. Fixes: 353da3c520b4 ("drm/amdgpu: add tracepoint for scheduler (v2)") Reviewed-by: Tvrtko Ursulin Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250218124149.118002-2-phasta@kernel.org --- drivers/gpu/drm/scheduler/gpu_scheduler_trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h index c75302ca3427..f56e77e7f6d0 100644 --- a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h +++ b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h @@ -21,7 +21,7 @@ * */ -#if !defined(_GPU_SCHED_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#if !defined(_GPU_SCHED_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) #define _GPU_SCHED_TRACE_H_ #include @@ -106,7 +106,7 @@ TRACE_EVENT(drm_sched_job_wait_dep, __entry->seqno) ); -#endif +#endif /* _GPU_SCHED_TRACE_H_ */ /* This part must be outside protection */ #undef TRACE_INCLUDE_PATH From b2653cd3b75f62f29b72df4070e20357acb52bc4 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 26 Feb 2025 17:25:32 -0800 Subject: [PATCH 0553/1090] KVM: SVM: Save host DR masks on CPUs with DebugSwap When running SEV-SNP guests on a CPU that supports DebugSwap, always save the host's DR0..DR3 mask MSR values irrespective of whether or not DebugSwap is enabled, to ensure the host values aren't clobbered by the CPU. And for now, also save DR0..DR3, even though doing so isn't necessary (see below). SVM_VMGEXIT_AP_CREATE is deeply flawed in that it allows the *guest* to create a VMSA with guest-controlled SEV_FEATURES. A well behaved guest can inform the hypervisor, i.e. KVM, of its "requested" features, but on CPUs without ALLOWED_SEV_FEATURES support, nothing prevents the guest from lying about which SEV features are being enabled (or not!). If a misbehaving guest enables DebugSwap in a secondary vCPU's VMSA, the CPU will load the DR0..DR3 mask MSRs on #VMEXIT, i.e. will clobber the MSRs with '0' if KVM doesn't save its desired value. Note, DR0..DR3 themselves are "ok", as DR7 is reset on #VMEXIT, and KVM restores all DRs in common x86 code as needed via hw_breakpoint_restore(). I.e. there is no risk of host DR0..DR3 being clobbered (when it matters). However, there is a flaw in the opposite direction; because the guest can lie about enabling DebugSwap, i.e. can *disable* DebugSwap without KVM's knowledge, KVM must not rely on the CPU to restore DRs. Defer fixing that wart, as it's more of a documentation issue than a bug in the code. Note, KVM added support for DebugSwap on commit d1f85fbe836e ("KVM: SEV: Enable data breakpoints in SEV-ES"), but that is not an appropriate Fixes, as the underlying flaw exists in hardware, not in KVM. I.e. all kernels that support SEV-SNP need to be patched, not just kernels with KVM's full support for DebugSwap (ignoring that DebugSwap support landed first). Opportunistically fix an incorrect statement in the comment; on CPUs without DebugSwap, the CPU does NOT save or load debug registers, i.e. Fixes: e366f92ea99e ("KVM: SEV: Support SEV-SNP AP Creation NAE event") Cc: stable@vger.kernel.org Cc: Naveen N Rao Cc: Kim Phillips Cc: Tom Lendacky Cc: Alexey Kardashevskiy Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20250227012541.3234589-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/sev.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index a2a794c32050..ef057c85a67c 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -4580,6 +4580,8 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm) void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_area *hostsa) { + struct kvm *kvm = svm->vcpu.kvm; + /* * All host state for SEV-ES guests is categorized into three swap types * based on how it is handled by hardware during a world switch: @@ -4603,10 +4605,15 @@ void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_are /* * If DebugSwap is enabled, debug registers are loaded but NOT saved by - * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both - * saves and loads debug registers (Type-A). + * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU does + * not save or load debug registers. Sadly, on CPUs without + * ALLOWED_SEV_FEATURES, KVM can't prevent SNP guests from enabling + * DebugSwap on secondary vCPUs without KVM's knowledge via "AP Create". + * Save all registers if DebugSwap is supported to prevent host state + * from being clobbered by a misbehaving guest. */ - if (sev_vcpu_has_debug_swap(svm)) { + if (sev_vcpu_has_debug_swap(svm) || + (sev_snp_guest(kvm) && cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP))) { hostsa->dr0 = native_get_debugreg(0); hostsa->dr1 = native_get_debugreg(1); hostsa->dr2 = native_get_debugreg(2); From 807cb9ce2ed9a1b6e79e70fb2cdb7860f1517dcc Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 26 Feb 2025 17:25:33 -0800 Subject: [PATCH 0554/1090] KVM: SVM: Don't rely on DebugSwap to restore host DR0..DR3 Never rely on the CPU to restore/load host DR0..DR3 values, even if the CPU supports DebugSwap, as there are no guarantees that SNP guests will actually enable DebugSwap on APs. E.g. if KVM were to rely on the CPU to load DR0..DR3 and skipped them during hw_breakpoint_restore(), KVM would run with clobbered-to-zero DRs if an SNP guest created APs without DebugSwap enabled. Update the comment to explain the dangers, and hopefully prevent breaking KVM in the future. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20250227012541.3234589-3-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/sev.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index ef057c85a67c..080f8cecd7ca 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -4606,18 +4606,21 @@ void sev_es_prepare_switch_to_guest(struct vcpu_svm *svm, struct sev_es_save_are /* * If DebugSwap is enabled, debug registers are loaded but NOT saved by * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU does - * not save or load debug registers. Sadly, on CPUs without - * ALLOWED_SEV_FEATURES, KVM can't prevent SNP guests from enabling - * DebugSwap on secondary vCPUs without KVM's knowledge via "AP Create". - * Save all registers if DebugSwap is supported to prevent host state - * from being clobbered by a misbehaving guest. + * not save or load debug registers. Sadly, KVM can't prevent SNP + * guests from lying about DebugSwap on secondary vCPUs, i.e. the + * SEV_FEATURES provided at "AP Create" isn't guaranteed to match what + * the guest has actually enabled (or not!) in the VMSA. + * + * If DebugSwap is *possible*, save the masks so that they're restored + * if the guest enables DebugSwap. But for the DRs themselves, do NOT + * rely on the CPU to restore the host values; KVM will restore them as + * needed in common code, via hw_breakpoint_restore(). Note, KVM does + * NOT support virtualizing Breakpoint Extensions, i.e. the mask MSRs + * don't need to be restored per se, KVM just needs to ensure they are + * loaded with the correct values *if* the CPU writes the MSRs. */ if (sev_vcpu_has_debug_swap(svm) || (sev_snp_guest(kvm) && cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP))) { - hostsa->dr0 = native_get_debugreg(0); - hostsa->dr1 = native_get_debugreg(1); - hostsa->dr2 = native_get_debugreg(2); - hostsa->dr3 = native_get_debugreg(3); hostsa->dr0_addr_mask = amd_get_dr_addr_mask(0); hostsa->dr1_addr_mask = amd_get_dr_addr_mask(1); hostsa->dr2_addr_mask = amd_get_dr_addr_mask(2); From d88ed5fb7c88f404e57fe2b2a6d19fefc35b4dc7 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 28 Feb 2025 15:08:04 -0800 Subject: [PATCH 0555/1090] KVM: selftests: Ensure all vCPUs hit -EFAULT during initial RO stage During the initial mprotect(RO) stage of mmu_stress_test, keep vCPUs spinning until all vCPUs have hit -EFAULT, i.e. until all vCPUs have tried to write to a read-only page. If a vCPU manages to complete an entire iteration of the loop without hitting a read-only page, *and* the vCPU observes mprotect_ro_done before starting a second iteration, then the vCPU will prematurely fall through to GUEST_SYNC(3) (on x86 and arm64) and get out of sequence. Replace the "do-while (!r)" loop around the associated _vcpu_run() with a single invocation, as barring a KVM bug, the vCPU is guaranteed to hit -EFAULT, and retrying on success is super confusion, hides KVM bugs, and complicates this fix. The do-while loop was semi-unintentionally added specifically to fudge around a KVM x86 bug, and said bug is unhittable without modifying the test to force x86 down the !(x86||arm64) path. On x86, if forced emulation is enabled, vcpu_arch_put_guest() may trigger emulation of the store to memory. Due a (very, very) longstanding bug in KVM x86's emulator, emulate writes to guest memory that fail during __kvm_write_guest_page() unconditionally return KVM_EXIT_MMIO. While that is desirable in the !memslot case, it's wrong in this case as the failure happens due to __copy_to_user() hitting a read-only page, not an emulated MMIO region. But as above, x86 only uses vcpu_arch_put_guest() if the __x86_64__ guards are clobbered to force x86 down the common path, and of course the unexpected MMIO is a KVM bug, i.e. *should* cause a test failure. Fixes: b6c304aec648 ("KVM: selftests: Verify KVM correctly handles mprotect(PROT_READ)") Reported-by: Yan Zhao Closes: https://lore.kernel.org/all/20250208105318.16861-1-yan.y.zhao@intel.com Debugged-by: Yan Zhao Reviewed-by: Yan Zhao Tested-by: Yan Zhao Link: https://lore.kernel.org/r/20250228230804.3845860-1-seanjc@google.com Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/mmu_stress_test.c | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/mmu_stress_test.c b/tools/testing/selftests/kvm/mmu_stress_test.c index d9c76b4c0d88..6a437d2be9fa 100644 --- a/tools/testing/selftests/kvm/mmu_stress_test.c +++ b/tools/testing/selftests/kvm/mmu_stress_test.c @@ -18,6 +18,7 @@ #include "ucall_common.h" static bool mprotect_ro_done; +static bool all_vcpus_hit_ro_fault; static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride) { @@ -36,9 +37,9 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride) /* * Write to the region while mprotect(PROT_READ) is underway. Keep - * looping until the memory is guaranteed to be read-only, otherwise - * vCPUs may complete their writes and advance to the next stage - * prematurely. + * looping until the memory is guaranteed to be read-only and a fault + * has occurred, otherwise vCPUs may complete their writes and advance + * to the next stage prematurely. * * For architectures that support skipping the faulting instruction, * generate the store via inline assembly to ensure the exact length @@ -56,7 +57,7 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride) #else vcpu_arch_put_guest(*((volatile uint64_t *)gpa), gpa); #endif - } while (!READ_ONCE(mprotect_ro_done)); + } while (!READ_ONCE(mprotect_ro_done) || !READ_ONCE(all_vcpus_hit_ro_fault)); /* * Only architectures that write the entire range can explicitly sync, @@ -81,6 +82,7 @@ struct vcpu_info { static int nr_vcpus; static atomic_t rendezvous; +static atomic_t nr_ro_faults; static void rendezvous_with_boss(void) { @@ -148,12 +150,16 @@ static void *vcpu_worker(void *data) * be stuck on the faulting instruction for other architectures. Go to * stage 3 without a rendezvous */ - do { - r = _vcpu_run(vcpu); - } while (!r); + r = _vcpu_run(vcpu); TEST_ASSERT(r == -1 && errno == EFAULT, "Expected EFAULT on write to RO memory, got r = %d, errno = %d", r, errno); + atomic_inc(&nr_ro_faults); + if (atomic_read(&nr_ro_faults) == nr_vcpus) { + WRITE_ONCE(all_vcpus_hit_ro_fault, true); + sync_global_to_guest(vm, all_vcpus_hit_ro_fault); + } + #if defined(__x86_64__) || defined(__aarch64__) /* * Verify *all* writes from the guest hit EFAULT due to the VMA now @@ -378,7 +384,6 @@ int main(int argc, char *argv[]) rendezvous_with_vcpus(&time_run2, "run 2"); mprotect(mem, slot_size, PROT_READ); - usleep(10); mprotect_ro_done = true; sync_global_to_guest(vm, mprotect_ro_done); From 3b2d3db368013729fd2167a0d91fec821dba807c Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 28 Feb 2025 15:38:52 -0800 Subject: [PATCH 0556/1090] KVM: selftests: Fix printf() format goof in SEV smoke test Print out the index of mismatching XSAVE bytes using unsigned decimal format. Some versions of clang complain about trying to print an integer as an unsigned char. x86/sev_smoke_test.c:55:51: error: format specifies type 'unsigned char' but the argument has type 'int' [-Werror,-Wformat] Fixes: 8c53183dbaa2 ("selftests: kvm: add test for transferring FPU state into VMSA") Link: https://lore.kernel.org/r/20250228233852.3855676-1-seanjc@google.com Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/x86/sev_smoke_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/x86/sev_smoke_test.c b/tools/testing/selftests/kvm/x86/sev_smoke_test.c index a1a688e75266..d97816dc476a 100644 --- a/tools/testing/selftests/kvm/x86/sev_smoke_test.c +++ b/tools/testing/selftests/kvm/x86/sev_smoke_test.c @@ -52,7 +52,8 @@ static void compare_xsave(u8 *from_host, u8 *from_guest) bool bad = false; for (i = 0; i < 4095; i++) { if (from_host[i] != from_guest[i]) { - printf("mismatch at %02hhx | %02hhx %02hhx\n", i, from_host[i], from_guest[i]); + printf("mismatch at %u | %02hhx %02hhx\n", + i, from_host[i], from_guest[i]); bad = true; } } From 9360dfe4cbd62ff1eb8217b815964931523b75b3 Mon Sep 17 00:00:00 2001 From: Andrea Righi Date: Mon, 3 Mar 2025 18:51:59 +0100 Subject: [PATCH 0557/1090] sched_ext: Validate prev_cpu in scx_bpf_select_cpu_dfl() If a BPF scheduler provides an invalid CPU (outside the nr_cpu_ids range) as prev_cpu to scx_bpf_select_cpu_dfl() it can cause a kernel crash. To prevent this, validate prev_cpu in scx_bpf_select_cpu_dfl() and trigger an scx error if an invalid CPU is specified. Fixes: f0e1a0643a59b ("sched_ext: Implement BPF extensible scheduler class") Cc: stable@vger.kernel.org # v6.12+ Signed-off-by: Andrea Righi Signed-off-by: Tejun Heo --- kernel/sched/ext.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 0f1da199cfc7..7b9dfee858e7 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -6422,6 +6422,9 @@ static bool check_builtin_idle_enabled(void) __bpf_kfunc s32 scx_bpf_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, bool *is_idle) { + if (!ops_cpu_valid(prev_cpu, NULL)) + goto prev_cpu; + if (!check_builtin_idle_enabled()) goto prev_cpu; From c01a74844b74c584160d5253f794bbd2af015bec Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:12 +0000 Subject: [PATCH 0558/1090] ASoC: Remove unused helper macro SOC_SINGLE_VALUE_EXT() has no users, so remove it. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 6bb2fca044c5..01151a6ada35 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -51,9 +51,6 @@ struct platform_device; .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) -#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .max = xmax, .invert = xinvert}) #define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ From b2b6913394488e031ee3d726f247b1c967057b40 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:13 +0000 Subject: [PATCH 0559/1090] ASoC: rt715: Remove duplicate SOC_DOUBLE_R_EXT() helper macro The rt715 does not appear to use the SOC_DOUBLE_R_EXT() macro and even if it did, the macro is defined identically in the ASoC headers. Remove the redundant macro definitions. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 8 -------- sound/soc/codecs/rt715.c | 8 -------- 2 files changed, 16 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 7e10fd913812..7fb02654c16b 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -427,14 +427,6 @@ static int rt715_sdca_fu_info(struct snd_kcontrol *kcontrol, .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, \ xshift, xinvert)} -#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ - xhandler_get, xhandler_put) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .info = snd_soc_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } - #define RT715_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ xhandler_put, tlv_array, xcount, xmax) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index 299c9b12377c..2cf461852091 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -486,14 +486,6 @@ static int rt715_vol_info(struct snd_kcontrol *kcontrol, return 0; } -#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ - xhandler_get, xhandler_put) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .info = snd_soc_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } - #define RT715_MAIN_SWITCH_EXT(xname, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = rt715_switch_info, \ From 17ec58ac3c08c5c43bbdf5b08020fa4188a3009a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:14 +0000 Subject: [PATCH 0560/1090] ASoC: sma1307: Use SOC_SINGLE_EXT() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/sma1307.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index 480bcea48541..dac17da9cedd 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1019,14 +1019,9 @@ static const struct snd_kcontrol_new sma1307_aif_out1_source_control = { .private_value = (unsigned long)&sma1307_aif_out_source_enum }; -static const struct snd_kcontrol_new sma1307_sdo_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Switch", - .info = snd_soc_info_volsw, - .get = sma1307_dapm_sdo_enable_get, - .put = sma1307_dapm_sdo_enable_put, - .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, 0, 1, 0, 0) -}; +static const struct snd_kcontrol_new sma1307_sdo_control = + SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, 0, 1, 0, + sma1307_dapm_sdo_enable_get, sma1307_dapm_sdo_enable_put); static const struct snd_kcontrol_new sma1307_enable_control = SOC_DAPM_SINGLE("Switch", SMA1307_00_SYSTEM_CTRL, 0, 1, 0); From aecdaa84adafb086b5b2939898d781bd63d6fe2e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:15 +0000 Subject: [PATCH 0561/1090] ASoC: tas2562: Use SOC_SINGLE_EXT_TLV() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index fef7ce39f664..8e00dcc09d0c 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -513,17 +513,9 @@ static const struct snd_kcontrol_new vsense_switch = static const struct snd_kcontrol_new tas2562_snd_controls[] = { SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0, tas2562_dac_tlv), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Volume Control", - .index = 0, - .tlv.p = dvc_tlv, - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_soc_info_volsw, - .get = tas2562_volume_control_get, - .put = tas2562_volume_control_put, - .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0), - }, + SOC_SINGLE_EXT_TLV("Digital Volume Control", TAS2562_DVC_CFG1, 0, 110, 0, + tas2562_volume_control_get, tas2562_volume_control_put, + dvc_tlv), }; static const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = { From 9bb7d7452363fc470b76766b0a6356807e752795 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:16 +0000 Subject: [PATCH 0562/1090] ASoC: wcd938x: Use SOC_SINGLE_EXT_TLV() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index f2a4f3262bdb..b536e8bdc5a7 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -70,13 +70,8 @@ #define WCD_MBHC_HS_V_MAX 1600 #define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ - .put = wcd938x_ear_pa_put_gain, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, snd_soc_get_volsw, \ + wcd938x_ear_pa_put_gain, tlv_array) enum { WCD9380 = 0, From bf19467b8512f855bdfae59ae78d326b1f434443 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:17 +0000 Subject: [PATCH 0563/1090] ASoC: wm9712: Use SOC_SINGLE_EXT() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm9712.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index e63921de0c37..8ff4b5f13b3a 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -275,13 +275,9 @@ static int wm9712_hp_mixer_get(struct snd_kcontrol *kcontrol, return 0; } -#define WM9712_HP_MIXER_CTRL(xname, xmixer, xshift) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = wm9712_hp_mixer_get, .put = wm9712_hp_mixer_put, \ - .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, \ - (xmixer << 8) | xshift, 1, 0, 0) \ -} +#define WM9712_HP_MIXER_CTRL(xname, xmixer, xshift) \ + SOC_SINGLE_EXT(xname, SND_SOC_NOPM, ((xmixer) << 8) | (xshift), \ + 1, 0, wm9712_hp_mixer_get, wm9712_hp_mixer_put) /* Left Headphone Mixers */ static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { From 516493232a9b80dd4f4f6b078541cfad00973dbb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:18 +0000 Subject: [PATCH 0564/1090] ASoC: wm9713: Use SOC_DOUBLE_EXT() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-8-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm9713.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 64b69316e4c7..0aa6491f2c84 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -284,13 +284,9 @@ static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol, return 0; } -#define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \ - .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \ - xshift, xmixer, 1, 0, 0) \ -} +#define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) \ + SOC_DOUBLE_EXT(xname, SND_SOC_NOPM, xshift, xmixer, 1, 0, \ + wm9713_hp_mixer_get, wm9713_hp_mixer_put) /* Left Headphone Mixers */ static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { From 98413be56faa1c12494f43e7f77746763fa41c4a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:19 +0000 Subject: [PATCH 0565/1090] ASoC: wsa881x: Use SOC_SINGLE_EXT_TLV() helper macro Rather than open coding use the helper macro provided by the ASoC core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-9-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wsa881x.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index dd2d6661adc7..a3999bb6d5e2 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -199,13 +199,8 @@ #define WSA881X_PROBE_TIMEOUT 1000 #define WSA881X_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ - .put = wsa881x_put_pa_gain, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ + snd_soc_get_volsw, wsa881x_put_pa_gain, tlv_array) static struct reg_default wsa881x_defaults[] = { { WSA881X_CHIP_ID0, 0x00 }, From 7c5b07b497eab8eba75cf5da00cba493216dfc12 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:20 +0000 Subject: [PATCH 0566/1090] ASoC: atmel: tse850-pcm5142: Use SOC_SINGLE_EXT() helper macro The TSE850_DAPM_SINGLE_EXT() macro is an identical duplicate of the core SOC_SINGLE_EXT() marco. Use the macro provided by the core. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-10-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 0a9efd5f2861..2a1d0408a4cf 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -227,16 +227,9 @@ static const struct snd_kcontrol_new mux1 = static const struct snd_kcontrol_new mux2 = SOC_DAPM_ENUM_EXT("MUX2", mux_enum, tse850_get_mux2, tse850_put_mux2); -#define TSE850_DAPM_SINGLE_EXT(xname, reg, shift, max, invert, xget, xput) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = xget, \ - .put = xput, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } - static const struct snd_kcontrol_new mix[] = { - TSE850_DAPM_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0, - tse850_get_mix, tse850_put_mix), + SOC_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0, + tse850_get_mix, tse850_put_mix), }; static const char * const ana_text[] = { From 9e6e7e088cb78ce58ea442106b1f29cd7b6ff76e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:21 +0000 Subject: [PATCH 0567/1090] ASoC: dapm: Add missing SOC_DAPM_DOUBLE_R_TLV() helper A few drivers are open coding SOC_DAPM_DOUBLE_R_TLV() add a core helper and use that instead. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-11-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 7 +++++++ sound/soc/codecs/jz4760.c | 32 ++++--------------------------- sound/soc/codecs/jz4770.c | 40 ++++++--------------------------------- 3 files changed, 17 insertions(+), 62 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 7cf52c8c9cf3..bed1c37529ac 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -347,6 +347,13 @@ struct soc_enum; .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } #define SOC_DAPM_SINGLE_VIRT(xname, max) \ SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0) +#define SOC_DAPM_DOUBLE_R_TLV(xname, lreg, rreg, shift, max, invert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_info_volsw, \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ + .private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) } #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c index 6217e611259f..e04af1b9ace8 100644 --- a/sound/soc/codecs/jz4760.c +++ b/sound/soc/codecs/jz4760.c @@ -314,37 +314,13 @@ static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = { }; static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Volume", - .info = snd_soc_info_volsw, - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ - | SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = dac_tlv, - .get = snd_soc_dapm_get_volsw, - .put = snd_soc_dapm_put_volsw, - .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6, - JZ4760_CODEC_REG_GCR5, - REG_GCR_GAIN_OFFSET, - REG_GCR_GAIN_MAX, 1), - }, + SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4760_CODEC_REG_GCR6, JZ4760_CODEC_REG_GCR5, + REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, dac_tlv), }; static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Volume", - .info = snd_soc_info_volsw, - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ - | SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = out_tlv, - .get = snd_soc_dapm_get_volsw, - .put = snd_soc_dapm_put_volsw, - .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2, - JZ4760_CODEC_REG_GCR1, - REG_GCR_GAIN_OFFSET, - REG_GCR_GAIN_MAX, 1), - }, + SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4760_CODEC_REG_GCR2, JZ4760_CODEC_REG_GCR1, + REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, out_tlv), }; static int hpout_event(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index acb9eaa7ea1c..312202ab5cea 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -331,43 +331,15 @@ static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = { }; static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Volume", - .info = snd_soc_info_volsw, - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ - | SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = dac_tlv, - .get = snd_soc_dapm_get_volsw, - .put = snd_soc_dapm_put_volsw, - /* - * NOTE: DACR/DACL are inversed; the gain value written to DACR - * seems to affect the left channel, and the gain value written - * to DACL seems to affect the right channel. - */ - .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR, - JZ4770_CODEC_REG_GCR_DACL, - REG_GCR_GAIN_OFFSET, - REG_GCR_GAIN_MAX, 1), - }, + SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4770_CODEC_REG_GCR_DACR, + JZ4770_CODEC_REG_GCR_DACL, REG_GCR_GAIN_OFFSET, + REG_GCR_GAIN_MAX, 1, dac_tlv), }; static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Volume", - .info = snd_soc_info_volsw, - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ - | SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = out_tlv, - .get = snd_soc_dapm_get_volsw, - .put = snd_soc_dapm_put_volsw, - /* HPR/HPL inversed for the same reason as above */ - .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR, - JZ4770_CODEC_REG_GCR_HPL, - REG_GCR_GAIN_OFFSET, - REG_GCR_GAIN_MAX, 1), - }, + SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4770_CODEC_REG_GCR_HPR, + JZ4770_CODEC_REG_GCR_HPL, REG_GCR_GAIN_OFFSET, + REG_GCR_GAIN_MAX, 1, out_tlv), }; static int hpout_event(struct snd_soc_dapm_widget *w, From c951b20766f019a263b3547b07627be52fff87b4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:22 +0000 Subject: [PATCH 0568/1090] ASoC: dapm: Use ASoC control macros where possible Update the DAPM kcontrol creation macros to use the ASoC macros where a helpful version exists. One minor fixup is required in adau17x1, the compiler doesn't like the extra level of macro indirection coupled with the inline struct definition. Make the struct definition explicit. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-12-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 66 ++++++++++++++----------------------- sound/soc/codecs/adau17x1.c | 10 +++--- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index bed1c37529ac..4b8ef5b8a391 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -326,41 +326,37 @@ struct soc_enum; /* dapm kcontrol types */ #define SOC_DAPM_DOUBLE(xname, reg, lshift, rshift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_DOUBLE_VALUE(reg, lshift, rshift, max, invert, 0) } + SOC_DOUBLE_EXT(xname, reg, lshift, rshift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) #define SOC_DAPM_DOUBLE_R(xname, lreg, rreg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) } + SOC_DOUBLE_R_EXT(xname, lreg, rreg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) +#define SOC_DAPM_SINGLE_VIRT(xname, max) \ + SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0) +#define SOC_DAPM_DOUBLE_R_TLV(xname, lreg, rreg, shift, max, invert, tlv_array) \ + SOC_DOUBLE_R_EXT_TLV(xname, lreg, rreg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \ + tlv_array) +#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ + SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \ + tlv_array) +#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ + SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) +#define SOC_DAPM_ENUM(xname, xenum) \ + SOC_ENUM_EXT(xname, xenum, snd_soc_dapm_get_enum_double, \ + snd_soc_dapm_put_enum_double) +#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ + SOC_ENUM_EXT(xname, xenum, xget, xput) + #define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } -#define SOC_DAPM_SINGLE_VIRT(xname, max) \ - SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0) -#define SOC_DAPM_DOUBLE_R_TLV(xname, lreg, rreg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) } -#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } #define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ @@ -368,20 +364,6 @@ struct soc_enum; .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } -#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ - SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) -#define SOC_DAPM_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = snd_soc_dapm_put_enum_double, \ - .private_value = (unsigned long)&xenum } -#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = xget, \ - .put = xput, \ - .private_value = (unsigned long)&xenum } #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 4dcc984761e0..2ebb5c90bdd9 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -254,11 +254,13 @@ static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol, } #define DECLARE_ADAU17X1_DSP_MUX_CTRL(_name, _label, _stream, _text) \ - const struct snd_kcontrol_new _name = \ - SOC_DAPM_ENUM_EXT(_label, (const struct soc_enum)\ + const struct soc_enum _name##_enum = \ SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \ - ARRAY_SIZE(_text), _text), \ - adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put) + ARRAY_SIZE(_text), _text); \ + const struct snd_kcontrol_new _name = \ + SOC_DAPM_ENUM_EXT(_label, _name##_enum, \ + adau17x1_dsp_mux_enum_get, \ + adau17x1_dsp_mux_enum_put) static const char * const adau17x1_dac_mux_text[] = { "DSP", From 1743dbb45b2cbe5500068900794a355a7e0dd853 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 3 Mar 2025 17:14:23 +0000 Subject: [PATCH 0569/1090] ASoC: Tidy up SOC_DOUBLE_R_* helpers Re-implement SOC_DOUBLE_R_VALUE() in terms of SOC_DOUBLE_R_S_VALUE(). SOC_DOUBLE_R_S_VALUE() already had a minimum value so add this to SOC_DOUBLE_R_VALUE() as well, which makes SOC_DOUBLE_R_RANGE_VALUE() redundant, so its usage is replaced. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250303171424.444556-13-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 01151a6ada35..390e08ba4dd4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -51,19 +51,14 @@ struct platform_device; .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) -#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .max = xmax, .invert = xinvert}) #define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin, .sign_bit = xsign_bit, \ .invert = xinvert}) -#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .min = xmin, .max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ + SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, 0, xinvert) + #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ @@ -127,13 +122,13 @@ struct platform_device; .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw_range, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -176,7 +171,7 @@ struct platform_device; .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -185,7 +180,7 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_range, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -195,10 +190,7 @@ struct platform_device; .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx, \ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xrreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_DOUBLE_R_VALUE(xreg, xrreg, xshift, xmin, xmax, 0) } #define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -272,7 +264,7 @@ struct platform_device; .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -313,7 +305,7 @@ struct platform_device; .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \ xsign_bit, xinvert, xhandler_get, xhandler_put, \ tlv_array) \ From cc5bfc4e16fc1d1c520cd7bb28646e82b6e69217 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Thu, 30 Jan 2025 23:49:31 +0000 Subject: [PATCH 0570/1090] usb: dwc3: Set SUSPENDENABLE soon after phy init After phy initialization, some phy operations can only be executed while in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid blocking phy ops. Previously the SUSPENDENABLE bits are only set after the controller initialization, which may not happen right away if there's no gadget driver or xhci driver bound. Revise this to clear SUSPENDENABLE bits only when there's mode switching (change in GCTL.PRTCAPDIR). Fixes: 6d735722063a ("usb: dwc3: core: Prevent phy suspend during init") Cc: stable Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/633aef0afee7d56d2316f7cc3e1b2a6d518a8cc9.1738280911.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 69 +++++++++++++++++++++++++---------------- drivers/usb/dwc3/core.h | 2 +- drivers/usb/dwc3/drd.c | 4 +-- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2c472cb97f6c..66a08b527165 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -131,11 +131,24 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) } } -void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) +void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) { + unsigned int hw_mode; u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GCTL); + + /* + * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE and + * GUSB2PHYCFG.SUSPHY should be cleared during mode switching, + * and they can be set after core initialization. + */ + hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); + if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && !ignore_susphy) { + if (DWC3_GCTL_PRTCAP(reg) != mode) + dwc3_enable_susphy(dwc, false); + } + reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); dwc3_writel(dwc->regs, DWC3_GCTL, reg); @@ -216,7 +229,7 @@ static void __dwc3_set_mode(struct work_struct *work) spin_lock_irqsave(&dwc->lock, flags); - dwc3_set_prtcap(dwc, desired_dr_role); + dwc3_set_prtcap(dwc, desired_dr_role, false); spin_unlock_irqrestore(&dwc->lock, flags); @@ -658,16 +671,7 @@ static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index) */ reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; - /* - * Above DWC_usb3.0 1.94a, it is recommended to set - * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration. - * So default value will be '0' when the core is reset. Application - * needs to set it to '1' after the core initialization is completed. - * - * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be - * cleared after power-on reset, and it can be set after core - * initialization. - */ + /* Ensure the GUSB3PIPECTL.SUSPENDENABLE is cleared prior to phy init. */ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; if (dwc->u2ss_inp3_quirk) @@ -747,15 +751,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index) break; } - /* - * Above DWC_usb3.0 1.94a, it is recommended to set - * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration. - * So default value will be '0' when the core is reset. Application - * needs to set it to '1' after the core initialization is completed. - * - * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared - * after power-on reset, and it can be set after core initialization. - */ + /* Ensure the GUSB2PHYCFG.SUSPHY is cleared prior to phy init. */ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_enblslpm_quirk) @@ -830,6 +826,25 @@ static int dwc3_phy_init(struct dwc3 *dwc) goto err_exit_usb3_phy; } + /* + * Above DWC_usb3.0 1.94a, it is recommended to set + * DWC3_GUSB3PIPECTL_SUSPHY and DWC3_GUSB2PHYCFG_SUSPHY to '0' during + * coreConsultant configuration. So default value will be '0' when the + * core is reset. Application needs to set it to '1' after the core + * initialization is completed. + * + * Certain phy requires to be in P0 power state during initialization. + * Make sure GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY are clear + * prior to phy init to maintain in the P0 state. + * + * After phy initialization, some phy operations can only be executed + * while in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and + * GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid + * blocking phy ops. + */ + if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) + dwc3_enable_susphy(dwc, true); + return 0; err_exit_usb3_phy: @@ -1588,7 +1603,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, false); if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, false); @@ -1600,7 +1615,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) return dev_err_probe(dev, ret, "failed to initialize gadget\n"); break; case USB_DR_MODE_HOST: - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, false); if (dwc->usb2_phy) otg_set_vbus(dwc->usb2_phy->otg, true); @@ -1645,7 +1660,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) } /* de-assert DRVVBUS for HOST and OTG mode */ - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true); } static void dwc3_get_software_properties(struct dwc3 *dwc) @@ -2453,7 +2468,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) if (ret) return ret; - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true); dwc3_gadget_resume(dwc); break; case DWC3_GCTL_PRTCAP_HOST: @@ -2461,7 +2476,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, true); break; } /* Restore GUSB2PHYCFG bits that were modified in suspend */ @@ -2490,7 +2505,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) if (ret) return ret; - dwc3_set_prtcap(dwc, dwc->current_dr_role); + dwc3_set_prtcap(dwc, dwc->current_dr_role, true); dwc3_otg_init(dwc); if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) { diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c955039bb4f6..aaa39e663f60 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1558,7 +1558,7 @@ struct dwc3_gadget_ep_cmd_params { #define DWC3_HAS_OTG BIT(3) /* prototypes */ -void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode); +void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy); void dwc3_set_mode(struct dwc3 *dwc, u32 mode); u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index d76ae676783c..7977860932b1 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -173,7 +173,7 @@ void dwc3_otg_init(struct dwc3 *dwc) * block "Initialize GCTL for OTG operation". */ /* GCTL.PrtCapDir=2'b11 */ - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true); /* GUSB2PHYCFG0.SusPHY=0 */ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; @@ -556,7 +556,7 @@ int dwc3_drd_init(struct dwc3 *dwc) dwc3_drd_update(dwc); } else { - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true); /* use OTG block to get ID event */ irq = dwc3_otg_get_irq(dwc); From dfd3df31c9db752234d7d2e09bef2aeabb643ce4 Mon Sep 17 00:00:00 2001 From: "Uladzislau Rezki (Sony)" Date: Fri, 28 Feb 2025 13:13:56 +0100 Subject: [PATCH 0571/1090] mm/slab/kvfree_rcu: Switch to WQ_MEM_RECLAIM wq Currently kvfree_rcu() APIs use a system workqueue which is "system_unbound_wq" to driver RCU machinery to reclaim a memory. Recently, it has been noted that the following kernel warning can be observed: workqueue: WQ_MEM_RECLAIM nvme-wq:nvme_scan_work is flushing !WQ_MEM_RECLAIM events_unbound:kfree_rcu_work WARNING: CPU: 21 PID: 330 at kernel/workqueue.c:3719 check_flush_dependency+0x112/0x120 Modules linked in: intel_uncore_frequency(E) intel_uncore_frequency_common(E) skx_edac(E) ... CPU: 21 UID: 0 PID: 330 Comm: kworker/u144:6 Tainted: G E 6.13.2-0_g925d379822da #1 Hardware name: Wiwynn Twin Lakes MP/Twin Lakes Passive MP, BIOS YMM20 02/01/2023 Workqueue: nvme-wq nvme_scan_work RIP: 0010:check_flush_dependency+0x112/0x120 Code: 05 9a 40 14 02 01 48 81 c6 c0 00 00 00 48 8b 50 18 48 81 c7 c0 00 00 00 48 89 f9 48 ... RSP: 0018:ffffc90000df7bd8 EFLAGS: 00010082 RAX: 000000000000006a RBX: ffffffff81622390 RCX: 0000000000000027 RDX: 00000000fffeffff RSI: 000000000057ffa8 RDI: ffff88907f960c88 RBP: 0000000000000000 R08: ffffffff83068e50 R09: 000000000002fffd R10: 0000000000000004 R11: 0000000000000000 R12: ffff8881001a4400 R13: 0000000000000000 R14: ffff88907f420fb8 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88907f940000(0000) knlGS:0000000000000000 CR2: 00007f60c3001000 CR3: 000000107d010005 CR4: 00000000007726f0 PKRU: 55555554 Call Trace: ? __warn+0xa4/0x140 ? check_flush_dependency+0x112/0x120 ? report_bug+0xe1/0x140 ? check_flush_dependency+0x112/0x120 ? handle_bug+0x5e/0x90 ? exc_invalid_op+0x16/0x40 ? asm_exc_invalid_op+0x16/0x20 ? timer_recalc_next_expiry+0x190/0x190 ? check_flush_dependency+0x112/0x120 ? check_flush_dependency+0x112/0x120 __flush_work.llvm.1643880146586177030+0x174/0x2c0 flush_rcu_work+0x28/0x30 kvfree_rcu_barrier+0x12f/0x160 kmem_cache_destroy+0x18/0x120 bioset_exit+0x10c/0x150 disk_release.llvm.6740012984264378178+0x61/0xd0 device_release+0x4f/0x90 kobject_put+0x95/0x180 nvme_put_ns+0x23/0xc0 nvme_remove_invalid_namespaces+0xb3/0xd0 nvme_scan_work+0x342/0x490 process_scheduled_works+0x1a2/0x370 worker_thread+0x2ff/0x390 ? pwq_release_workfn+0x1e0/0x1e0 kthread+0xb1/0xe0 ? __kthread_parkme+0x70/0x70 ret_from_fork+0x30/0x40 ? __kthread_parkme+0x70/0x70 ret_from_fork_asm+0x11/0x20 ---[ end trace 0000000000000000 ]--- To address this switch to use of independent WQ_MEM_RECLAIM workqueue, so the rules are not violated from workqueue framework point of view. Apart of that, since kvfree_rcu() does reclaim memory it is worth to go with WQ_MEM_RECLAIM type of wq because it is designed for this purpose. Fixes: 6c6c47b063b5 ("mm, slab: call kvfree_rcu_barrier() from kmem_cache_destroy()"), Reported-by: Keith Busch Closes: https://lore.kernel.org/all/Z7iqJtCjHKfo8Kho@kbusch-mbp/ Cc: stable@vger.kernel.org Signed-off-by: Uladzislau Rezki (Sony) Reviewed-by: Joel Fernandes Signed-off-by: Vlastimil Babka --- mm/slab_common.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mm/slab_common.c b/mm/slab_common.c index 4030907b6b7d..4c9f0a87f733 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1304,6 +1304,8 @@ module_param(rcu_min_cached_objs, int, 0444); static int rcu_delay_page_cache_fill_msec = 5000; module_param(rcu_delay_page_cache_fill_msec, int, 0444); +static struct workqueue_struct *rcu_reclaim_wq; + /* Maximum number of jiffies to wait before draining a batch. */ #define KFREE_DRAIN_JIFFIES (5 * HZ) #define KFREE_N_BATCHES 2 @@ -1632,10 +1634,10 @@ __schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp) if (delayed_work_pending(&krcp->monitor_work)) { delay_left = krcp->monitor_work.timer.expires - jiffies; if (delay < delay_left) - mod_delayed_work(system_unbound_wq, &krcp->monitor_work, delay); + mod_delayed_work(rcu_reclaim_wq, &krcp->monitor_work, delay); return; } - queue_delayed_work(system_unbound_wq, &krcp->monitor_work, delay); + queue_delayed_work(rcu_reclaim_wq, &krcp->monitor_work, delay); } static void @@ -1733,7 +1735,7 @@ kvfree_rcu_queue_batch(struct kfree_rcu_cpu *krcp) // "free channels", the batch can handle. Break // the loop since it is done with this CPU thus // queuing an RCU work is _always_ success here. - queued = queue_rcu_work(system_unbound_wq, &krwp->rcu_work); + queued = queue_rcu_work(rcu_reclaim_wq, &krwp->rcu_work); WARN_ON_ONCE(!queued); break; } @@ -1883,7 +1885,7 @@ run_page_cache_worker(struct kfree_rcu_cpu *krcp) if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING && !atomic_xchg(&krcp->work_in_progress, 1)) { if (atomic_read(&krcp->backoff_page_cache_fill)) { - queue_delayed_work(system_unbound_wq, + queue_delayed_work(rcu_reclaim_wq, &krcp->page_cache_work, msecs_to_jiffies(rcu_delay_page_cache_fill_msec)); } else { @@ -2120,6 +2122,10 @@ void __init kvfree_rcu_init(void) int i, j; struct shrinker *kfree_rcu_shrinker; + rcu_reclaim_wq = alloc_workqueue("kvfree_rcu_reclaim", + WQ_UNBOUND | WQ_MEM_RECLAIM, 0); + WARN_ON(!rcu_reclaim_wq); + /* Clamp it to [0:100] seconds interval. */ if (rcu_delay_page_cache_fill_msec < 0 || rcu_delay_page_cache_fill_msec > 100 * MSEC_PER_SEC) { From 8177c6bedb7013cf736137da586cf783922309dd Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Tue, 4 Mar 2025 09:51:12 +0100 Subject: [PATCH 0572/1090] x86/cacheinfo: Validate CPUID leaf 0x2 EDX output CPUID leaf 0x2 emits one-byte descriptors in its four output registers EAX, EBX, ECX, and EDX. For these descriptors to be valid, the most significant bit (MSB) of each register must be clear. The historical Git commit: 019361a20f016 ("- pre6: Intel: start to add Pentium IV specific stuff (128-byte cacheline etc)...") introduced leaf 0x2 output parsing. It only validated the MSBs of EAX, EBX, and ECX, but left EDX unchecked. Validate EDX's most-significant bit. Signed-off-by: Ahmed S. Darwish Signed-off-by: Ingo Molnar Cc: stable@vger.kernel.org Cc: "H. Peter Anvin" Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250304085152.51092-2-darwi@linutronix.de --- arch/x86/kernel/cpu/cacheinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c index e6fa03ed9172..a6c6bccfa8b8 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -808,7 +808,7 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c) cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); /* If bit 31 is set, this is an unknown format */ - for (j = 0 ; j < 3 ; j++) + for (j = 0 ; j < 4 ; j++) if (regs[j] & (1 << 31)) regs[j] = 0; From 1881148215c67151b146450fb89ec22fd92337a7 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Tue, 4 Mar 2025 09:51:13 +0100 Subject: [PATCH 0573/1090] x86/cpu: Validate CPUID leaf 0x2 EDX output CPUID leaf 0x2 emits one-byte descriptors in its four output registers EAX, EBX, ECX, and EDX. For these descriptors to be valid, the most significant bit (MSB) of each register must be clear. Leaf 0x2 parsing at intel.c only validated the MSBs of EAX, EBX, and ECX, but left EDX unchecked. Validate EDX's most-significant bit as well. Fixes: e0ba94f14f74 ("x86/tlb_info: get last level TLB entry number of CPU") Signed-off-by: Ahmed S. Darwish Signed-off-by: Ingo Molnar Cc: stable@kernel.org Cc: "H. Peter Anvin" Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250304085152.51092-3-darwi@linutronix.de --- arch/x86/kernel/cpu/intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 3dce22f00dc3..2a3716afee63 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -799,7 +799,7 @@ static void intel_detect_tlb(struct cpuinfo_x86 *c) cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); /* If bit 31 is set, this is an unknown format */ - for (j = 0 ; j < 3 ; j++) + for (j = 0 ; j < 4 ; j++) if (regs[j] & (1 << 31)) regs[j] = 0; From f6bdaab79ee4228a143ee1b4cb80416d6ffc0c63 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Tue, 4 Mar 2025 09:51:14 +0100 Subject: [PATCH 0574/1090] x86/cpu: Properly parse CPUID leaf 0x2 TLB descriptor 0x63 CPUID leaf 0x2's one-byte TLB descriptors report the number of entries for specific TLB types, among other properties. Typically, each emitted descriptor implies the same number of entries for its respective TLB type(s). An emitted 0x63 descriptor is an exception: it implies 4 data TLB entries for 1GB pages and 32 data TLB entries for 2MB or 4MB pages. For the TLB descriptors parsing code, the entry count for 1GB pages is encoded at the intel_tlb_table[] mapping, but the 2MB/4MB entry count is totally ignored. Update leaf 0x2's parsing logic 0x2 to account for 32 data TLB entries for 2MB/4MB pages implied by the 0x63 descriptor. Fixes: e0ba94f14f74 ("x86/tlb_info: get last level TLB entry number of CPU") Signed-off-by: Ahmed S. Darwish Signed-off-by: Ingo Molnar Cc: stable@kernel.org Cc: "H. Peter Anvin" Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250304085152.51092-4-darwi@linutronix.de --- arch/x86/kernel/cpu/intel.c | 50 +++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 2a3716afee63..134368a3f4b1 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -635,26 +635,37 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) } #endif -#define TLB_INST_4K 0x01 -#define TLB_INST_4M 0x02 -#define TLB_INST_2M_4M 0x03 +#define TLB_INST_4K 0x01 +#define TLB_INST_4M 0x02 +#define TLB_INST_2M_4M 0x03 -#define TLB_INST_ALL 0x05 -#define TLB_INST_1G 0x06 +#define TLB_INST_ALL 0x05 +#define TLB_INST_1G 0x06 -#define TLB_DATA_4K 0x11 -#define TLB_DATA_4M 0x12 -#define TLB_DATA_2M_4M 0x13 -#define TLB_DATA_4K_4M 0x14 +#define TLB_DATA_4K 0x11 +#define TLB_DATA_4M 0x12 +#define TLB_DATA_2M_4M 0x13 +#define TLB_DATA_4K_4M 0x14 -#define TLB_DATA_1G 0x16 +#define TLB_DATA_1G 0x16 +#define TLB_DATA_1G_2M_4M 0x17 -#define TLB_DATA0_4K 0x21 -#define TLB_DATA0_4M 0x22 -#define TLB_DATA0_2M_4M 0x23 +#define TLB_DATA0_4K 0x21 +#define TLB_DATA0_4M 0x22 +#define TLB_DATA0_2M_4M 0x23 -#define STLB_4K 0x41 -#define STLB_4K_2M 0x42 +#define STLB_4K 0x41 +#define STLB_4K_2M 0x42 + +/* + * All of leaf 0x2's one-byte TLB descriptors implies the same number of + * entries for their respective TLB types. The 0x63 descriptor is an + * exception: it implies 4 dTLB entries for 1GB pages 32 dTLB entries + * for 2MB or 4MB pages. Encode descriptor 0x63 dTLB entry count for + * 2MB/4MB pages here, as its count for dTLB 1GB pages is already at the + * intel_tlb_table[] mapping. + */ +#define TLB_0x63_2M_4M_ENTRIES 32 static const struct _tlb_table intel_tlb_table[] = { { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" }, @@ -676,7 +687,8 @@ static const struct _tlb_table intel_tlb_table[] = { { 0x5c, TLB_DATA_4K_4M, 128, " TLB_DATA 4 KByte and 4 MByte pages" }, { 0x5d, TLB_DATA_4K_4M, 256, " TLB_DATA 4 KByte and 4 MByte pages" }, { 0x61, TLB_INST_4K, 48, " TLB_INST 4 KByte pages, full associative" }, - { 0x63, TLB_DATA_1G, 4, " TLB_DATA 1 GByte pages, 4-way set associative" }, + { 0x63, TLB_DATA_1G_2M_4M, 4, " TLB_DATA 1 GByte pages, 4-way set associative" + " (plus 32 entries TLB_DATA 2 MByte or 4 MByte pages, not encoded here)" }, { 0x6b, TLB_DATA_4K, 256, " TLB_DATA 4 KByte pages, 8-way associative" }, { 0x6c, TLB_DATA_2M_4M, 128, " TLB_DATA 2 MByte or 4 MByte pages, 8-way associative" }, { 0x6d, TLB_DATA_1G, 16, " TLB_DATA 1 GByte pages, fully associative" }, @@ -776,6 +788,12 @@ static void intel_tlb_lookup(const unsigned char desc) if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries) tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries; break; + case TLB_DATA_1G_2M_4M: + if (tlb_lld_2m[ENTRIES] < TLB_0x63_2M_4M_ENTRIES) + tlb_lld_2m[ENTRIES] = TLB_0x63_2M_4M_ENTRIES; + if (tlb_lld_4m[ENTRIES] < TLB_0x63_2M_4M_ENTRIES) + tlb_lld_4m[ENTRIES] = TLB_0x63_2M_4M_ENTRIES; + fallthrough; case TLB_DATA_1G: if (tlb_lld_1g[ENTRIES] < intel_tlb_table[k].entries) tlb_lld_1g[ENTRIES] = intel_tlb_table[k].entries; From 1a82d19ca2d6835904ee71e2d40fd331098f94a0 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Thu, 27 Feb 2025 18:41:29 +0200 Subject: [PATCH 0575/1090] be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink Partially revert commit b71724147e73 ("be2net: replace polling with sleeping in the FW completion path") w.r.t mcc mutex it introduces and the use of usleep_range. The be2net be_ndo_bridge_getlink() callback is called with rcu_read_lock, so this code has been broken for a long time. Both the mutex_lock and the usleep_range can cause the issue Ian Kumlien reported[1]. The call path is: be_ndo_bridge_getlink -> be_cmd_get_hsw_config -> be_mcc_notify_wait -> be_mcc_wait_compl -> usleep_range() [1] https://lore.kernel.org/netdev/CAA85sZveppNgEVa_FD+qhOMtG_AavK9_mFiU+jWrMtXmwqefGA@mail.gmail.com/ Tested-by: Ian Kumlien Fixes: b71724147e73 ("be2net: replace polling with sleeping in the FW completion path") Signed-off-by: Nikolay Aleksandrov Link: https://patch.msgid.link/20250227164129.1201164-1-razor@blackwall.org Signed-off-by: Paolo Abeni --- drivers/net/ethernet/emulex/benet/be.h | 2 +- drivers/net/ethernet/emulex/benet/be_cmds.c | 197 ++++++++++---------- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- 3 files changed, 100 insertions(+), 101 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index e48b861e4ce1..270ff9aab335 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -562,7 +562,7 @@ struct be_adapter { struct be_dma_mem mbox_mem_alloced; struct be_mcc_obj mcc_obj; - struct mutex mcc_lock; /* For serializing mcc cmds to BE card */ + spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ spinlock_t mcc_cq_lock; u16 cfg_num_rx_irqs; /* configured via set-channels */ diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 61adcebeef01..51b8377edd1d 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -575,7 +575,7 @@ int be_process_mcc(struct be_adapter *adapter) /* Wait till no more pending mcc requests are present */ static int be_mcc_wait_compl(struct be_adapter *adapter) { -#define mcc_timeout 12000 /* 12s timeout */ +#define mcc_timeout 120000 /* 12s timeout */ int i, status = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; @@ -589,7 +589,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) if (atomic_read(&mcc_obj->q.used) == 0) break; - usleep_range(500, 1000); + udelay(100); } if (i == mcc_timeout) { dev_err(&adapter->pdev->dev, "FW not responding\n"); @@ -866,7 +866,7 @@ static bool use_mcc(struct be_adapter *adapter) static int be_cmd_lock(struct be_adapter *adapter) { if (use_mcc(adapter)) { - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); return 0; } else { return mutex_lock_interruptible(&adapter->mbox_lock); @@ -877,7 +877,7 @@ static int be_cmd_lock(struct be_adapter *adapter) static void be_cmd_unlock(struct be_adapter *adapter) { if (use_mcc(adapter)) - return mutex_unlock(&adapter->mcc_lock); + return spin_unlock_bh(&adapter->mcc_lock); else return mutex_unlock(&adapter->mbox_lock); } @@ -1047,7 +1047,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, struct be_cmd_req_mac_query *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1076,7 +1076,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1088,7 +1088,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, struct be_cmd_req_pmac_add *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1113,7 +1113,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST) status = -EPERM; @@ -1131,7 +1131,7 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) if (pmac_id == -1) return 0; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1151,7 +1151,7 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1414,7 +1414,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_dma_mem *q_mem = &rxq->dma_mem; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1444,7 +1444,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1508,7 +1508,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) struct be_cmd_req_q_destroy *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1525,7 +1525,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) q->created = false; err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1593,7 +1593,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) struct be_cmd_req_hdr *hdr; int status = 0; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1621,7 +1621,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) adapter->stats_cmd_sent = true; err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1637,7 +1637,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, CMD_SUBSYSTEM_ETH)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1660,7 +1660,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, adapter->stats_cmd_sent = true; err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1697,7 +1697,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, struct be_cmd_req_link_status *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); if (link_status) *link_status = LINK_DOWN; @@ -1736,7 +1736,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1747,7 +1747,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) struct be_cmd_req_get_cntl_addnl_attribs *req; int status = 0; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1762,7 +1762,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) status = be_mcc_notify(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1811,7 +1811,7 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) if (!get_fat_cmd.va) return -ENOMEM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); while (total_size) { buf_size = min(total_size, (u32)60 * 1024); @@ -1849,9 +1849,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) log_offset += buf_size; } err: + spin_unlock_bh(&adapter->mcc_lock); dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size, get_fat_cmd.va, get_fat_cmd.dma); - mutex_unlock(&adapter->mcc_lock); return status; } @@ -1862,7 +1862,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter) struct be_cmd_req_get_fw_version *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1885,7 +1885,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter) sizeof(adapter->fw_on_flash)); } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1899,7 +1899,7 @@ static int __be_cmd_modify_eqd(struct be_adapter *adapter, struct be_cmd_req_modify_eq_delay *req; int status = 0, i; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1922,7 +1922,7 @@ static int __be_cmd_modify_eqd(struct be_adapter *adapter, status = be_mcc_notify(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1949,7 +1949,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, struct be_cmd_req_vlan_config *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -1971,7 +1971,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1982,7 +1982,7 @@ static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) struct be_cmd_req_rx_filter *req = mem->va; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2015,7 +2015,7 @@ static int __be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2046,7 +2046,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) CMD_SUBSYSTEM_COMMON)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2066,7 +2066,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED) return -EOPNOTSUPP; @@ -2085,7 +2085,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) CMD_SUBSYSTEM_COMMON)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2108,7 +2108,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2189,7 +2189,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) return 0; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2214,7 +2214,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2226,7 +2226,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, struct be_cmd_req_enable_disable_beacon *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2247,7 +2247,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2258,7 +2258,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) struct be_cmd_req_get_beacon_state *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2282,7 +2282,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2306,7 +2306,7 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, return -ENOMEM; } - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2328,7 +2328,7 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, memcpy(data, resp->page_data + off, len); } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); return status; } @@ -2345,7 +2345,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, void *ctxt = NULL; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); adapter->flash_status = 0; wrb = wrb_from_mccq(adapter); @@ -2387,7 +2387,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, if (status) goto err_unlock; - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); if (!wait_for_completion_timeout(&adapter->et_cmd_compl, msecs_to_jiffies(60000))) @@ -2406,7 +2406,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter, return status; err_unlock: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2460,7 +2460,7 @@ static int lancer_cmd_delete_object(struct be_adapter *adapter, struct be_mcc_wrb *wrb; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2478,7 +2478,7 @@ static int lancer_cmd_delete_object(struct be_adapter *adapter, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2491,7 +2491,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, struct lancer_cmd_resp_read_object *resp; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2525,7 +2525,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, } err_unlock: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2537,7 +2537,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_cmd_write_flashrom *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); adapter->flash_status = 0; wrb = wrb_from_mccq(adapter); @@ -2562,7 +2562,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, if (status) goto err_unlock; - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); if (!wait_for_completion_timeout(&adapter->et_cmd_compl, msecs_to_jiffies(40000))) @@ -2573,7 +2573,7 @@ static int be_cmd_write_flashrom(struct be_adapter *adapter, return status; err_unlock: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2584,7 +2584,7 @@ static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, struct be_mcc_wrb *wrb; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -2611,7 +2611,7 @@ static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, memcpy(flashed_crc, req->crc, 4); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3217,7 +3217,7 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_cmd_req_acpi_wol_magic_config *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3234,7 +3234,7 @@ int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3249,7 +3249,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, CMD_SUBSYSTEM_LOWLEVEL)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3272,7 +3272,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, if (status) goto err_unlock; - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); if (!wait_for_completion_timeout(&adapter->et_cmd_compl, msecs_to_jiffies(SET_LB_MODE_TIMEOUT))) @@ -3281,7 +3281,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, return status; err_unlock: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3298,7 +3298,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, CMD_SUBSYSTEM_LOWLEVEL)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3324,7 +3324,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, if (status) goto err; - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); wait_for_completion(&adapter->et_cmd_compl); resp = embedded_payload(wrb); @@ -3332,7 +3332,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, return status; err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3348,7 +3348,7 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, CMD_SUBSYSTEM_LOWLEVEL)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3382,7 +3382,7 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3393,7 +3393,7 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter, struct be_cmd_req_seeprom_read *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3409,7 +3409,7 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3424,7 +3424,7 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) CMD_SUBSYSTEM_COMMON)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3469,7 +3469,7 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) } dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3479,7 +3479,7 @@ static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) struct be_cmd_req_set_qos *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3499,7 +3499,7 @@ static int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain) status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3611,7 +3611,7 @@ int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, struct be_cmd_req_get_fn_privileges *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3643,7 +3643,7 @@ int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3655,7 +3655,7 @@ int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, struct be_cmd_req_set_fn_privileges *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3675,7 +3675,7 @@ int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3707,7 +3707,7 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, return -ENOMEM; } - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3771,7 +3771,7 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, } out: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size, get_mac_list_cmd.va, get_mac_list_cmd.dma); return status; @@ -3831,7 +3831,7 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, if (!cmd.va) return -ENOMEM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3853,7 +3853,7 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, err: dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3889,7 +3889,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, CMD_SUBSYSTEM_COMMON)) return -EPERM; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3930,7 +3930,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -3944,7 +3944,7 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, int status; u16 vid; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -3991,7 +3991,7 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -4190,7 +4190,7 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, struct be_cmd_req_set_ext_fat_caps *req; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -4206,7 +4206,7 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -4684,7 +4684,7 @@ int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) if (iface == 0xFFFFFFFF) return -1; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -4701,7 +4701,7 @@ int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op) status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -4735,7 +4735,7 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, struct be_cmd_resp_get_iface_list *resp; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -4756,7 +4756,7 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, } err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -4850,7 +4850,7 @@ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) if (BEx_chip(adapter)) return 0; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -4868,7 +4868,7 @@ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) req->enable = 1; status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -4941,7 +4941,7 @@ __be_cmd_set_logical_link_config(struct be_adapter *adapter, u32 link_config = 0; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -4969,7 +4969,7 @@ __be_cmd_set_logical_link_config(struct be_adapter *adapter, status = be_mcc_notify_wait(adapter); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -5000,8 +5000,7 @@ int be_cmd_set_features(struct be_adapter *adapter) struct be_mcc_wrb *wrb; int status; - if (mutex_lock_interruptible(&adapter->mcc_lock)) - return -1; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -5039,7 +5038,7 @@ err: dev_info(&adapter->pdev->dev, "Adapter does not support HW error recovery\n"); - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -5053,7 +5052,7 @@ int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, struct be_cmd_resp_hdr *resp; int status; - mutex_lock(&adapter->mcc_lock); + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { @@ -5076,7 +5075,7 @@ int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length); be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length); err: - mutex_unlock(&adapter->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } EXPORT_SYMBOL(be_roce_mcc_cmd); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 875fe379eea2..3d2e21592119 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5667,8 +5667,8 @@ static int be_drv_init(struct be_adapter *adapter) } mutex_init(&adapter->mbox_lock); - mutex_init(&adapter->mcc_lock); mutex_init(&adapter->rx_filter_lock); + spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); init_completion(&adapter->et_cmd_compl); From c34424eb3be4c01db831428c0d7d483701ae820f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 27 Feb 2025 16:45:34 -0800 Subject: [PATCH 0576/1090] net: dsa: rtl8366rb: don't prompt users for LED control Make NET_DSA_REALTEK_RTL8366RB_LEDS a hidden symbol. It seems very unlikely user would want to intentionally disable it. Signed-off-by: Jakub Kicinski Link: https://patch.msgid.link/20250228004534.3428681-1-kuba@kernel.org Signed-off-by: Paolo Abeni --- drivers/net/dsa/realtek/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig index 10687722d14c..d6eb6713e5f6 100644 --- a/drivers/net/dsa/realtek/Kconfig +++ b/drivers/net/dsa/realtek/Kconfig @@ -44,7 +44,7 @@ config NET_DSA_REALTEK_RTL8366RB Select to enable support for Realtek RTL8366RB. config NET_DSA_REALTEK_RTL8366RB_LEDS - bool "Support RTL8366RB LED control" + bool depends on (LEDS_CLASS=y || LEDS_CLASS=NET_DSA_REALTEK_RTL8366RB) depends on NET_DSA_REALTEK_RTL8366RB default NET_DSA_REALTEK_RTL8366RB From 1f860eb4cdda634589d75e78ff586d5dff20b8af Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 Mar 2025 11:05:36 +0100 Subject: [PATCH 0577/1090] wifi: nl80211: disable multi-link reconfiguration Both the APIs in cfg80211 and the implementation in mac80211 aren't really ready yet, we have a large number of fixes. In addition, it's not possible right now to discover support for this feature from userspace. Disable it for now, there's no rush. Link: https://patch.msgid.link/20250303110538.fbeef42a5687.Iab122c22137e5675ebd99f5c031e30c0e5c7af2e@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fdb2aac951d1..e87267fbb442 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16534,7 +16534,7 @@ static int nl80211_assoc_ml_reconf(struct sk_buff *skb, struct genl_info *info) goto out; } - err = cfg80211_assoc_ml_reconf(rdev, dev, links, rem_links); + err = -EOPNOTSUPP; out: for (link_id = 0; link_id < ARRAY_SIZE(links); link_id++) From b7365eab39831487a84e63a9638209b68dc54008 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 28 Feb 2025 18:52:58 +0800 Subject: [PATCH 0578/1090] net: hns3: make sure ptp clock is unregister and freed if hclge_ptp_get_cycle returns an error During the initialization of ptp, hclge_ptp_get_cycle might return an error and returned directly without unregister clock and free it. To avoid that, call hclge_ptp_destroy_clock to unregist and free clock if hclge_ptp_get_cycle failed. Fixes: 8373cd38a888 ("net: hns3: change the method of obtaining default ptp cycle") Signed-off-by: Peiyang Wang Signed-off-by: Jijie Shao Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250228105258.1243461-1-shaojijie@huawei.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c index bab16c2191b2..181af419b878 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -483,7 +483,7 @@ int hclge_ptp_init(struct hclge_dev *hdev) ret = hclge_ptp_get_cycle(hdev); if (ret) - return ret; + goto out; } ret = hclge_ptp_int_en(hdev, true); From 79c080c75cdd0a5ba38be039f6f9bb66ec53b0c4 Mon Sep 17 00:00:00 2001 From: Louis-Alexis Eyraud Date: Fri, 28 Feb 2025 11:32:19 +0100 Subject: [PATCH 0579/1090] ASoC: mediatek: mt6359: Fix DT parse error due to wrong child node name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A recent dtbs_check error fix in mt6359.dtsi file changed a node name (from "mt6359codec" to "audio-codec") without modifying the mt6539 codec code that uses it. It leads to a probe failure after devicetree parsing returns in error: ``` [ 1.354025] mt6359-sound mt6359-sound: mt6359_platform_driver_probe() failed to parse dts [ 1.355066] mt6359-sound mt6359-sound: probe with driver mt6359-sound failed with error -22 ``` So, add the child node retrieval with the new name and if not found, try with the older one for backward compatibility. Fixes: 76b35f59bbe6 ("arm64: dts: mediatek: mt6359: fix dtbs_check error for audio-codec") Signed-off-by: Louis-Alexis Eyraud Reviewed-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250228-mt6359-fix-probe-failed-v1-1-64941d387b2c@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c index 0b76a55664b0..f73120c6a6ce 100644 --- a/sound/soc/codecs/mt6359.c +++ b/sound/soc/codecs/mt6359.c @@ -2867,9 +2867,12 @@ static int mt6359_parse_dt(struct mt6359_priv *priv) struct device *dev = priv->dev; struct device_node *np; - np = of_get_child_by_name(dev->parent->of_node, "mt6359codec"); - if (!np) - return -EINVAL; + np = of_get_child_by_name(dev->parent->of_node, "audio-codec"); + if (!np) { + np = of_get_child_by_name(dev->parent->of_node, "mt6359codec"); + if (!np) + return -EINVAL; + } ret = of_property_read_u32(np, "mediatek,dmic-mode", &priv->dmic_one_wire_mode); From 1d251a7adc5b720a71641c758a45b8a119971d80 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 4 Mar 2025 11:38:07 +0100 Subject: [PATCH 0580/1090] ASoC: dt-bindings: everest,es8328: Mark ES8388 compatible with ES8328 Based on Linux driver, the ES8388 looks fully compatible with ES8328. One upstream DTS (ARM rk3288-rock2-square.dts) already uses ES8328 fallback, so mark the devices as compatible in the binding. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250304103808.75236-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/everest,es8328.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/everest,es8328.yaml b/Documentation/devicetree/bindings/sound/everest,es8328.yaml index ed18e40dcaac..309c4d01db76 100644 --- a/Documentation/devicetree/bindings/sound/everest,es8328.yaml +++ b/Documentation/devicetree/bindings/sound/everest,es8328.yaml @@ -24,9 +24,13 @@ maintainers: properties: compatible: - enum: - - everest,es8328 - - everest,es8388 + oneOf: + - enum: + - everest,es8328 + - items: + - enum: + - everest,es8388 + - const: everest,es8328 reg: maxItems: 1 From 8243a49145e59f19032b86b20d8906f05e31bdcc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 4 Mar 2025 11:38:08 +0100 Subject: [PATCH 0581/1090] ASoC: dt-bindings: everest,es8328: Require reg property ES8328 and ES8388 codecs are I2C or SPI devices, thus they are addressable on their bus and 'reg' property should be always provided. Requiring 'reg' is pretty close to redundant, because the I2C and SPI controller/bus bindings require it already, but the convention is to mention 'reg' also in the device schemas. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250304103808.75236-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/everest,es8328.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/everest,es8328.yaml b/Documentation/devicetree/bindings/sound/everest,es8328.yaml index 309c4d01db76..ddddd7b143ab 100644 --- a/Documentation/devicetree/bindings/sound/everest,es8328.yaml +++ b/Documentation/devicetree/bindings/sound/everest,es8328.yaml @@ -60,6 +60,7 @@ properties: required: - compatible + - reg - clocks - DVDD-supply - AVDD-supply From b19d340d5d08c5940ce612c2a1b5fe3a8a401f9d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:41 +0100 Subject: [PATCH 0582/1090] ASoC: samsung: bells: Drop unused include This file does not use the symbols from the legacy header, so let's drop it. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-1-56a2299dd928@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Mark Brown --- sound/soc/samsung/bells.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 365b1aca4855..b4c0857ae351 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "../codecs/wm5102.h" From c4b2d9643a06a5326a778c4d77d6fa60e0f3d6b1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:42 +0100 Subject: [PATCH 0583/1090] ASoC: samsung: littlemill: Drop unused include This file does not use the symbols from the legacy header, so let's drop it. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-2-56a2299dd928@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Mark Brown --- sound/soc/samsung/littlemill.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index c5260e101c2a..9fa5e3ff9215 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "../codecs/wm8994.h" From 5c06f7f3d8374df1cec3b353306a4d1032a60f44 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:43 +0100 Subject: [PATCH 0584/1090] ASoC: samsung: lowland: Drop unused include This file does not use the symbols from the legacy header, so let's drop it. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-3-56a2299dd928@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Mark Brown --- sound/soc/samsung/lowland.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 702cb4cc1ce9..d4088b72d43c 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "../codecs/wm5100.h" From da9146c19b1774926148ff271c4a3dc8d7891b18 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:44 +0100 Subject: [PATCH 0585/1090] ASoC: samsung: speyside: Convert to GPIO descriptor The Speyside ASoC uses a single GPIO from the WM8996 that we can provide from the local offset on that chip rather than from the global GPIO numberspace as is being done currently. The offset 2 was done by calculating the base offset for the CODEC (i.e. wm8996) GPIOs to 212, by reading arch/arm/mach-s3c/gpio-samsung-s3c64xx.h and arch/arm/mach-s3c/crag6410.h and adding up all the offsets that were occasionally adding a +1 blank GPIO between each GPIO provider. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-4-56a2299dd928@linaro.org Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 37 +++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 79476e8eb680..947b85ff83f0 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -7,13 +7,13 @@ #include #include #include -#include +#include +#include #include #include "../codecs/wm8996.h" #include "../codecs/wm9081.h" -#define WM8996_HPSEL_GPIO 214 #define MCLK_AUDIO_RATE (512 * 48000) static int speyside_set_bias_level(struct snd_soc_card *card, @@ -105,6 +105,7 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = { }, }; +static struct gpio_desc *speyside_hpsel_gpio; /* Default the headphone selection to active high */ static int speyside_jack_polarity; @@ -123,7 +124,7 @@ static void speyside_set_polarity(struct snd_soc_component *component, int polarity) { speyside_jack_polarity = !polarity; - gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); + gpiod_direction_output(speyside_hpsel_gpio, speyside_jack_polarity); /* Re-run DAPM to make sure we're using the correct mic bias */ snd_soc_dapm_sync(snd_soc_component_get_dapm(component)); @@ -145,16 +146,22 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_component *component = dai->component; + enum gpiod_flags flags; int ret; ret = snd_soc_dai_set_sysclk(dai, WM8996_SYSCLK_MCLK2, 32768, 0); if (ret < 0) return ret; - ret = gpio_request(WM8996_HPSEL_GPIO, "HP_SEL"); - if (ret != 0) - pr_err("Failed to request HP_SEL GPIO: %d\n", ret); - gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity); + if (speyside_jack_polarity) + flags = GPIOD_OUT_HIGH; + else + flags = GPIOD_OUT_LOW; + speyside_hpsel_gpio = devm_gpiod_get(rtd->card->dev, + "hp-sel", + flags); + if (IS_ERR(speyside_hpsel_gpio)) + return PTR_ERR(speyside_hpsel_gpio); ret = snd_soc_card_jack_new_pins(rtd->card, "Headset", SND_JACK_LINEOUT | SND_JACK_HEADSET | @@ -325,6 +332,21 @@ static struct snd_soc_card speyside = { .late_probe = speyside_late_probe, }; +static struct gpiod_lookup_table wm8996_gpiod_table = { + /* Hardcoded device name in board file mach-crag6410.c */ + .dev_id = "speyside", + .table = { + /* + * This line was hardcoded to 214 in the global GPIO + * number space, S3C GPIO macros seems top set the + * wm8996 codec GPIO start offset to 212, so this will + * be GPIO 214 - 212 = 2 on the wm8996. + */ + GPIO_LOOKUP("wm8996", 2, "hp-sel", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static int speyside_probe(struct platform_device *pdev) { struct snd_soc_card *card = &speyside; @@ -332,6 +354,7 @@ static int speyside_probe(struct platform_device *pdev) card->dev = &pdev->dev; + gpiod_add_lookup_table(&wm8996_gpiod_table); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n"); From c095b7a27529d1d18b3b36a47f77a1419f0de939 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:45 +0100 Subject: [PATCH 0586/1090] ASoC: samsung: tobermory: Drop unused include This file does not use the symbols from the legacy header, so let's drop it. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-5-56a2299dd928@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Mark Brown --- sound/soc/samsung/tobermory.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index 2bdd81bf821a..bc2608dbaddc 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "../codecs/wm8962.h" From 0a22454ab2eca530702b2689858909b608953703 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 3 Mar 2025 09:41:46 +0100 Subject: [PATCH 0587/1090] ASoC: samsung: tm2_wm5110: Drop unused include This file does not use the symbols from the legacy header, so let's drop it. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250303-samsung-codecs-v1-6-56a2299dd928@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 2417b91a328f..cc76963105d9 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -6,7 +6,6 @@ // Sylwester Nawrocki #include -#include #include #include #include From c7c1f3b05c67173f462d73d301d572b3f9e57e3b Mon Sep 17 00:00:00 2001 From: Michal Pecio Date: Tue, 4 Mar 2025 13:31:47 +0200 Subject: [PATCH 0588/1090] usb: xhci: Fix host controllers "dying" after suspend and resume A recent cleanup went a bit too far and dropped clearing the cycle bit of link TRBs, so it stays different from the rest of the ring half of the time. Then a race occurs: if the xHC reaches such link TRB before more commands are queued, the link's cycle bit unintentionally matches the xHC's cycle so it follows the link and waits for further commands. If more commands are queued before the xHC gets there, inc_enq() flips the bit so the xHC later sees a mismatch and stops executing commands. This function is called before suspend and 50% of times after resuming the xHC is doomed to get stuck sooner or later. Then some Stop Endpoint command fails to complete in 5 seconds and this shows up xhci_hcd 0000:00:10.0: xHCI host not responding to stop endpoint command xhci_hcd 0000:00:10.0: xHCI host controller not responding, assume dead xhci_hcd 0000:00:10.0: HC died; cleaning up followed by loss of all USB decives on the affected bus. That's if you are lucky, because if Set Deq gets stuck instead, the failure is silent. Likely responsible for kernel bug 219824. I found this while searching for possible causes of that regression and reproduced it locally before hearing back from the reporter. To repro, simply wait for link cycle to become set (debugfs), then suspend, resume and wait. To accelerate the failure I used a script which repeatedly starts and stops a UVC camera. Some HCs get fully reinitialized on resume and they are not affected. Link: https://bugzilla.kernel.org/show_bug.cgi?id=219824 Fixes: 36b972d4b7ce ("usb: xhci: improve xhci_clear_command_ring()") Cc: stable@vger.kernel.org Signed-off-by: Michal Pecio Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20250304113147.3322584-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 45653114ccd7..1a90ebc8a30e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -780,8 +780,12 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) struct xhci_segment *seg; ring = xhci->cmd_ring; - xhci_for_each_ring_seg(ring->first_seg, seg) + xhci_for_each_ring_seg(ring->first_seg, seg) { + /* erase all TRBs before the link */ memset(seg->trbs, 0, sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1)); + /* clear link cycle bit */ + seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= cpu_to_le32(~TRB_CYCLE); + } xhci_initialize_ring_info(ring); /* From 5623bc23a1cb9f9a9470fa73b3a20321dc4c4870 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 25 Feb 2025 10:53:10 +0100 Subject: [PATCH 0589/1090] s390/traps: Fix test_monitor_call() inline assembly The test_monitor_call() inline assembly uses the xgr instruction, which also modifies the condition code, to clear a register. However the clobber list of the inline assembly does not specify that the condition code is modified, which may lead to incorrect code generation. Use the lhi instruction instead to clear the register without that the condition code is modified. Furthermore this limits clearing to the lower 32 bits of val, since its type is int. Fixes: 17248ea03674 ("s390: fix __EMIT_BUG() macro") Cc: stable@vger.kernel.org Reviewed-by: Juergen Christ Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/traps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 24fee11b030d..b746213d3110 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -285,10 +285,10 @@ static void __init test_monitor_call(void) return; asm volatile( " mc 0,0\n" - "0: xgr %0,%0\n" + "0: lhi %[val],0\n" "1:\n" - EX_TABLE(0b,1b) - : "+d" (val)); + EX_TABLE(0b, 1b) + : [val] "+d" (val)); if (!val) panic("Monitor call doesn't work!\n"); } From a22ee38d2efe18edc53791fd1036396c23b43ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 17 Feb 2025 14:04:18 +0100 Subject: [PATCH 0590/1090] selftests/vDSO: Fix GNU hash table entry size for s390x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 14be4e6f3522 ("selftests: vDSO: fix ELF hash table entry size for s390x") changed the type of the ELF hash table entries to 64bit on s390x. However the *GNU* hash tables entries are always 32bit. The "bucket" pointer is shared between both hash algorithms. On s390, this caused the GNU hash algorithm to access its 32-bit entries as if they were 64-bit, triggering compiler warnings (assignment between "Elf64_Xword *" and "Elf64_Word *") and runtime crashes. Introduce a new dedicated "gnu_bucket" pointer which is used by the GNU hash. Fixes: e0746bde6f82 ("selftests/vDSO: support DT_GNU_HASH") Reviewed-by: Jens Remus Signed-off-by: Thomas Weißschuh Acked-by: Shuah Khan Link: https://lore.kernel.org/r/20250217-selftests-vdso-s390-gnu-hash-v2-1-f6c2532ffe2a@linutronix.de Signed-off-by: Vasily Gorbik --- tools/testing/selftests/vDSO/parse_vdso.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 2fe5e983cb22..f89d052c730e 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -53,7 +53,7 @@ static struct vdso_info /* Symbol table */ ELF(Sym) *symtab; const char *symstrings; - ELF(Word) *gnu_hash; + ELF(Word) *gnu_hash, *gnu_bucket; ELF_HASH_ENTRY *bucket, *chain; ELF_HASH_ENTRY nbucket, nchain; @@ -185,8 +185,8 @@ void vdso_init_from_sysinfo_ehdr(uintptr_t base) /* The bucket array is located after the header (4 uint32) and the bloom * filter (size_t array of gnu_hash[2] elements). */ - vdso_info.bucket = vdso_info.gnu_hash + 4 + - sizeof(size_t) / 4 * vdso_info.gnu_hash[2]; + vdso_info.gnu_bucket = vdso_info.gnu_hash + 4 + + sizeof(size_t) / 4 * vdso_info.gnu_hash[2]; } else { vdso_info.nbucket = hash[0]; vdso_info.nchain = hash[1]; @@ -268,11 +268,11 @@ void *vdso_sym(const char *version, const char *name) if (vdso_info.gnu_hash) { uint32_t h1 = gnu_hash(name), h2, *hashval; - i = vdso_info.bucket[h1 % vdso_info.nbucket]; + i = vdso_info.gnu_bucket[h1 % vdso_info.nbucket]; if (i == 0) return 0; h1 |= 1; - hashval = vdso_info.bucket + vdso_info.nbucket + + hashval = vdso_info.gnu_bucket + vdso_info.nbucket + (i - vdso_info.gnu_hash[1]); for (;; i++) { ELF(Sym) *sym = &vdso_info.symtab[i]; From b4a1dec11793936ffe1a9fb811724532ff3b1174 Mon Sep 17 00:00:00 2001 From: Sumanth Korikkar Date: Mon, 24 Feb 2025 12:27:04 +0100 Subject: [PATCH 0591/1090] s390/ftrace: Fix return address recovery of traced function When fgraph is enabled the traced function return address is replaced with trampoline return_to_handler(). The original return address of the traced function is saved in per task return stack along with a stack pointer for reliable stack unwinding via function_graph_enter_regs(). During stack unwinding e.g. for livepatching, ftrace_graph_ret_addr() identifies the original return address of the traced function with the saved stack pointer. With a recent change, the stack pointers passed to ftrace_graph_ret_addr() and function_graph_enter_regs() do not match anymore, and therefore the original return address is not found. Pass the correct stack pointer to function_graph_enter_regs() to fix this. Fixes: 7495e179b478 ("s390/tracing: Enable HAVE_FTRACE_GRAPH_FUNC") Reviewed-by: Heiko Carstens Signed-off-by: Sumanth Korikkar Signed-off-by: Vasily Gorbik --- arch/s390/kernel/ftrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 63ba6306632e..e540b022ceb2 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -266,12 +266,13 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { unsigned long *parent = &arch_ftrace_regs(fregs)->regs.gprs[14]; + unsigned long sp = arch_ftrace_regs(fregs)->regs.gprs[15]; if (unlikely(ftrace_graph_is_dead())) return; if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; - if (!function_graph_enter_regs(*parent, ip, 0, parent, fregs)) + if (!function_graph_enter_regs(*parent, ip, 0, (unsigned long *)sp, fregs)) *parent = (unsigned long)&return_to_handler; } From 6db63090272768785e6bb4a3afa16650c1e96c54 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 4 Mar 2025 14:05:00 +0000 Subject: [PATCH 0592/1090] ASoC: Tidy up SOC_DOUBLE_* and SOC_SINGLE_* helpers Re-implement SOC_DOUBLE_VALUE() in terms of SOC_DOUBLE_S_VALUE(). SOC_DOUBLE_S_VALUE() already had a minimum value so add this to SOC_DOUBLE_VALUE as well, this allows replacement of several hard coded value entries. Likewise update SOC_SINGLE_VALUE to match, which allows replacement of even more hard coded values. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250304140500.976127-14-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 4 +-- include/sound/soc.h | 65 +++++++++++++++------------------------- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 4b8ef5b8a391..af802ef536e7 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -356,14 +356,14 @@ struct soc_enum; { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) } #define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) } #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ diff --git a/include/sound/soc.h b/include/sound/soc.h index 390e08ba4dd4..de1abad06a9b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -39,18 +39,17 @@ struct platform_device; /* * Convenience kcontrol builders */ -#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .max = xmax, \ - .invert = xinvert, .autodisable = xautodisable}) -#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \ +#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, \ + xinvert, xautodisable) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = shift_left, \ .rshift = shift_right, .min = xmin, .max = xmax, \ .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) -#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ - SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) +#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, 0, xinvert, \ + xautodisable) +#define SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmin, xmax, xinvert, xautodisable) #define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ @@ -63,15 +62,12 @@ struct platform_device; { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .invert = xinvert} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -79,7 +75,7 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -88,10 +84,7 @@ struct platform_device; .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx,\ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, 0, 0) } #define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -99,16 +92,13 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_range, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .invert = xinvert} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_STS(xname, reg, shift_left, shift_right, max, invert) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -116,7 +106,7 @@ struct platform_device; .access = SNDRV_CTL_ELEM_ACCESS_READ | \ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ @@ -138,7 +128,7 @@ struct platform_device; .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -147,10 +137,8 @@ struct platform_device; .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx, \ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .min = xmin} } + .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ + xmin, xmax, 0, 0) } #define SOC_DOUBLE_RANGE_TLV(xname, xreg, xshift_left, xshift_right, xmin, xmax, \ xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -159,10 +147,8 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = xshift_left, .rshift = xshift_right, \ - .min = xmin, .max = xmax, .invert = xinvert} } + .private_value = SOC_DOUBLE_VALUE(xreg, xshift_left, xshift_right, \ + xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -250,14 +236,14 @@ struct platform_device; { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = \ - SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } + SOC_DOUBLE_VALUE(reg, shift_left, shift_right, 0, max, invert, 0) } #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -273,7 +259,7 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -282,10 +268,7 @@ struct platform_device; .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw_range, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .invert = xinvert} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -295,7 +278,7 @@ struct platform_device; .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ - xmax, xinvert, 0) } + 0, xmax, xinvert, 0) } #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ From f9dc8fb3afc968042bdaf4b6e445a9272071c9f3 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Tue, 4 Mar 2025 03:23:14 -0500 Subject: [PATCH 0593/1090] KVM: x86: Explicitly zero EAX and EBX when PERFMON_V2 isn't supported by KVM Fix a goof where KVM sets CPUID.0x80000022.EAX to CPUID.0x80000022.EBX instead of zeroing both when PERFMON_V2 isn't supported by KVM. In practice, barring a buggy CPU (or vCPU model when running nested) only the !enable_pmu case is affected, as KVM always supports PERFMON_V2 if it's available in hardware, i.e. CPUID.0x80000022.EBX will be '0' if PERFMON_V2 is unsupported. For the !enable_pmu case, the bug is relatively benign as KVM will refuse to enable PMU capabilities, but a VMM that reflects KVM's supported CPUID into the guest could inadvertently induce #GPs in the guest due to advertising support for MSRs that KVM refuses to emulate. Fixes: 94cdeebd8211 ("KVM: x86/cpuid: Add AMD CPUID ExtPerfMonAndDbg leaf 0x80000022") Signed-off-by: Xiaoyao Li Link: https://lore.kernel.org/r/20250304082314.472202-3-xiaoyao.li@intel.com [sean: massage shortlog and changelog, tag for stable] Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson --- arch/x86/kvm/cpuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 8eb3a88707f2..121edf1f2a79 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1763,7 +1763,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) entry->ecx = entry->edx = 0; if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) { - entry->eax = entry->ebx; + entry->eax = entry->ebx = 0; break; } From 3d252160b818045f3a152b13756f6f37ca34639d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 4 Mar 2025 13:51:38 +0000 Subject: [PATCH 0594/1090] fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex pipe_readable(), pipe_writable(), and pipe_poll() can read "pipe->head" and "pipe->tail" outside of "pipe->mutex" critical section. When the head and the tail are read individually in that order, there is a window for interruption between the two reads in which both the head and the tail can be updated by concurrent readers and writers. One of the problematic scenarios observed with hackbench running multiple groups on a large server on a particular pipe inode is as follows: pipe->head = 36 pipe->tail = 36 hackbench-118762 [057] ..... 1029.550548: pipe_write: *wakes up: pipe not full* hackbench-118762 [057] ..... 1029.550548: pipe_write: head: 36 -> 37 [tail: 36] hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next reader 118740* hackbench-118762 [057] ..... 1029.550548: pipe_write: *wake up next writer 118768* hackbench-118768 [206] ..... 1029.55055X: pipe_write: *writer wakes up* hackbench-118768 [206] ..... 1029.55055X: pipe_write: head = READ_ONCE(pipe->head) [37] ... CPU 206 interrupted (exact wakeup was not traced but 118768 did read head at 37 in traces) hackbench-118740 [057] ..... 1029.550558: pipe_read: *reader wakes up: pipe is not empty* hackbench-118740 [057] ..... 1029.550558: pipe_read: tail: 36 -> 37 [head = 37] hackbench-118740 [057] ..... 1029.550559: pipe_read: *pipe is empty; wakeup writer 118768* hackbench-118740 [057] ..... 1029.550559: pipe_read: *sleeps* hackbench-118766 [185] ..... 1029.550592: pipe_write: *New writer comes in* hackbench-118766 [185] ..... 1029.550592: pipe_write: head: 37 -> 38 [tail: 37] hackbench-118766 [185] ..... 1029.550592: pipe_write: *wakes up reader 118766* hackbench-118740 [185] ..... 1029.550598: pipe_read: *reader wakes up; pipe not empty* hackbench-118740 [185] ..... 1029.550599: pipe_read: tail: 37 -> 38 [head: 38] hackbench-118740 [185] ..... 1029.550599: pipe_read: *pipe is empty* hackbench-118740 [185] ..... 1029.550599: pipe_read: *reader sleeps; wakeup writer 118768* ... CPU 206 switches back to writer hackbench-118768 [206] ..... 1029.550601: pipe_write: tail = READ_ONCE(pipe->tail) [38] hackbench-118768 [206] ..... 1029.550601: pipe_write: pipe_full()? (u32)(37 - 38) >= 16? Yes hackbench-118768 [206] ..... 1029.550601: pipe_write: *writer goes back to sleep* [ Tasks 118740 and 118768 can then indefinitely wait on each other. ] The unsigned arithmetic in pipe_occupancy() wraps around when "pipe->tail > pipe->head" leading to pipe_full() returning true despite the pipe being empty. The case of genuine wraparound of "pipe->head" is handled since pipe buffer has data allowing readers to make progress until the pipe->tail wraps too after which the reader will wakeup a sleeping writer, however, mistaking the pipe to be full when it is in fact empty can lead to readers and writers waiting on each other indefinitely. This issue became more problematic and surfaced as a hang in hackbench after the optimization in commit aaec5a95d596 ("pipe_read: don't wake up the writer if the pipe is still full") significantly reduced the number of spurious wakeups of writers that had previously helped mask the issue. To avoid missing any updates between the reads of "pipe->head" and "pipe->write", unionize the two with a single unsigned long "pipe->head_tail" member that can be loaded atomically. Using "pipe->head_tail" to read the head and the tail ensures the lockless checks do not miss any updates to the head or the tail and since those two are only updated under "pipe->mutex", it ensures that the head is always ahead of, or equal to the tail resulting in correct calculations. [ prateek: commit log, testing on x86 platforms. ] Reported-and-debugged-by: Swapnil Sapkal Closes: https://lore.kernel.org/lkml/e813814e-7094-4673-bc69-731af065a0eb@amd.com/ Reported-by: Alexey Gladkov Closes: https://lore.kernel.org/all/Z8Wn0nTvevLRG_4m@example.org/ Fixes: 8cefc107ca54 ("pipe: Use head and tail pointers for the ring, not cursor and length") Tested-by: Swapnil Sapkal Reviewed-by: Oleg Nesterov Tested-by: Alexey Gladkov Signed-off-by: K Prateek Nayak Signed-off-by: Linus Torvalds --- fs/pipe.c | 19 ++++++++----------- include/linux/pipe_fs_i.h | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index ce1af7592780..e8e6698f3698 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -210,11 +210,10 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ static inline bool pipe_readable(const struct pipe_inode_info *pipe) { - unsigned int head = READ_ONCE(pipe->head); - unsigned int tail = READ_ONCE(pipe->tail); + union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; unsigned int writers = READ_ONCE(pipe->writers); - return !pipe_empty(head, tail) || !writers; + return !pipe_empty(idx.head, idx.tail) || !writers; } static inline unsigned int pipe_update_tail(struct pipe_inode_info *pipe, @@ -417,11 +416,10 @@ static inline int is_packetized(struct file *file) /* Done while waiting without holding the pipe lock - thus the READ_ONCE() */ static inline bool pipe_writable(const struct pipe_inode_info *pipe) { - unsigned int head = READ_ONCE(pipe->head); - unsigned int tail = READ_ONCE(pipe->tail); + union pipe_index idx = { .head_tail = READ_ONCE(pipe->head_tail) }; unsigned int max_usage = READ_ONCE(pipe->max_usage); - return !pipe_full(head, tail, max_usage) || + return !pipe_full(idx.head, idx.tail, max_usage) || !READ_ONCE(pipe->readers); } @@ -659,7 +657,7 @@ pipe_poll(struct file *filp, poll_table *wait) { __poll_t mask; struct pipe_inode_info *pipe = filp->private_data; - unsigned int head, tail; + union pipe_index idx; /* Epoll has some historical nasty semantics, this enables them */ WRITE_ONCE(pipe->poll_usage, true); @@ -680,19 +678,18 @@ pipe_poll(struct file *filp, poll_table *wait) * if something changes and you got it wrong, the poll * table entry will wake you up and fix it. */ - head = READ_ONCE(pipe->head); - tail = READ_ONCE(pipe->tail); + idx.head_tail = READ_ONCE(pipe->head_tail); mask = 0; if (filp->f_mode & FMODE_READ) { - if (!pipe_empty(head, tail)) + if (!pipe_empty(idx.head, idx.tail)) mask |= EPOLLIN | EPOLLRDNORM; if (!pipe->writers && filp->f_pipe != pipe->w_counter) mask |= EPOLLHUP; } if (filp->f_mode & FMODE_WRITE) { - if (!pipe_full(head, tail, pipe->max_usage)) + if (!pipe_full(idx.head, idx.tail, pipe->max_usage)) mask |= EPOLLOUT | EPOLLWRNORM; /* * Most Unices do not set EPOLLERR for FIFOs but on Linux they diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 8ff23bf5a819..3cc4f8eab853 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -31,6 +31,33 @@ struct pipe_buffer { unsigned long private; }; +/* + * Really only alpha needs 32-bit fields, but + * might as well do it for 64-bit architectures + * since that's what we've historically done, + * and it makes 'head_tail' always be a simple + * 'unsigned long'. + */ +#ifdef CONFIG_64BIT +typedef unsigned int pipe_index_t; +#else +typedef unsigned short pipe_index_t; +#endif + +/* + * We have to declare this outside 'struct pipe_inode_info', + * but then we can't use 'union pipe_index' for an anonymous + * union, so we end up having to duplicate this declaration + * below. Annoying. + */ +union pipe_index { + unsigned long head_tail; + struct { + pipe_index_t head; + pipe_index_t tail; + }; +}; + /** * struct pipe_inode_info - a linux kernel pipe * @mutex: mutex protecting the whole thing @@ -58,8 +85,16 @@ struct pipe_buffer { struct pipe_inode_info { struct mutex mutex; wait_queue_head_t rd_wait, wr_wait; - unsigned int head; - unsigned int tail; + + /* This has to match the 'union pipe_index' above */ + union { + unsigned long head_tail; + struct { + pipe_index_t head; + pipe_index_t tail; + }; + }; + unsigned int max_usage; unsigned int ring_size; unsigned int nr_accounted; From dfc1b168a8c4b376fa222b27b97c2c4ad4b786e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 17 Feb 2025 08:27:54 +0100 Subject: [PATCH 0595/1090] kbuild: userprogs: use correct lld when linking through clang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The userprog infrastructure links objects files through $(CC). Either explicitly by manually calling $(CC) on multiple object files or implicitly by directly compiling a source file to an executable. The documentation at Documentation/kbuild/llvm.rst indicates that ld.lld would be used for linking if LLVM=1 is specified. However clang instead will use either a globally installed cross linker from $PATH called ${target}-ld or fall back to the system linker, which probably does not support crosslinking. For the normal kernel build this is not an issue because the linker is always executed directly, without the compiler being involved. Explicitly pass --ld-path to clang so $(LD) is respected. As clang 13.0.1 is required to build the kernel, this option is available. Fixes: 7f3a59db274c ("kbuild: add infrastructure to build userspace programs") Cc: stable@vger.kernel.org # needs wrapping in $(cc-option) for < 6.9 Signed-off-by: Thomas Weißschuh Reviewed-by: Nathan Chancellor Signed-off-by: Masahiro Yamada --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 70bdbf2218fc..6a8e5be6b004 100644 --- a/Makefile +++ b/Makefile @@ -1123,6 +1123,11 @@ endif KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) +# userspace programs are linked via the compiler, use the correct linker +ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy) +KBUILD_USERLDFLAGS += --ld-path=$(LD) +endif + # make the checker run with the right architecture CHECKFLAGS += --arch=$(ARCH) From 02e9a22ceef0227175e391902d8760425fa072c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 25 Feb 2025 11:00:31 +0100 Subject: [PATCH 0596/1090] kbuild: hdrcheck: fix cross build with clang The headercheck tries to call clang with a mix of compiler arguments that don't include the target architecture. When building e.g. x86 headers on arm64, this produces a warning like clang: warning: unknown platform, assuming -mfloat-abi=soft Add in the KBUILD_CPPFLAGS, which contain the target, in order to make it build properly. See also 1b71c2fb04e7 ("kbuild: userprogs: fix bitsize and target detection on clang"). Reviewed-by: Nathan Chancellor Fixes: feb843a469fb ("kbuild: add $(CLANG_FLAGS) to KBUILD_CPPFLAGS") Signed-off-by: Arnd Bergmann --- usr/include/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/include/Makefile b/usr/include/Makefile index 6c6de1b1622b..e3d6b03527fe 100644 --- a/usr/include/Makefile +++ b/usr/include/Makefile @@ -10,7 +10,7 @@ UAPI_CFLAGS := -std=c90 -Wall -Werror=implicit-function-declaration # In theory, we do not care -m32 or -m64 for header compile tests. # It is here just because CONFIG_CC_CAN_LINK is tested with -m32 or -m64. -UAPI_CFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS)) +UAPI_CFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) # USERCFLAGS might contain sysroot location for CC. UAPI_CFLAGS += $(USERCFLAGS) From dd0b7d4a56e3349de65bf9752734510fb55baf29 Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Fri, 28 Feb 2025 20:37:08 +0900 Subject: [PATCH 0597/1090] docs: Kconfig: fix defconfig description Commit 2a86f6612164 ("kbuild: use KBUILD_DEFCONFIG as the fallback for DEFCONFIG_LIST") removed arch/$ARCH/defconfig; however, the document has not been updated to reflect this change yet. Signed-off-by: Satoru Takeuchi Signed-off-by: Masahiro Yamada --- Documentation/admin-guide/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/README.rst b/Documentation/admin-guide/README.rst index eb9452668909..b557cf1c820d 100644 --- a/Documentation/admin-guide/README.rst +++ b/Documentation/admin-guide/README.rst @@ -176,7 +176,7 @@ Configuring the kernel values without prompting. "make defconfig" Create a ./.config file by using the default - symbol values from either arch/$ARCH/defconfig + symbol values from either arch/$ARCH/configs/defconfig or arch/$ARCH/configs/${PLATFORM}_defconfig, depending on the architecture. From 30bfc151f0c1ec80c27a80a7651b2c15c648ad16 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 10 Dec 2024 09:31:02 +0100 Subject: [PATCH 0598/1090] drm/xe: Remove double pageflip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already handled below in the code by fixup_initial_plane_config. Fixes: a8153627520a ("drm/i915: Try to relocate the BIOS fb to the start of ggtt") Cc: Ville Syrjälä Reviewed-by: Vinod Govindapillai Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20241210083111.230484-3-dev@lankhorst.se Signed-off-by: Maarten Lankhorst (cherry picked from commit 2218704997979fbf11765281ef752f07c5cf25bb) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/display/xe_plane_initial.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c b/drivers/gpu/drm/xe/display/xe_plane_initial.c index 2eb9633f163a..2a2f250fa495 100644 --- a/drivers/gpu/drm/xe/display/xe_plane_initial.c +++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c @@ -194,8 +194,6 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, to_intel_plane(crtc->base.primary); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); struct drm_framebuffer *fb; struct i915_vma *vma; @@ -241,14 +239,6 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, atomic_or(plane->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); plane_config->vma = vma; - - /* - * Flip to the newly created mapping ASAP, so we can re-use the - * first part of GGTT for WOPCM, prevent flickering, and prevent - * the lookup of sysmem scratch pages. - */ - plane->check_plane(crtc_state, plane_state); - plane->async_flip(NULL, plane, crtc_state, plane_state, true); return; nofb: From d1039a3c12fffe501c5379c7eb1372eaab318e0a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 26 Feb 2025 15:56:26 +0200 Subject: [PATCH 0599/1090] drm/i915/mst: update max stream count to match number of pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We create the stream encoders and attach connectors for each pipe we have. As the number of pipes has increased, we've failed to update the topology manager maximum number of payloads to match that. Bump up the max stream count to match number of pipes, enabling the fourth stream on platforms that support four pipes. Cc: stable@vger.kernel.org Cc: Imre Deak Cc: Ville Syrjala Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250226135626.1956012-1-jani.nikula@intel.com Signed-off-by: Jani Nikula (cherry picked from commit 15bccbfb78d63a2a621b30caff8b9424160c6c89) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index a65cf97ad12d..86d6185fda50 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1867,7 +1867,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) /* create encoders */ mst_stream_encoders_create(dig_port); ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, display->drm, - &intel_dp->aux, 16, 3, conn_base_id); + &intel_dp->aux, 16, + INTEL_NUM_PIPES(display), conn_base_id); if (ret) { intel_dp->mst_mgr.cbs = NULL; return ret; From 475d06e00b7496c7915d87f7ae67af26738e4649 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 26 Feb 2025 17:47:49 +0000 Subject: [PATCH 0600/1090] drm/xe/userptr: properly setup pfn_flags_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we just leave it uninitialised, which at first looks harmless, however we also don't zero out the pfn array, and with pfn_flags_mask the idea is to be able set individual flags for a given range of pfn or completely ignore them, outside of default_flags. So here we end up with pfn[i] & pfn_flags_mask, and if both are uninitialised we might get back an unexpected flags value, like asking for read only with default_flags, but getting back write on top, leading to potentially bogus behaviour. To fix this ensure we zero the pfn_flags_mask, such that hmm only considers the default_flags and not also the initial pfn[i] value. v2 (Thomas): - Prefer proper initializer. Fixes: 81e058a3e7fd ("drm/xe: Introduce helper to populate userptr") Signed-off-by: Matthew Auld Cc: Matthew Brost Cc: Thomas Hellström Cc: # v6.10+ Reviewed-by: Thomas Hellström Reviewed-by: Tejas Upadhyay Link: https://patchwork.freedesktop.org/patch/msgid/20250226174748.294285-2-matthew.auld@intel.com (cherry picked from commit dd8c01e42f4c5c1eaf02f003d7d588ba6706aa71) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hmm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c index 089834467880..2e4ae61567d8 100644 --- a/drivers/gpu/drm/xe/xe_hmm.c +++ b/drivers/gpu/drm/xe/xe_hmm.c @@ -166,13 +166,20 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, { unsigned long timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); - unsigned long *pfns, flags = HMM_PFN_REQ_FAULT; + unsigned long *pfns; struct xe_userptr *userptr; struct xe_vma *vma = &uvma->vma; u64 userptr_start = xe_vma_userptr(vma); u64 userptr_end = userptr_start + xe_vma_size(vma); struct xe_vm *vm = xe_vma_vm(vma); - struct hmm_range hmm_range; + struct hmm_range hmm_range = { + .pfn_flags_mask = 0, /* ignore pfns */ + .default_flags = HMM_PFN_REQ_FAULT, + .start = userptr_start, + .end = userptr_end, + .notifier = &uvma->userptr.notifier, + .dev_private_owner = vm->xe, + }; bool write = !xe_vma_read_only(vma); unsigned long notifier_seq; u64 npages; @@ -199,19 +206,14 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, return -ENOMEM; if (write) - flags |= HMM_PFN_REQ_WRITE; + hmm_range.default_flags |= HMM_PFN_REQ_WRITE; if (!mmget_not_zero(userptr->notifier.mm)) { ret = -EFAULT; goto free_pfns; } - hmm_range.default_flags = flags; hmm_range.hmm_pfns = pfns; - hmm_range.notifier = &userptr->notifier; - hmm_range.start = userptr_start; - hmm_range.end = userptr_end; - hmm_range.dev_private_owner = vm->xe; while (true) { hmm_range.notifier_seq = mmu_interval_read_begin(&userptr->notifier); From 54f94dc7f6b4db45dbc23b4db3d20c7194e2c54f Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 27 Feb 2025 10:13:00 +0000 Subject: [PATCH 0601/1090] drm/xe: Fix GT "for each engine" workarounds Any rules using engine matching are currently broken due RTP processing happening too in early init, before the list of hardware engines has been initialised. Fix this by moving workaround processing to later in the driver probe sequence, to just before the processed list is used for the first time. Looking at the debugfs gt0/workarounds on ADL-P we notice 14011060649 should be present while we see, before: GT Workarounds 14011059788 14015795083 And with the patch: GT Workarounds 14011060649 14011059788 14015795083 Signed-off-by: Tvrtko Ursulin Cc: Lucas De Marchi Cc: Matt Roper Cc: stable@vger.kernel.org # v6.11+ Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20250227101304.46660-2-tvrtko.ursulin@igalia.com Signed-off-by: Lucas De Marchi (cherry picked from commit 25d434cef791e03cf40680f5441b576c639bfa84) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_gt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 5d6fb79957b6..9f4f27d1ef4a 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -380,9 +380,7 @@ int xe_gt_init_early(struct xe_gt *gt) if (err) return err; - xe_wa_process_gt(gt); xe_wa_process_oob(gt); - xe_tuning_process_gt(gt); xe_force_wake_init_gt(gt, gt_to_fw(gt)); spin_lock_init(>->global_invl_lock); @@ -474,6 +472,8 @@ static int all_fw_domain_init(struct xe_gt *gt) } xe_gt_mcr_set_implicit_defaults(gt); + xe_wa_process_gt(gt); + xe_tuning_process_gt(gt); xe_reg_sr_apply_mmio(>->reg_sr, gt); err = xe_gt_clock_init(gt); From 778b94d7ac17b5800aa857222911f09cc986b509 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 11:01:53 -0600 Subject: [PATCH 0602/1090] ACPI: platform_profile: Add support for hidden choices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When two drivers don't support all the same profiles the legacy interface only exports the common profiles. This causes problems for cases where one driver uses low-power but another uses quiet because the result is that neither is exported to sysfs. To allow two drivers to disagree, add support for "hidden choices". Hidden choices are platform profiles that a driver supports to be compatible with the platform profile of another driver. Fixes: 688834743d67 ("ACPI: platform_profile: Allow multiple handlers") Reported-by: Antheas Kapenekakis Closes: https://lore.kernel.org/platform-driver-x86/e64b771e-3255-42ad-9257-5b8fc6c24ac9@gmx.de/T/#mc068042dd29df36c16c8af92664860fc4763974b Signed-off-by: Mario Limonciello Tested-by: Antheas Kapenekakis Tested-by: Derek J. Clark Acked-by: Ilpo Järvinen Link: https://patch.msgid.link/20250228170155.2623386-2-superm1@kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/acpi/platform_profile.c | 94 +++++++++++++++++++++++++------- include/linux/platform_profile.h | 3 + 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 2ad53cc6aae5..ef9444482db1 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -21,9 +21,15 @@ struct platform_profile_handler { struct device dev; int minor; unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + unsigned long hidden_choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; const struct platform_profile_ops *ops; }; +struct aggregate_choices_data { + unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + int count; +}; + static const char * const profile_names[] = { [PLATFORM_PROFILE_LOW_POWER] = "low-power", [PLATFORM_PROFILE_COOL] = "cool", @@ -73,7 +79,7 @@ static int _store_class_profile(struct device *dev, void *data) lockdep_assert_held(&profile_lock); handler = to_pprof_handler(dev); - if (!test_bit(*bit, handler->choices)) + if (!test_bit(*bit, handler->choices) && !test_bit(*bit, handler->hidden_choices)) return -EOPNOTSUPP; return handler->ops->profile_set(dev, *bit); @@ -239,21 +245,44 @@ static const struct class platform_profile_class = { /** * _aggregate_choices - Aggregate the available profile choices * @dev: The device - * @data: The available profile choices + * @arg: struct aggregate_choices_data * * Return: 0 on success, -errno on failure */ -static int _aggregate_choices(struct device *dev, void *data) +static int _aggregate_choices(struct device *dev, void *arg) { + unsigned long tmp[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + struct aggregate_choices_data *data = arg; struct platform_profile_handler *handler; - unsigned long *aggregate = data; lockdep_assert_held(&profile_lock); handler = to_pprof_handler(dev); - if (test_bit(PLATFORM_PROFILE_LAST, aggregate)) - bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST); + bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST); + if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate)) + bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST); else - bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST); + bitmap_and(data->aggregate, tmp, data->aggregate, PLATFORM_PROFILE_LAST); + data->count++; + + return 0; +} + +/** + * _remove_hidden_choices - Remove hidden choices from aggregate data + * @dev: The device + * @arg: struct aggregate_choices_data + * + * Return: 0 on success, -errno on failure + */ +static int _remove_hidden_choices(struct device *dev, void *arg) +{ + struct aggregate_choices_data *data = arg; + struct platform_profile_handler *handler; + + lockdep_assert_held(&profile_lock); + handler = to_pprof_handler(dev); + bitmap_andnot(data->aggregate, handler->choices, + handler->hidden_choices, PLATFORM_PROFILE_LAST); return 0; } @@ -270,22 +299,31 @@ static ssize_t platform_profile_choices_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + struct aggregate_choices_data data = { + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, + .count = 0, + }; int err; - set_bit(PLATFORM_PROFILE_LAST, aggregate); + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { err = class_for_each_device(&platform_profile_class, NULL, - aggregate, _aggregate_choices); + &data, _aggregate_choices); if (err) return err; + if (data.count == 1) { + err = class_for_each_device(&platform_profile_class, NULL, + &data, _remove_hidden_choices); + if (err) + return err; + } } /* no profile handler registered any more */ - if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST)) + if (bitmap_empty(data.aggregate, PLATFORM_PROFILE_LAST)) return -EINVAL; - return _commmon_choices_show(aggregate, buf); + return _commmon_choices_show(data.aggregate, buf); } /** @@ -373,7 +411,10 @@ static ssize_t platform_profile_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + struct aggregate_choices_data data = { + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, + .count = 0, + }; int ret; int i; @@ -381,13 +422,13 @@ static ssize_t platform_profile_store(struct device *dev, i = sysfs_match_string(profile_names, buf); if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) return -EINVAL; - set_bit(PLATFORM_PROFILE_LAST, choices); + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { ret = class_for_each_device(&platform_profile_class, NULL, - choices, _aggregate_choices); + &data, _aggregate_choices); if (ret) return ret; - if (!test_bit(i, choices)) + if (!test_bit(i, data.aggregate)) return -EOPNOTSUPP; ret = class_for_each_device(&platform_profile_class, NULL, &i, @@ -453,12 +494,15 @@ EXPORT_SYMBOL_GPL(platform_profile_notify); */ int platform_profile_cycle(void) { + struct aggregate_choices_data data = { + .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, + .count = 0, + }; enum platform_profile_option next = PLATFORM_PROFILE_LAST; enum platform_profile_option profile = PLATFORM_PROFILE_LAST; - unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; int err; - set_bit(PLATFORM_PROFILE_LAST, choices); + set_bit(PLATFORM_PROFILE_LAST, data.aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { err = class_for_each_device(&platform_profile_class, NULL, &profile, _aggregate_profiles); @@ -470,14 +514,14 @@ int platform_profile_cycle(void) return -EINVAL; err = class_for_each_device(&platform_profile_class, NULL, - choices, _aggregate_choices); + &data, _aggregate_choices); if (err) return err; /* never iterate into a custom if all drivers supported it */ - clear_bit(PLATFORM_PROFILE_CUSTOM, choices); + clear_bit(PLATFORM_PROFILE_CUSTOM, data.aggregate); - next = find_next_bit_wrap(choices, + next = find_next_bit_wrap(data.aggregate, PLATFORM_PROFILE_LAST, profile + 1); @@ -532,6 +576,14 @@ struct device *platform_profile_register(struct device *dev, const char *name, return ERR_PTR(-EINVAL); } + if (ops->hidden_choices) { + err = ops->hidden_choices(drvdata, pprof->hidden_choices); + if (err) { + dev_err(dev, "platform_profile hidden_choices failed\n"); + return ERR_PTR(err); + } + } + guard(mutex)(&profile_lock); /* create class interface for individual handler */ diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index 8ab5b0e8eb2c..8c9df7dadd5d 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -33,6 +33,8 @@ enum platform_profile_option { * @probe: Callback to setup choices available to the new class device. These * choices will only be enforced when setting a new profile, not when * getting the current one. + * @hidden_choices: Callback to setup choices that are not visible to the user + * but can be set by the driver. * @profile_get: Callback that will be called when showing the current platform * profile in sysfs. * @profile_set: Callback that will be called when storing a new platform @@ -40,6 +42,7 @@ enum platform_profile_option { */ struct platform_profile_ops { int (*probe)(void *drvdata, unsigned long *choices); + int (*hidden_choices)(void *drvdata, unsigned long *choices); int (*profile_get)(struct device *dev, enum platform_profile_option *profile); int (*profile_set)(struct device *dev, enum platform_profile_option profile); }; From 44e94fece5170ed9110564efec592d0e88830a28 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 11:01:54 -0600 Subject: [PATCH 0603/1090] platform/x86/amd: pmf: Add 'quiet' to hidden choices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When amd-pmf and asus-wmi are both bound no low power option shows up in sysfs. Add a hidden choice for amd-pmf to support 'quiet' mode to let both bind. Fixes: 688834743d67 ("ACPI: platform_profile: Allow multiple handlers") Suggested-by: Antheas Kapenekakis Signed-off-by: Mario Limonciello Tested-by: Antheas Kapenekakis Tested-by: Derek J. Clark Acked-by: Ilpo Järvinen Link: https://patch.msgid.link/20250228170155.2623386-3-superm1@kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/amd/pmf/sps.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c index e6cf0b22dac3..3a0079c17cb1 100644 --- a/drivers/platform/x86/amd/pmf/sps.c +++ b/drivers/platform/x86/amd/pmf/sps.c @@ -303,6 +303,7 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf) mode = POWER_MODE_BALANCED_POWER; break; case PLATFORM_PROFILE_LOW_POWER: + case PLATFORM_PROFILE_QUIET: mode = POWER_MODE_POWER_SAVER; break; default: @@ -387,6 +388,13 @@ static int amd_pmf_profile_set(struct device *dev, return 0; } +static int amd_pmf_hidden_choices(void *drvdata, unsigned long *choices) +{ + set_bit(PLATFORM_PROFILE_QUIET, choices); + + return 0; +} + static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices) { set_bit(PLATFORM_PROFILE_LOW_POWER, choices); @@ -398,6 +406,7 @@ static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices) static const struct platform_profile_ops amd_pmf_profile_ops = { .probe = amd_pmf_profile_probe, + .hidden_choices = amd_pmf_hidden_choices, .profile_get = amd_pmf_profile_get, .profile_set = amd_pmf_profile_set, }; From 9a43102daf64dd0d172d8b39836dbc1dba4da1ea Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 11:01:55 -0600 Subject: [PATCH 0604/1090] platform/x86/amd: pmf: Add balanced-performance to hidden choices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acer's WMI driver uses balanced-performance but AMD-PMF doesn't. In case a machine binds with both drivers let amd-pmf use balanced-performance as well. Fixes: 688834743d67 ("ACPI: platform_profile: Allow multiple handlers") Suggested-by: Antheas Kapenekakis Signed-off-by: Mario Limonciello Tested-by: Antheas Kapenekakis Tested-by: Derek J. Clark Acked-by: Ilpo Järvinen Link: https://patch.msgid.link/20250228170155.2623386-4-superm1@kernel.org Signed-off-by: Rafael J. Wysocki --- drivers/platform/x86/amd/pmf/sps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c index 3a0079c17cb1..d3083383f11f 100644 --- a/drivers/platform/x86/amd/pmf/sps.c +++ b/drivers/platform/x86/amd/pmf/sps.c @@ -297,6 +297,7 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf) switch (pmf->current_profile) { case PLATFORM_PROFILE_PERFORMANCE: + case PLATFORM_PROFILE_BALANCED_PERFORMANCE: mode = POWER_MODE_PERFORMANCE; break; case PLATFORM_PROFILE_BALANCED: @@ -391,6 +392,7 @@ static int amd_pmf_profile_set(struct device *dev, static int amd_pmf_hidden_choices(void *drvdata, unsigned long *choices) { set_bit(PLATFORM_PROFILE_QUIET, choices); + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); return 0; } From 723aa55c08c9d1e0734e39a815fd41272eac8269 Mon Sep 17 00:00:00 2001 From: Wentao Guan Date: Fri, 14 Feb 2025 19:04:18 +0800 Subject: [PATCH 0605/1090] HID: i2c-hid: improve i2c_hid_get_report error message We have two places to print "failed to set a report to ...", use "get a report from" instead of "set a report to", it makes people who knows less about the module to know where the error happened. Before: i2c_hid_acpi i2c-FTSC1000:00: failed to set a report to device: -11 After: i2c_hid_acpi i2c-FTSC1000:00: failed to get a report from device: -11 Signed-off-by: Wentao Guan Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 75544448c239..d3912e3f2f13 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -290,7 +290,7 @@ static int i2c_hid_get_report(struct i2c_hid *ihid, ihid->rawbuf, recv_len + sizeof(__le16)); if (error) { dev_err(&ihid->client->dev, - "failed to set a report to device: %d\n", error); + "failed to get a report from device: %d\n", error); return error; } From 221cea1003d8a412e5ec64a58df7ab19b654f490 Mon Sep 17 00:00:00 2001 From: Alex Henrie Date: Sun, 23 Feb 2025 22:36:30 -0700 Subject: [PATCH 0606/1090] HID: apple: disable Fn key handling on the Omoton KB066 Remove the fixup to make the Omoton KB066's F6 key F6 when not holding Fn. That was really just a hack to allow typing F6 in fnmode>0, and it didn't fix any of the other F keys that were likewise untypable in fnmode>0. Instead, because the Omoton's Fn key is entirely internal to the keyboard, completely disable Fn key translation when an Omoton is detected, which will prevent the hid-apple driver from interfering with the keyboard's built-in Fn key handling. All of the F keys, including F6, are then typable when Fn is held. The Omoton KB066 and the Apple A1255 both have HID product code 05ac:022c. The self-reported name of every original A1255 when they left the factory was "Apple Wireless Keyboard". By default, Mac OS changes the name to "'s keyboard" when pairing with the keyboard, but Mac OS allows the user to set the internal name of Apple keyboards to anything they like. The Omoton KB066's name, on the other hand, is not configurable: It is always "Bluetooth Keyboard". Because that name is so generic that a user might conceivably use the same name for a real Apple keyboard, detect Omoton keyboards based on both having that exact name and having HID product code 022c. Fixes: 819083cb6eed ("HID: apple: fix up the F6 key on the Omoton KB066 keyboard") Signed-off-by: Alex Henrie Reviewed-by: Aditya Garg Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 49812a76b7ed..d900dd05c335 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -378,6 +378,12 @@ static bool apple_is_non_apple_keyboard(struct hid_device *hdev) return false; } +static bool apple_is_omoton_kb066(struct hid_device *hdev) +{ + return hdev->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI && + strcmp(hdev->name, "Bluetooth Keyboard") == 0; +} + static inline void apple_setup_key_translation(struct input_dev *input, const struct apple_key_translation *table) { @@ -546,9 +552,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } } - if (usage->hid == 0xc0301) /* Omoton KB066 quirk */ - code = KEY_F6; - if (usage->code != code) { input_event_with_scancode(input, usage->type, code, usage->hid, value); @@ -728,7 +731,7 @@ static int apple_input_configured(struct hid_device *hdev, { struct apple_sc *asc = hid_get_drvdata(hdev); - if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) { + if (((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) || apple_is_omoton_kb066(hdev)) { hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n"); asc->quirks &= ~APPLE_HAS_FN; } From 2ff5baa9b5275e3acafdf7f2089f74cccb2f38d1 Mon Sep 17 00:00:00 2001 From: Daniil Dulov Date: Mon, 24 Feb 2025 20:30:30 +0300 Subject: [PATCH 0607/1090] HID: appleir: Fix potential NULL dereference at raw event handle Syzkaller reports a NULL pointer dereference issue in input_event(). BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:68 [inline] BUG: KASAN: null-ptr-deref in _test_bit include/asm-generic/bitops/instrumented-non-atomic.h:141 [inline] BUG: KASAN: null-ptr-deref in is_event_supported drivers/input/input.c:67 [inline] BUG: KASAN: null-ptr-deref in input_event+0x42/0xa0 drivers/input/input.c:395 Read of size 8 at addr 0000000000000028 by task syz-executor199/2949 CPU: 0 UID: 0 PID: 2949 Comm: syz-executor199 Not tainted 6.13.0-rc4-syzkaller-00076-gf097a36ef88d #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120 kasan_report+0xd9/0x110 mm/kasan/report.c:602 check_region_inline mm/kasan/generic.c:183 [inline] kasan_check_range+0xef/0x1a0 mm/kasan/generic.c:189 instrument_atomic_read include/linux/instrumented.h:68 [inline] _test_bit include/asm-generic/bitops/instrumented-non-atomic.h:141 [inline] is_event_supported drivers/input/input.c:67 [inline] input_event+0x42/0xa0 drivers/input/input.c:395 input_report_key include/linux/input.h:439 [inline] key_down drivers/hid/hid-appleir.c:159 [inline] appleir_raw_event+0x3e5/0x5e0 drivers/hid/hid-appleir.c:232 __hid_input_report.constprop.0+0x312/0x440 drivers/hid/hid-core.c:2111 hid_ctrl+0x49f/0x550 drivers/hid/usbhid/hid-core.c:484 __usb_hcd_giveback_urb+0x389/0x6e0 drivers/usb/core/hcd.c:1650 usb_hcd_giveback_urb+0x396/0x450 drivers/usb/core/hcd.c:1734 dummy_timer+0x17f7/0x3960 drivers/usb/gadget/udc/dummy_hcd.c:1993 __run_hrtimer kernel/time/hrtimer.c:1739 [inline] __hrtimer_run_queues+0x20a/0xae0 kernel/time/hrtimer.c:1803 hrtimer_run_softirq+0x17d/0x350 kernel/time/hrtimer.c:1820 handle_softirqs+0x206/0x8d0 kernel/softirq.c:561 __do_softirq kernel/softirq.c:595 [inline] invoke_softirq kernel/softirq.c:435 [inline] __irq_exit_rcu+0xfa/0x160 kernel/softirq.c:662 irq_exit_rcu+0x9/0x30 kernel/softirq.c:678 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline] sysvec_apic_timer_interrupt+0x90/0xb0 arch/x86/kernel/apic/apic.c:1049 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702 __mod_timer+0x8f6/0xdc0 kernel/time/timer.c:1185 add_timer+0x62/0x90 kernel/time/timer.c:1295 schedule_timeout+0x11f/0x280 kernel/time/sleep_timeout.c:98 usbhid_wait_io+0x1c7/0x380 drivers/hid/usbhid/hid-core.c:645 usbhid_init_reports+0x19f/0x390 drivers/hid/usbhid/hid-core.c:784 hiddev_ioctl+0x1133/0x15b0 drivers/hid/usbhid/hiddev.c:794 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:906 [inline] __se_sys_ioctl fs/ioctl.c:892 [inline] __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f This happens due to the malformed report items sent by the emulated device which results in a report, that has no fields, being added to the report list. Due to this appleir_input_configured() is never called, hidinput_connect() fails which results in the HID_CLAIMED_INPUT flag is not being set. However, it does not make appleir_probe() fail and lets the event callback to be called without the associated input device. Thus, add a check for the HID_CLAIMED_INPUT flag and leave the event hook early if the driver didn't claim any input_dev for some reason. Moreover, some other hid drivers accessing input_dev in their event callbacks do have similar checks, too. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: 9a4a5574ce42 ("HID: appleir: add support for Apple ir devices") Cc: stable@vger.kernel.org Signed-off-by: Daniil Dulov Signed-off-by: Jiri Kosina --- drivers/hid/hid-appleir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c index 8deded185725..c45e5aa569d2 100644 --- a/drivers/hid/hid-appleir.c +++ b/drivers/hid/hid-appleir.c @@ -188,7 +188,7 @@ static int appleir_raw_event(struct hid_device *hid, struct hid_report *report, static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 }; unsigned long flags; - if (len != 5) + if (len != 5 || !(hid->claimed & HID_CLAIMED_INPUT)) goto out; if (!memcmp(data, keydown, sizeof(keydown))) { From a6a4f4e9b8018806cca30049b59a1c3c8b513701 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Feb 2025 22:33:57 +0000 Subject: [PATCH 0608/1090] HID: debug: Fix spelling mistake "Messanger" -> "Messenger" There is a spelling mistake in a literal string. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Jiri Kosina --- drivers/hid/hid-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 541d682af15a..8433306148d5 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -3450,7 +3450,7 @@ static const char *keys[KEY_MAX + 1] = { [KEY_MACRO_RECORD_START] = "MacroRecordStart", [KEY_MACRO_RECORD_STOP] = "MacroRecordStop", [KEY_MARK_WAYPOINT] = "MarkWayPoint", [KEY_MEDIA_REPEAT] = "MediaRepeat", - [KEY_MEDIA_TOP_MENU] = "MediaTopMenu", [KEY_MESSENGER] = "Messanger", + [KEY_MEDIA_TOP_MENU] = "MediaTopMenu", [KEY_MESSENGER] = "Messenger", [KEY_NAV_CHART] = "NavChar", [KEY_NAV_INFO] = "NavInfo", [KEY_NEWS] = "News", [KEY_NEXT_ELEMENT] = "NextElement", [KEY_NEXT_FAVORITE] = "NextFavorite", [KEY_NOTIFICATION_CENTER] = "NotificationCenter", From e53fc232a65f7488ab75d03a5b95f06aaada7262 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 27 Feb 2025 15:41:33 -0800 Subject: [PATCH 0609/1090] HID: hid-steam: Fix use-after-free when detaching device When a hid-steam device is removed it must clean up the client_hdev used for intercepting hidraw access. This can lead to scheduling deferred work to reattach the input device. Though the cleanup cancels the deferred work, this was done before the client_hdev itself is cleaned up, so it gets rescheduled. This patch fixes the ordering to make sure the deferred work is properly canceled. Reported-by: syzbot+0154da2d403396b2bd59@syzkaller.appspotmail.com Fixes: 79504249d7e2 ("HID: hid-steam: Move hidraw input (un)registering to work") Signed-off-by: Vicki Pfau Signed-off-by: Jiri Kosina --- drivers/hid/hid-steam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index c9e65e9088b3..10460b7bde1a 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -1327,11 +1327,11 @@ static void steam_remove(struct hid_device *hdev) return; } + hid_destroy_device(steam->client_hdev); cancel_delayed_work_sync(&steam->mode_switch); cancel_work_sync(&steam->work_connect); cancel_work_sync(&steam->rumble_work); cancel_work_sync(&steam->unregister_work); - hid_destroy_device(steam->client_hdev); steam->client_hdev = NULL; steam->client_opened = 0; if (steam->quirks & STEAM_QUIRK_WIRELESS) { From 0132c406705a466b95854ce1058f3d8354f90a42 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 28 Feb 2025 08:41:39 +0000 Subject: [PATCH 0610/1090] HID: intel-thc-hid: Fix spelling mistake "intput" -> "input" There is a spelling mistake in a dev_err_once message. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Even Xu Signed-off-by: Jiri Kosina --- drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c index 7373238ceb18..918050af73e5 100644 --- a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c +++ b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c @@ -107,7 +107,7 @@ static int quickspi_get_device_descriptor(struct quickspi_device *qsdev) return 0; } - dev_err_once(qsdev->dev, "Unexpected intput report type: %d\n", input_rep_type); + dev_err_once(qsdev->dev, "Unexpected input report type: %d\n", input_rep_type); return -EINVAL; } From db52926fb0be40e1d588a346df73f5ea3a34a4c6 Mon Sep 17 00:00:00 2001 From: Even Xu Date: Tue, 4 Mar 2025 11:22:55 +0800 Subject: [PATCH 0611/1090] HID: Intel-thc-hid: Intel-quickspi: Correct device state after S4 During S4 retore flow, quickspi device was resetted by driver and state was changed to RESETTED. It is needed to be change to ENABLED state after S4 re-initialization finished, otherwise, device will run in wrong state and HID input data will be dropped. Signed-off-by: Even Xu Fixes: 6912aaf3fd24 ("HID: intel-thc-hid: intel-quickspi: Add PM implementation") Signed-off-by: Jiri Kosina --- drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c index 4641e818dfa4..6b2c7620be2b 100644 --- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c +++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c @@ -909,6 +909,8 @@ static int quickspi_restore(struct device *device) thc_change_ltr_mode(qsdev->thc_hw, THC_LTR_MODE_ACTIVE); + qsdev->state = QUICKSPI_ENABLED; + return 0; } From 5eb3dc1396aa7e315486b24df80df782912334b7 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Thu, 27 Feb 2025 11:33:40 +0100 Subject: [PATCH 0612/1090] net: ipa: Fix v4.7 resource group names In the downstream IPA driver there's only one group defined for source and destination, and the destination group doesn't have a _DPL suffix. Fixes: b310de784bac ("net: ipa: add IPA v4.7 support") Signed-off-by: Luca Weiss Reviewed-by: Alex Elder Link: https://patch.msgid.link/20250227-ipa-v4-7-fixes-v1-1-a88dd8249d8a@fairphone.com Signed-off-by: Jakub Kicinski --- drivers/net/ipa/data/ipa_data-v4.7.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/ipa/data/ipa_data-v4.7.c b/drivers/net/ipa/data/ipa_data-v4.7.c index c8c23d9be961..7e315779e664 100644 --- a/drivers/net/ipa/data/ipa_data-v4.7.c +++ b/drivers/net/ipa/data/ipa_data-v4.7.c @@ -28,12 +28,10 @@ enum ipa_resource_type { enum ipa_rsrc_group_id { /* Source resource group identifiers */ IPA_RSRC_GROUP_SRC_UL_DL = 0, - IPA_RSRC_GROUP_SRC_UC_RX_Q, IPA_RSRC_GROUP_SRC_COUNT, /* Last in set; not a source group */ /* Destination resource group identifiers */ - IPA_RSRC_GROUP_DST_UL_DL_DPL = 0, - IPA_RSRC_GROUP_DST_UNUSED_1, + IPA_RSRC_GROUP_DST_UL_DL = 0, IPA_RSRC_GROUP_DST_COUNT, /* Last; not a destination group */ }; @@ -81,7 +79,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { }, .endpoint = { .config = { - .resource_group = IPA_RSRC_GROUP_DST_UL_DL_DPL, + .resource_group = IPA_RSRC_GROUP_DST_UL_DL, .aggregation = true, .status_enable = true, .rx = { @@ -128,7 +126,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { }, .endpoint = { .config = { - .resource_group = IPA_RSRC_GROUP_DST_UL_DL_DPL, + .resource_group = IPA_RSRC_GROUP_DST_UL_DL, .qmap = true, .aggregation = true, .rx = { @@ -197,12 +195,12 @@ static const struct ipa_resource ipa_resource_src[] = { /* Destination resource configuration data for an SoC having IPA v4.7 */ static const struct ipa_resource ipa_resource_dst[] = { [IPA_RESOURCE_TYPE_DST_DATA_SECTORS] = { - .limits[IPA_RSRC_GROUP_DST_UL_DL_DPL] = { + .limits[IPA_RSRC_GROUP_DST_UL_DL] = { .min = 7, .max = 7, }, }, [IPA_RESOURCE_TYPE_DST_DPS_DMARS] = { - .limits[IPA_RSRC_GROUP_DST_UL_DL_DPL] = { + .limits[IPA_RSRC_GROUP_DST_UL_DL] = { .min = 2, .max = 2, }, }, From 6a2843aaf551d87beb92d774f7d5b8ae007fe774 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Thu, 27 Feb 2025 11:33:41 +0100 Subject: [PATCH 0613/1090] net: ipa: Fix QSB data for v4.7 As per downstream reference, max_writes should be 12 and max_reads should be 13. Fixes: b310de784bac ("net: ipa: add IPA v4.7 support") Signed-off-by: Luca Weiss Reviewed-by: Alex Elder Link: https://patch.msgid.link/20250227-ipa-v4-7-fixes-v1-2-a88dd8249d8a@fairphone.com Signed-off-by: Jakub Kicinski --- drivers/net/ipa/data/ipa_data-v4.7.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ipa/data/ipa_data-v4.7.c b/drivers/net/ipa/data/ipa_data-v4.7.c index 7e315779e664..e63dcf8d4556 100644 --- a/drivers/net/ipa/data/ipa_data-v4.7.c +++ b/drivers/net/ipa/data/ipa_data-v4.7.c @@ -38,8 +38,8 @@ enum ipa_rsrc_group_id { /* QSB configuration data for an SoC having IPA v4.7 */ static const struct ipa_qsb_data ipa_qsb_data[] = { [IPA_QSB_MASTER_DDR] = { - .max_writes = 8, - .max_reads = 0, /* no limit (hardware max) */ + .max_writes = 12, + .max_reads = 13, .max_reads_beats = 120, }, }; From 934e69669e32eb653234898424ae007bae2f636e Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Thu, 27 Feb 2025 11:33:42 +0100 Subject: [PATCH 0614/1090] net: ipa: Enable checksum for IPA_ENDPOINT_AP_MODEM_{RX,TX} for v4.7 Enable the checksum option for these two endpoints in order to allow mobile data to actually work. Without this, no packets seem to make it through the IPA. Fixes: b310de784bac ("net: ipa: add IPA v4.7 support") Signed-off-by: Luca Weiss Reviewed-by: Alex Elder Link: https://patch.msgid.link/20250227-ipa-v4-7-fixes-v1-3-a88dd8249d8a@fairphone.com Signed-off-by: Jakub Kicinski --- drivers/net/ipa/data/ipa_data-v4.7.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ipa/data/ipa_data-v4.7.c b/drivers/net/ipa/data/ipa_data-v4.7.c index e63dcf8d4556..41f212209993 100644 --- a/drivers/net/ipa/data/ipa_data-v4.7.c +++ b/drivers/net/ipa/data/ipa_data-v4.7.c @@ -104,6 +104,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { .filter_support = true, .config = { .resource_group = IPA_RSRC_GROUP_SRC_UL_DL, + .checksum = true, .qmap = true, .status_enable = true, .tx = { @@ -127,6 +128,7 @@ static const struct ipa_gsi_endpoint_data ipa_gsi_endpoint_data[] = { .endpoint = { .config = { .resource_group = IPA_RSRC_GROUP_DST_UL_DL, + .checksum = true, .qmap = true, .aggregation = true, .rx = { From 4c2d14c40a68678d885eab4008a0129646805bae Mon Sep 17 00:00:00 2001 From: Jiayuan Chen Date: Fri, 28 Feb 2025 22:14:08 +0800 Subject: [PATCH 0615/1090] ppp: Fix KMSAN uninit-value warning with bpf Syzbot caught an "KMSAN: uninit-value" warning [1], which is caused by the ppp driver not initializing a 2-byte header when using socket filter. The following code can generate a PPP filter BPF program: ''' struct bpf_program fp; pcap_t *handle; handle = pcap_open_dead(DLT_PPP_PPPD, 65535); pcap_compile(handle, &fp, "ip and outbound", 0, 0); bpf_dump(&fp, 1); ''' Its output is: ''' (000) ldh [2] (001) jeq #0x21 jt 2 jf 5 (002) ldb [0] (003) jeq #0x1 jt 4 jf 5 (004) ret #65535 (005) ret #0 ''' Wen can find similar code at the following link: https://github.com/ppp-project/ppp/blob/master/pppd/options.c#L1680 The maintainer of this code repository is also the original maintainer of the ppp driver. As you can see the BPF program skips 2 bytes of data and then reads the 'Protocol' field to determine if it's an IP packet. Then it read the first byte of the first 2 bytes to determine the direction. The issue is that only the first byte indicating direction is initialized in current ppp driver code while the second byte is not initialized. For normal BPF programs generated by libpcap, uninitialized data won't be used, so it's not a problem. However, for carefully crafted BPF programs, such as those generated by syzkaller [2], which start reading from offset 0, the uninitialized data will be used and caught by KMSAN. [1] https://syzkaller.appspot.com/bug?extid=853242d9c9917165d791 [2] https://syzkaller.appspot.com/text?tag=ReproC&x=11994913980000 Cc: Paul Mackerras Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot+853242d9c9917165d791@syzkaller.appspotmail.com Closes: https://lore.kernel.org/bpf/000000000000dea025060d6bc3bc@google.com/ Signed-off-by: Jiayuan Chen Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250228141408.393864-1-jiayuan.chen@linux.dev Signed-off-by: Jakub Kicinski --- drivers/net/ppp/ppp_generic.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 4583e15ad03a..1420c4efa48e 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -72,6 +72,17 @@ #define PPP_PROTO_LEN 2 #define PPP_LCP_HDRLEN 4 +/* The filter instructions generated by libpcap are constructed + * assuming a four-byte PPP header on each packet, where the last + * 2 bytes are the protocol field defined in the RFC and the first + * byte of the first 2 bytes indicates the direction. + * The second byte is currently unused, but we still need to initialize + * it to prevent crafted BPF programs from reading them which would + * cause reading of uninitialized data. + */ +#define PPP_FILTER_OUTBOUND_TAG 0x0100 +#define PPP_FILTER_INBOUND_TAG 0x0000 + /* * An instance of /dev/ppp can be associated with either a ppp * interface unit or a ppp channel. In both cases, file->private_data @@ -1762,10 +1773,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) if (proto < 0x8000) { #ifdef CONFIG_PPP_FILTER - /* check if we should pass this packet */ - /* the filter instructions are constructed assuming - a four-byte PPP header on each packet */ - *(u8 *)skb_push(skb, 2) = 1; + /* check if the packet passes the pass and active filters. + * See comment for PPP_FILTER_OUTBOUND_TAG above. + */ + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); if (ppp->pass_filter && bpf_prog_run(ppp->pass_filter, skb) == 0) { if (ppp->debug & 1) @@ -2482,14 +2493,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) /* network protocol frame - give it to the kernel */ #ifdef CONFIG_PPP_FILTER - /* check if the packet passes the pass and active filters */ - /* the filter instructions are constructed assuming - a four-byte PPP header on each packet */ if (ppp->pass_filter || ppp->active_filter) { if (skb_unclone(skb, GFP_ATOMIC)) goto err; - - *(u8 *)skb_push(skb, 2) = 0; + /* Check if the packet passes the pass and active filters. + * See comment for PPP_FILTER_INBOUND_TAG above. + */ + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); if (ppp->pass_filter && bpf_prog_run(ppp->pass_filter, skb) == 0) { if (ppp->debug & 1) From 637399bf7e77797811adf340090b561a8f9d1213 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 1 Mar 2025 15:11:13 +0100 Subject: [PATCH 0616/1090] net: ethtool: netlink: Allow NULL nlattrs when getting a phy_device ethnl_req_get_phydev() is used to lookup a phy_device, in the case an ethtool netlink command targets a specific phydev within a netdev's topology. It takes as a parameter a const struct nlattr *header that's used for error handling : if (!phydev) { NL_SET_ERR_MSG_ATTR(extack, header, "no phy matching phyindex"); return ERR_PTR(-ENODEV); } In the notify path after a ->set operation however, there's no request attributes available. The typical callsite for the above function looks like: phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_XXX_HEADER], info->extack); So, when tb is NULL (such as in the ethnl notify path), we have a nice crash. It turns out that there's only the PLCA command that is in that case, as the other phydev-specific commands don't have a notification. This commit fixes the crash by passing the cmd index and the nlattr array separately, allowing NULL-checking it directly inside the helper. Fixes: c15e065b46dc ("net: ethtool: Allow passing a phy index for some commands") Signed-off-by: Maxime Chevallier Reviewed-by: Kory Maincent Reported-by: Parthiban Veerasooran Link: https://patch.msgid.link/20250301141114.97204-1-maxime.chevallier@bootlin.com Signed-off-by: Jakub Kicinski --- net/ethtool/cabletest.c | 8 ++++---- net/ethtool/linkstate.c | 2 +- net/ethtool/netlink.c | 6 +++--- net/ethtool/netlink.h | 5 +++-- net/ethtool/phy.c | 2 +- net/ethtool/plca.c | 6 +++--- net/ethtool/pse-pd.c | 4 ++-- net/ethtool/stats.c | 2 +- net/ethtool/strset.c | 2 +- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/net/ethtool/cabletest.c b/net/ethtool/cabletest.c index f22051f33868..84096f6b0236 100644 --- a/net/ethtool/cabletest.c +++ b/net/ethtool/cabletest.c @@ -72,8 +72,8 @@ int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev; rtnl_lock(); - phydev = ethnl_req_get_phydev(&req_info, - tb[ETHTOOL_A_CABLE_TEST_HEADER], + phydev = ethnl_req_get_phydev(&req_info, tb, + ETHTOOL_A_CABLE_TEST_HEADER, info->extack); if (IS_ERR_OR_NULL(phydev)) { ret = -EOPNOTSUPP; @@ -339,8 +339,8 @@ int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info) goto out_dev_put; rtnl_lock(); - phydev = ethnl_req_get_phydev(&req_info, - tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER], + phydev = ethnl_req_get_phydev(&req_info, tb, + ETHTOOL_A_CABLE_TEST_TDR_HEADER, info->extack); if (IS_ERR_OR_NULL(phydev)) { ret = -EOPNOTSUPP; diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c index af19e1bed303..05a5f72c99fa 100644 --- a/net/ethtool/linkstate.c +++ b/net/ethtool/linkstate.c @@ -103,7 +103,7 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base, struct phy_device *phydev; int ret; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_LINKSTATE_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_LINKSTATE_HEADER, info->extack); if (IS_ERR(phydev)) { ret = PTR_ERR(phydev); diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index b4c45207fa32..734849a57369 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -211,7 +211,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, } struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info, - const struct nlattr *header, + struct nlattr **tb, unsigned int header, struct netlink_ext_ack *extack) { struct phy_device *phydev; @@ -225,8 +225,8 @@ struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info, return req_info->dev->phydev; phydev = phy_link_topo_get_phy(req_info->dev, req_info->phy_index); - if (!phydev) { - NL_SET_ERR_MSG_ATTR(extack, header, + if (!phydev && tb) { + NL_SET_ERR_MSG_ATTR(extack, tb[header], "no phy matching phyindex"); return ERR_PTR(-ENODEV); } diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index ff69ca0715de..ec6ab5443a6f 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -275,7 +275,8 @@ static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info) * ethnl_req_get_phydev() - Gets the phy_device targeted by this request, * if any. Must be called under rntl_lock(). * @req_info: The ethnl request to get the phy from. - * @header: The netlink header, used for error reporting. + * @tb: The netlink attributes array, for error reporting. + * @header: The netlink header index, used for error reporting. * @extack: The netlink extended ACK, for error reporting. * * The caller must hold RTNL, until it's done interacting with the returned @@ -289,7 +290,7 @@ static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info) * is returned. */ struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info, - const struct nlattr *header, + struct nlattr **tb, unsigned int header, struct netlink_ext_ack *extack); /** diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c index ed8f690f6bac..e067cc234419 100644 --- a/net/ethtool/phy.c +++ b/net/ethtool/phy.c @@ -125,7 +125,7 @@ static int ethnl_phy_parse_request(struct ethnl_req_info *req_base, struct phy_req_info *req_info = PHY_REQINFO(req_base); struct phy_device *phydev; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PHY_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PHY_HEADER, extack); if (!phydev) return 0; diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c index d95d92f173a6..e1f7820a6158 100644 --- a/net/ethtool/plca.c +++ b/net/ethtool/plca.c @@ -62,7 +62,7 @@ static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, struct phy_device *phydev; int ret; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PLCA_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER, info->extack); // check that the PHY device is available and connected if (IS_ERR_OR_NULL(phydev)) { @@ -152,7 +152,7 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) bool mod = false; int ret; - phydev = ethnl_req_get_phydev(req_info, tb[ETHTOOL_A_PLCA_HEADER], + phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PLCA_HEADER, info->extack); // check that the PHY device is available and connected if (IS_ERR_OR_NULL(phydev)) @@ -211,7 +211,7 @@ static int plca_get_status_prepare_data(const struct ethnl_req_info *req_base, struct phy_device *phydev; int ret; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PLCA_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER, info->extack); // check that the PHY device is available and connected if (IS_ERR_OR_NULL(phydev)) { diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c index 2819e2ba6be2..4f6b99eab2a6 100644 --- a/net/ethtool/pse-pd.c +++ b/net/ethtool/pse-pd.c @@ -64,7 +64,7 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base, if (ret < 0) return ret; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_PSE_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PSE_HEADER, info->extack); if (IS_ERR(phydev)) return -ENODEV; @@ -261,7 +261,7 @@ ethnl_set_pse(struct ethnl_req_info *req_info, struct genl_info *info) struct phy_device *phydev; int ret; - phydev = ethnl_req_get_phydev(req_info, tb[ETHTOOL_A_PSE_HEADER], + phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PSE_HEADER, info->extack); ret = ethnl_set_pse_validate(phydev, info); if (ret) diff --git a/net/ethtool/stats.c b/net/ethtool/stats.c index 038a2558f052..3ca8eb2a3b31 100644 --- a/net/ethtool/stats.c +++ b/net/ethtool/stats.c @@ -138,7 +138,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, struct phy_device *phydev; int ret; - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_STATS_HEADER], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_STATS_HEADER, info->extack); if (IS_ERR(phydev)) return PTR_ERR(phydev); diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c index 6b76c05caba4..f6a67109beda 100644 --- a/net/ethtool/strset.c +++ b/net/ethtool/strset.c @@ -309,7 +309,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, return 0; } - phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_HEADER_FLAGS], + phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_HEADER_FLAGS, info->extack); /* phydev can be NULL, check for errors only */ From 022bfe24aad8937705704ff2e414b100cf0f2e1a Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Mon, 3 Mar 2025 18:10:13 +0100 Subject: [PATCH 0617/1090] mptcp: fix 'scheduling while atomic' in mptcp_pm_nl_append_new_local_addr If multiple connection requests attempt to create an implicit mptcp endpoint in parallel, more than one caller may end up in mptcp_pm_nl_append_new_local_addr because none found the address in local_addr_list during their call to mptcp_pm_nl_get_local_id. In this case, the concurrent new_local_addr calls may delete the address entry created by the previous caller. These deletes use synchronize_rcu, but this is not permitted in some of the contexts where this function may be called. During packet recv, the caller may be in a rcu read critical section and have preemption disabled. An example stack: BUG: scheduling while atomic: swapper/2/0/0x00000302 Call Trace: dump_stack_lvl (lib/dump_stack.c:117 (discriminator 1)) dump_stack (lib/dump_stack.c:124) __schedule_bug (kernel/sched/core.c:5943) schedule_debug.constprop.0 (arch/x86/include/asm/preempt.h:33 kernel/sched/core.c:5970) __schedule (arch/x86/include/asm/jump_label.h:27 include/linux/jump_label.h:207 kernel/sched/features.h:29 kernel/sched/core.c:6621) schedule (arch/x86/include/asm/preempt.h:84 kernel/sched/core.c:6804 kernel/sched/core.c:6818) schedule_timeout (kernel/time/timer.c:2160) wait_for_completion (kernel/sched/completion.c:96 kernel/sched/completion.c:116 kernel/sched/completion.c:127 kernel/sched/completion.c:148) __wait_rcu_gp (include/linux/rcupdate.h:311 kernel/rcu/update.c:444) synchronize_rcu (kernel/rcu/tree.c:3609) mptcp_pm_nl_append_new_local_addr (net/mptcp/pm_netlink.c:966 net/mptcp/pm_netlink.c:1061) mptcp_pm_nl_get_local_id (net/mptcp/pm_netlink.c:1164) mptcp_pm_get_local_id (net/mptcp/pm.c:420) subflow_check_req (net/mptcp/subflow.c:98 net/mptcp/subflow.c:213) subflow_v4_route_req (net/mptcp/subflow.c:305) tcp_conn_request (net/ipv4/tcp_input.c:7216) subflow_v4_conn_request (net/mptcp/subflow.c:651) tcp_rcv_state_process (net/ipv4/tcp_input.c:6709) tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1934) tcp_v4_rcv (net/ipv4/tcp_ipv4.c:2334) ip_protocol_deliver_rcu (net/ipv4/ip_input.c:205 (discriminator 1)) ip_local_deliver_finish (include/linux/rcupdate.h:813 net/ipv4/ip_input.c:234) ip_local_deliver (include/linux/netfilter.h:314 include/linux/netfilter.h:308 net/ipv4/ip_input.c:254) ip_sublist_rcv_finish (include/net/dst.h:461 net/ipv4/ip_input.c:580) ip_sublist_rcv (net/ipv4/ip_input.c:640) ip_list_rcv (net/ipv4/ip_input.c:675) __netif_receive_skb_list_core (net/core/dev.c:5583 net/core/dev.c:5631) netif_receive_skb_list_internal (net/core/dev.c:5685 net/core/dev.c:5774) napi_complete_done (include/linux/list.h:37 include/net/gro.h:449 include/net/gro.h:444 net/core/dev.c:6114) igb_poll (drivers/net/ethernet/intel/igb/igb_main.c:8244) igb __napi_poll (net/core/dev.c:6582) net_rx_action (net/core/dev.c:6653 net/core/dev.c:6787) handle_softirqs (kernel/softirq.c:553) __irq_exit_rcu (kernel/softirq.c:588 kernel/softirq.c:427 kernel/softirq.c:636) irq_exit_rcu (kernel/softirq.c:651) common_interrupt (arch/x86/kernel/irq.c:247 (discriminator 14)) This problem seems particularly prevalent if the user advertises an endpoint that has a different external vs internal address. In the case where the external address is advertised and multiple connections already exist, multiple subflow SYNs arrive in parallel which tends to trigger the race during creation of the first local_addr_list entries which have the internal address instead. Fix by skipping the replacement of an existing implicit local address if called via mptcp_pm_nl_get_local_id. Fixes: d045b9eb95a9 ("mptcp: introduce implicit endpoints") Cc: stable@vger.kernel.org Suggested-by: Paolo Abeni Signed-off-by: Krister Johansen Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250303-net-mptcp-fix-sched-while-atomic-v1-1-f6a216c5a74c@kernel.org Signed-off-by: Jakub Kicinski --- net/mptcp/pm_netlink.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index c0e47f4f7b1a..7868207c4e9d 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -977,7 +977,7 @@ static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry) static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, struct mptcp_pm_addr_entry *entry, - bool needs_id) + bool needs_id, bool replace) { struct mptcp_pm_addr_entry *cur, *del_entry = NULL; unsigned int addr_max; @@ -1017,6 +1017,17 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet, if (entry->addr.id) goto out; + /* allow callers that only need to look up the local + * addr's id to skip replacement. This allows them to + * avoid calling synchronize_rcu in the packet recv + * path. + */ + if (!replace) { + kfree(entry); + ret = cur->addr.id; + goto out; + } + pernet->addrs--; entry->addr.id = cur->addr.id; list_del_rcu(&cur->list); @@ -1165,7 +1176,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc entry->ifindex = 0; entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; entry->lsk = NULL; - ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true); + ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true, false); if (ret < 0) kfree(entry); @@ -1433,7 +1444,8 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info) } } ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, - !mptcp_pm_has_addr_attr_id(attr, info)); + !mptcp_pm_has_addr_attr_id(attr, info), + true); if (ret < 0) { GENL_SET_ERR_MSG_FMT(info, "too many addresses or duplicate one: %d", ret); goto out_free; From b33a534610067ade2bdaf2052900aaad99701353 Mon Sep 17 00:00:00 2001 From: Oscar Maes Date: Mon, 3 Mar 2025 16:56:19 +0100 Subject: [PATCH 0618/1090] vlan: enforce underlying device type Currently, VLAN devices can be created on top of non-ethernet devices. Besides the fact that it doesn't make much sense, this also causes a bug which leaks the address of a kernel function to usermode. When creating a VLAN device, we initialize GARP (garp_init_applicant) and MRP (mrp_init_applicant) for the underlying device. As part of the initialization process, we add the multicast address of each applicant to the underlying device, by calling dev_mc_add. __dev_mc_add uses dev->addr_len to determine the length of the new multicast address. This causes an out-of-bounds read if dev->addr_len is greater than 6, since the multicast addresses provided by GARP and MRP are only 6 bytes long. This behaviour can be reproduced using the following commands: ip tunnel add gretest mode ip6gre local ::1 remote ::2 dev lo ip l set up dev gretest ip link add link gretest name vlantest type vlan id 100 Then, the following command will display the address of garp_pdu_rcv: ip maddr show | grep 01:80:c2:00:00:21 Fix the bug by enforcing the type of the underlying device during VLAN device initialization. Fixes: 22bedad3ce11 ("net: convert multicast list to list_head") Reported-by: syzbot+91161fe81857b396c8a0@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/000000000000ca9a81061a01ec20@google.com/ Signed-off-by: Oscar Maes Reviewed-by: Jiri Pirko Link: https://patch.msgid.link/20250303155619.8918-1-oscmaes92@gmail.com Signed-off-by: Jakub Kicinski --- net/8021q/vlan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index e45187b88220..41be38264493 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -131,7 +131,8 @@ int vlan_check_real_dev(struct net_device *real_dev, { const char *name = real_dev->name; - if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { + if (real_dev->features & NETIF_F_VLAN_CHALLENGED || + real_dev->type != ARPHRD_ETHER) { pr_info("VLANs not supported on %s\n", name); NL_SET_ERR_MSG_MOD(extack, "VLANs not supported on device"); return -EOPNOTSUPP; From 0d3e0dfd68fb9e6b0ec865be9f3377cc3ff55733 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 5 Mar 2025 07:00:05 +0200 Subject: [PATCH 0619/1090] x86/sgx: Fix size overflows in sgx_encl_create() The total size calculated for EPC can overflow u64 given the added up page for SECS. Further, the total size calculated for shmem can overflow even when the EPC size stays within limits of u64, given that it adds the extra space for 128 byte PCMD structures (one for each page). Address this by pre-evaluating the micro-architectural requirement of SGX: the address space size must be power of two. This is eventually checked up by ECREATE but the pre-check has the additional benefit of making sure that there is some space for additional data. Fixes: 888d24911787 ("x86/sgx: Add SGX_IOC_ENCLAVE_CREATE") Reported-by: Dan Carpenter Signed-off-by: Jarkko Sakkinen Signed-off-by: Ingo Molnar Acked-by: Dave Hansen Cc: Peter Zijlstra Cc: "H. Peter Anvin" Link: https://lore.kernel.org/r/20250305050006.43896-1-jarkko@kernel.org Closes: https://lore.kernel.org/linux-sgx/c87e01a0-e7dd-4749-a348-0980d3444f04@stanley.mountain/ --- arch/x86/kernel/cpu/sgx/ioctl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c index b65ab214bdf5..776a20172867 100644 --- a/arch/x86/kernel/cpu/sgx/ioctl.c +++ b/arch/x86/kernel/cpu/sgx/ioctl.c @@ -64,6 +64,13 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs) struct file *backing; long ret; + /* + * ECREATE would detect this too, but checking here also ensures + * that the 'encl_size' calculations below can never overflow. + */ + if (!is_power_of_2(secs->size)) + return -EINVAL; + va_page = sgx_encl_grow(encl, true); if (IS_ERR(va_page)) return PTR_ERR(va_page); From 50dc696c3a482ea35bd0691f728d47e40b668483 Mon Sep 17 00:00:00 2001 From: Aiden Ma Date: Tue, 4 Mar 2025 19:54:01 +0800 Subject: [PATCH 0620/1090] doc: correcting two prefix errors in idmappings.rst Add the 'k' prefix to id 21000. And id `u1000` in the third idmapping should be mapped to `k31000`, not `u31000`. Signed-off-by: Aiden Ma Link: https://lore.kernel.org/r/tencent_4E7B1F143E8051530C21FCADF4E014DCBB06@qq.com Signed-off-by: Christian Brauner --- Documentation/filesystems/idmappings.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/idmappings.rst b/Documentation/filesystems/idmappings.rst index 77930c77fcfe..2a206129f828 100644 --- a/Documentation/filesystems/idmappings.rst +++ b/Documentation/filesystems/idmappings.rst @@ -63,8 +63,8 @@ what id ``k11000`` corresponds to in the second or third idmapping. The straightforward algorithm to use is to apply the inverse of the first idmapping, mapping ``k11000`` up to ``u1000``. Afterwards, we can map ``u1000`` down using either the second idmapping mapping or third idmapping mapping. The second -idmapping would map ``u1000`` down to ``21000``. The third idmapping would map -``u1000`` down to ``u31000``. +idmapping would map ``u1000`` down to ``k21000``. The third idmapping would map +``u1000`` down to ``k31000``. If we were given the same task for the following three idmappings:: From 9ba93cb8212d62bccd8b41b8adb6656abf37280a Mon Sep 17 00:00:00 2001 From: Shyam Sundar S K Date: Wed, 5 Mar 2025 10:28:41 +0530 Subject: [PATCH 0621/1090] platform/x86/amd/pmf: Propagate PMF-TA return codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the amd_pmf_invoke_cmd_init() function within the PMF driver ensure that the actual result from the PMF-TA is returned rather than a generic EIO. This change allows for proper handling of errors originating from the PMF-TA. Reviewed-by: Mario Limonciello Co-developed-by: Patil Rajesh Reddy Signed-off-by: Patil Rajesh Reddy Signed-off-by: Shyam Sundar S K Link: https://lore.kernel.org/r/20250305045842.4117767-1-Shyam-sundar.S-k@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/tee-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c index 8c88769ea1d8..b404764550c4 100644 --- a/drivers/platform/x86/amd/pmf/tee-if.c +++ b/drivers/platform/x86/amd/pmf/tee-if.c @@ -323,7 +323,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) } else { dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res); dev->smart_pc_enabled = false; - return -EIO; + return res; } return 0; From 376a8c2a144397d9cf2a67d403dd64f4a7ff9104 Mon Sep 17 00:00:00 2001 From: Shyam Sundar S K Date: Wed, 5 Mar 2025 10:28:42 +0530 Subject: [PATCH 0622/1090] platform/x86/amd/pmf: Update PMF Driver for Compatibility with new PMF-TA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PMF driver allocates a shared memory buffer using tee_shm_alloc_kernel_buf() for communication with the PMF-TA. The latest PMF-TA version introduces new structures with OEM debug information and additional policy input conditions for evaluating the policy binary. Consequently, the shared memory size must be increased to ensure compatibility between the PMF driver and the updated PMF-TA. To do so, introduce the new PMF-TA UUID and update the PMF shared memory configuration to ensure compatibility with the latest PMF-TA version. Additionally, export the TA UUID. These updates will result in modifications to the prototypes of amd_pmf_tee_init() and amd_pmf_ta_open_session(). Link: https://lore.kernel.org/all/55ac865f-b1c7-fa81-51c4-d211c7963e7e@linux.intel.com/ Reviewed-by: Mario Limonciello Co-developed-by: Patil Rajesh Reddy Signed-off-by: Patil Rajesh Reddy Signed-off-by: Shyam Sundar S K Link: https://lore.kernel.org/r/20250305045842.4117767-2-Shyam-sundar.S-k@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/pmf.h | 5 ++- drivers/platform/x86/amd/pmf/tee-if.c | 50 +++++++++++++++++++-------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 41b2b91b8fdc..e6bdee68ccf3 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -106,9 +106,12 @@ struct cookie_header { #define PMF_TA_IF_VERSION_MAJOR 1 #define TA_PMF_ACTION_MAX 32 #define TA_PMF_UNDO_MAX 8 -#define TA_OUTPUT_RESERVED_MEM 906 +#define TA_OUTPUT_RESERVED_MEM 922 #define MAX_OPERATION_PARAMS 4 +#define TA_ERROR_CRYPTO_INVALID_PARAM 0x20002 +#define TA_ERROR_CRYPTO_BIN_TOO_LARGE 0x2000d + #define PMF_IF_V1 1 #define PMF_IF_V2 2 diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c index b404764550c4..ceaff1ebb7b9 100644 --- a/drivers/platform/x86/amd/pmf/tee-if.c +++ b/drivers/platform/x86/amd/pmf/tee-if.c @@ -27,8 +27,11 @@ module_param(pb_side_load, bool, 0444); MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures"); #endif -static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, - 0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43); +static const uuid_t amd_pmf_ta_uuid[] = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8, 0x8a, + 0xcc, 0x2b, 0x2b, 0x60, 0xd6), + UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d, 0xc5, + 0x29, 0xb1, 0x3d, 0x85, 0x43), + }; static const char *amd_pmf_uevent_as_str(unsigned int state) { @@ -321,7 +324,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) */ schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3)); } else { - dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res); + dev_dbg(dev->dev, "ta invoke cmd init failed err: %x\n", res); dev->smart_pc_enabled = false; return res; } @@ -390,12 +393,12 @@ static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const voi return ver->impl_id == TEE_IMPL_ID_AMDTEE; } -static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id) +static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id, const uuid_t *uuid) { struct tee_ioctl_open_session_arg sess_arg = {}; int rc; - export_uuid(sess_arg.uuid, &amd_pmf_ta_uuid); + export_uuid(sess_arg.uuid, uuid); sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC; sess_arg.num_params = 0; @@ -434,7 +437,7 @@ static int amd_pmf_register_input_device(struct amd_pmf_dev *dev) return 0; } -static int amd_pmf_tee_init(struct amd_pmf_dev *dev) +static int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid) { u32 size; int ret; @@ -445,7 +448,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev) return PTR_ERR(dev->tee_ctx); } - ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id); + ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id, uuid); if (ret) { dev_err(dev->dev, "Failed to open TA session (%d)\n", ret); ret = -EINVAL; @@ -489,7 +492,8 @@ static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev) int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) { - int ret; + bool status; + int ret, i; ret = apmf_check_smart_pc(dev); if (ret) { @@ -502,10 +506,6 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) return -ENODEV; } - ret = amd_pmf_tee_init(dev); - if (ret) - return ret; - INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd); ret = amd_pmf_set_dram_addr(dev, true); @@ -534,8 +534,30 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) goto error; } - ret = amd_pmf_start_policy_engine(dev); - if (ret) + for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) { + ret = amd_pmf_tee_init(dev, &amd_pmf_ta_uuid[i]); + if (ret) + return ret; + + ret = amd_pmf_start_policy_engine(dev); + switch (ret) { + case TA_PMF_TYPE_SUCCESS: + status = true; + break; + case TA_ERROR_CRYPTO_INVALID_PARAM: + case TA_ERROR_CRYPTO_BIN_TOO_LARGE: + amd_pmf_tee_deinit(dev); + status = false; + break; + default: + goto error; + } + + if (status) + break; + } + + if (!status && !pb_side_load) goto error; if (pb_side_load) From de22dc76e11d1291d4f50b73dbbaa158ba9d6acd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Mar 2025 00:24:06 +0000 Subject: [PATCH 0623/1090] ASoC: doc: use SND_SOC_DAILINK_xxx() macro We can use SND_SOC_DAILINK_xxx() macro to define CPU/Codec/Platform. Let's use it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87tt88z5nd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dpcm.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Documentation/sound/soc/dpcm.rst b/Documentation/sound/soc/dpcm.rst index a12636552f50..7b6aeab3c207 100644 --- a/Documentation/sound/soc/dpcm.rst +++ b/Documentation/sound/soc/dpcm.rst @@ -147,14 +147,16 @@ For the example above we have to define 4 FE DAI links and 6 BE DAI links. The FE DAI links are defined as follows :- :: + SND_SOC_DAILINK_DEFS(pcm0, + DAILINK_COMP_ARRAY(COMP_CPU("System Pin")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_PLATFORM("dsp-audio"))); + static struct snd_soc_dai_link machine_dais[] = { { .name = "PCM0 System", .stream_name = "System Playback", - .cpu_dai_name = "System Pin", - .platform_name = "dsp-audio", - .codec_name = "snd-soc-dummy", - .codec_dai_name = "snd-soc-dummy-dai", + SND_SOC_DAILINK_REG(pcm0), .dynamic = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, }, @@ -174,15 +176,16 @@ dynamic and will change depending on runtime config. The BE DAIs are configured as follows :- :: + SND_SOC_DAILINK_DEFS(headset, + DAILINK_COMP_ARRAY(COMP_CPU("ssp-dai.0")), + DAILINK_COMP_ARRAY(COMP_CODEC("rt5640.0-001c", "rt5640-aif1"))); + static struct snd_soc_dai_link machine_dais[] = { .....< FE DAI links here > { .name = "Codec Headset", - .cpu_dai_name = "ssp-dai.0", - .platform_name = "snd-soc-dummy", + SND_SOC_DAILINK_REG(headset), .no_pcm = 1, - .codec_name = "rt5640.0-001c", - .codec_dai_name = "rt5640-aif1", .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = hswult_ssp0_fixup, From 12f65d1203507f7db3ba59930fe29a3b8eee9945 Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Mon, 24 Feb 2025 23:31:26 +0900 Subject: [PATCH 0624/1090] gpio: aggregator: protect driver attr handlers against module unload Both new_device_store and delete_device_store touch module global resources (e.g. gpio_aggregator_lock). To prevent race conditions with module unload, a reference needs to be held. Add try_module_get() in these handlers. For new_device_store, this eliminates what appears to be the most dangerous scenario: if an id is allocated from gpio_aggregator_idr but platform_device_register has not yet been called or completed, a concurrent module unload could fail to unregister/delete the device, leaving behind a dangling platform device/GPIO forwarder. This can result in various issues. The following simple reproducer demonstrates these problems: #!/bin/bash while :; do # note: whether 'gpiochip0 0' exists or not does not matter. echo 'gpiochip0 0' > /sys/bus/platform/drivers/gpio-aggregator/new_device done & while :; do modprobe gpio-aggregator modprobe -r gpio-aggregator done & wait Starting with the following warning, several kinds of warnings will appear and the system may become unstable: ------------[ cut here ]------------ list_del corruption, ffff888103e2e980->next is LIST_POISON1 (dead000000000100) WARNING: CPU: 1 PID: 1327 at lib/list_debug.c:56 __list_del_entry_valid_or_report+0xa3/0x120 [...] RIP: 0010:__list_del_entry_valid_or_report+0xa3/0x120 [...] Call Trace: ? __list_del_entry_valid_or_report+0xa3/0x120 ? __warn.cold+0x93/0xf2 ? __list_del_entry_valid_or_report+0xa3/0x120 ? report_bug+0xe6/0x170 ? __irq_work_queue_local+0x39/0xe0 ? handle_bug+0x58/0x90 ? exc_invalid_op+0x13/0x60 ? asm_exc_invalid_op+0x16/0x20 ? __list_del_entry_valid_or_report+0xa3/0x120 gpiod_remove_lookup_table+0x22/0x60 new_device_store+0x315/0x350 [gpio_aggregator] kernfs_fop_write_iter+0x137/0x1f0 vfs_write+0x262/0x430 ksys_write+0x60/0xd0 do_syscall_64+0x6c/0x180 entry_SYSCALL_64_after_hwframe+0x76/0x7e [...] ---[ end trace 0000000000000000 ]--- Fixes: 828546e24280 ("gpio: Add GPIO Aggregator") Cc: stable@vger.kernel.org Signed-off-by: Koichiro Den Link: https://lore.kernel.org/r/20250224143134.3024598-2-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-aggregator.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 65f41cc3eafc..d668ddb2e81d 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -119,10 +119,15 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, struct platform_device *pdev; int res, id; + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + /* kernfs guarantees string termination, so count + 1 is safe */ aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL); - if (!aggr) - return -ENOMEM; + if (!aggr) { + res = -ENOMEM; + goto put_module; + } memcpy(aggr->args, buf, count + 1); @@ -161,6 +166,7 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf, } aggr->pdev = pdev; + module_put(THIS_MODULE); return count; remove_table: @@ -175,6 +181,8 @@ free_table: kfree(aggr->lookups); free_ga: kfree(aggr); +put_module: + module_put(THIS_MODULE); return res; } @@ -203,13 +211,19 @@ static ssize_t delete_device_store(struct device_driver *driver, if (error) return error; + if (!try_module_get(THIS_MODULE)) + return -ENOENT; + mutex_lock(&gpio_aggregator_lock); aggr = idr_remove(&gpio_aggregator_idr, id); mutex_unlock(&gpio_aggregator_lock); - if (!aggr) + if (!aggr) { + module_put(THIS_MODULE); return -ENOENT; + } gpio_aggregator_free(aggr); + module_put(THIS_MODULE); return count; } static DRIVER_ATTR_WO(delete_device); From f02c41f87cfe61440c18bf77d1ef0a884b9ee2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 21 Jan 2025 14:58:33 +0100 Subject: [PATCH 0625/1090] gpio: rcar: Use raw_spinlock to protect register access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use raw_spinlock in order to fix spurious messages about invalid context when spinlock debugging is enabled. The lock is only used to serialize register access. [ 4.239592] ============================= [ 4.239595] [ BUG: Invalid wait context ] [ 4.239599] 6.13.0-rc7-arm64-renesas-05496-gd088502a519f #35 Not tainted [ 4.239603] ----------------------------- [ 4.239606] kworker/u8:5/76 is trying to lock: [ 4.239609] ffff0000091898a0 (&p->lock){....}-{3:3}, at: gpio_rcar_config_interrupt_input_mode+0x34/0x164 [ 4.239641] other info that might help us debug this: [ 4.239643] context-{5:5} [ 4.239646] 5 locks held by kworker/u8:5/76: [ 4.239651] #0: ffff0000080fb148 ((wq_completion)async){+.+.}-{0:0}, at: process_one_work+0x190/0x62c [ 4.250180] OF: /soc/sound@ec500000/ports/port@0/endpoint: Read of boolean property 'frame-master' with a value. [ 4.254094] #1: ffff80008299bd80 ((work_completion)(&entry->work)){+.+.}-{0:0}, at: process_one_work+0x1b8/0x62c [ 4.254109] #2: ffff00000920c8f8 [ 4.258345] OF: /soc/sound@ec500000/ports/port@1/endpoint: Read of boolean property 'bitclock-master' with a value. [ 4.264803] (&dev->mutex){....}-{4:4}, at: __device_attach_async_helper+0x3c/0xdc [ 4.264820] #3: ffff00000a50ca40 (request_class#2){+.+.}-{4:4}, at: __setup_irq+0xa0/0x690 [ 4.264840] #4: [ 4.268872] OF: /soc/sound@ec500000/ports/port@1/endpoint: Read of boolean property 'frame-master' with a value. [ 4.273275] ffff00000a50c8c8 (lock_class){....}-{2:2}, at: __setup_irq+0xc4/0x690 [ 4.296130] renesas_sdhi_internal_dmac ee100000.mmc: mmc1 base at 0x00000000ee100000, max clock rate 200 MHz [ 4.304082] stack backtrace: [ 4.304086] CPU: 1 UID: 0 PID: 76 Comm: kworker/u8:5 Not tainted 6.13.0-rc7-arm64-renesas-05496-gd088502a519f #35 [ 4.304092] Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT) [ 4.304097] Workqueue: async async_run_entry_fn [ 4.304106] Call trace: [ 4.304110] show_stack+0x14/0x20 (C) [ 4.304122] dump_stack_lvl+0x6c/0x90 [ 4.304131] dump_stack+0x14/0x1c [ 4.304138] __lock_acquire+0xdfc/0x1584 [ 4.426274] lock_acquire+0x1c4/0x33c [ 4.429942] _raw_spin_lock_irqsave+0x5c/0x80 [ 4.434307] gpio_rcar_config_interrupt_input_mode+0x34/0x164 [ 4.440061] gpio_rcar_irq_set_type+0xd4/0xd8 [ 4.444422] __irq_set_trigger+0x5c/0x178 [ 4.448435] __setup_irq+0x2e4/0x690 [ 4.452012] request_threaded_irq+0xc4/0x190 [ 4.456285] devm_request_threaded_irq+0x7c/0xf4 [ 4.459398] ata1: link resume succeeded after 1 retries [ 4.460902] mmc_gpiod_request_cd_irq+0x68/0xe0 [ 4.470660] mmc_start_host+0x50/0xac [ 4.474327] mmc_add_host+0x80/0xe4 [ 4.477817] tmio_mmc_host_probe+0x2b0/0x440 [ 4.482094] renesas_sdhi_probe+0x488/0x6f4 [ 4.486281] renesas_sdhi_internal_dmac_probe+0x60/0x78 [ 4.491509] platform_probe+0x64/0xd8 [ 4.495178] really_probe+0xb8/0x2a8 [ 4.498756] __driver_probe_device+0x74/0x118 [ 4.503116] driver_probe_device+0x3c/0x154 [ 4.507303] __device_attach_driver+0xd4/0x160 [ 4.511750] bus_for_each_drv+0x84/0xe0 [ 4.515588] __device_attach_async_helper+0xb0/0xdc [ 4.520470] async_run_entry_fn+0x30/0xd8 [ 4.524481] process_one_work+0x210/0x62c [ 4.528494] worker_thread+0x1ac/0x340 [ 4.532245] kthread+0x10c/0x110 [ 4.535476] ret_from_fork+0x10/0x20 Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250121135833.3769310-1-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rcar.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 2ecee3269a0c..8e0544e92488 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -40,7 +40,7 @@ struct gpio_rcar_info { struct gpio_rcar_priv { void __iomem *base; - spinlock_t lock; + raw_spinlock_t lock; struct device *dev; struct gpio_chip gpio_chip; unsigned int irq_parent; @@ -123,7 +123,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, * "Setting Level-Sensitive Interrupt Input Mode" */ - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); /* Configure positive or negative logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge); @@ -142,7 +142,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, if (!level_trigger) gpio_rcar_write(p, INTCLR, BIT(hwirq)); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type) @@ -246,7 +246,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, * "Setting General Input Mode" */ - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); /* Configure positive logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, gpio, false); @@ -261,7 +261,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, if (p->info.has_outdtsel && output) gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset) @@ -347,7 +347,7 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask, return 0; } - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); outputs = gpio_rcar_read(p, INOUTSEL); m = outputs & bankmask; if (m) @@ -356,7 +356,7 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask, m = ~outputs & bankmask; if (m) val |= gpio_rcar_read(p, INDT) & m; - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); bits[0] = val; return 0; @@ -367,9 +367,9 @@ static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value) struct gpio_rcar_priv *p = gpiochip_get_data(chip); unsigned long flags; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); gpio_rcar_modify_bit(p, OUTDT, offset, value); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, @@ -386,12 +386,12 @@ static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, if (!bankmask) return; - spin_lock_irqsave(&p->lock, flags); + raw_spin_lock_irqsave(&p->lock, flags); val = gpio_rcar_read(p, OUTDT); val &= ~bankmask; val |= (bankmask & bits[0]); gpio_rcar_write(p, OUTDT, val); - spin_unlock_irqrestore(&p->lock, flags); + raw_spin_unlock_irqrestore(&p->lock, flags); } static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, @@ -505,7 +505,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) return -ENOMEM; p->dev = dev; - spin_lock_init(&p->lock); + raw_spin_lock_init(&p->lock); /* Get device configuration from DT node */ ret = gpio_rcar_parse_dt(p, &npins); From 6697f819a10b238ccf01998c3f203d65d8374696 Mon Sep 17 00:00:00 2001 From: Yuezhang Mo Date: Fri, 22 Nov 2024 10:50:55 +0800 Subject: [PATCH 0626/1090] exfat: fix just enough dentries but allocate a new cluster to dir This commit fixes the condition for allocating cluster to parent directory to avoid allocating new cluster to parent directory when there are just enough empty directory entries at the end of the parent directory. Fixes: af02c72d0b62 ("exfat: convert exfat_find_empty_entry() to use dentry cache") Signed-off-by: Yuezhang Mo Signed-off-by: Namjae Jeon --- fs/exfat/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index 691dd77b6ab5..5b16181a4c2e 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -232,7 +232,7 @@ static int exfat_search_empty_slot(struct super_block *sb, dentry = 0; } - while (dentry + num_entries < total_entries && + while (dentry + num_entries <= total_entries && clu.dir != EXFAT_EOF_CLUSTER) { i = dentry & (dentries_per_clu - 1); From 9da33619e0ca53627641bc97d1b93ec741299111 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 31 Jan 2025 12:55:55 +0900 Subject: [PATCH 0627/1090] exfat: fix soft lockup in exfat_clear_bitmap bitmap clear loop will take long time in __exfat_free_cluster() if data size of file/dir enty is invalid. If cluster bit in bitmap is already clear, stop clearing bitmap go to out of loop. Fixes: 31023864e67a ("exfat: add fat entry operations") Reported-by: Kun Hu , Jiaji Qin Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon --- fs/exfat/balloc.c | 10 ++++++++-- fs/exfat/exfat_fs.h | 2 +- fs/exfat/fatent.c | 11 +++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c index ce9be95c9172..9ff825f1502d 100644 --- a/fs/exfat/balloc.c +++ b/fs/exfat/balloc.c @@ -141,7 +141,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync) return 0; } -void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) +int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) { int i, b; unsigned int ent_idx; @@ -150,13 +150,17 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) struct exfat_mount_options *opts = &sbi->options; if (!is_valid_cluster(sbi, clu)) - return; + return -EIO; ent_idx = CLUSTER_TO_BITMAP_ENT(clu); i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + if (!test_bit_le(b, sbi->vol_amap[i]->b_data)) + return -EIO; + clear_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sbi->vol_amap[i], sync); if (opts->discard) { @@ -171,6 +175,8 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) opts->discard = 0; } } + + return 0; } /* diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 78be6964a8a0..d30ce18a88b7 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -456,7 +456,7 @@ int exfat_count_num_clusters(struct super_block *sb, int exfat_load_bitmap(struct super_block *sb); void exfat_free_bitmap(struct exfat_sb_info *sbi); int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync); -void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); +int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu); int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count); int exfat_trim_fs(struct inode *inode, struct fstrim_range *range); diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c index 9e5492ac409b..6f3651c6ca91 100644 --- a/fs/exfat/fatent.c +++ b/fs/exfat/fatent.c @@ -175,6 +175,7 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu)); if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + int err; unsigned int last_cluster = p_chain->dir + p_chain->size - 1; do { bool sync = false; @@ -189,7 +190,9 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain cur_cmap_i = next_cmap_i; } - exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + err = exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + if (err) + break; clu++; num_clusters++; } while (num_clusters < p_chain->size); @@ -210,12 +213,13 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain cur_cmap_i = next_cmap_i; } - exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)))) + break; clu = n_clu; num_clusters++; if (err) - goto dec_used_clus; + break; if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) { /* @@ -229,7 +233,6 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain } while (clu != EXFAT_EOF_CLUSTER); } -dec_used_clus: sbi->used_clusters -= num_clusters; return 0; } From fda94a9919fd632033979ad7765a99ae3cab9289 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 11 Feb 2025 14:14:21 -0600 Subject: [PATCH 0628/1090] exfat: short-circuit zero-byte writes in exfat_file_write_iter When generic_write_checks() returns zero, it means that iov_iter_count() is zero, and there is no work to do. Simply return success like all other filesystems do, rather than proceeding down the write path, which today yields an -EFAULT in generic_perform_write() via the (fault_in_iov_iter_readable(i, bytes) == bytes) check when bytes == 0. Fixes: 11a347fb6cef ("exfat: change to get file size from DataLength") Reported-by: Noah Signed-off-by: Eric Sandeen Reviewed-by: Yuezhang Mo Signed-off-by: Namjae Jeon --- fs/exfat/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 05b51e721783..807349d8ea05 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -587,7 +587,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) valid_size = ei->valid_size; ret = generic_write_checks(iocb, iter); - if (ret < 0) + if (ret <= 0) goto unlock; if (iocb->ki_flags & IOCB_DIRECT) { From 13940cef95491472760ca261b6713692ece9b946 Mon Sep 17 00:00:00 2001 From: Yuezhang Mo Date: Sat, 8 Feb 2025 17:16:58 +0800 Subject: [PATCH 0629/1090] exfat: add a check for invalid data size Add a check for invalid data size to avoid corrupted filesystem from being further corrupted. Signed-off-by: Yuezhang Mo Signed-off-by: Namjae Jeon --- fs/exfat/namei.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index 5b16181a4c2e..8b30027d8251 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -646,6 +646,11 @@ static int exfat_find(struct inode *dir, struct qstr *qname, info->valid_size = le64_to_cpu(ep2->dentry.stream.valid_size); info->size = le64_to_cpu(ep2->dentry.stream.size); + if (unlikely(EXFAT_B_TO_CLU_ROUND_UP(info->size, sbi) > sbi->used_clusters)) { + exfat_fs_error(sb, "data size is invalid(%lld)", info->size); + return -EIO; + } + info->start_clu = le32_to_cpu(ep2->dentry.stream.start_clu); if (!is_valid_cluster(sbi, info->start_clu) && info->size) { exfat_warn(sb, "start_clu is invalid cluster(0x%x)", From 3c9231ea6497dfc50ac0ef69fff484da27d0df66 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Tue, 4 Mar 2025 08:44:29 +0800 Subject: [PATCH 0630/1090] net-timestamp: support TCP GSO case for a few missing flags When I read through the TSO codes, I found out that we probably miss initializing the tx_flags of last seg when TSO is turned off, which means at the following points no more timestamp (for this last one) will be generated. There are three flags to be handled in this patch: 1. SKBTX_HW_TSTAMP 2. SKBTX_BPF 3. SKBTX_SCHED_TSTAMP Note that SKBTX_BPF[1] was added in 6.14.0-rc2 by commit 6b98ec7e882af ("bpf: Add BPF_SOCK_OPS_TSTAMP_SCHED_CB callback") and only belongs to net-next branch material for now. The common issue of the above three flags can be fixed by this single patch. This patch initializes the tx_flags to SKBTX_ANY_TSTAMP like what the UDP GSO does to make the newly segmented last skb inherit the tx_flags so that requested timestamp will be generated in each certain layer, or else that last one has zero value of tx_flags which leads to no timestamp at all. Fixes: 4ed2d765dfacc ("net-timestamp: TCP timestamping") Signed-off-by: Jason Xing Reviewed-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/tcp_offload.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 2308665b51c5..2dfac79dc78b 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -13,12 +13,15 @@ #include #include -static void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq, +static void tcp_gso_tstamp(struct sk_buff *skb, struct sk_buff *gso_skb, unsigned int seq, unsigned int mss) { + u32 flags = skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP; + u32 ts_seq = skb_shinfo(gso_skb)->tskey; + while (skb) { if (before(ts_seq, seq + mss)) { - skb_shinfo(skb)->tx_flags |= SKBTX_SW_TSTAMP; + skb_shinfo(skb)->tx_flags |= flags; skb_shinfo(skb)->tskey = ts_seq; return; } @@ -193,8 +196,8 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, th = tcp_hdr(skb); seq = ntohl(th->seq); - if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_SW_TSTAMP)) - tcp_gso_tstamp(segs, skb_shinfo(gso_skb)->tskey, seq, mss); + if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP)) + tcp_gso_tstamp(segs, gso_skb, seq, mss); newcheck = ~csum_fold(csum_add(csum_unfold(th->check), delta)); From b92bc4d6e21f1802a39975e3c7cc4f76f591d46f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 5 Mar 2025 00:12:52 +0000 Subject: [PATCH 0631/1090] ASoC: soc-pcm: merge soc_pcm_hw_update_format/subformat() format() and subformat() should be handled in the same time, no need to have each functions. Let's merge these soc_pcm_hw_update_format() soc_pcm_hw_update_subformat() Signed-off-by: Kuninori Morimoto Cc: Cezary Rojewski Cc: Jaroslav Kysela Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/87v7soz664.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2a53a2eb4acd..c2d4becf0c3d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -603,13 +603,8 @@ static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw, static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw, const struct snd_soc_pcm_stream *p) { - hw->formats &= p->formats; -} - -static void soc_pcm_hw_update_subformat(struct snd_pcm_hardware *hw, - const struct snd_soc_pcm_stream *p) -{ - hw->subformats &= p->subformats; + hw->formats &= p->formats; + hw->subformats &= p->subformats; } /** @@ -650,7 +645,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, soc_pcm_hw_update_chan(hw, cpu_stream); soc_pcm_hw_update_rate(hw, cpu_stream); soc_pcm_hw_update_format(hw, cpu_stream); - soc_pcm_hw_update_subformat(hw, cpu_stream); } cpu_chan_min = hw->channels_min; cpu_chan_max = hw->channels_max; @@ -672,7 +666,6 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, soc_pcm_hw_update_chan(hw, codec_stream); soc_pcm_hw_update_rate(hw, codec_stream); soc_pcm_hw_update_format(hw, codec_stream); - soc_pcm_hw_update_subformat(hw, codec_stream); } /* Verify both a valid CPU DAI and a valid CODEC DAI were found */ @@ -1765,7 +1758,6 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream) soc_pcm_hw_update_rate(hw, cpu_stream); soc_pcm_hw_update_chan(hw, cpu_stream); soc_pcm_hw_update_format(hw, cpu_stream); - soc_pcm_hw_update_subformat(hw, cpu_stream); } } @@ -1803,7 +1795,6 @@ static void dpcm_runtime_setup_be_format(struct snd_pcm_substream *substream) codec_stream = snd_soc_dai_get_pcm_stream(dai, stream); soc_pcm_hw_update_format(hw, codec_stream); - soc_pcm_hw_update_subformat(hw, codec_stream); } } } From 8b36447c9ae102539d82d6278971b23b20d87629 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:35 +0800 Subject: [PATCH 0632/1090] ASoC: Intel: adl: add 2xrt1316 audio configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is a speaker only configuration and 2 rt1316 are on link 0 and 2. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20250305135443.201884-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-adl-match.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index bb1324fb588e..a68efbe98948 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -214,6 +214,15 @@ static const struct snd_soc_acpi_adr_device rt1316_1_group2_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1316_2_group2_adr[] = { + { + .adr = 0x000232025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + } +}; + static const struct snd_soc_acpi_adr_device rt1316_1_single_adr[] = { { .adr = 0x000130025D131601ull, @@ -547,6 +556,20 @@ static const struct snd_soc_acpi_link_adr adl_chromebook_base[] = { {} }; +static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link02[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt1316_0_group2_adr), + .adr_d = rt1316_0_group2_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_group2_adr), + .adr_d = rt1316_2_group2_adr, + }, + {} +}; + static const struct snd_soc_acpi_codecs adl_max98357a_amp = { .num_codecs = 1, .codecs = {"MX98357A"} @@ -749,6 +772,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-adl-sdw-max98373-rt5682.tplg", }, + { + .link_mask = BIT(0) | BIT(2), + .links = adl_sdw_rt1316_link02, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt1316-l02.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_sdw_machines); From 02467341e3577836648753a9e9a5c196f08187da Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 5 Mar 2025 21:54:36 +0800 Subject: [PATCH 0633/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add rt712_vb_l3_rt1320_l2 support Add rt712_vb on SDW link 3 and 1 rt1320 on SDW link 2 configuration support. Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://patch.msgid.link/20250305135443.201884-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-ptl-match.c | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index dd7993b76dee..8807acb92ecf 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -134,6 +134,15 @@ static const struct snd_soc_acpi_adr_device rt712_vb_2_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt712_vb_3_group1_adr[] = { + { + .adr = 0x000330025D071201ull, + .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints_endpoints), + .endpoints = jack_amp_g1_dmic_endpoints_endpoints, + .name_prefix = "rt712" + } +}; + static const struct snd_soc_acpi_adr_device rt713_vb_2_adr[] = { { .adr = 0x000230025d071301ull, @@ -206,6 +215,15 @@ static const struct snd_soc_acpi_adr_device rt1320_1_group2_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1320_2_group1_adr[] = { + { + .adr = 0x000230025D132001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1320-1" + } +}; + static const struct snd_soc_acpi_adr_device rt1320_3_group2_adr[] = { { .adr = 0x000330025D132001ull, @@ -284,6 +302,20 @@ static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l2_rt1320_l1[] = { {} }; +static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l3_rt1320_l2[] = { + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt712_vb_3_group1_adr), + .adr_d = rt712_vb_3_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1320_2_group1_adr), + .adr_d = rt1320_2_group1_adr, + }, + {} +}; + /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { /* mockup tests need to be first */ @@ -342,6 +374,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, .sof_tplg_filename = "sof-ptl-rt712-l2-rt1320-l1.tplg" }, + { + .link_mask = BIT(2) | BIT(3), + .links = ptl_sdw_rt712_vb_l3_rt1320_l2, + .drv_name = "sof_sdw", + .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, + .sof_tplg_filename = "sof-ptl-rt712-l3-rt1320-l2.tplg" + }, { .link_mask = BIT(1) | BIT(2) | BIT(3), .links = ptl_sdw_rt713_vb_l2_rt1320_l13, From ffe450cb6bce16eb15f6bf90b85b7e5f9bfbc1e3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 5 Mar 2025 21:54:37 +0800 Subject: [PATCH 0634/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add rt713_vb_l3_rt1320_l12 support Add rt713_vb on SDW link 3 and 2 rt1320 on SDW link 1 and 2 configuration support. Signed-off-by: Peter Ujfalusi Reviewed-by: Liam Girdwood Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Link: https://patch.msgid.link/20250305135443.201884-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-ptl-match.c | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 8807acb92ecf..5c1ece913a18 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -152,6 +152,15 @@ static const struct snd_soc_acpi_adr_device rt713_vb_2_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt713_vb_3_adr[] = { + { + .adr = 0x000330025D071301ull, + .num_endpoints = ARRAY_SIZE(jack_dmic_endpoints), + .endpoints = jack_dmic_endpoints, + .name_prefix = "rt713" + } +}; + static const struct snd_soc_acpi_adr_device rt721_3_single_adr[] = { { .adr = 0x000330025d072101ull, @@ -224,6 +233,15 @@ static const struct snd_soc_acpi_adr_device rt1320_2_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1320_2_group2_adr[] = { + { + .adr = 0x000230025D132001ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1320-1" + } +}; + static const struct snd_soc_acpi_adr_device rt1320_3_group2_adr[] = { { .adr = 0x000330025D132001ull, @@ -288,6 +306,25 @@ static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l2_rt1320_l13[] = { {} }; +static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l3_rt1320_l12[] = { + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt713_vb_3_adr), + .adr_d = rt713_vb_3_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1320_1_group2_adr), + .adr_d = rt1320_1_group2_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1320_2_group2_adr), + .adr_d = rt1320_2_group2_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l2_rt1320_l1[] = { { .mask = BIT(2), @@ -388,6 +425,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, .sof_tplg_filename = "sof-ptl-rt713-l2-rt1320-l13.tplg" }, + { + .link_mask = BIT(1) | BIT(2) | BIT(3), + .links = ptl_sdw_rt713_vb_l3_rt1320_l12, + .drv_name = "sof_sdw", + .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb, + .sof_tplg_filename = "sof-ptl-rt713-l3-rt1320-l12.tplg" + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_sdw_machines); From 65e246d33dede0008f281d3d09b7695bef2d18eb Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:38 +0800 Subject: [PATCH 0635/1090] ASoC: sdw_utils: add mic and amp dais to 0xaaaa codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit part id 0xaaaa codec is a mockup codec. Make it be a multi function codec. So that we can test multi function with a mockup codec. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20250305135443.201884-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sdw_utils/soc_sdw_utils.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 6ee7d30b8ece..5175818ff2c1 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -586,8 +586,20 @@ struct asoc_sdw_codec_info codec_info_list[] = { .dai_type = SOC_SDW_DAI_TYPE_JACK, .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, }, + { + .direction = {true, false}, + .dai_name = "sdw-mockup-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + }, + { + .direction = {false, true}, + .dai_name = "sdw-mockup-aif1", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + }, }, - .dai_num = 1, + .dai_num = 3, }, { .part_id = 0xaa55, /* headset codec mockup */ From e1a0657c6d943528ef58671594ca7e5b17db5394 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:39 +0800 Subject: [PATCH 0636/1090] ASoC: Intel: add multi-function SDW mockup codec match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SoundWire multi function codecs are common used in recent platforms. Add a multi function mockup codec to test without real codec. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20250305135443.201884-6-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../common/soc-acpi-intel-sdw-mockup-match.c | 42 +++++++++++++++++++ .../common/soc-acpi-intel-sdw-mockup-match.h | 1 + 2 files changed, 43 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c index a3d33997736a..d122ce69fa4f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c @@ -31,6 +31,30 @@ static const struct snd_soc_acpi_endpoint sdw_mockup_r_endpoint = { .group_id = 1, }; +static const struct snd_soc_acpi_endpoint jack_amp_g1_dmic_endpoints[] = { + /* Jack Endpoint */ + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + /* Amp Endpoint, work as spk_l_endpoint */ + { + .num = 1, + .aggregated = 1, + .group_position = 0, + .group_id = 1, + }, + /* DMIC Endpoint */ + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device sdw_mockup_headset_0_adr[] = { { .adr = 0x0000000105AA5500ull, @@ -103,6 +127,15 @@ static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device sdw_mockup_multi_function_adr[] = { + { + .adr = 0x0000000105AAAA01ull, + .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints), + .endpoints = jack_amp_g1_dmic_endpoints, + .name_prefix = "sdw_mockup_mmulti-function" + } +}; + const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[] = { { .mask = BIT(0), @@ -164,3 +197,12 @@ const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[] = { }, {} }; + +const struct snd_soc_acpi_link_adr sdw_mockup_multi_func[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(sdw_mockup_multi_function_adr), + .adr_d = sdw_mockup_multi_function_adr, + }, + {} +}; diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h index c99eecd19e03..f7ed5beaca96 100644 --- a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h +++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h @@ -13,5 +13,6 @@ extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[]; extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[]; extern const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[]; +extern const struct snd_soc_acpi_link_adr sdw_mockup_multi_func[]; #endif From 438405704eec45c06be9adc94eb5f94855412790 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:40 +0800 Subject: [PATCH 0637/1090] ASoC: Intel: soc-acpi-intel-lnl-match: add sdw multi function mockup codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a SoundWire multi function mockup codec support. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20250305135443.201884-7-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-lnl-match.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 0b4a9c27c47e..1e24e969ad15 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -552,6 +552,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-lnl-rt715-rt711-rt1308-mono.tplg", }, + { + .link_mask = BIT(0), + .links = sdw_mockup_multi_func, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-lnl-rt722-l0.tplg", /* Reuse the existing tplg file */ + }, { .link_mask = GENMASK(3, 0), .links = lnl_3_in_1_sdca, From c7a6a74f847923bb726029b85a3fd0e05e9fbb04 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:41 +0800 Subject: [PATCH 0638/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add sdw multi function mockup codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a SoundWire multi function mockup codec support. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20250305135443.201884-8-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-ptl-match.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 5c1ece913a18..28ee768efd57 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -374,6 +374,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-ptl-rt715-rt711-rt1308-mono.tplg", }, + { + .link_mask = BIT(0), + .links = sdw_mockup_multi_func, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt722.tplg", /* Reuse the existing tplg file */ + }, { .link_mask = BIT(0), .links = ptl_rvp, From 1ff07522690d2c2b67343099d2d046e88f71cddb Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:42 +0800 Subject: [PATCH 0639/1090] ASoC: Intel: soc-acpi-intel-lnl-match: add cs42l43 6x cs35l56 support This add a match for cs42l43 on sdw link 2, 3 cs35l56 on sdw link 1 and 3. All speakers are aggregated. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Link: https://patch.msgid.link/20250305135443.201884-9-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-lnl-match.c | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 1e24e969ad15..e04f6de746eb 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -37,6 +37,13 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = { .group_id = 1, }; +static const struct snd_soc_acpi_endpoint spk_1_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1, +}; + static const struct snd_soc_acpi_endpoint spk_2_endpoint = { .num = 0, .aggregated = 1, @@ -51,6 +58,27 @@ static const struct snd_soc_acpi_endpoint spk_3_endpoint = { .group_id = 1, }; +static const struct snd_soc_acpi_endpoint spk_4_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 4, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_5_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 5, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_6_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 6, + .group_id = 1, +}; + static const struct snd_soc_acpi_endpoint rt712_endpoints[] = { { .num = 0, @@ -159,6 +187,33 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint cs42l43_amp_spkagg_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 1, + .group_position = 0, + .group_id = 1, + }, +}; + static const struct snd_soc_acpi_adr_device cs35l56_2_l_adr[] = { { .adr = 0x00023001FA355601ull, @@ -204,6 +259,48 @@ static const struct snd_soc_acpi_adr_device cs35l56_3_lr_adr[] = { } }; +static const struct snd_soc_acpi_adr_device cs35l56_1_3amp_adr[] = { + { + .adr = 0x00013001fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_1_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013201fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP3" + } +}; + +static const struct snd_soc_acpi_adr_device cs35l56_3_3amp_adr[] = { + { + .adr = 0x00033301fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_4_endpoint, + .name_prefix = "AMP4" + }, + { + .adr = 0x00033401fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_5_endpoint, + .name_prefix = "AMP5" + }, + { + .adr = 0x00033501fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_6_endpoint, + .name_prefix = "AMP6" + } +}; + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { { .adr = 0x00003001FA424301ull, @@ -213,6 +310,15 @@ static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = { + { + .adr = 0x00023001fa424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_amp_spkagg_endpoints), + .endpoints = cs42l43_amp_spkagg_endpoints, + .name_prefix = "cs42l43" + } +}; + static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { { .adr = 0x000030025D071101ull, @@ -408,6 +514,25 @@ static const struct snd_soc_acpi_link_adr lnl_cs42l43_l0_cs35l56_l23[] = { {} }; +static const struct snd_soc_acpi_link_adr lnl_cs42l43_l2_cs35l56x6_l13[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(cs42l43_2_adr), + .adr_d = cs42l43_2_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56_1_3amp_adr), + .adr_d = cs35l56_1_3amp_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(cs35l56_3_3amp_adr), + .adr_d = cs35l56_3_3amp_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr lnl_rvp[] = { { .mask = BIT(0), @@ -570,6 +695,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-lnl-cs42l43-l0-cs35l56-l23.tplg", }, + { + .link_mask = BIT(1) | BIT(2) | BIT(3), + .links = lnl_cs42l43_l2_cs35l56x6_l13, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-lnl-cs42l43-l2-cs35l56x6-l13.tplg", + }, { .link_mask = BIT(0) | BIT(3), .links = lnl_cs42l43_l0_cs35l56_l3, From 7172d9ae29afd00c8ee9a8e3a4eba4cea5d5e403 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Mar 2025 21:54:43 +0800 Subject: [PATCH 0640/1090] ASoC: Intel: soc-acpi-intel-ptl-match: add cs42l43 6x cs35l56 support This add a match for cs42l43 on sdw link 2, 3 cs35l56 on sdw link 1 and 3. All speakers are aggregated. Signed-off-by: Bard Liao Reviewed-by: Liam Girdwood Link: https://patch.msgid.link/20250305135443.201884-10-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-ptl-match.c | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index 28ee768efd57..a07526eb802b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -50,6 +50,48 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = { .group_id = 1, }; +static const struct snd_soc_acpi_endpoint spk_1_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_2_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 2, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_3_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 3, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_4_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 4, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_5_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 5, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_6_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 6, + .group_id = 1, +}; + /* * Multi-function codecs with three endpoints created for * headset, amp and dmic functions. @@ -116,6 +158,84 @@ static const struct snd_soc_acpi_endpoint jack_amp_g1_dmic_endpoints_endpoints[] }, }; +static const struct snd_soc_acpi_endpoint cs42l43_amp_spkagg_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 1, + .group_position = 0, + .group_id = 1, + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = { + { + .adr = 0x00023001fa424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_amp_spkagg_endpoints), + .endpoints = cs42l43_amp_spkagg_endpoints, + .name_prefix = "cs42l43" + } +}; + +static const struct snd_soc_acpi_adr_device cs35l56_1_3amp_adr[] = { + { + .adr = 0x00013001fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_1_endpoint, + .name_prefix = "AMP1" + }, + { + .adr = 0x00013101fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_2_endpoint, + .name_prefix = "AMP2" + }, + { + .adr = 0x00013201fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_3_endpoint, + .name_prefix = "AMP3" + } +}; + +static const struct snd_soc_acpi_adr_device cs35l56_3_3amp_adr[] = { + { + .adr = 0x00033301fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_4_endpoint, + .name_prefix = "AMP4" + }, + { + .adr = 0x00033401fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_5_endpoint, + .name_prefix = "AMP5" + }, + { + .adr = 0x00033501fa355601ull, + .num_endpoints = 1, + .endpoints = &spk_6_endpoint, + .name_prefix = "AMP6" + } +}; + static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { { .adr = 0x000030025D071101ull, @@ -251,6 +371,25 @@ static const struct snd_soc_acpi_adr_device rt1320_3_group2_adr[] = { } }; +static const struct snd_soc_acpi_link_adr ptl_cs42l43_l2_cs35l56x6_l13[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(cs42l43_2_adr), + .adr_d = cs42l43_2_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(cs35l56_1_3amp_adr), + .adr_d = cs35l56_1_3amp_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(cs35l56_3_3amp_adr), + .adr_d = cs35l56_3_3amp_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr ptl_rt722_only[] = { { .mask = BIT(0), @@ -374,6 +513,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-ptl-rt715-rt711-rt1308-mono.tplg", }, + { + .link_mask = BIT(1) | BIT(2) | BIT(3), + .links = ptl_cs42l43_l2_cs35l56x6_l13, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-cs42l43-l2-cs35l56x6-l13.tplg", + }, { .link_mask = BIT(0), .links = sdw_mockup_multi_func, From 5ac60242b0173be83709603ebaf27a473f16c4e4 Mon Sep 17 00:00:00 2001 From: Uday Shankar Date: Tue, 4 Mar 2025 14:34:26 -0700 Subject: [PATCH 0641/1090] ublk: set_params: properly check if parameters can be applied The parameters set by the set_params call are only applied to the block device in the start_dev call. So if a device has already been started, a subsequently issued set_params on that device will not have the desired effect, and should return an error. There is an existing check for this - set_params fails on devices in the LIVE state. But this check is not sufficient to cover the recovery case. In this case, the device will be in the QUIESCED or FAIL_IO states, so set_params will succeed. But this success is misleading, because the parameters will not be applied, since the device has already been started (by a previous ublk server). The bit UB_STATE_USED is set on completion of the start_dev; use it to detect and fail set_params commands which arrive too late to be applied (after start_dev). Signed-off-by: Uday Shankar Fixes: 0aa73170eba5 ("ublk_drv: add SET_PARAMS/GET_PARAMS control command") Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20250304-set_params-v1-1-17b5e0887606@purestorage.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 529085181f35..ca9a67b5b537 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -2715,9 +2715,12 @@ static int ublk_ctrl_set_params(struct ublk_device *ub, if (ph.len > sizeof(struct ublk_params)) ph.len = sizeof(struct ublk_params); - /* parameters can only be changed when device isn't live */ mutex_lock(&ub->mutex); - if (ub->dev_info.state == UBLK_S_DEV_LIVE) { + if (test_bit(UB_STATE_USED, &ub->state)) { + /* + * Parameters can only be changed when device hasn't + * been started yet + */ ret = -EACCES; } else if (copy_from_user(&ub->params, argp, ph.len)) { ret = -EFAULT; From e06472bab2a5393430cc2fbc3211cd3602422c1e Mon Sep 17 00:00:00 2001 From: Olivier Gayot Date: Wed, 5 Mar 2025 10:21:54 +0800 Subject: [PATCH 0642/1090] block: fix conversion of GPT partition name to 7-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The utf16_le_to_7bit function claims to, naively, convert a UTF-16 string to a 7-bit ASCII string. By naively, we mean that it: * drops the first byte of every character in the original UTF-16 string * checks if all characters are printable, and otherwise replaces them by exclamation mark "!". This means that theoretically, all characters outside the 7-bit ASCII range should be replaced by another character. Examples: * lower-case alpha (É’) 0x0252 becomes 0x52 (R) * ligature OE (Å“) 0x0153 becomes 0x53 (S) * hangul letter pieup (ã…‚) 0x3142 becomes 0x42 (B) * upper-case gamma (Æ”) 0x0194 becomes 0x94 (not printable) so gets replaced by "!" The result of this conversion for the GPT partition name is passed to user-space as PARTNAME via udev, which is confusing and feels questionable. However, there is a flaw in the conversion function itself. By dropping one byte of each character and using isprint() to check if the remaining byte corresponds to a printable character, we do not actually guarantee that the resulting character is 7-bit ASCII. This happens because we pass 8-bit characters to isprint(), which in the kernel returns 1 for many values > 0x7f - as defined in ctype.c. This results in many values which should be replaced by "!" to be kept as-is, despite not being valid 7-bit ASCII. Examples: * e with acute accent (é) 0x00E9 becomes 0xE9 - kept as-is because isprint(0xE9) returns 1. * euro sign (€) 0x20AC becomes 0xAC - kept as-is because isprint(0xAC) returns 1. This way has broken pyudev utility[1], fixes it by using a mask of 7 bits instead of 8 bits before calling isprint. Link: https://github.com/pyudev/pyudev/issues/490#issuecomment-2685794648 [1] Link: https://lore.kernel.org/linux-block/4cac90c2-e414-4ebb-ae62-2a4589d9dc6e@canonical.com/ Cc: Mulhern Cc: Davidlohr Bueso Cc: stable@vger.kernel.org Signed-off-by: Olivier Gayot Signed-off-by: Ming Lei Link: https://lore.kernel.org/r/20250305022154.3903128-1-ming.lei@redhat.com Signed-off-by: Jens Axboe --- block/partitions/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 5e9be13a56a8..7acba66eed48 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -682,7 +682,7 @@ static void utf16_le_to_7bit(const __le16 *in, unsigned int size, u8 *out) out[size] = 0; while (i < size) { - u8 c = le16_to_cpu(in[i]) & 0xff; + u8 c = le16_to_cpu(in[i]) & 0x7f; if (c && !isprint(c)) c = '!'; From 3be83ee9de0298f8321aa0b148d8f9995102e40f Mon Sep 17 00:00:00 2001 From: Larysa Zaremba Date: Mon, 9 Dec 2024 15:08:53 +0100 Subject: [PATCH 0643/1090] ice: do not configure destination override for switchdev After switchdev is enabled and disabled later, LLDP packets sending stops, despite working perfectly fine before and during switchdev state. To reproduce (creating/destroying VF is what triggers the reconfiguration): devlink dev eswitch set pci/
mode switchdev echo '2' > /sys/class/net//device/sriov_numvfs echo '0' > /sys/class/net//device/sriov_numvfs This happens because LLDP relies on the destination override functionality. It needs to 1) set a flag in the descriptor, 2) set the VSI permission to make it valid. The permissions are set when the PF VSI is first configured, but switchdev then enables it for the uplink VSI (which is always the PF) once more when configured and disables when deconfigured, which leads to software-generated LLDP packets being blocked. Do not modify the destination override permissions when configuring switchdev, as the enabled state is the default configuration that is never modified. Fixes: 1a1c40df2e80 ("ice: set and release switchdev environment") Reviewed-by: Michal Swiatkowski Signed-off-by: Larysa Zaremba Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 6 ------ drivers/net/ethernet/intel/ice/ice_lib.c | 18 ------------------ drivers/net/ethernet/intel/ice/ice_lib.h | 4 ---- 3 files changed, 28 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index d649c197cf67..ed21d7f55ac1 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -49,9 +49,6 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) if (vlan_ops->dis_rx_filtering(uplink_vsi)) goto err_vlan_filtering; - if (ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_set_allow_override)) - goto err_override_uplink; - if (ice_vsi_update_local_lb(uplink_vsi, true)) goto err_override_local_lb; @@ -63,8 +60,6 @@ static int ice_eswitch_setup_env(struct ice_pf *pf) err_up: ice_vsi_update_local_lb(uplink_vsi, false); err_override_local_lb: - ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); -err_override_uplink: vlan_ops->ena_rx_filtering(uplink_vsi); err_vlan_filtering: ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false, @@ -275,7 +270,6 @@ static void ice_eswitch_release_env(struct ice_pf *pf) vlan_ops = ice_get_compat_vsi_vlan_ops(uplink_vsi); ice_vsi_update_local_lb(uplink_vsi, false); - ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override); vlan_ops->ena_rx_filtering(uplink_vsi); ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, false, ICE_FLTR_TX); diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 38a1c8372180..d0faa087793d 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3936,24 +3936,6 @@ void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx) ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); } -/** - * ice_vsi_ctx_set_allow_override - allow destination override on VSI - * @ctx: pointer to VSI ctx structure - */ -void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx) -{ - ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; -} - -/** - * ice_vsi_ctx_clear_allow_override - turn off destination override on VSI - * @ctx: pointer to VSI ctx structure - */ -void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx) -{ - ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; -} - /** * ice_vsi_update_local_lb - update sw block in VSI with local loopback bit * @vsi: pointer to VSI structure diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index eabb35834a24..b4c9cb28a016 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -105,10 +105,6 @@ ice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *)) void ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx); void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx); - -void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx); - -void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx); int ice_vsi_update_local_lb(struct ice_vsi *vsi, bool set); int ice_vsi_add_vlan_zero(struct ice_vsi *vsi); int ice_vsi_del_vlan_zero(struct ice_vsi *vsi); From 3b4035ddbfc8e4521f85569998a7569668cccf51 Mon Sep 17 00:00:00 2001 From: Zecheng Li Date: Tue, 4 Mar 2025 21:40:31 +0000 Subject: [PATCH 0644/1090] sched/fair: Fix potential memory corruption in child_cfs_rq_on_list child_cfs_rq_on_list attempts to convert a 'prev' pointer to a cfs_rq. This 'prev' pointer can originate from struct rq's leaf_cfs_rq_list, making the conversion invalid and potentially leading to memory corruption. Depending on the relative positions of leaf_cfs_rq_list and the task group (tg) pointer within the struct, this can cause a memory fault or access garbage data. The issue arises in list_add_leaf_cfs_rq, where both cfs_rq->leaf_cfs_rq_list and rq->leaf_cfs_rq_list are added to the same leaf list. Also, rq->tmp_alone_branch can be set to rq->leaf_cfs_rq_list. This adds a check `if (prev == &rq->leaf_cfs_rq_list)` after the main conditional in child_cfs_rq_on_list. This ensures that the container_of operation will convert a correct cfs_rq struct. This check is sufficient because only cfs_rqs on the same CPU are added to the list, so verifying the 'prev' pointer against the current rq's list head is enough. Fixes a potential memory corruption issue that due to current struct layout might not be manifesting as a crash but could lead to unpredictable behavior when the layout changes. Fixes: fdaba61ef8a2 ("sched/fair: Ensure that the CFS parent is added after unthrottling") Signed-off-by: Zecheng Li Reviewed-and-tested-by: K Prateek Nayak Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Vincent Guittot Link: https://lore.kernel.org/r/20250304214031.2882646-1-zecheng@google.com --- kernel/sched/fair.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1c0ef435a7aa..c798d2795243 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4045,15 +4045,17 @@ static inline bool child_cfs_rq_on_list(struct cfs_rq *cfs_rq) { struct cfs_rq *prev_cfs_rq; struct list_head *prev; + struct rq *rq = rq_of(cfs_rq); if (cfs_rq->on_list) { prev = cfs_rq->leaf_cfs_rq_list.prev; } else { - struct rq *rq = rq_of(cfs_rq); - prev = rq->tmp_alone_branch; } + if (prev == &rq->leaf_cfs_rq_list) + return false; + prev_cfs_rq = container_of(prev, struct cfs_rq, leaf_cfs_rq_list); return (prev_cfs_rq->tg->parent == cfs_rq->tg); From 23d97f18901ef5e4e264e3b1777fe65c760186b5 Mon Sep 17 00:00:00 2001 From: Grzegorz Nitka Date: Thu, 23 Jan 2025 09:15:39 +0100 Subject: [PATCH 0645/1090] ice: fix memory leak in aRFS after reset Fix aRFS (accelerated Receive Flow Steering) structures memory leak by adding a checker to verify if aRFS memory is already allocated while configuring VSI. aRFS objects are allocated in two cases: - as part of VSI initialization (at probe), and - as part of reset handling However, VSI reconfiguration executed during reset involves memory allocation one more time, without prior releasing already allocated resources. This led to the memory leak with the following signature: [root@os-delivery ~]# cat /sys/kernel/debug/kmemleak unreferenced object 0xff3c1ca7252e6000 (size 8192): comm "kworker/0:0", pid 8, jiffies 4296833052 hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace (crc 0): [] __kmalloc_cache_noprof+0x275/0x340 [] ice_init_arfs+0x3a/0xe0 [ice] [] ice_vsi_cfg_def+0x607/0x850 [ice] [] ice_vsi_setup+0x5b/0x130 [ice] [] ice_init+0x1c1/0x460 [ice] [] ice_probe+0x2af/0x520 [ice] [] local_pci_probe+0x43/0xa0 [] work_for_cpu_fn+0x13/0x20 [] process_one_work+0x179/0x390 [] worker_thread+0x239/0x340 [] kthread+0xcc/0x100 [] ret_from_fork+0x2d/0x50 [] ret_from_fork_asm+0x1a/0x30 ... Fixes: 28bf26724fdb ("ice: Implement aRFS") Reviewed-by: Michal Swiatkowski Signed-off-by: Grzegorz Nitka Reviewed-by: Simon Horman Tested-by: Rinitha S (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_arfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c index 7cee365cc7d1..405ddd17de1b 100644 --- a/drivers/net/ethernet/intel/ice/ice_arfs.c +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c @@ -511,7 +511,7 @@ void ice_init_arfs(struct ice_vsi *vsi) struct hlist_head *arfs_fltr_list; unsigned int i; - if (!vsi || vsi->type != ICE_VSI_PF) + if (!vsi || vsi->type != ICE_VSI_PF || ice_is_arfs_active(vsi)) return; arfs_fltr_list = kcalloc(ICE_MAX_ARFS_LIST, sizeof(*arfs_fltr_list), From dce97cb0a3e34204c0b99345418a714eac85953f Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Thu, 2 Jan 2025 20:07:52 +0100 Subject: [PATCH 0646/1090] ice: Fix switchdev slow-path in LAG Ever since removing switchdev control VSI and using PF for port representor Tx/Rx, switchdev slow-path has been working improperly after failover in SR-IOV LAG. LAG assumes that the first uplink to be added to the aggregate will own VFs and have switchdev configured. After failing-over to the other uplink, representors are still configured to Tx through the uplink they are set up on, which fails because that uplink is now down. On failover, update all PRs on primary uplink to use the currently active uplink for Tx. Call netif_keep_dst(), as the secondary uplink might not be in switchdev mode. Also make sure to call ice_eswitch_set_target_vsi() if uplink is in LAG. On the Rx path, representors are already working properly, because default Tx from VFs is set to PF owning the eswitch. After failover the same PF is receiving traffic from VFs, even though link is down. Fixes: defd52455aee ("ice: do Tx through PF netdev in slow-path") Reviewed-by: Michal Swiatkowski Signed-off-by: Marcin Szycik Reviewed-by: Simon Horman Tested-by: Rafal Romanowski Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lag.c | 27 +++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_txrx.c | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 1ccb572ce285..22371011c249 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -1000,6 +1000,28 @@ static void ice_lag_link(struct ice_lag *lag) netdev_info(lag->netdev, "Shared SR-IOV resources in bond are active\n"); } +/** + * ice_lag_config_eswitch - configure eswitch to work with LAG + * @lag: lag info struct + * @netdev: active network interface device struct + * + * Updates all port representors in eswitch to use @netdev for Tx. + * + * Configures the netdev to keep dst metadata (also used in representor Tx). + * This is required for an uplink without switchdev mode configured. + */ +static void ice_lag_config_eswitch(struct ice_lag *lag, + struct net_device *netdev) +{ + struct ice_repr *repr; + unsigned long id; + + xa_for_each(&lag->pf->eswitch.reprs, id, repr) + repr->dst->u.port_info.lower_dev = netdev; + + netif_keep_dst(netdev); +} + /** * ice_lag_unlink - handle unlink event * @lag: LAG info struct @@ -1021,6 +1043,9 @@ static void ice_lag_unlink(struct ice_lag *lag) ice_lag_move_vf_nodes(lag, act_port, pri_port); lag->primary = false; lag->active_port = ICE_LAG_INVALID_PORT; + + /* Config primary's eswitch back to normal operation. */ + ice_lag_config_eswitch(lag, lag->netdev); } else { struct ice_lag *primary_lag; @@ -1419,6 +1444,7 @@ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) ice_lag_move_vf_nodes(lag, prim_port, event_port); lag->active_port = event_port; + ice_lag_config_eswitch(lag, event_netdev); return; } @@ -1428,6 +1454,7 @@ static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) /* new active port */ ice_lag_move_vf_nodes(lag, lag->active_port, event_port); lag->active_port = event_port; + ice_lag_config_eswitch(lag, event_netdev); } else { /* port not set as currently active (e.g. new active port * has already claimed the nodes and filters diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 9c9ea4c1b93b..380ba1e8b3b2 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -2424,7 +2424,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) ICE_TXD_CTX_QW1_CMD_S); ice_tstamp(tx_ring, skb, first, &offload); - if (ice_is_switchdev_running(vsi->back) && vsi->type != ICE_VSI_SF) + if ((ice_is_switchdev_running(vsi->back) || + ice_lag_is_switchdev_running(vsi->back)) && + vsi->type != ICE_VSI_SF) ice_eswitch_set_target_vsi(skb, &offload); if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) { From 374c9faac5a763a05bc3f68ad9f73dab3c6aec90 Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Wed, 26 Feb 2025 16:37:31 +0800 Subject: [PATCH 0647/1090] drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params Null pointer dereference issue could occur when pipe_ctx->plane_state is null. The fix adds a check to ensure 'pipe_ctx->plane_state' is not null before accessing. This prevents a null pointer dereference. Found by code review. Fixes: 3be5262e353b ("drm/amd/display: Rename more dc_surface stuff to plane_state") Reviewed-by: Alex Hung Signed-off-by: Ma Ke Signed-off-by: Alex Deucher (cherry picked from commit 63e6a77ccf239337baa9b1e7787cde9fa0462092) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 520a34a42827..a45037cb4cc0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1455,7 +1455,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); /* Invalid input */ - if (!plane_state->dst_rect.width || + if (!plane_state || + !plane_state->dst_rect.width || !plane_state->dst_rect.height || !plane_state->src_rect.width || !plane_state->src_rect.height) { From 2a3e89a14864090ee4804fcec655ffc15fabf45c Mon Sep 17 00:00:00 2001 From: Przemek Kitszel Date: Wed, 19 Feb 2025 14:30:39 +0100 Subject: [PATCH 0648/1090] ice: register devlink prior to creating health reporters ice_health_init() was introduced in the commit 2a82874a3b7b ("ice: add Tx hang devlink health reporter"). The call to it should have been put after ice_devlink_register(). It went unnoticed until next reporter by Konrad, which receives events from FW. FW is reporting all events, also from prior driver load, and thus it is not unlikely to have something at the very beginning. And that results in a splat: [ 24.455950] ? devlink_recover_notify.constprop.0+0x198/0x1b0 [ 24.455973] devlink_health_report+0x5d/0x2a0 [ 24.455976] ? __pfx_ice_health_status_lookup_compare+0x10/0x10 [ice] [ 24.456044] ice_process_health_status_event+0x1b7/0x200 [ice] Do the analogous thing for deinit patch. Fixes: 85d6164ec56d ("ice: add fw and port health reporters") Reviewed-by: Aleksandr Loktionov Reviewed-by: Michal Swiatkowski Reviewed-by: Konrad Knitter Signed-off-by: Przemek Kitszel Tested-by: Sunitha Mekala (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index c3a0fb97c5ee..e13bd5a6cb6c 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -5065,16 +5065,16 @@ static int ice_init_devlink(struct ice_pf *pf) return err; ice_devlink_init_regions(pf); - ice_health_init(pf); ice_devlink_register(pf); + ice_health_init(pf); return 0; } static void ice_deinit_devlink(struct ice_pf *pf) { - ice_devlink_unregister(pf); ice_health_deinit(pf); + ice_devlink_unregister(pf); ice_devlink_destroy_regions(pf); ice_devlink_unregister_params(pf); } From fd617ea3b79d2116d53f76cdb5a3601c0ba6e42f Mon Sep 17 00:00:00 2001 From: Andrew Martin Date: Fri, 28 Feb 2025 11:26:48 -0500 Subject: [PATCH 0649/1090] drm/amdkfd: Fix NULL Pointer Dereference in KFD queue Through KFD IOCTL Fuzzing we encountered a NULL pointer derefrence when calling kfd_queue_acquire_buffers. Fixes: 629568d25fea ("drm/amdkfd: Validate queue cwsr area and eop buffer size") Signed-off-by: Andrew Martin Reviewed-by: Philip Yang Signed-off-by: Andrew Martin Signed-off-by: Alex Deucher (cherry picked from commit 049e5bf3c8406f87c3d8e1958e0a16804fa1d530) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c index ecccd7adbab4..24396a2c77bd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c @@ -266,8 +266,8 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope /* EOP buffer is not required for all ASICs */ if (properties->eop_ring_buffer_address) { if (properties->eop_ring_buffer_size != topo_dev->node_props.eop_buffer_size) { - pr_debug("queue eop bo size 0x%lx not equal to node eop buf size 0x%x\n", - properties->eop_buf_bo->tbo.base.size, + pr_debug("queue eop bo size 0x%x not equal to node eop buf size 0x%x\n", + properties->eop_ring_buffer_size, topo_dev->node_props.eop_buffer_size); err = -EINVAL; goto out_err_unreserve; From c27c66afc449b80f3b4b84d123358c0248f2cf63 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 5 Mar 2025 07:08:09 -1000 Subject: [PATCH 0650/1090] fs/pipe: Fix pipe_occupancy() with 16-bit indexes The pipe_occupancy() logic implicitly relied on the natural unsigned modulo arithmetic in C, but that doesn't work for the new 'pipe_index_t' case, since any arithmetic will be done in 'int' (and here we had also made it 'unsigned int' due to the function call boundary). So make the modulo arithmetic explicit by casting the result to the proper type. Cc: Oleg Nesterov Cc: Mateusz Guzik Cc: Manfred Spraul Cc: Christian Brauner Cc: Swapnil Sapkal Cc: Alexey Gladkov Cc: K Prateek Nayak Link: https://lore.kernel.org/all/CAHk-=wjyHsGLx=rxg6PKYBNkPYAejgo7=CbyL3=HGLZLsAaJFQ@mail.gmail.com/ Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") Signed-off-by: Linus Torvalds --- include/linux/pipe_fs_i.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 3cc4f8eab853..1f013ed7577e 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -192,7 +192,7 @@ static inline bool pipe_empty(unsigned int head, unsigned int tail) */ static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) { - return head - tail; + return (pipe_index_t)(head - tail); } /** From cfced12f5100e50d56bc587299393fd33c1169a9 Mon Sep 17 00:00:00 2001 From: K Prateek Nayak Date: Wed, 5 Mar 2025 11:23:01 +0000 Subject: [PATCH 0651/1090] include/linux/pipe_fs_i: Add htmldoc annotation for "head_tail" member Add htmldoc annotation for the newly introduced "head_tail" member describing it to be a union of the pipe_inode_info's @head and @tail members. Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/lkml/20250305204609.5e64768e@canb.auug.org.au/ Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex") Signed-off-by: K Prateek Nayak Signed-off-by: Linus Torvalds --- include/linux/pipe_fs_i.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 1f013ed7577e..05ccbc5d0129 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -65,6 +65,7 @@ union pipe_index { * @wr_wait: writer wait point in case of full pipe * @head: The point of buffer production * @tail: The point of buffer consumption + * @head_tail: unsigned long union of @head and @tail * @note_loss: The next read() should insert a data-lost message * @max_usage: The maximum number of slots that may be used in the ring * @ring_size: total number of buffers (should be a power of 2) From 29ffeb73b216ce3eff10229eb077cf9b7812119d Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Mon, 17 Jun 2019 23:46:27 +0200 Subject: [PATCH 0652/1090] drm/radeon: Fix rs400_gpu_init for ATI mobility radeon Xpress 200M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit num_gb_pipes was set to a wrong value using r420_pipe_config This have lead to HyperZ glitches on fast Z clearing. Closes: https://bugs.freedesktop.org/show_bug.cgi?id=110897 Reviewed-by: Marek Olšák Signed-off-by: Richard Thier Signed-off-by: Alex Deucher (cherry picked from commit 044e59a85c4d84e3c8d004c486e5c479640563a6) Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/r300.c | 3 ++- drivers/gpu/drm/radeon/radeon_asic.h | 1 + drivers/gpu/drm/radeon/rs400.c | 18 ++++++++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 05c13102a8cb..d22889fbfa9c 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -359,7 +359,8 @@ int r300_mc_wait_for_idle(struct radeon_device *rdev) return -1; } -static void r300_gpu_init(struct radeon_device *rdev) +/* rs400_gpu_init also calls this! */ +void r300_gpu_init(struct radeon_device *rdev) { uint32_t gb_tile_config, tmp; diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 1e00f6b99f94..8f5e07834fcc 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -165,6 +165,7 @@ void r200_set_safe_registers(struct radeon_device *rdev); */ extern int r300_init(struct radeon_device *rdev); extern void r300_fini(struct radeon_device *rdev); +extern void r300_gpu_init(struct radeon_device *rdev); extern int r300_suspend(struct radeon_device *rdev); extern int r300_resume(struct radeon_device *rdev); extern int r300_asic_reset(struct radeon_device *rdev, bool hard); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index d6c18fd740ec..13cd0a688a65 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -256,8 +256,22 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev) static void rs400_gpu_init(struct radeon_device *rdev) { - /* FIXME: is this correct ? */ - r420_pipes_init(rdev); + /* Earlier code was calling r420_pipes_init and then + * rs400_mc_wait_for_idle(rdev). The problem is that + * at least on my Mobility Radeon Xpress 200M RC410 card + * that ends up in this code path ends up num_gb_pipes == 3 + * while the card seems to have only one pipe. With the + * r420 pipe initialization method. + * + * Problems shown up as HyperZ glitches, see: + * https://bugs.freedesktop.org/show_bug.cgi?id=110897 + * + * Delegating initialization to r300 code seems to work + * and results in proper pipe numbers. The rs400 cards + * are said to be not r400, but r300 kind of cards. + */ + r300_gpu_init(rdev); + if (rs400_mc_wait_for_idle(rdev)) { pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); From da552bda987420e877500fdd90bd0172e3bf412b Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Fri, 28 Feb 2025 17:02:11 +0800 Subject: [PATCH 0653/1090] drm/amd/pm: always allow ih interrupt from fw always allow ih interrupt from fw on smu v14 based on the interface requirement Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher (cherry picked from commit a3199eba46c54324193607d9114a1e321292d7a1) Cc: stable@vger.kernel.org # 6.12.x --- drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 9b2f4fe1578b..ddb6444406d2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -1895,16 +1895,6 @@ static int smu_v14_0_allow_ih_interrupt(struct smu_context *smu) NULL); } -static int smu_v14_0_process_pending_interrupt(struct smu_context *smu) -{ - int ret = 0; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_ACDC_BIT)) - ret = smu_v14_0_allow_ih_interrupt(smu); - - return ret; -} - int smu_v14_0_enable_thermal_alert(struct smu_context *smu) { int ret = 0; @@ -1916,7 +1906,7 @@ int smu_v14_0_enable_thermal_alert(struct smu_context *smu) if (ret) return ret; - return smu_v14_0_process_pending_interrupt(smu); + return smu_v14_0_allow_ih_interrupt(smu); } int smu_v14_0_disable_thermal_alert(struct smu_context *smu) From 0d2d0f3d93ddd6556f23c917d910becd9925ddeb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 5 Mar 2025 07:35:40 -1000 Subject: [PATCH 0654/1090] fs/pipe: remove buggy and unused 'helper' function While looking for incorrect users of the pipe head/tail fields (see commit c27c66afc449: "fs/pipe: Fix pipe_occupancy() with 16-bit indexes"), I found a bug in pipe_discard_from() that looked entirely broken. However, the fix is trivial: this buggy function isn't actually called by anything, so let's just remove it ASAP. Signed-off-by: Linus Torvalds --- include/linux/pipe_fs_i.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 05ccbc5d0129..e572e6fc4f81 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -281,15 +281,6 @@ static inline bool pipe_buf_try_steal(struct pipe_inode_info *pipe, return buf->ops->try_steal(pipe, buf); } -static inline void pipe_discard_from(struct pipe_inode_info *pipe, - unsigned int old_head) -{ - unsigned int mask = pipe->ring_size - 1; - - while (pipe->head > old_head) - pipe_buf_release(pipe, &pipe->bufs[--pipe->head & mask]); -} - /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ #define PIPE_SIZE PAGE_SIZE From 528361c49962708a60f51a1afafeb00987cebedf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Mar 2025 18:52:59 +0300 Subject: [PATCH 0655/1090] nvme-tcp: fix signedness bug in nvme_tcp_init_connection() The kernel_recvmsg() function returns an int which could be either negative error codes or the number of bytes received. The problem is that the condition: if (ret < sizeof(*icresp)) { is type promoted to type unsigned long and negative values are treated as high positive values which is success, when they should be treated as failure. Handle invalid positive returns separately from negative error codes to avoid this problem. Fixes: 578539e09690 ("nvme-tcp: fix connect failure on receiving partial ICResp PDU") Signed-off-by: Dan Carpenter Reviewed-by: Caleb Sander Mateos Reviewed-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Keith Busch --- drivers/nvme/host/tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 23f11527d29d..327f3f2f5399 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -1521,11 +1521,11 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue) msg.msg_flags = MSG_WAITALL; ret = kernel_recvmsg(queue->sock, &msg, &iov, 1, iov.iov_len, msg.msg_flags); - if (ret < sizeof(*icresp)) { + if (ret >= 0 && ret < sizeof(*icresp)) + ret = -ECONNRESET; + if (ret < 0) { pr_warn("queue %d: failed to receive icresp, error %d\n", nvme_tcp_queue_id(queue), ret); - if (ret >= 0) - ret = -ECONNRESET; goto free_icresp; } ret = -ENOTCONN; From f2052a4a62465c0037aef7ea7426bffdb3531e41 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Mon, 3 Mar 2025 13:11:21 +0000 Subject: [PATCH 0656/1090] clk: samsung: gs101: fix synchronous external abort in samsung_clk_save() EARLY_WAKEUP_SW_TRIG_*_SET and EARLY_WAKEUP_SW_TRIG_*_CLEAR registers are only writeable. Attempting to read these registers during samsung_clk_save() causes a synchronous external abort. Remove these 8 registers from cmu_top_clk_regs[] array so that system suspend gets further. Note: the code path can be exercised using the following command: echo mem > /sys/power/state Fixes: 2c597bb7d66a ("clk: samsung: clk-gs101: Add cmu_top, cmu_misc and cmu_apm support") Signed-off-by: Peter Griffin Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250303-clk-suspend-fix-v1-1-c2edaf66260f@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index 86b39edba122..08b867ae3ed9 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -382,17 +382,9 @@ static const unsigned long cmu_top_clk_regs[] __initconst = { EARLY_WAKEUP_DPU_DEST, EARLY_WAKEUP_CSIS_DEST, EARLY_WAKEUP_SW_TRIG_APM, - EARLY_WAKEUP_SW_TRIG_APM_SET, - EARLY_WAKEUP_SW_TRIG_APM_CLEAR, EARLY_WAKEUP_SW_TRIG_CLUSTER0, - EARLY_WAKEUP_SW_TRIG_CLUSTER0_SET, - EARLY_WAKEUP_SW_TRIG_CLUSTER0_CLEAR, EARLY_WAKEUP_SW_TRIG_DPU, - EARLY_WAKEUP_SW_TRIG_DPU_SET, - EARLY_WAKEUP_SW_TRIG_DPU_CLEAR, EARLY_WAKEUP_SW_TRIG_CSIS, - EARLY_WAKEUP_SW_TRIG_CSIS_SET, - EARLY_WAKEUP_SW_TRIG_CSIS_CLEAR, CLK_CON_MUX_MUX_CLKCMU_BO_BUS, CLK_CON_MUX_MUX_CLKCMU_BUS0_BUS, CLK_CON_MUX_MUX_CLKCMU_BUS1_BUS, From 53517a70873c7a91675f7244768aad5006cc45de Mon Sep 17 00:00:00 2001 From: Varada Pavani Date: Tue, 25 Feb 2025 18:49:18 +0530 Subject: [PATCH 0657/1090] clk: samsung: update PLL locktime for PLL142XX used on FSD platform Currently PLL142XX locktime is 270. As per spec, it should be 150. Hence update PLL142XX controller locktime to 150. Cc: stable@vger.kernel.org Fixes: 4f346005aaed ("clk: samsung: fsd: Add initial clock support") Signed-off-by: Varada Pavani Link: https://lore.kernel.org/r/20250225131918.50925-3-v.pavani@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-pll.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 2e94bba6c396..023a25af73c4 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -206,6 +206,7 @@ static const struct clk_ops samsung_pll3000_clk_ops = { */ /* Maximum lock time can be 270 * PDIV cycles */ #define PLL35XX_LOCK_FACTOR (270) +#define PLL142XX_LOCK_FACTOR (150) #define PLL35XX_MDIV_MASK (0x3FF) #define PLL35XX_PDIV_MASK (0x3F) @@ -272,7 +273,11 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, } /* Set PLL lock time. */ - writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR, + if (pll->type == pll_142xx) + writel_relaxed(rate->pdiv * PLL142XX_LOCK_FACTOR, + pll->lock_reg); + else + writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR, pll->lock_reg); /* Change PLL PMS values */ From e775e2a060d99180edc5366fb9f4299d0f07b66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 28 Feb 2025 08:30:55 +0100 Subject: [PATCH 0658/1090] drm/xe/vm: Validate userptr during gpu vma prefetching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a userptr vma subject to prefetching was already invalidated or invalidated during the prefetch operation, the operation would repeatedly return -EAGAIN which would typically cause an infinite loop. Validate the userptr to ensure this doesn't happen. v2: - Don't fallthrough from UNMAP to PREFETCH (Matthew Brost) Fixes: 5bd24e78829a ("drm/xe/vm: Subclass userptr vmas") Fixes: 617eebb9c480 ("drm/xe: Fix array of binds") Cc: Matthew Brost Cc: # v6.9+ Suggested-by: Matthew Brost Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250228073058.59510-2-thomas.hellstrom@linux.intel.com (cherry picked from commit 03c346d4d0d85d210d549d43c8cfb3dfb7f20e0a) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_vm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 30259eba450b..d2cd227e4d69 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -2286,8 +2286,17 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, break; } case DRM_GPUVA_OP_UNMAP: + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); + break; case DRM_GPUVA_OP_PREFETCH: - /* FIXME: Need to skip some prefetch ops */ + vma = gpuva_to_vma(op->base.prefetch.va); + + if (xe_vma_is_userptr(vma)) { + err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); + if (err) + return err; + } + xe_vma_ops_incr_pt_update_ops(vops, op->tile_mask); break; default: From 1414d95d5805b1dc221d22db9b8dc5287ef083bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 28 Feb 2025 08:30:56 +0100 Subject: [PATCH 0659/1090] drm/xe/vm: Fix a misplaced #endif MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a (harmless) misplaced #endif leading to declarations appearing multiple times. Fixes: 0eb2a18a8fad ("drm/xe: Implement VM snapshot support for BO's and userptr") Cc: Maarten Lankhorst Cc: José Roberto de Souza Cc: # v6.12+ Signed-off-by: Thomas Hellström Reviewed-by: Lucas De Marchi Reviewed-by: Tejas Upadhyay Link: https://patchwork.freedesktop.org/patch/msgid/20250228073058.59510-3-thomas.hellstrom@linux.intel.com (cherry picked from commit fcc20a4c752214b3e25632021c57d7d1d71ee1dd) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_vm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 23adb7442881..256a837c2704 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -274,9 +274,9 @@ static inline void vm_dbg(const struct drm_device *dev, const char *format, ...) { /* noop */ } #endif -#endif struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm); void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap); void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p); void xe_vm_snapshot_free(struct xe_vm_snapshot *snap); +#endif From 84211b1c0db6b9dbe0020fa97192fb9661617f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 28 Feb 2025 08:30:57 +0100 Subject: [PATCH 0660/1090] drm/xe: Fix fault mode invalidation with unbind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix fault mode invalidation racing with unbind leading to the PTE zapping potentially traversing an invalid page-table tree. Do this by holding the notifier lock across PTE zapping. This might transfer any contention waiting on the notifier seqlock read side to the notifier lock read side, but that shouldn't be a major problem. At the same time get rid of the open-coded invalidation in the bind code by relying on the notifier even when the vma bind is not yet committed. Finally let userptr invalidation call a dedicated xe_vm function performing a full invalidation. Fixes: e8babb280b5e ("drm/xe: Convert multiple bind ops into single job") Cc: Thomas Hellström Cc: Matthew Brost Cc: Matthew Auld Cc: # v6.12+ Signed-off-by: Thomas Hellström Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250228073058.59510-4-thomas.hellstrom@linux.intel.com (cherry picked from commit 100a5b8dadfca50d91d9a4c9fc01431b42a25cab) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_pt.c | 38 ++++---------- drivers/gpu/drm/xe/xe_vm.c | 85 +++++++++++++++++++++----------- drivers/gpu/drm/xe/xe_vm.h | 8 +++ drivers/gpu/drm/xe/xe_vm_types.h | 4 +- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 1ddcc7e79a93..12a627a23eb4 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1213,42 +1213,22 @@ static int vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma, return 0; uvma = to_userptr_vma(vma); + if (xe_pt_userptr_inject_eagain(uvma)) + xe_vma_userptr_force_invalidate(uvma); + notifier_seq = uvma->userptr.notifier_seq; - if (uvma->userptr.initial_bind && !xe_vm_in_fault_mode(vm)) - return 0; - if (!mmu_interval_read_retry(&uvma->userptr.notifier, - notifier_seq) && - !xe_pt_userptr_inject_eagain(uvma)) + notifier_seq)) return 0; - if (xe_vm_in_fault_mode(vm)) { + if (xe_vm_in_fault_mode(vm)) return -EAGAIN; - } else { - spin_lock(&vm->userptr.invalidated_lock); - list_move_tail(&uvma->userptr.invalidate_link, - &vm->userptr.invalidated); - spin_unlock(&vm->userptr.invalidated_lock); - - if (xe_vm_in_preempt_fence_mode(vm)) { - struct dma_resv_iter cursor; - struct dma_fence *fence; - long err; - - dma_resv_iter_begin(&cursor, xe_vm_resv(vm), - DMA_RESV_USAGE_BOOKKEEP); - dma_resv_for_each_fence_unlocked(&cursor, fence) - dma_fence_enable_sw_signaling(fence); - dma_resv_iter_end(&cursor); - - err = dma_resv_wait_timeout(xe_vm_resv(vm), - DMA_RESV_USAGE_BOOKKEEP, - false, MAX_SCHEDULE_TIMEOUT); - XE_WARN_ON(err <= 0); - } - } + /* + * Just continue the operation since exec or rebind worker + * will take care of rebinding. + */ return 0; } diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index d2cd227e4d69..d54aaa5eaff3 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -579,51 +579,26 @@ out_unlock_outer: trace_xe_vm_rebind_worker_exit(vm); } -static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, - const struct mmu_notifier_range *range, - unsigned long cur_seq) +static void __vma_userptr_invalidate(struct xe_vm *vm, struct xe_userptr_vma *uvma) { - struct xe_userptr *userptr = container_of(mni, typeof(*userptr), notifier); - struct xe_userptr_vma *uvma = container_of(userptr, typeof(*uvma), userptr); + struct xe_userptr *userptr = &uvma->userptr; struct xe_vma *vma = &uvma->vma; - struct xe_vm *vm = xe_vma_vm(vma); struct dma_resv_iter cursor; struct dma_fence *fence; long err; - xe_assert(vm->xe, xe_vma_is_userptr(vma)); - trace_xe_vma_userptr_invalidate(vma); - - if (!mmu_notifier_range_blockable(range)) - return false; - - vm_dbg(&xe_vma_vm(vma)->xe->drm, - "NOTIFIER: addr=0x%016llx, range=0x%016llx", - xe_vma_start(vma), xe_vma_size(vma)); - - down_write(&vm->userptr.notifier_lock); - mmu_interval_set_seq(mni, cur_seq); - - /* No need to stop gpu access if the userptr is not yet bound. */ - if (!userptr->initial_bind) { - up_write(&vm->userptr.notifier_lock); - return true; - } - /* * Tell exec and rebind worker they need to repin and rebind this * userptr. */ if (!xe_vm_in_fault_mode(vm) && - !(vma->gpuva.flags & XE_VMA_DESTROYED) && vma->tile_present) { + !(vma->gpuva.flags & XE_VMA_DESTROYED)) { spin_lock(&vm->userptr.invalidated_lock); list_move_tail(&userptr->invalidate_link, &vm->userptr.invalidated); spin_unlock(&vm->userptr.invalidated_lock); } - up_write(&vm->userptr.notifier_lock); - /* * Preempt fences turn into schedule disables, pipeline these. * Note that even in fault mode, we need to wait for binds and @@ -641,11 +616,35 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, false, MAX_SCHEDULE_TIMEOUT); XE_WARN_ON(err <= 0); - if (xe_vm_in_fault_mode(vm)) { + if (xe_vm_in_fault_mode(vm) && userptr->initial_bind) { err = xe_vm_invalidate_vma(vma); XE_WARN_ON(err); } +} +static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, + const struct mmu_notifier_range *range, + unsigned long cur_seq) +{ + struct xe_userptr_vma *uvma = container_of(mni, typeof(*uvma), userptr.notifier); + struct xe_vma *vma = &uvma->vma; + struct xe_vm *vm = xe_vma_vm(vma); + + xe_assert(vm->xe, xe_vma_is_userptr(vma)); + trace_xe_vma_userptr_invalidate(vma); + + if (!mmu_notifier_range_blockable(range)) + return false; + + vm_dbg(&xe_vma_vm(vma)->xe->drm, + "NOTIFIER: addr=0x%016llx, range=0x%016llx", + xe_vma_start(vma), xe_vma_size(vma)); + + down_write(&vm->userptr.notifier_lock); + mmu_interval_set_seq(mni, cur_seq); + + __vma_userptr_invalidate(vm, uvma); + up_write(&vm->userptr.notifier_lock); trace_xe_vma_userptr_invalidate_complete(vma); return true; @@ -655,6 +654,34 @@ static const struct mmu_interval_notifier_ops vma_userptr_notifier_ops = { .invalidate = vma_userptr_invalidate, }; +#if IS_ENABLED(CONFIG_DRM_XE_USERPTR_INVAL_INJECT) +/** + * xe_vma_userptr_force_invalidate() - force invalidate a userptr + * @uvma: The userptr vma to invalidate + * + * Perform a forced userptr invalidation for testing purposes. + */ +void xe_vma_userptr_force_invalidate(struct xe_userptr_vma *uvma) +{ + struct xe_vm *vm = xe_vma_vm(&uvma->vma); + + /* Protect against concurrent userptr pinning */ + lockdep_assert_held(&vm->lock); + /* Protect against concurrent notifiers */ + lockdep_assert_held(&vm->userptr.notifier_lock); + /* + * Protect against concurrent instances of this function and + * the critical exec sections + */ + xe_vm_assert_held(vm); + + if (!mmu_interval_read_retry(&uvma->userptr.notifier, + uvma->userptr.notifier_seq)) + uvma->userptr.notifier_seq -= 2; + __vma_userptr_invalidate(vm, uvma); +} +#endif + int xe_vm_userptr_pin(struct xe_vm *vm) { struct xe_userptr_vma *uvma, *next; diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 256a837c2704..b882bfb31bd0 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -279,4 +279,12 @@ struct xe_vm_snapshot *xe_vm_snapshot_capture(struct xe_vm *vm); void xe_vm_snapshot_capture_delayed(struct xe_vm_snapshot *snap); void xe_vm_snapshot_print(struct xe_vm_snapshot *snap, struct drm_printer *p); void xe_vm_snapshot_free(struct xe_vm_snapshot *snap); + +#if IS_ENABLED(CONFIG_DRM_XE_USERPTR_INVAL_INJECT) +void xe_vma_userptr_force_invalidate(struct xe_userptr_vma *uvma); +#else +static inline void xe_vma_userptr_force_invalidate(struct xe_userptr_vma *uvma) +{ +} +#endif #endif diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 7f9a303e51d8..d2511819cdf4 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -227,8 +227,8 @@ struct xe_vm { * up for revalidation. Protected from access with the * @invalidated_lock. Removing items from the list * additionally requires @lock in write mode, and adding - * items to the list requires the @userptr.notifer_lock in - * write mode. + * items to the list requires either the @userptr.notifer_lock in + * write mode, OR @lock in write mode. */ struct list_head invalidated; } userptr; From ae482ec8cd1a85bde3307f71921a7780086fbec0 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Fri, 28 Feb 2025 08:30:58 +0100 Subject: [PATCH 0661/1090] drm/xe: Add staging tree for VM binds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Concurrent VM bind staging and zapping of PTEs from a userptr notifier do not work because the view of PTEs is not stable. VM binds cannot acquire the notifier lock during staging, as memory allocations are required. To resolve this race condition, use a staging tree for VM binds that is committed only under the userptr notifier lock during the final step of the bind. This ensures a consistent view of the PTEs in the userptr notifier. A follow up may only use staging for VM in fault mode as this is the only mode in which the above race exists. v3: - Drop zap PTE change (Thomas) - s/xe_pt_entry/xe_pt_entry_staging (Thomas) Suggested-by: Thomas Hellström Cc: Fixes: e8babb280b5e ("drm/xe: Convert multiple bind ops into single job") Fixes: a708f6501c69 ("drm/xe: Update PT layer with better error handling") Signed-off-by: Matthew Brost Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20250228073058.59510-5-thomas.hellstrom@linux.intel.com Signed-off-by: Thomas Hellström (cherry picked from commit 6f39b0c5ef0385eae586760d10b9767168037aa5) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_pt.c | 58 +++++++++++++++++++++++---------- drivers/gpu/drm/xe/xe_pt_walk.c | 3 +- drivers/gpu/drm/xe/xe_pt_walk.h | 4 +++ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 12a627a23eb4..dc24baa84092 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -28,6 +28,8 @@ struct xe_pt_dir { struct xe_pt pt; /** @children: Array of page-table child nodes */ struct xe_ptw *children[XE_PDES]; + /** @staging: Array of page-table staging nodes */ + struct xe_ptw *staging[XE_PDES]; }; #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM) @@ -48,9 +50,10 @@ static struct xe_pt_dir *as_xe_pt_dir(struct xe_pt *pt) return container_of(pt, struct xe_pt_dir, pt); } -static struct xe_pt *xe_pt_entry(struct xe_pt_dir *pt_dir, unsigned int index) +static struct xe_pt * +xe_pt_entry_staging(struct xe_pt_dir *pt_dir, unsigned int index) { - return container_of(pt_dir->children[index], struct xe_pt, base); + return container_of(pt_dir->staging[index], struct xe_pt, base); } static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm, @@ -125,6 +128,7 @@ struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile, } pt->bo = bo; pt->base.children = level ? as_xe_pt_dir(pt)->children : NULL; + pt->base.staging = level ? as_xe_pt_dir(pt)->staging : NULL; if (vm->xef) xe_drm_client_add_bo(vm->xef->client, pt->bo); @@ -206,8 +210,8 @@ void xe_pt_destroy(struct xe_pt *pt, u32 flags, struct llist_head *deferred) struct xe_pt_dir *pt_dir = as_xe_pt_dir(pt); for (i = 0; i < XE_PDES; i++) { - if (xe_pt_entry(pt_dir, i)) - xe_pt_destroy(xe_pt_entry(pt_dir, i), flags, + if (xe_pt_entry_staging(pt_dir, i)) + xe_pt_destroy(xe_pt_entry_staging(pt_dir, i), flags, deferred); } } @@ -376,8 +380,10 @@ xe_pt_insert_entry(struct xe_pt_stage_bind_walk *xe_walk, struct xe_pt *parent, /* Continue building a non-connected subtree. */ struct iosys_map *map = &parent->bo->vmap; - if (unlikely(xe_child)) + if (unlikely(xe_child)) { parent->base.children[offset] = &xe_child->base; + parent->base.staging[offset] = &xe_child->base; + } xe_pt_write(xe_walk->vm->xe, map, offset, pte); parent->num_live++; @@ -614,6 +620,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma, .ops = &xe_pt_stage_bind_ops, .shifts = xe_normal_pt_shifts, .max_level = XE_PT_HIGHEST_LEVEL, + .staging = true, }, .vm = xe_vma_vm(vma), .tile = tile, @@ -873,7 +880,7 @@ static void xe_pt_cancel_bind(struct xe_vma *vma, } } -static void xe_pt_commit_locks_assert(struct xe_vma *vma) +static void xe_pt_commit_prepare_locks_assert(struct xe_vma *vma) { struct xe_vm *vm = xe_vma_vm(vma); @@ -885,6 +892,16 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma) xe_vm_assert_held(vm); } +static void xe_pt_commit_locks_assert(struct xe_vma *vma) +{ + struct xe_vm *vm = xe_vma_vm(vma); + + xe_pt_commit_prepare_locks_assert(vma); + + if (xe_vma_is_userptr(vma)) + lockdep_assert_held_read(&vm->userptr.notifier_lock); +} + static void xe_pt_commit(struct xe_vma *vma, struct xe_vm_pgtable_update *entries, u32 num_entries, struct llist_head *deferred) @@ -895,13 +912,17 @@ static void xe_pt_commit(struct xe_vma *vma, for (i = 0; i < num_entries; i++) { struct xe_pt *pt = entries[i].pt; + struct xe_pt_dir *pt_dir; if (!pt->level) continue; + pt_dir = as_xe_pt_dir(pt); for (j = 0; j < entries[i].qwords; j++) { struct xe_pt *oldpte = entries[i].pt_entries[j].pt; + int j_ = j + entries[i].ofs; + pt_dir->children[j_] = pt_dir->staging[j_]; xe_pt_destroy(oldpte, xe_vma_vm(vma)->flags, deferred); } } @@ -913,7 +934,7 @@ static void xe_pt_abort_bind(struct xe_vma *vma, { int i, j; - xe_pt_commit_locks_assert(vma); + xe_pt_commit_prepare_locks_assert(vma); for (i = num_entries - 1; i >= 0; --i) { struct xe_pt *pt = entries[i].pt; @@ -928,10 +949,10 @@ static void xe_pt_abort_bind(struct xe_vma *vma, pt_dir = as_xe_pt_dir(pt); for (j = 0; j < entries[i].qwords; j++) { u32 j_ = j + entries[i].ofs; - struct xe_pt *newpte = xe_pt_entry(pt_dir, j_); + struct xe_pt *newpte = xe_pt_entry_staging(pt_dir, j_); struct xe_pt *oldpte = entries[i].pt_entries[j].pt; - pt_dir->children[j_] = oldpte ? &oldpte->base : 0; + pt_dir->staging[j_] = oldpte ? &oldpte->base : 0; xe_pt_destroy(newpte, xe_vma_vm(vma)->flags, NULL); } } @@ -943,7 +964,7 @@ static void xe_pt_commit_prepare_bind(struct xe_vma *vma, { u32 i, j; - xe_pt_commit_locks_assert(vma); + xe_pt_commit_prepare_locks_assert(vma); for (i = 0; i < num_entries; i++) { struct xe_pt *pt = entries[i].pt; @@ -961,10 +982,10 @@ static void xe_pt_commit_prepare_bind(struct xe_vma *vma, struct xe_pt *newpte = entries[i].pt_entries[j].pt; struct xe_pt *oldpte = NULL; - if (xe_pt_entry(pt_dir, j_)) - oldpte = xe_pt_entry(pt_dir, j_); + if (xe_pt_entry_staging(pt_dir, j_)) + oldpte = xe_pt_entry_staging(pt_dir, j_); - pt_dir->children[j_] = &newpte->base; + pt_dir->staging[j_] = &newpte->base; entries[i].pt_entries[j].pt = oldpte; } } @@ -1494,6 +1515,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile, struct xe_vma *vma, .ops = &xe_pt_stage_unbind_ops, .shifts = xe_normal_pt_shifts, .max_level = XE_PT_HIGHEST_LEVEL, + .staging = true, }, .tile = tile, .modified_start = xe_vma_start(vma), @@ -1535,7 +1557,7 @@ static void xe_pt_abort_unbind(struct xe_vma *vma, { int i, j; - xe_pt_commit_locks_assert(vma); + xe_pt_commit_prepare_locks_assert(vma); for (i = num_entries - 1; i >= 0; --i) { struct xe_vm_pgtable_update *entry = &entries[i]; @@ -1548,7 +1570,7 @@ static void xe_pt_abort_unbind(struct xe_vma *vma, continue; for (j = entry->ofs; j < entry->ofs + entry->qwords; j++) - pt_dir->children[j] = + pt_dir->staging[j] = entries[i].pt_entries[j - entry->ofs].pt ? &entries[i].pt_entries[j - entry->ofs].pt->base : NULL; } @@ -1561,7 +1583,7 @@ xe_pt_commit_prepare_unbind(struct xe_vma *vma, { int i, j; - xe_pt_commit_locks_assert(vma); + xe_pt_commit_prepare_locks_assert(vma); for (i = 0; i < num_entries; ++i) { struct xe_vm_pgtable_update *entry = &entries[i]; @@ -1575,8 +1597,8 @@ xe_pt_commit_prepare_unbind(struct xe_vma *vma, pt_dir = as_xe_pt_dir(pt); for (j = entry->ofs; j < entry->ofs + entry->qwords; j++) { entry->pt_entries[j - entry->ofs].pt = - xe_pt_entry(pt_dir, j); - pt_dir->children[j] = NULL; + xe_pt_entry_staging(pt_dir, j); + pt_dir->staging[j] = NULL; } } } diff --git a/drivers/gpu/drm/xe/xe_pt_walk.c b/drivers/gpu/drm/xe/xe_pt_walk.c index b8b3d2aea492..be602a763ff3 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.c +++ b/drivers/gpu/drm/xe/xe_pt_walk.c @@ -74,7 +74,8 @@ int xe_pt_walk_range(struct xe_ptw *parent, unsigned int level, u64 addr, u64 end, struct xe_pt_walk *walk) { pgoff_t offset = xe_pt_offset(addr, level, walk); - struct xe_ptw **entries = parent->children ? parent->children : NULL; + struct xe_ptw **entries = walk->staging ? (parent->staging ?: NULL) : + (parent->children ?: NULL); const struct xe_pt_walk_ops *ops = walk->ops; enum page_walk_action action; struct xe_ptw *child; diff --git a/drivers/gpu/drm/xe/xe_pt_walk.h b/drivers/gpu/drm/xe/xe_pt_walk.h index 5ecc4d2f0f65..5c02c244f7de 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.h +++ b/drivers/gpu/drm/xe/xe_pt_walk.h @@ -11,12 +11,14 @@ /** * struct xe_ptw - base class for driver pagetable subclassing. * @children: Pointer to an array of children if any. + * @staging: Pointer to an array of staging if any. * * Drivers could subclass this, and if it's a page-directory, typically * embed an array of xe_ptw pointers. */ struct xe_ptw { struct xe_ptw **children; + struct xe_ptw **staging; }; /** @@ -41,6 +43,8 @@ struct xe_pt_walk { * as shared pagetables. */ bool shared_pt_mode; + /** @staging: Walk staging PT structure */ + bool staging; }; /** From e3e2e7fc4cd8414c9a966ef1b344db543f8614f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Tue, 4 Mar 2025 18:33:40 +0100 Subject: [PATCH 0662/1090] drm/xe/hmm: Style- and include fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add proper #ifndef around the xe_hmm.h header, proper spacing and since the documentation mostly follows kerneldoc format, make it kerneldoc. Also prepare for upcoming -stable fixes. Fixes: 81e058a3e7fd ("drm/xe: Introduce helper to populate userptr") Cc: Oak Zeng Cc: # v6.10+ Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Acked-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250304173342.22009-2-thomas.hellstrom@linux.intel.com (cherry picked from commit bbe2b06b55bc061c8fcec034ed26e88287f39143) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hmm.c | 9 +++------ drivers/gpu/drm/xe/xe_hmm.h | 5 +++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c index 2e4ae61567d8..6ddcf88d8a39 100644 --- a/drivers/gpu/drm/xe/xe_hmm.c +++ b/drivers/gpu/drm/xe/xe_hmm.c @@ -19,11 +19,10 @@ static u64 xe_npages_in_range(unsigned long start, unsigned long end) return (end - start) >> PAGE_SHIFT; } -/* +/** * xe_mark_range_accessed() - mark a range is accessed, so core mm * have such information for memory eviction or write back to * hard disk - * * @range: the range to mark * @write: if write to this range, we mark pages in this range * as dirty @@ -43,11 +42,10 @@ static void xe_mark_range_accessed(struct hmm_range *range, bool write) } } -/* +/** * xe_build_sg() - build a scatter gather table for all the physical pages/pfn * in a hmm_range. dma-map pages if necessary. dma-address is save in sg table * and will be used to program GPU page table later. - * * @xe: the xe device who will access the dma-address in sg table * @range: the hmm range that we build the sg table from. range->hmm_pfns[] * has the pfn numbers of pages that back up this hmm address range. @@ -112,9 +110,8 @@ free_pages: return ret; } -/* +/** * xe_hmm_userptr_free_sg() - Free the scatter gather table of userptr - * * @uvma: the userptr vma which hold the scatter gather table * * With function xe_userptr_populate_range, we allocate storage of diff --git a/drivers/gpu/drm/xe/xe_hmm.h b/drivers/gpu/drm/xe/xe_hmm.h index 909dc2bdcd97..9602cb7d976d 100644 --- a/drivers/gpu/drm/xe/xe_hmm.h +++ b/drivers/gpu/drm/xe/xe_hmm.h @@ -3,9 +3,14 @@ * Copyright © 2024 Intel Corporation */ +#ifndef _XE_HMM_H_ +#define _XE_HMM_H_ + #include struct xe_userptr_vma; int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, bool is_mm_mmap_locked); + void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma); +#endif From 0a98219bcc961edd3388960576e4353e123b4a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Tue, 4 Mar 2025 18:33:41 +0100 Subject: [PATCH 0663/1090] drm/xe/hmm: Don't dereference struct page pointers without notifier lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pnfs that we obtain from hmm_range_fault() point to pages that we don't have a reference on, and the guarantee that they are still in the cpu page-tables is that the notifier lock must be held and the notifier seqno is still valid. So while building the sg table and marking the pages accesses / dirty we need to hold this lock with a validated seqno. However, the lock is reclaim tainted which makes sg_alloc_table_from_pages_segment() unusable, since it internally allocates memory. Instead build the sg-table manually. For the non-iommu case this might lead to fewer coalesces, but if that's a problem it can be fixed up later in the resource cursor code. For the iommu case, the whole sg-table may still be coalesced to a single contigous device va region. This avoids marking pages that we don't own dirty and accessed, and it also avoid dereferencing struct pages that we don't own. v2: - Use assert to check whether hmm pfns are valid (Matthew Auld) - Take into account that large pages may cross range boundaries (Matthew Auld) v3: - Don't unnecessarily check for a non-freed sg-table. (Matthew Auld) - Add a missing up_read() in an error path. (Matthew Auld) Fixes: 81e058a3e7fd ("drm/xe: Introduce helper to populate userptr") Cc: Oak Zeng Cc: # v6.10+ Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Acked-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250304173342.22009-3-thomas.hellstrom@linux.intel.com (cherry picked from commit ea3e66d280ce2576664a862693d1da8fd324c317) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hmm.c | 116 +++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c index 6ddcf88d8a39..be284b852307 100644 --- a/drivers/gpu/drm/xe/xe_hmm.c +++ b/drivers/gpu/drm/xe/xe_hmm.c @@ -42,6 +42,42 @@ static void xe_mark_range_accessed(struct hmm_range *range, bool write) } } +static int xe_alloc_sg(struct xe_device *xe, struct sg_table *st, + struct hmm_range *range, struct rw_semaphore *notifier_sem) +{ + unsigned long i, npages, hmm_pfn; + unsigned long num_chunks = 0; + int ret; + + /* HMM docs says this is needed. */ + ret = down_read_interruptible(notifier_sem); + if (ret) + return ret; + + if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) { + up_read(notifier_sem); + return -EAGAIN; + } + + npages = xe_npages_in_range(range->start, range->end); + for (i = 0; i < npages;) { + unsigned long len; + + hmm_pfn = range->hmm_pfns[i]; + xe_assert(xe, hmm_pfn & HMM_PFN_VALID); + + len = 1UL << hmm_pfn_to_map_order(hmm_pfn); + + /* If order > 0 the page may extend beyond range->start */ + len -= (hmm_pfn & ~HMM_PFN_FLAGS) & (len - 1); + i += len; + num_chunks++; + } + up_read(notifier_sem); + + return sg_alloc_table(st, num_chunks, GFP_KERNEL); +} + /** * xe_build_sg() - build a scatter gather table for all the physical pages/pfn * in a hmm_range. dma-map pages if necessary. dma-address is save in sg table @@ -50,6 +86,7 @@ static void xe_mark_range_accessed(struct hmm_range *range, bool write) * @range: the hmm range that we build the sg table from. range->hmm_pfns[] * has the pfn numbers of pages that back up this hmm address range. * @st: pointer to the sg table. + * @notifier_sem: The xe notifier lock. * @write: whether we write to this range. This decides dma map direction * for system pages. If write we map it bi-diretional; otherwise * DMA_TO_DEVICE @@ -76,38 +113,41 @@ static void xe_mark_range_accessed(struct hmm_range *range, bool write) * Returns 0 if successful; -ENOMEM if fails to allocate memory */ static int xe_build_sg(struct xe_device *xe, struct hmm_range *range, - struct sg_table *st, bool write) + struct sg_table *st, + struct rw_semaphore *notifier_sem, + bool write) { + unsigned long npages = xe_npages_in_range(range->start, range->end); struct device *dev = xe->drm.dev; - struct page **pages; - u64 i, npages; - int ret; + struct scatterlist *sgl; + struct page *page; + unsigned long i, j; - npages = xe_npages_in_range(range->start, range->end); - pages = kvmalloc_array(npages, sizeof(*pages), GFP_KERNEL); - if (!pages) - return -ENOMEM; + lockdep_assert_held(notifier_sem); - for (i = 0; i < npages; i++) { - pages[i] = hmm_pfn_to_page(range->hmm_pfns[i]); - xe_assert(xe, !is_device_private_page(pages[i])); + i = 0; + for_each_sg(st->sgl, sgl, st->nents, j) { + unsigned long hmm_pfn, size; + + hmm_pfn = range->hmm_pfns[i]; + page = hmm_pfn_to_page(hmm_pfn); + xe_assert(xe, !is_device_private_page(page)); + + size = 1UL << hmm_pfn_to_map_order(hmm_pfn); + size -= page_to_pfn(page) & (size - 1); + i += size; + + if (unlikely(j == st->nents - 1)) { + if (i > npages) + size -= (i - npages); + sg_mark_end(sgl); + } + sg_set_page(sgl, page, size << PAGE_SHIFT, 0); } + xe_assert(xe, i == npages); - ret = sg_alloc_table_from_pages_segment(st, pages, npages, 0, npages << PAGE_SHIFT, - xe_sg_segment_size(dev), GFP_KERNEL); - if (ret) - goto free_pages; - - ret = dma_map_sgtable(dev, st, write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_NO_KERNEL_MAPPING); - if (ret) { - sg_free_table(st); - st = NULL; - } - -free_pages: - kvfree(pages); - return ret; + return dma_map_sgtable(dev, st, write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_NO_KERNEL_MAPPING); } /** @@ -237,16 +277,36 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, if (ret) goto free_pfns; - ret = xe_build_sg(vm->xe, &hmm_range, &userptr->sgt, write); + ret = xe_alloc_sg(vm->xe, &userptr->sgt, &hmm_range, &vm->userptr.notifier_lock); if (ret) goto free_pfns; + ret = down_read_interruptible(&vm->userptr.notifier_lock); + if (ret) + goto free_st; + + if (mmu_interval_read_retry(hmm_range.notifier, hmm_range.notifier_seq)) { + ret = -EAGAIN; + goto out_unlock; + } + + ret = xe_build_sg(vm->xe, &hmm_range, &userptr->sgt, + &vm->userptr.notifier_lock, write); + if (ret) + goto out_unlock; + xe_mark_range_accessed(&hmm_range, write); userptr->sg = &userptr->sgt; userptr->notifier_seq = hmm_range.notifier_seq; + up_read(&vm->userptr.notifier_lock); + kvfree(pfns); + return 0; +out_unlock: + up_read(&vm->userptr.notifier_lock); +free_st: + sg_free_table(&userptr->sgt); free_pfns: kvfree(pfns); return ret; } - From 333b8906336174478efbbfc1e24a89e3397ffe65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Tue, 4 Mar 2025 18:33:42 +0100 Subject: [PATCH 0664/1090] drm/xe/userptr: Unmap userptrs in the mmu notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If userptr pages are freed after a call to the xe mmu notifier, the device will not be blocked out from theoretically accessing these pages unless they are also unmapped from the iommu, and this violates some aspects of the iommu-imposed security. Ensure that userptrs are unmapped in the mmu notifier to mitigate this. A naive attempt would try to free the sg table, but the sg table itself may be accessed by a concurrent bind operation, so settle for only unmapping. v3: - Update lockdep asserts. - Fix a typo (Matthew Auld) Fixes: 81e058a3e7fd ("drm/xe: Introduce helper to populate userptr") Cc: Oak Zeng Cc: Matthew Auld Cc: # v6.10+ Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Acked-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250304173342.22009-4-thomas.hellstrom@linux.intel.com (cherry picked from commit ba767b9d01a2c552d76cf6f46b125d50ec4147a6) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hmm.c | 51 ++++++++++++++++++++++++++------ drivers/gpu/drm/xe/xe_hmm.h | 2 ++ drivers/gpu/drm/xe/xe_vm.c | 4 +++ drivers/gpu/drm/xe/xe_vm_types.h | 4 +++ 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c index be284b852307..392102515f3d 100644 --- a/drivers/gpu/drm/xe/xe_hmm.c +++ b/drivers/gpu/drm/xe/xe_hmm.c @@ -150,6 +150,45 @@ static int xe_build_sg(struct xe_device *xe, struct hmm_range *range, DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_NO_KERNEL_MAPPING); } +static void xe_hmm_userptr_set_mapped(struct xe_userptr_vma *uvma) +{ + struct xe_userptr *userptr = &uvma->userptr; + struct xe_vm *vm = xe_vma_vm(&uvma->vma); + + lockdep_assert_held_write(&vm->lock); + lockdep_assert_held(&vm->userptr.notifier_lock); + + mutex_lock(&userptr->unmap_mutex); + xe_assert(vm->xe, !userptr->mapped); + userptr->mapped = true; + mutex_unlock(&userptr->unmap_mutex); +} + +void xe_hmm_userptr_unmap(struct xe_userptr_vma *uvma) +{ + struct xe_userptr *userptr = &uvma->userptr; + struct xe_vma *vma = &uvma->vma; + bool write = !xe_vma_read_only(vma); + struct xe_vm *vm = xe_vma_vm(vma); + struct xe_device *xe = vm->xe; + + if (!lockdep_is_held_type(&vm->userptr.notifier_lock, 0) && + !lockdep_is_held_type(&vm->lock, 0) && + !(vma->gpuva.flags & XE_VMA_DESTROYED)) { + /* Don't unmap in exec critical section. */ + xe_vm_assert_held(vm); + /* Don't unmap while mapping the sg. */ + lockdep_assert_held(&vm->lock); + } + + mutex_lock(&userptr->unmap_mutex); + if (userptr->sg && userptr->mapped) + dma_unmap_sgtable(xe->drm.dev, userptr->sg, + write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, 0); + userptr->mapped = false; + mutex_unlock(&userptr->unmap_mutex); +} + /** * xe_hmm_userptr_free_sg() - Free the scatter gather table of userptr * @uvma: the userptr vma which hold the scatter gather table @@ -161,16 +200,9 @@ static int xe_build_sg(struct xe_device *xe, struct hmm_range *range, void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma) { struct xe_userptr *userptr = &uvma->userptr; - struct xe_vma *vma = &uvma->vma; - bool write = !xe_vma_read_only(vma); - struct xe_vm *vm = xe_vma_vm(vma); - struct xe_device *xe = vm->xe; - struct device *dev = xe->drm.dev; - - xe_assert(xe, userptr->sg); - dma_unmap_sgtable(dev, userptr->sg, - write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, 0); + xe_assert(xe_vma_vm(&uvma->vma)->xe, userptr->sg); + xe_hmm_userptr_unmap(uvma); sg_free_table(userptr->sg); userptr->sg = NULL; } @@ -297,6 +329,7 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, xe_mark_range_accessed(&hmm_range, write); userptr->sg = &userptr->sgt; + xe_hmm_userptr_set_mapped(uvma); userptr->notifier_seq = hmm_range.notifier_seq; up_read(&vm->userptr.notifier_lock); kvfree(pfns); diff --git a/drivers/gpu/drm/xe/xe_hmm.h b/drivers/gpu/drm/xe/xe_hmm.h index 9602cb7d976d..0ea98d8e7bbc 100644 --- a/drivers/gpu/drm/xe/xe_hmm.h +++ b/drivers/gpu/drm/xe/xe_hmm.h @@ -13,4 +13,6 @@ struct xe_userptr_vma; int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, bool is_mm_mmap_locked); void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma); + +void xe_hmm_userptr_unmap(struct xe_userptr_vma *uvma); #endif diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index d54aaa5eaff3..ec6ec18ab3fa 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -620,6 +620,8 @@ static void __vma_userptr_invalidate(struct xe_vm *vm, struct xe_userptr_vma *uv err = xe_vm_invalidate_vma(vma); XE_WARN_ON(err); } + + xe_hmm_userptr_unmap(uvma); } static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, @@ -1039,6 +1041,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, INIT_LIST_HEAD(&userptr->invalidate_link); INIT_LIST_HEAD(&userptr->repin_link); vma->gpuva.gem.offset = bo_offset_or_userptr; + mutex_init(&userptr->unmap_mutex); err = mmu_interval_notifier_insert(&userptr->notifier, current->mm, @@ -1080,6 +1083,7 @@ static void xe_vma_destroy_late(struct xe_vma *vma) * them anymore */ mmu_interval_notifier_remove(&userptr->notifier); + mutex_destroy(&userptr->unmap_mutex); xe_vm_put(vm); } else if (xe_vma_is_null(vma)) { xe_vm_put(vm); diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index d2511819cdf4..a4b4091cfd0d 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -59,12 +59,16 @@ struct xe_userptr { struct sg_table *sg; /** @notifier_seq: notifier sequence number */ unsigned long notifier_seq; + /** @unmap_mutex: Mutex protecting dma-unmapping */ + struct mutex unmap_mutex; /** * @initial_bind: user pointer has been bound at least once. * write: vm->userptr.notifier_lock in read mode and vm->resv held. * read: vm->userptr.notifier_lock in write mode or vm->resv held. */ bool initial_bind; + /** @mapped: Whether the @sgt sg-table is dma-mapped. Protected by @unmap_mutex. */ + bool mapped; #if IS_ENABLED(CONFIG_DRM_XE_USERPTR_INVAL_INJECT) u32 divisor; #endif From bcb0fda3c2da9fe4721d3e73d80e778c038e7d27 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 5 Mar 2025 14:03:34 -0700 Subject: [PATCH 0665/1090] io_uring/rw: ensure reissue path is correctly handled for IOPOLL The IOPOLL path posts CQEs when the io_kiocb is marked as completed, so it cannot rely on the usual retry that non-IOPOLL requests do for read/write requests. If -EAGAIN is received and the request should be retried, go through the normal completion path and let the normal flush logic catch it and reissue it, like what is done for !IOPOLL reads or writes. Fixes: d803d123948f ("io_uring/rw: handle -EAGAIN retry at IO completion time") Reported-by: John Garry Link: https://lore.kernel.org/io-uring/2b43ccfa-644d-4a09-8f8f-39ad71810f41@oracle.com/ Signed-off-by: Jens Axboe --- io_uring/rw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/io_uring/rw.c b/io_uring/rw.c index 9edc6baebd01..e5528cebcd06 100644 --- a/io_uring/rw.c +++ b/io_uring/rw.c @@ -560,11 +560,10 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res) if (kiocb->ki_flags & IOCB_WRITE) io_req_end_write(req); if (unlikely(res != req->cqe.res)) { - if (res == -EAGAIN && io_rw_should_reissue(req)) { + if (res == -EAGAIN && io_rw_should_reissue(req)) req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE; - return; - } - req->cqe.res = res; + else + req->cqe.res = res; } /* order with io_iopoll_complete() checking ->iopoll_completed */ From df08c94baafb001de6cf44bb7098bb557f36c335 Mon Sep 17 00:00:00 2001 From: Nicklas Bo Jensen Date: Thu, 27 Feb 2025 13:32:34 +0000 Subject: [PATCH 0666/1090] netfilter: nf_conncount: garbage collection is not skipped when jiffies wrap around nf_conncount is supposed to skip garbage collection if it has already run garbage collection in the same jiffy. Unfortunately, this is broken when jiffies wrap around which this patch fixes. The problem is that last_gc in the nf_conncount_list struct is an u32, but jiffies is an unsigned long which is 8 bytes on my systems. When those two are compared it only works until last_gc wraps around. See bug report: https://bugzilla.netfilter.org/show_bug.cgi?id=1778 for more details. Fixes: d265929930e2 ("netfilter: nf_conncount: reduce unnecessary GC") Signed-off-by: Nicklas Bo Jensen Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conncount.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index 4890af4dc263..ebe38ed2e6f4 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -132,7 +132,7 @@ static int __nf_conncount_add(struct net *net, struct nf_conn *found_ct; unsigned int collect = 0; - if (time_is_after_eq_jiffies((unsigned long)list->last_gc)) + if ((u32)jiffies == list->last_gc) goto add_new_node; /* check the saved connections */ @@ -234,7 +234,7 @@ bool nf_conncount_gc_list(struct net *net, bool ret = false; /* don't bother if we just did GC */ - if (time_is_after_eq_jiffies((unsigned long)READ_ONCE(list->last_gc))) + if ((u32)jiffies == READ_ONCE(list->last_gc)) return false; /* don't bother if other cpu is already doing GC */ From 374908a15af4cd60862ebc51a6e012ace2212c76 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 3 Mar 2025 18:10:30 +0100 Subject: [PATCH 0667/1090] rust: remove leftover mentions of the `alloc` crate In commit 392e34b6bc22 ("kbuild: rust: remove the `alloc` crate and `GlobalAlloc`") we stopped using the upstream `alloc` crate. Thus remove a few leftover mentions treewide. Cc: stable@vger.kernel.org # Also to 6.12.y after the `alloc` backport lands Fixes: 392e34b6bc22 ("kbuild: rust: remove the `alloc` crate and `GlobalAlloc`") Reviewed-by: Danilo Krummrich Reviewed-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250303171030.1081134-1-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- Documentation/rust/quick-start.rst | 2 +- rust/kernel/lib.rs | 2 +- scripts/rustdoc_test_gen.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/rust/quick-start.rst b/Documentation/rust/quick-start.rst index 4aa50e5fcb8c..6d2607870ba4 100644 --- a/Documentation/rust/quick-start.rst +++ b/Documentation/rust/quick-start.rst @@ -145,7 +145,7 @@ Rust standard library source **************************** The Rust standard library source is required because the build system will -cross-compile ``core`` and ``alloc``. +cross-compile ``core``. If ``rustup`` is being used, run:: diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 398242f92a96..7697c60b2d1a 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -6,7 +6,7 @@ //! usage by Rust code in the kernel and is shared by all of them. //! //! In other words, all the rest of the Rust code in the kernel (e.g. kernel -//! modules written in Rust) depends on [`core`], [`alloc`] and this crate. +//! modules written in Rust) depends on [`core`] and this crate. //! //! If you need a kernel C API that is not ported or wrapped yet here, then //! do so first instead of bypassing this crate. diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs index 5ebd42ae4a3f..76aaa8329413 100644 --- a/scripts/rustdoc_test_gen.rs +++ b/scripts/rustdoc_test_gen.rs @@ -15,8 +15,8 @@ //! - Test code should be able to define functions and call them, without having to carry //! the context. //! -//! - Later on, we may want to be able to test non-kernel code (e.g. `core`, `alloc` or -//! third-party crates) which likely use the standard library `assert*!` macros. +//! - Later on, we may want to be able to test non-kernel code (e.g. `core` or third-party +//! crates) which likely use the standard library `assert*!` macros. //! //! For this reason, instead of the passed context, `kunit_get_current_test()` is used instead //! (i.e. `current->kunit_test`). From df27cef153603b18a7d094b53cc3d5264ff32797 Mon Sep 17 00:00:00 2001 From: Benno Lossin Date: Wed, 5 Mar 2025 13:29:01 +0000 Subject: [PATCH 0668/1090] rust: init: fix `Zeroable` implementation for `Option>` and `Option>` According to [1], `NonNull` and `#[repr(transparent)]` wrapper types such as our custom `KBox` have the null pointer optimization only if `T: Sized`. Thus remove the `Zeroable` implementation for the unsized case. Link: https://doc.rust-lang.org/stable/std/option/index.html#representation [1] Reported-by: Alice Ryhl Closes: https://lore.kernel.org/rust-for-linux/CAH5fLghL+qzrD8KiCF1V3vf2YcC6aWySzkmaE2Zzrnh1gKj-hw@mail.gmail.com/ Cc: stable@vger.kernel.org # v6.12+ (a custom patch will be needed for 6.6.y) Fixes: 38cde0bd7b67 ("rust: init: add `Zeroable` trait and `init::zeroed` function") Signed-off-by: Benno Lossin Reviewed-by: Alice Ryhl Reviewed-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250305132836.2145476-1-benno.lossin@proton.me [ Added Closes tag and moved up the Reported-by one. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/init.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 7fd1ea8265a5..8bbd5e3398fc 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -1418,17 +1418,14 @@ impl_zeroable! { // SAFETY: `T: Zeroable` and `UnsafeCell` is `repr(transparent)`. {} UnsafeCell, - // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee). + // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee: + // https://doc.rust-lang.org/stable/std/option/index.html#representation). Option, Option, Option, Option, Option, Option, Option, Option, Option, Option, Option, Option, - - // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee). - // - // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant. - {} Option>, - {} Option>, + {} Option>, + {} Option>, // SAFETY: `null` pointer is valid. // From ff64846bee0e7e3e7bc9363ebad3bab42dd27e24 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 13 Feb 2025 06:34:18 -0500 Subject: [PATCH 0669/1090] rust: alloc: satisfy POSIX alignment requirement ISO C's `aligned_alloc` is partially implementation-defined; on some systems it inherits stricter requirements from POSIX's `posix_memalign`. This causes the call added in commit dd09538fb409 ("rust: alloc: implement `Cmalloc` in module allocator_test") to fail on macOS because it doesn't meet the requirements of `posix_memalign`. Adjust the call to meet the POSIX requirement and add a comment. This fixes failures in `make rusttest` on macOS. Acked-by: Danilo Krummrich Cc: stable@vger.kernel.org Fixes: dd09538fb409 ("rust: alloc: implement `Cmalloc` in module allocator_test") Signed-off-by: Tamir Duberstein Reviewed-by: Gary Guo Link: https://lore.kernel.org/r/20250213-aligned-alloc-v7-1-d2a2d0be164b@gmail.com [ Added Cc: stable. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/alloc/allocator_test.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/rust/kernel/alloc/allocator_test.rs b/rust/kernel/alloc/allocator_test.rs index e3240d16040b..c37d4c0c64e9 100644 --- a/rust/kernel/alloc/allocator_test.rs +++ b/rust/kernel/alloc/allocator_test.rs @@ -62,6 +62,24 @@ unsafe impl Allocator for Cmalloc { )); } + // ISO C (ISO/IEC 9899:2011) defines `aligned_alloc`: + // + // > The value of alignment shall be a valid alignment supported by the implementation + // [...]. + // + // As an example of the "supported by the implementation" requirement, POSIX.1-2001 (IEEE + // 1003.1-2001) defines `posix_memalign`: + // + // > The value of alignment shall be a power of two multiple of sizeof (void *). + // + // and POSIX-based implementations of `aligned_alloc` inherit this requirement. At the time + // of writing, this is known to be the case on macOS (but not in glibc). + // + // Satisfy the stricter requirement to avoid spurious test failures on some platforms. + let min_align = core::mem::size_of::<*const crate::ffi::c_void>(); + let layout = layout.align_to(min_align).map_err(|_| AllocError)?; + let layout = layout.pad_to_align(); + // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or // exceeds the given size and alignment requirements. let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) } as *mut u8; From f2e413f00ebec10a8725b1b75b1b523c561bd403 Mon Sep 17 00:00:00 2001 From: Alban Kurti Date: Thu, 6 Feb 2025 21:07:52 +0000 Subject: [PATCH 0670/1090] rust: docs: add missing newline to printing macro examples Fix adding a newline at the end of the usage of pr_info! in the documentation Fixes: e3c3d34507c7 ("docs: rust: Add description of Rust documentation test as KUnit ones") Reported-by: Miguel Ojeda Link: https://github.com/Rust-for-Linux/linux/issues/1139 Signed-off-by: Alban Kurti Reviewed-by: David Gow Link: https://lore.kernel.org/r/20250206-printing_fix-v3-1-a85273b501ae@invicto.ai [ Replaced Closes with Link since it fixes part of the issue. - Miguel ] Signed-off-by: Miguel Ojeda --- Documentation/rust/testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/rust/testing.rst b/Documentation/rust/testing.rst index 568b71b415a4..180b886e0f1e 100644 --- a/Documentation/rust/testing.rst +++ b/Documentation/rust/testing.rst @@ -97,7 +97,7 @@ operator are also supported as usual, e.g.: /// ``` /// # use kernel::{spawn_work_item, workqueue}; - /// spawn_work_item!(workqueue::system(), || pr_info!("x"))?; + /// spawn_work_item!(workqueue::system(), || pr_info!("x\n"))?; /// # Ok::<(), Error>(()) /// ``` From 6f5c36f56d475732981dcf624e0ac0cc7c8984c8 Mon Sep 17 00:00:00 2001 From: Alban Kurti Date: Thu, 6 Feb 2025 21:07:53 +0000 Subject: [PATCH 0671/1090] rust: error: add missing newline to pr_warn! calls Added missing newline at the end of pr_warn! usage so the log is not missed. Fixes: 6551a7fe0acb ("rust: error: Add Error::from_errno{_unchecked}()") Reported-by: Miguel Ojeda Link: https://github.com/Rust-for-Linux/linux/issues/1139 Signed-off-by: Alban Kurti Link: https://lore.kernel.org/r/20250206-printing_fix-v3-2-a85273b501ae@invicto.ai [ Replaced Closes with Link since it fixes part of the issue. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index f6ecf09cb65f..a194d83e6835 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -107,7 +107,7 @@ impl Error { } else { // TODO: Make it a `WARN_ONCE` once available. crate::pr_warn!( - "attempted to create `Error` with out of range `errno`: {}", + "attempted to create `Error` with out of range `errno`: {}\n", errno ); code::EINVAL From ccc2f5a436fbb0ae1fb598932a9b8e48423c1959 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 4 Mar 2025 09:50:23 +0100 Subject: [PATCH 0672/1090] net: dsa: mt7530: Fix traffic flooding for MMIO devices On MMIO devices (e.g. MT7988 or EN7581) unicast traffic received on lanX port is flooded on all other user ports if the DSA switch is configured without VLAN support since PORT_MATRIX in PCR regs contains all user ports. Similar to MDIO devices (e.g. MT7530 and MT7531) fix the issue defining default VLAN-ID 0 for MT7530 MMIO devices. Fixes: 110c18bfed414 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") Signed-off-by: Lorenzo Bianconi Reviewed-by: Chester A. Unal Link: https://patch.msgid.link/20250304-mt7988-flooding-fix-v1-1-905523ae83e9@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 1c83af805209..5883eb93efb1 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2591,7 +2591,8 @@ mt7531_setup_common(struct dsa_switch *ds) if (ret < 0) return ret; - return 0; + /* Setup VLAN ID 0 for VLAN-unaware bridges */ + return mt7530_setup_vlan0(priv); } static int @@ -2687,11 +2688,6 @@ mt7531_setup(struct dsa_switch *ds) if (ret) return ret; - /* Setup VLAN ID 0 for VLAN-unaware bridges */ - ret = mt7530_setup_vlan0(priv); - if (ret) - return ret; - ds->assisted_learning_on_cpu_port = true; ds->mtu_enforcement_ingress = true; From 0a7565ee6ec31eb16c0476adbfc1af3f2271cb6b Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Thu, 13 Feb 2025 19:38:50 -0800 Subject: [PATCH 0673/1090] Revert "selftests/mm: remove local __NR_* definitions" This reverts commit a5c6bc590094a1a73cf6fa3f505e1945d2bf2461. The general approach described in commit e076eaca5906 ("selftests: break the dependency upon local header files") was taken one step too far here: it should not have been extended to include the syscall numbers. This is because doing so would require per-arch support in tools/include/uapi, and no such support exists. This revert fixes two separate reports of test failures, from Dave Hansen[1], and Li Wang[2]. An excerpt of Dave's report: Before this commit (a5c6bc590094a1a73cf6fa3f505e1945d2bf2461) things are fine. But after, I get: running PKEY tests for unsupported CPU/OS An excerpt of Li's report: I just found that mlock2_() return a wrong value in mlock2-test [1] https://lore.kernel.org/dc585017-6740-4cab-a536-b12b37a7582d@intel.com [2] https://lore.kernel.org/CAEemH2eW=UMu9+turT2jRie7+6ewUazXmA6kL+VBo3cGDGU6RA@mail.gmail.com Link: https://lkml.kernel.org/r/20250214033850.235171-1-jhubbard@nvidia.com Fixes: a5c6bc590094 ("selftests/mm: remove local __NR_* definitions") Signed-off-by: John Hubbard Cc: Dave Hansen Cc: Li Wang Cc: David Hildenbrand Cc: Jeff Xu Cc: Andrei Vagin Cc: Axel Rasmussen Cc: Christian Brauner Cc: Kees Cook Cc: Kent Overstreet Cc: Liam R. Howlett Cc: Muhammad Usama Anjum Cc: Peter Xu Cc: Rich Felker Cc: Shuah Khan Cc: Signed-off-by: Andrew Morton --- tools/testing/selftests/mm/hugepage-mremap.c | 2 +- tools/testing/selftests/mm/ksm_functional_tests.c | 8 +++++++- tools/testing/selftests/mm/memfd_secret.c | 14 +++++++++++++- tools/testing/selftests/mm/mkdirty.c | 8 +++++++- tools/testing/selftests/mm/mlock2.h | 1 - tools/testing/selftests/mm/protection_keys.c | 2 +- tools/testing/selftests/mm/uffd-common.c | 4 ++++ tools/testing/selftests/mm/uffd-stress.c | 15 ++++++++++++++- tools/testing/selftests/mm/uffd-unit-tests.c | 14 +++++++++++++- 9 files changed, 60 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/mm/hugepage-mremap.c b/tools/testing/selftests/mm/hugepage-mremap.c index ada9156cc497..c463d1c09c9b 100644 --- a/tools/testing/selftests/mm/hugepage-mremap.c +++ b/tools/testing/selftests/mm/hugepage-mremap.c @@ -15,7 +15,7 @@ #define _GNU_SOURCE #include #include -#include +#include #include #include #include /* Definition of O_* constants */ diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c index 66b4e111b5a2..b61803e36d1c 100644 --- a/tools/testing/selftests/mm/ksm_functional_tests.c +++ b/tools/testing/selftests/mm/ksm_functional_tests.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -369,6 +369,7 @@ unmap: munmap(map, size); } +#ifdef __NR_userfaultfd static void test_unmerge_uffd_wp(void) { struct uffdio_writeprotect uffd_writeprotect; @@ -429,6 +430,7 @@ close_uffd: unmap: munmap(map, size); } +#endif /* Verify that KSM can be enabled / queried with prctl. */ static void test_prctl(void) @@ -684,7 +686,9 @@ int main(int argc, char **argv) exit(test_child_ksm()); } +#ifdef __NR_userfaultfd tests++; +#endif ksft_print_header(); ksft_set_plan(tests); @@ -696,7 +700,9 @@ int main(int argc, char **argv) test_unmerge(); test_unmerge_zero_pages(); test_unmerge_discarded(); +#ifdef __NR_userfaultfd test_unmerge_uffd_wp(); +#endif test_prot_none(); diff --git a/tools/testing/selftests/mm/memfd_secret.c b/tools/testing/selftests/mm/memfd_secret.c index 74c911aa3aea..9a0597310a76 100644 --- a/tools/testing/selftests/mm/memfd_secret.c +++ b/tools/testing/selftests/mm/memfd_secret.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -28,6 +28,8 @@ #define pass(fmt, ...) ksft_test_result_pass(fmt, ##__VA_ARGS__) #define skip(fmt, ...) ksft_test_result_skip(fmt, ##__VA_ARGS__) +#ifdef __NR_memfd_secret + #define PATTERN 0x55 static const int prot = PROT_READ | PROT_WRITE; @@ -332,3 +334,13 @@ int main(int argc, char *argv[]) ksft_finished(); } + +#else /* __NR_memfd_secret */ + +int main(int argc, char *argv[]) +{ + printf("skip: skipping memfd_secret test (missing __NR_memfd_secret)\n"); + return KSFT_SKIP; +} + +#endif /* __NR_memfd_secret */ diff --git a/tools/testing/selftests/mm/mkdirty.c b/tools/testing/selftests/mm/mkdirty.c index af2fce496912..09feeb453646 100644 --- a/tools/testing/selftests/mm/mkdirty.c +++ b/tools/testing/selftests/mm/mkdirty.c @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include #include #include @@ -265,6 +265,7 @@ munmap: munmap(mmap_mem, mmap_size); } +#ifdef __NR_userfaultfd static void test_uffdio_copy(void) { struct uffdio_register uffdio_register; @@ -322,6 +323,7 @@ munmap: munmap(dst, pagesize); free(src); } +#endif /* __NR_userfaultfd */ int main(void) { @@ -334,7 +336,9 @@ int main(void) thpsize / 1024); tests += 3; } +#ifdef __NR_userfaultfd tests += 1; +#endif /* __NR_userfaultfd */ ksft_print_header(); ksft_set_plan(tests); @@ -364,7 +368,9 @@ int main(void) if (thpsize) test_pte_mapped_thp(); /* Placing a fresh page via userfaultfd may set the PTE dirty. */ +#ifdef __NR_userfaultfd test_uffdio_copy(); +#endif /* __NR_userfaultfd */ err = ksft_get_fail_cnt(); if (err) diff --git a/tools/testing/selftests/mm/mlock2.h b/tools/testing/selftests/mm/mlock2.h index 1e5731bab499..4417eaa5cfb7 100644 --- a/tools/testing/selftests/mm/mlock2.h +++ b/tools/testing/selftests/mm/mlock2.h @@ -3,7 +3,6 @@ #include #include #include -#include static int mlock2_(void *start, size_t len, int flags) { diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c index a4683f2476f2..35565af308af 100644 --- a/tools/testing/selftests/mm/protection_keys.c +++ b/tools/testing/selftests/mm/protection_keys.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include diff --git a/tools/testing/selftests/mm/uffd-common.c b/tools/testing/selftests/mm/uffd-common.c index 717539eddf98..7ad6ba660c7d 100644 --- a/tools/testing/selftests/mm/uffd-common.c +++ b/tools/testing/selftests/mm/uffd-common.c @@ -673,7 +673,11 @@ int uffd_open_dev(unsigned int flags) int uffd_open_sys(unsigned int flags) { +#ifdef __NR_userfaultfd return syscall(__NR_userfaultfd, flags); +#else + return -1; +#endif } int uffd_open(unsigned int flags) diff --git a/tools/testing/selftests/mm/uffd-stress.c b/tools/testing/selftests/mm/uffd-stress.c index a4b83280998a..944d559ade21 100644 --- a/tools/testing/selftests/mm/uffd-stress.c +++ b/tools/testing/selftests/mm/uffd-stress.c @@ -33,10 +33,11 @@ * pthread_mutex_lock will also verify the atomicity of the memory * transfer (UFFDIO_COPY). */ -#include + #include "uffd-common.h" uint64_t features; +#ifdef __NR_userfaultfd #define BOUNCE_RANDOM (1<<0) #define BOUNCE_RACINGFAULTS (1<<1) @@ -471,3 +472,15 @@ int main(int argc, char **argv) nr_pages, nr_pages_per_cpu); return userfaultfd_stress(); } + +#else /* __NR_userfaultfd */ + +#warning "missing __NR_userfaultfd definition" + +int main(void) +{ + printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n"); + return KSFT_SKIP; +} + +#endif /* __NR_userfaultfd */ diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c index 9ff71fa1f9bf..74c8bc02b506 100644 --- a/tools/testing/selftests/mm/uffd-unit-tests.c +++ b/tools/testing/selftests/mm/uffd-unit-tests.c @@ -5,11 +5,12 @@ * Copyright (C) 2015-2023 Red Hat, Inc. */ -#include #include "uffd-common.h" #include "../../../../mm/gup_test.h" +#ifdef __NR_userfaultfd + /* The unit test doesn't need a large or random size, make it 32MB for now */ #define UFFD_TEST_MEM_SIZE (32UL << 20) @@ -1558,3 +1559,14 @@ int main(int argc, char *argv[]) return ksft_get_fail_cnt() ? KSFT_FAIL : KSFT_PASS; } +#else /* __NR_userfaultfd */ + +#warning "missing __NR_userfaultfd definition" + +int main(void) +{ + printf("Skipping %s (missing __NR_userfaultfd)\n", __file__); + return KSFT_SKIP; +} + +#endif /* __NR_userfaultfd */ From 349db086a66051bc6114b64b4446787c20ac3f00 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Mon, 17 Feb 2025 10:23:04 -0800 Subject: [PATCH 0674/1090] selftests/damon/damos_quota_goal: handle minimum quota that cannot be further reduced damos_quota_goal.py selftest see if DAMOS quota goals tuning feature increases or reduces the effective size quota for given score as expected. The tuning feature sets the minimum quota size as one byte, so if the effective size quota is already one, we cannot expect it further be reduced. However the test is not aware of the edge case, and fails since it shown no expected change of the effective quota. Handle the case by updating the failure logic for no change to see if it was the case, and simply skips to next test input. Link: https://lkml.kernel.org/r/20250217182304.45215-1-sj@kernel.org Fixes: f1c07c0a1662 ("selftests/damon: add a test for DAMOS quota goal") Signed-off-by: SeongJae Park Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202502171423.b28a918d-lkp@intel.com Cc: Shuah Khan Cc: [6.10.x] Signed-off-by: Andrew Morton --- tools/testing/selftests/damon/damos_quota_goal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/testing/selftests/damon/damos_quota_goal.py b/tools/testing/selftests/damon/damos_quota_goal.py index 18246f3b62f7..f76e0412b564 100755 --- a/tools/testing/selftests/damon/damos_quota_goal.py +++ b/tools/testing/selftests/damon/damos_quota_goal.py @@ -63,6 +63,9 @@ def main(): if last_effective_bytes != 0 else -1.0)) if last_effective_bytes == goal.effective_bytes: + # effective quota was already minimum that cannot be more reduced + if expect_increase is False and last_effective_bytes == 1: + continue print('efective bytes not changed: %d' % goal.effective_bytes) exit(1) From 7277dd0a0ba4f8259f7abe37c4b7280fbfc2a182 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Tue, 18 Feb 2025 00:00:17 +0800 Subject: [PATCH 0675/1090] m68k: sun3: add check for __pgd_alloc() Add check for the return value of __pgd_alloc() in pgd_alloc() to prevent null pointer dereference. Link: https://lkml.kernel.org/r/20250217160017.2375536-1-haoxiang_li2024@163.com Fixes: a9b3c355c2e6 ("asm-generic: pgalloc: provide generic __pgd_{alloc,free}") Signed-off-by: Haoxiang Li Reviewed-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Cc: Dave Hansen Cc: Kevin Brodsky Cc: Qi Zheng Cc: Sam Creasey Cc: Signed-off-by: Andrew Morton --- arch/m68k/include/asm/sun3_pgalloc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h index f1ae4ed890db..80afc3a18724 100644 --- a/arch/m68k/include/asm/sun3_pgalloc.h +++ b/arch/m68k/include/asm/sun3_pgalloc.h @@ -44,8 +44,10 @@ static inline pgd_t * pgd_alloc(struct mm_struct *mm) pgd_t *new_pgd; new_pgd = __pgd_alloc(mm, 0); - memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE); - memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT)); + if (likely(new_pgd != NULL)) { + memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE); + memset(new_pgd, 0, (PAGE_OFFSET >> PGDIR_SHIFT)); + } return new_pgd; } From a564ccfe300fa6a065beda06ab7f3c140d6b4d63 Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Mon, 17 Feb 2025 10:49:24 +0800 Subject: [PATCH 0676/1090] arm: pgtable: fix NULL pointer dereference issue When update_mmu_cache_range() is called by update_mmu_cache(), the vmf parameter is NULL, which will cause a NULL pointer dereference issue in adjust_pte(): Unable to handle kernel NULL pointer dereference at virtual address 00000030 when read Hardware name: Atmel AT91SAM9 PC is at update_mmu_cache_range+0x1e0/0x278 LR is at pte_offset_map_rw_nolock+0x18/0x2c Call trace: update_mmu_cache_range from remove_migration_pte+0x29c/0x2ec remove_migration_pte from rmap_walk_file+0xcc/0x130 rmap_walk_file from remove_migration_ptes+0x90/0xa4 remove_migration_ptes from migrate_pages_batch+0x6d4/0x858 migrate_pages_batch from migrate_pages+0x188/0x488 migrate_pages from compact_zone+0x56c/0x954 compact_zone from compact_node+0x90/0xf0 compact_node from kcompactd+0x1d4/0x204 kcompactd from kthread+0x120/0x12c kthread from ret_from_fork+0x14/0x38 Exception stack(0xc0d8bfb0 to 0xc0d8bff8) To fix it, do not rely on whether 'ptl' is equal to decide whether to hold the pte lock, but decide it by whether CONFIG_SPLIT_PTE_PTLOCKS is enabled. In addition, if two vmas map to the same PTE page, there is no need to hold the pte lock again, otherwise a deadlock will occur. Just add the need_lock parameter to let adjust_pte() know this information. Link: https://lkml.kernel.org/r/20250217024924.57996-1-zhengqi.arch@bytedance.com Fixes: fc9c45b71f43 ("arm: adjust_pte() use pte_offset_map_rw_nolock()") Signed-off-by: Qi Zheng Reported-by: Ezra Buehler Closes: https://lore.kernel.org/lkml/CAM1KZSmZ2T_riHvay+7cKEFxoPgeVpHkVFTzVVEQ1BO0cLkHEQ@mail.gmail.com/ Acked-by: David Hildenbrand Tested-by: Ezra Buehler Cc: Hugh Dickins Cc: Muchun Song Cc: Qi Zheng Cc: Russel King Cc: Ryan Roberts Cc: Signed-off-by: Andrew Morton --- arch/arm/mm/fault-armv.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 2bec87c3327d..39fd5df73317 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -62,7 +62,7 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, } static int adjust_pte(struct vm_area_struct *vma, unsigned long address, - unsigned long pfn, struct vm_fault *vmf) + unsigned long pfn, bool need_lock) { spinlock_t *ptl; pgd_t *pgd; @@ -99,12 +99,11 @@ again: if (!pte) return 0; - /* - * If we are using split PTE locks, then we need to take the page - * lock here. Otherwise we are using shared mm->page_table_lock - * which is already locked, thus cannot take it. - */ - if (ptl != vmf->ptl) { + if (need_lock) { + /* + * Use nested version here to indicate that we are already + * holding one similar spinlock. + */ spin_lock_nested(ptl, SINGLE_DEPTH_NESTING); if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmd)))) { pte_unmap_unlock(pte, ptl); @@ -114,7 +113,7 @@ again: ret = do_adjust_pte(vma, address, pfn, pte); - if (ptl != vmf->ptl) + if (need_lock) spin_unlock(ptl); pte_unmap(pte); @@ -123,9 +122,10 @@ again: static void make_coherent(struct address_space *mapping, struct vm_area_struct *vma, - unsigned long addr, pte_t *ptep, unsigned long pfn, - struct vm_fault *vmf) + unsigned long addr, pte_t *ptep, unsigned long pfn) { + const unsigned long pmd_start_addr = ALIGN_DOWN(addr, PMD_SIZE); + const unsigned long pmd_end_addr = pmd_start_addr + PMD_SIZE; struct mm_struct *mm = vma->vm_mm; struct vm_area_struct *mpnt; unsigned long offset; @@ -141,6 +141,14 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, */ flush_dcache_mmap_lock(mapping); vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) { + /* + * If we are using split PTE locks, then we need to take the pte + * lock. Otherwise we are using shared mm->page_table_lock which + * is already locked, thus cannot take it. + */ + bool need_lock = IS_ENABLED(CONFIG_SPLIT_PTE_PTLOCKS); + unsigned long mpnt_addr; + /* * If this VMA is not in our MM, we can ignore it. * Note that we intentionally mask out the VMA @@ -151,7 +159,12 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, if (!(mpnt->vm_flags & VM_MAYSHARE)) continue; offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; - aliases += adjust_pte(mpnt, mpnt->vm_start + offset, pfn, vmf); + mpnt_addr = mpnt->vm_start + offset; + + /* Avoid deadlocks by not grabbing the same PTE lock again. */ + if (mpnt_addr >= pmd_start_addr && mpnt_addr < pmd_end_addr) + need_lock = false; + aliases += adjust_pte(mpnt, mpnt_addr, pfn, need_lock); } flush_dcache_mmap_unlock(mapping); if (aliases) @@ -194,7 +207,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, __flush_dcache_folio(mapping, folio); if (mapping) { if (cache_is_vivt()) - make_coherent(mapping, vma, addr, ptep, pfn, vmf); + make_coherent(mapping, vma, addr, ptep, pfn); else if (vma->vm_flags & VM_EXEC) __flush_icache_all(); } From b81679b1633aa43c0d973adfa816d78c1ed0d032 Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 17 Feb 2025 09:43:27 +0800 Subject: [PATCH 0677/1090] mm: memory-failure: update ttu flag inside unmap_poisoned_folio Patch series "mm: memory_failure: unmap poisoned folio during migrate properly", v3. Fix two bugs during folio migration if the folio is poisoned. This patch (of 3): Commit 6da6b1d4a7df ("mm/hwpoison: convert TTU_IGNORE_HWPOISON to TTU_HWPOISON") introduce TTU_HWPOISON to replace TTU_IGNORE_HWPOISON in order to stop send SIGBUS signal when accessing an error page after a memory error on a clean folio. However during page migration, anon folio must be set with TTU_HWPOISON during unmap_*(). For pagecache we need some policy just like the one in hwpoison_user_mappings to set this flag. So move this policy from hwpoison_user_mappings to unmap_poisoned_folio to handle this warning properly. Warning will be produced during unamp poison folio with the following log: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 365 at mm/rmap.c:1847 try_to_unmap_one+0x8fc/0xd3c Modules linked in: CPU: 1 UID: 0 PID: 365 Comm: bash Tainted: G W 6.13.0-rc1-00018-gacdb4bbda7ab #42 Tainted: [W]=WARN Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : try_to_unmap_one+0x8fc/0xd3c lr : try_to_unmap_one+0x3dc/0xd3c Call trace: try_to_unmap_one+0x8fc/0xd3c (P) try_to_unmap_one+0x3dc/0xd3c (L) rmap_walk_anon+0xdc/0x1f8 rmap_walk+0x3c/0x58 try_to_unmap+0x88/0x90 unmap_poisoned_folio+0x30/0xa8 do_migrate_range+0x4a0/0x568 offline_pages+0x5a4/0x670 memory_block_action+0x17c/0x374 memory_subsys_offline+0x3c/0x78 device_offline+0xa4/0xd0 state_store+0x8c/0xf0 dev_attr_store+0x18/0x2c sysfs_kf_write+0x44/0x54 kernfs_fop_write_iter+0x118/0x1a8 vfs_write+0x3a8/0x4bc ksys_write+0x6c/0xf8 __arm64_sys_write+0x1c/0x28 invoke_syscall+0x44/0x100 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x30/0xd0 el0t_64_sync_handler+0xc8/0xcc el0t_64_sync+0x198/0x19c ---[ end trace 0000000000000000 ]--- [mawupeng1@huawei.com: unmap_poisoned_folio(): remove shadowed local `mapping', per Miaohe] Link: https://lkml.kernel.org/r/20250219060653.3849083-1-mawupeng1@huawei.com Link: https://lkml.kernel.org/r/20250217014329.3610326-1-mawupeng1@huawei.com Link: https://lkml.kernel.org/r/20250217014329.3610326-2-mawupeng1@huawei.com Fixes: 6da6b1d4a7df ("mm/hwpoison: convert TTU_IGNORE_HWPOISON to TTU_HWPOISON") Signed-off-by: Ma Wupeng Suggested-by: David Hildenbrand Acked-by: David Hildenbrand Acked-by: Miaohe Lin Cc: Ma Wupeng Cc: Michal Hocko Cc: Naoya Horiguchi Cc: Oscar Salvador Cc: Signed-off-by: Andrew Morton --- mm/internal.h | 5 ++-- mm/memory-failure.c | 63 ++++++++++++++++++++++----------------------- mm/memory_hotplug.c | 3 ++- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index 109ef30fee11..20b3535935a3 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1115,7 +1115,7 @@ static inline int find_next_best_node(int node, nodemask_t *used_node_mask) * mm/memory-failure.c */ #ifdef CONFIG_MEMORY_FAILURE -void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu); +int unmap_poisoned_folio(struct folio *folio, unsigned long pfn, bool must_kill); void shake_folio(struct folio *folio); extern int hwpoison_filter(struct page *p); @@ -1138,8 +1138,9 @@ unsigned long page_mapped_in_vma(const struct page *page, struct vm_area_struct *vma); #else -static inline void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu) +static inline int unmap_poisoned_folio(struct folio *folio, unsigned long pfn, bool must_kill) { + return -EBUSY; } #endif diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 995a15eb67e2..327e02fdc029 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1556,11 +1556,35 @@ static int get_hwpoison_page(struct page *p, unsigned long flags) return ret; } -void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu) +int unmap_poisoned_folio(struct folio *folio, unsigned long pfn, bool must_kill) { - if (folio_test_hugetlb(folio) && !folio_test_anon(folio)) { - struct address_space *mapping; + enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_HWPOISON; + struct address_space *mapping; + if (folio_test_swapcache(folio)) { + pr_err("%#lx: keeping poisoned page in swap cache\n", pfn); + ttu &= ~TTU_HWPOISON; + } + + /* + * Propagate the dirty bit from PTEs to struct page first, because we + * need this to decide if we should kill or just drop the page. + * XXX: the dirty test could be racy: set_page_dirty() may not always + * be called inside page lock (it's recommended but not enforced). + */ + mapping = folio_mapping(folio); + if (!must_kill && !folio_test_dirty(folio) && mapping && + mapping_can_writeback(mapping)) { + if (folio_mkclean(folio)) { + folio_set_dirty(folio); + } else { + ttu &= ~TTU_HWPOISON; + pr_info("%#lx: corrupted page was clean: dropped without side effects\n", + pfn); + } + } + + if (folio_test_hugetlb(folio) && !folio_test_anon(folio)) { /* * For hugetlb folios in shared mappings, try_to_unmap * could potentially call huge_pmd_unshare. Because of @@ -1572,7 +1596,7 @@ void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu) if (!mapping) { pr_info("%#lx: could not lock mapping for mapped hugetlb folio\n", folio_pfn(folio)); - return; + return -EBUSY; } try_to_unmap(folio, ttu|TTU_RMAP_LOCKED); @@ -1580,6 +1604,8 @@ void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu) } else { try_to_unmap(folio, ttu); } + + return folio_mapped(folio) ? -EBUSY : 0; } /* @@ -1589,8 +1615,6 @@ void unmap_poisoned_folio(struct folio *folio, enum ttu_flags ttu) static bool hwpoison_user_mappings(struct folio *folio, struct page *p, unsigned long pfn, int flags) { - enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_HWPOISON; - struct address_space *mapping; LIST_HEAD(tokill); bool unmap_success; int forcekill; @@ -1613,29 +1637,6 @@ static bool hwpoison_user_mappings(struct folio *folio, struct page *p, if (!folio_mapped(folio)) return true; - if (folio_test_swapcache(folio)) { - pr_err("%#lx: keeping poisoned page in swap cache\n", pfn); - ttu &= ~TTU_HWPOISON; - } - - /* - * Propagate the dirty bit from PTEs to struct page first, because we - * need this to decide if we should kill or just drop the page. - * XXX: the dirty test could be racy: set_page_dirty() may not always - * be called inside page lock (it's recommended but not enforced). - */ - mapping = folio_mapping(folio); - if (!(flags & MF_MUST_KILL) && !folio_test_dirty(folio) && mapping && - mapping_can_writeback(mapping)) { - if (folio_mkclean(folio)) { - folio_set_dirty(folio); - } else { - ttu &= ~TTU_HWPOISON; - pr_info("%#lx: corrupted page was clean: dropped without side effects\n", - pfn); - } - } - /* * First collect all the processes that have the page * mapped in dirty form. This has to be done before try_to_unmap, @@ -1643,9 +1644,7 @@ static bool hwpoison_user_mappings(struct folio *folio, struct page *p, */ collect_procs(folio, p, &tokill, flags & MF_ACTION_REQUIRED); - unmap_poisoned_folio(folio, ttu); - - unmap_success = !folio_mapped(folio); + unmap_success = !unmap_poisoned_folio(folio, pfn, flags & MF_MUST_KILL); if (!unmap_success) pr_err("%#lx: failed to unmap page (folio mapcount=%d)\n", pfn, folio_mapcount(folio)); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index e3655f07dd6e..e7e47838fd49 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1833,7 +1833,8 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) if (WARN_ON(folio_test_lru(folio))) folio_isolate_lru(folio); if (folio_mapped(folio)) - unmap_poisoned_folio(folio, TTU_IGNORE_MLOCK); + unmap_poisoned_folio(folio, pfn, false); + continue; } From 773b9a6aa6d38894b95088e3ed6f8a701d9f50fd Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 17 Feb 2025 09:43:28 +0800 Subject: [PATCH 0678/1090] mm: memory-hotplug: check folio ref count first in do_migrate_range If a folio has an increased reference count, folio_try_get() will acquire it, perform necessary operations, and then release it. In the case of a poisoned folio without an elevated reference count (which is unlikely for memory-failure), folio_try_get() will simply bypass it. Therefore, relocate the folio_try_get() function, responsible for checking and acquiring this reference count at first. Link: https://lkml.kernel.org/r/20250217014329.3610326-3-mawupeng1@huawei.com Signed-off-by: Ma Wupeng Acked-by: David Hildenbrand Acked-by: Miaohe Lin Cc: Michal Hocko Cc: Naoya Horiguchi Cc: Oscar Salvador Cc: Signed-off-by: Andrew Morton --- mm/memory_hotplug.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index e7e47838fd49..a6abd8d4a09c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1822,12 +1822,12 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) if (folio_test_large(folio)) pfn = folio_pfn(folio) + folio_nr_pages(folio) - 1; - /* - * HWPoison pages have elevated reference counts so the migration would - * fail on them. It also doesn't make any sense to migrate them in the - * first place. Still try to unmap such a page in case it is still mapped - * (keep the unmap as the catch all safety net). - */ + if (!folio_try_get(folio)) + continue; + + if (unlikely(page_folio(page) != folio)) + goto put_folio; + if (folio_test_hwpoison(folio) || (folio_test_large(folio) && folio_test_has_hwpoisoned(folio))) { if (WARN_ON(folio_test_lru(folio))) @@ -1835,14 +1835,8 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) if (folio_mapped(folio)) unmap_poisoned_folio(folio, pfn, false); - continue; - } - - if (!folio_try_get(folio)) - continue; - - if (unlikely(page_folio(page) != folio)) goto put_folio; + } if (!isolate_folio_to_list(folio, &source)) { if (__ratelimit(&migrate_rs)) { From af288a426c3e3552b62595c6138ec6371a17dbba Mon Sep 17 00:00:00 2001 From: Ma Wupeng Date: Mon, 17 Feb 2025 09:43:29 +0800 Subject: [PATCH 0679/1090] hwpoison, memory_hotplug: lock folio before unmap hwpoisoned folio Commit b15c87263a69 ("hwpoison, memory_hotplug: allow hwpoisoned pages to be offlined) add page poison checks in do_migrate_range in order to make offline hwpoisoned page possible by introducing isolate_lru_page and try_to_unmap for hwpoisoned page. However folio lock must be held before calling try_to_unmap. Add it to fix this problem. Warning will be produced if folio is not locked during unmap: ------------[ cut here ]------------ kernel BUG at ./include/linux/swapops.h:400! Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP Modules linked in: CPU: 4 UID: 0 PID: 411 Comm: bash Tainted: G W 6.13.0-rc1-00016-g3c434c7ee82a-dirty #41 Tainted: [W]=WARN Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 pstate: 40400005 (nZcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : try_to_unmap_one+0xb08/0xd3c lr : try_to_unmap_one+0x3dc/0xd3c Call trace: try_to_unmap_one+0xb08/0xd3c (P) try_to_unmap_one+0x3dc/0xd3c (L) rmap_walk_anon+0xdc/0x1f8 rmap_walk+0x3c/0x58 try_to_unmap+0x88/0x90 unmap_poisoned_folio+0x30/0xa8 do_migrate_range+0x4a0/0x568 offline_pages+0x5a4/0x670 memory_block_action+0x17c/0x374 memory_subsys_offline+0x3c/0x78 device_offline+0xa4/0xd0 state_store+0x8c/0xf0 dev_attr_store+0x18/0x2c sysfs_kf_write+0x44/0x54 kernfs_fop_write_iter+0x118/0x1a8 vfs_write+0x3a8/0x4bc ksys_write+0x6c/0xf8 __arm64_sys_write+0x1c/0x28 invoke_syscall+0x44/0x100 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x30/0xd0 el0t_64_sync_handler+0xc8/0xcc el0t_64_sync+0x198/0x19c Code: f9407be0 b5fff320 d4210000 17ffff97 (d4210000) ---[ end trace 0000000000000000 ]--- Link: https://lkml.kernel.org/r/20250217014329.3610326-4-mawupeng1@huawei.com Fixes: b15c87263a69 ("hwpoison, memory_hotplug: allow hwpoisoned pages to be offlined") Signed-off-by: Ma Wupeng Acked-by: David Hildenbrand Acked-by: Miaohe Lin Cc: Michal Hocko Cc: Naoya Horiguchi Cc: Oscar Salvador Cc: Signed-off-by: Andrew Morton --- mm/memory_hotplug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a6abd8d4a09c..16cf9e17077e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1832,8 +1832,11 @@ static void do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) (folio_test_large(folio) && folio_test_has_hwpoisoned(folio))) { if (WARN_ON(folio_test_lru(folio))) folio_isolate_lru(folio); - if (folio_mapped(folio)) + if (folio_mapped(folio)) { + folio_lock(folio); unmap_poisoned_folio(folio, pfn, false); + folio_unlock(folio); + } goto put_folio; } From 04ec365e3fdf136ba5f9053b02fb6c3368a22e83 Mon Sep 17 00:00:00 2001 From: Ujwal Kundur Date: Sat, 15 Feb 2025 16:21:07 +0530 Subject: [PATCH 0680/1090] Documentation: fix doc link to fault-injection.rst Fix incorrect reference to fault-injection docs Link: https://lkml.kernel.org/r/20250215105106.734-1-ujwal.kundur@gmail.com Signed-off-by: Ujwal Kundur Signed-off-by: Andrew Morton --- lib/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1af972a92d06..35796c290ca3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2103,7 +2103,7 @@ config FAIL_SKB_REALLOC reallocated, catching possible invalid pointers to the skb. For more information, check - Documentation/dev-tools/fault-injection/fault-injection.rst + Documentation/fault-injection/fault-injection.rst config FAULT_INJECTION_CONFIGFS bool "Configfs interface for fault-injection capabilities" From 19fac3c93991502a22c5132824c40b6a2e64b136 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 18 Feb 2025 10:14:11 +0100 Subject: [PATCH 0681/1090] dma: kmsan: export kmsan_handle_dma() for modules kmsan_handle_dma() is used by virtio_ring() which can be built as a module. kmsan_handle_dma() needs to be exported otherwise building the virtio_ring fails. Export kmsan_handle_dma for modules. Link: https://lkml.kernel.org/r/20250218091411.MMS3wBN9@linutronix.de Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502150634.qjxwSeJR-lkp@intel.com/ Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings") Signed-off-by: Sebastian Andrzej Siewior Cc: Alexander Potapenko Cc: Dmitriy Vyukov Cc: Macro Elver Cc: Peter Zijlstra (Intel) Cc: Thomas Gleixner Cc: Signed-off-by: Andrew Morton --- mm/kmsan/hooks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/kmsan/hooks.c b/mm/kmsan/hooks.c index 3ea50f09311f..3df45c25c1f6 100644 --- a/mm/kmsan/hooks.c +++ b/mm/kmsan/hooks.c @@ -357,6 +357,7 @@ void kmsan_handle_dma(struct page *page, size_t offset, size_t size, size -= to_go; } } +EXPORT_SYMBOL_GPL(kmsan_handle_dma); void kmsan_handle_dma_sg(struct scatterlist *sg, int nents, enum dma_data_direction dir) From c3e998398de48a7528842f05858a3a6bb21002e6 Mon Sep 17 00:00:00 2001 From: gao xu Date: Wed, 19 Feb 2025 01:56:28 +0000 Subject: [PATCH 0682/1090] mm: fix possible NULL pointer dereference in __swap_duplicate Add a NULL check on the return value of swp_swap_info in __swap_duplicate to prevent crashes caused by NULL pointer dereference. The reason why swp_swap_info() returns NULL is unclear; it may be due to CPU cache issues or DDR bit flips. The probability of this issue is very small - it has been observed to occur approximately 1 in 500,000 times per week. The stack info we encountered is as follows: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000058 [RB/E]rb_sreason_str_set: sreason_str set null_pointer Mem abort info: ESR = 0x0000000096000005 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x05: level 1 translation fault Data abort info: ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 user pgtable: 4k pages, 39-bit VAs, pgdp=00000008a80e5000 [0000000000000058] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP Skip md ftrace buffer dump for: 0x1609e0 ... pc : swap_duplicate+0x44/0x164 lr : copy_page_range+0x508/0x1e78 sp : ffffffc0f2a699e0 x29: ffffffc0f2a699e0 x28: ffffff8a5b28d388 x27: ffffff8b06603388 x26: ffffffdf7291fe70 x25: 0000000000000006 x24: 0000000000100073 x23: 00000000002d2d2f x22: 0000000000000008 x21: 0000000000000000 x20: 00000000002d2d2f x19: 18000000002d2d2f x18: ffffffdf726faec0 x17: 0000000000000000 x16: 0010000000000001 x15: 0040000000000001 x14: 0400000000000001 x13: ff7ffffffffffb7f x12: ffeffffffffffbff x11: ffffff8a5c7e1898 x10: 0000000000000018 x9 : 0000000000000006 x8 : 1800000000000000 x7 : 0000000000000000 x6 : ffffff8057c01f10 x5 : 000000000000a318 x4 : 0000000000000000 x3 : 0000000000000000 x2 : 0000006daf200000 x1 : 0000000000000001 x0 : 18000000002d2d2f Call trace: swap_duplicate+0x44/0x164 copy_page_range+0x508/0x1e78 copy_process+0x1278/0x21cc kernel_clone+0x90/0x438 __arm64_sys_clone+0x5c/0x8c invoke_syscall+0x58/0x110 do_el0_svc+0x8c/0xe0 el0_svc+0x38/0x9c el0t_64_sync_handler+0x44/0xec el0t_64_sync+0x1a8/0x1ac Code: 9139c35a 71006f3f 54000568 f8797b55 (f9402ea8) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Oops: Fatal exception SMP: stopping secondary CPUs The patch seems to only provide a workaround, but there are no more effective software solutions to handle the bit flips problem. This path will change the issue from a system crash to a process exception, thereby reducing the impact on the entire machine. akpm: this is probably a kernel bug, but this patch keeps the system running and doesn't reduce that bug's debuggability. Link: https://lkml.kernel.org/r/e223b0e6ba2f4924984b1917cc717bd5@honor.com Signed-off-by: gao xu Reviewed-by: Barry Song Cc: Suren Baghdasaryan Cc: Yosry Ahmed Signed-off-by: Andrew Morton --- mm/swapfile.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/swapfile.c b/mm/swapfile.c index ba19430dd4ea..fab99d67026a 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3542,6 +3542,10 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr) int err, i; si = swp_swap_info(entry); + if (WARN_ON_ONCE(!si)) { + pr_err("%s%08lx\n", Bad_file, entry.val); + return -EINVAL; + } offset = swp_offset(entry); VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER); From 67bab13307c83fb742c2556b06cdc39dbad27f07 Mon Sep 17 00:00:00 2001 From: Ge Yang Date: Wed, 19 Feb 2025 11:46:44 +0800 Subject: [PATCH 0683/1090] mm/hugetlb: wait for hugetlb folios to be freed Since the introduction of commit c77c0a8ac4c52 ("mm/hugetlb: defer freeing of huge pages if in non-task context"), which supports deferring the freeing of hugetlb pages, the allocation of contiguous memory through cma_alloc() may fail probabilistically. In the CMA allocation process, if it is found that the CMA area is occupied by in-use hugetlb folios, these in-use hugetlb folios need to be migrated to another location. When there are no available hugetlb folios in the free hugetlb pool during the migration of in-use hugetlb folios, new folios are allocated from the buddy system. A temporary state is set on the newly allocated folio. Upon completion of the hugetlb folio migration, the temporary state is transferred from the new folios to the old folios. Normally, when the old folios with the temporary state are freed, it is directly released back to the buddy system. However, due to the deferred freeing of hugetlb pages, the PageBuddy() check fails, ultimately leading to the failure of cma_alloc(). Here is a simplified call trace illustrating the process: cma_alloc() ->__alloc_contig_migrate_range() // Migrate in-use hugetlb folios ->unmap_and_move_huge_page() ->folio_putback_hugetlb() // Free old folios ->test_pages_isolated() ->__test_page_isolated_in_pageblock() ->PageBuddy(page) // Check if the page is in buddy To resolve this issue, we have implemented a function named wait_for_freed_hugetlb_folios(). This function ensures that the hugetlb folios are properly released back to the buddy system after their migration is completed. By invoking wait_for_freed_hugetlb_folios() before calling PageBuddy(), we ensure that PageBuddy() will succeed. Link: https://lkml.kernel.org/r/1739936804-18199-1-git-send-email-yangge1116@126.com Fixes: c77c0a8ac4c5 ("mm/hugetlb: defer freeing of huge pages if in non-task context") Signed-off-by: Ge Yang Reviewed-by: Muchun Song Acked-by: David Hildenbrand Cc: Baolin Wang Cc: Barry Song <21cnbao@gmail.com> Cc: Oscar Salvador Cc: Signed-off-by: Andrew Morton --- include/linux/hugetlb.h | 5 +++++ mm/hugetlb.c | 8 ++++++++ mm/page_isolation.c | 10 ++++++++++ 3 files changed, 23 insertions(+) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index ec8c0ccc8f95..dbe76d4f1bfc 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -682,6 +682,7 @@ struct huge_bootmem_page { int isolate_or_dissolve_huge_page(struct page *page, struct list_head *list); int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn); +void wait_for_freed_hugetlb_folios(void); struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, unsigned long addr, bool cow_from_owner); struct folio *alloc_hugetlb_folio_nodemask(struct hstate *h, int preferred_nid, @@ -1066,6 +1067,10 @@ static inline int replace_free_hugepage_folios(unsigned long start_pfn, return 0; } +static inline void wait_for_freed_hugetlb_folios(void) +{ +} + static inline struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, unsigned long addr, bool cow_from_owner) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 163190e89ea1..811b29f77abf 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2943,6 +2943,14 @@ int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn) return ret; } +void wait_for_freed_hugetlb_folios(void) +{ + if (llist_empty(&hpage_freelist)) + return; + + flush_work(&free_hpage_work); +} + typedef enum { /* * For either 0/1: we checked the per-vma resv map, and one resv diff --git a/mm/page_isolation.c b/mm/page_isolation.c index c608e9d72865..a051a29e95ad 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -607,6 +607,16 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn, struct zone *zone; int ret; + /* + * Due to the deferred freeing of hugetlb folios, the hugepage folios may + * not immediately release to the buddy system. This can cause PageBuddy() + * to fail in __test_page_isolated_in_pageblock(). To ensure that the + * hugetlb folios are properly released back to the buddy system, we + * invoke the wait_for_freed_hugetlb_folios() function to wait for the + * release to complete. + */ + wait_for_freed_hugetlb_folios(); + /* * Note: pageblock_nr_pages != MAX_PAGE_ORDER. Then, chunks of free * pages are not aligned to pageblock_nr_pages. From 47b16d0462a460000b8f05dfb1292377ac48f3ca Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Sat, 22 Feb 2025 16:19:52 +0000 Subject: [PATCH 0684/1090] mm: abort vma_modify() on merge out of memory failure The remainder of vma_modify() relies upon the vmg state remaining pristine after a merge attempt. Usually this is the case, however in the one edge case scenario of a merge attempt failing not due to the specified range being unmergeable, but rather due to an out of memory error arising when attempting to commit the merge, this assumption becomes untrue. This results in vmg->start, end being modified, and thus the proceeding attempts to split the VMA will be done with invalid start/end values. Thankfully, it is likely practically impossible for us to hit this in reality, as it would require a maple tree node pre-allocation failure that would likely never happen due to it being 'too small to fail', i.e. the kernel would simply keep retrying reclaim until it succeeded. However, this scenario remains theoretically possible, and what we are doing here is wrong so we must correct it. The safest option is, when this scenario occurs, to simply give up the operation. If we cannot allocate memory to merge, then we cannot allocate memory to split either (perhaps moreso!). Any scenario where this would be happening would be under very extreme (likely fatal) memory pressure, so it's best we give up early. So there is no doubt it is appropriate to simply bail out in this scenario. However, in general we must if at all possible never assume VMG state is stable after a merge attempt, since merge operations update VMG fields. As a result, additionally also make this clear by storing start, end in local variables. The issue was reported originally by syzkaller, and by Brad Spengler (via an off-list discussion), and in both instances it manifested as a triggering of the assert: VM_WARN_ON_VMG(start >= end, vmg); In vma_merge_existing_range(). It seems at least one scenario in which this is occurring is one in which the merge being attempted is due to an madvise() across multiple VMAs which looks like this: start end |<------>| |----------|------| | vma | next | |----------|------| When madvise_walk_vmas() is invoked, we first find vma in the above (determining prev to be equal to vma as we are offset into vma), and then enter the loop. We determine the end of vma that forms part of the range we are madvise()'ing by setting 'tmp' to this value: /* Here vma->vm_start <= start < (end|vma->vm_end) */ tmp = vma->vm_end; We then invoke the madvise() operation via visit(), letting prev get updated to point to vma as part of the operation: /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */ error = visit(vma, &prev, start, tmp, arg); Where the visit() function pointer in this instance is madvise_vma_behavior(). As observed in syzkaller reports, it is ultimately madvise_update_vma() that is invoked, calling vma_modify_flags_name() and vma_modify() in turn. Then, in vma_modify(), we attempt the merge: merged = vma_merge_existing_range(vmg); if (merged) return merged; We invoke this with vmg->start, end set to start, tmp as such: start tmp |<--->| |----------|------| | vma | next | |----------|------| We find ourselves in the merge right scenario, but the one in which we cannot remove the middle (we are offset into vma). Here we have a special case where vmg->start, end get set to perhaps unintuitive values - we intended to shrink the middle VMA and expand the next. This means vmg->start, end are set to... vma->vm_start, start. Now the commit_merge() fails, and vmg->start, end are left like this. This means we return to the rest of vma_modify() with vmg->start, end (here denoted as start', end') set as: start' end' |<-->| |----------|------| | vma | next | |----------|------| So we now erroneously try to split accordingly. This is where the unfortunate stuff begins. We start with: /* Split any preceding portion of the VMA. */ if (vma->vm_start < vmg->start) { ... } This doesn't trigger as we are no longer offset into vma at the start. But then we invoke: /* Split any trailing portion of the VMA. */ if (vma->vm_end > vmg->end) { ... } Which does get invoked. This leaves us with: start' end' |<-->| |----|-----|------| | vma| new | next | |----|-----|------| We then return ultimately to madvise_walk_vmas(). Here 'new' is unknown, and putting back the values known in this function we are faced with: start tmp end | | | |----|-----|------| | vma| new | next | |----|-----|------| prev Then: start = tmp; So: start end | | |----|-----|------| | vma| new | next | |----|-----|------| prev The following code does not cause anything to happen: if (prev && start < prev->vm_end) start = prev->vm_end; if (start >= end) break; And then we invoke: if (prev) vma = find_vma(mm, prev->vm_end); Which is where a problem occurs - we don't know about 'new' so we essentially look for the vma after prev, which is new, whereas we actually intended to discover next! So we end up with: start end | | |----|-----|------| |prev| vma | next | |----|-----|------| And we have successfully bypassed all of the checks madvise_walk_vmas() has to ensure early exit should we end up moving out of range. We loop around, and hit: /* Here vma->vm_start <= start < (end|vma->vm_end) */ tmp = vma->vm_end; Oh dear. Now we have: tmp start end | | |----|-----|------| |prev| vma | next | |----|-----|------| We then invoke: /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */ error = visit(vma, &prev, start, tmp, arg); Where start == tmp. That is, a zero range. This is not good. We invoke visit() which is madvise_vma_behavior() which does not check the range (for good reason, it assumes all checks have been done before it was called), which in turn finally calls madvise_update_vma(). The madvise_update_vma() function calls vma_modify_flags_name() in turn, which ultimately invokes vma_modify() with... start == end. vma_modify() calls vma_merge_existing_range() and finally we hit: VM_WARN_ON_VMG(start >= end, vmg); Which triggers, as start == end. While it might be useful to add some CONFIG_DEBUG_VM asserts in these instances to catch this kind of error, since we have just eliminated any possibility of that happening, we will add such asserts separately as to reduce churn and aid backporting. Link: https://lkml.kernel.org/r/20250222161952.41957-1-lorenzo.stoakes@oracle.com Fixes: 2f1c6611b0a8 ("mm: introduce vma_merge_struct and abstract vma_merge(),vma_modify()") Signed-off-by: Lorenzo Stoakes Tested-by: Brad Spengler Reported-by: Brad Spengler Reported-by: syzbot+46423ed8fa1f1148c6e4@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-mm/6774c98f.050a0220.25abdd.0991.GAE@google.com/ Cc: Jann Horn Cc: Liam Howlett Cc: Vlastimil Babka Cc: Signed-off-by: Andrew Morton --- mm/vma.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mm/vma.c b/mm/vma.c index af1d549b179c..96bcb372c90e 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -1509,24 +1509,28 @@ int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm, static struct vm_area_struct *vma_modify(struct vma_merge_struct *vmg) { struct vm_area_struct *vma = vmg->vma; + unsigned long start = vmg->start; + unsigned long end = vmg->end; struct vm_area_struct *merged; /* First, try to merge. */ merged = vma_merge_existing_range(vmg); if (merged) return merged; + if (vmg_nomem(vmg)) + return ERR_PTR(-ENOMEM); /* Split any preceding portion of the VMA. */ - if (vma->vm_start < vmg->start) { - int err = split_vma(vmg->vmi, vma, vmg->start, 1); + if (vma->vm_start < start) { + int err = split_vma(vmg->vmi, vma, start, 1); if (err) return ERR_PTR(err); } /* Split any trailing portion of the VMA. */ - if (vma->vm_end > vmg->end) { - int err = split_vma(vmg->vmi, vma, vmg->end, 0); + if (vma->vm_end > end) { + int err = split_vma(vmg->vmi, vma, end, 0); if (err) return ERR_PTR(err); From 51f271c1940fc9a5f77931ec603b457ea293bd56 Mon Sep 17 00:00:00 2001 From: Kemeng Shi Date: Mon, 24 Feb 2025 19:39:10 +0800 Subject: [PATCH 0685/1090] mm: swap: add back full cluster when no entry is reclaimed If no swap cache is reclaimed, cluster taken off from full_clusters list will not be put in any list and we can't reclaime HAS_CACHE slots efficiently. Do relocate_cluster for such cluster to avoid inefficiency. Link: https://lkml.kernel.org/r/20250224113910.522439-1-shikemeng@huaweicloud.com Fixes: 3b644773eefd ("mm, swap: reduce contention on device lock") Signed-off-by: Kemeng Shi Reviewed-by: Kairui Song Signed-off-by: Andrew Morton --- mm/swapfile.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/swapfile.c b/mm/swapfile.c index fab99d67026a..a6c41c7ffb03 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -858,6 +858,10 @@ static void swap_reclaim_full_clusters(struct swap_info_struct *si, bool force) offset++; } + /* in case no swap cache is reclaimed */ + if (ci->flags == CLUSTER_FLAG_NONE) + relocate_cluster(si, ci); + unlock_cluster(ci); if (to_scan <= 0) break; From 7a2e7ae5d13658ada38898e5a3a8a40a7910db06 Mon Sep 17 00:00:00 2001 From: Kemeng Shi Date: Sun, 23 Feb 2025 00:08:46 +0800 Subject: [PATCH 0686/1090] mm: swap: use correct step in loop to wait all clusters in wait_for_allocation() Use correct step in loop to wait all clusters in wait_for_allocation(). If we miss some cluster in wait_for_allocation(), use after free may occur as follows: shmem_writepage swapoff folio_alloc_swap get_swap_pages scan_swap_map_slots cluster_alloc_swap_entry alloc_swap_scan_cluster cluster_alloc_range /* SWP_WRITEOK is valid */ if (!(si->flags & SWP_WRITEOK)) ... del_from_avail_list(p, true); ... /* miss the cluster in shmem_writepage */ wait_for_allocation() ... try_to_unuse() memset(si->swap_map + start, usage, nr_pages); swap_range_alloc(si, nr_pages); ci->count += nr_pages; /* return a valid entry */ ... exit_swap_address_space(p->type); ... ... add_to_swap_cache /* dereference swap_address_space(entry) which is NULL */ xas_lock_irq(&xas); Link: https://lkml.kernel.org/r/20250222160850.505274-3-shikemeng@huaweicloud.com Fixes: 9a0ddeb79880 ("mm, swap: hold a reference during scan and cleanup flag usage") Signed-off-by: Kemeng Shi Reviewed-by: Kairui Song Signed-off-by: Andrew Morton --- mm/swapfile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index a6c41c7ffb03..6460b6cb36c9 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2645,7 +2645,6 @@ static void wait_for_allocation(struct swap_info_struct *si) for (offset = 0; offset < end; offset += SWAPFILE_CLUSTER) { ci = lock_cluster(si, offset); unlock_cluster(ci); - offset += SWAPFILE_CLUSTER; } } From 57d910cffaa0be981f558ff603e2d896b36b8241 Mon Sep 17 00:00:00 2001 From: Kemeng Shi Date: Sun, 23 Feb 2025 00:08:47 +0800 Subject: [PATCH 0687/1090] mm, swap: avoid BUG_ON in relocate_cluster() If allocation is racy with swapoff, we may call free_cluster for cluster already in free list and trigger BUG_ON() as following: Allocation Swapoff cluster_alloc_swap_entry ... /* may get a free cluster with offset */ offset = xxx; if (offset) ci = lock_cluster(si, offset); ... del_from_avail_list(p, true); si->flags &= ~SWP_WRITEOK; alloc_swap_scan_cluster(si, ci, ...) ... /* failed to alloc entry from free entry */ if (!cluster_alloc_range(...)) break; ... /* add back a free cluster */ relocate_cluster(si, ci); if (!ci->count) free_cluster(si, ci); VM_BUG_ON(ci->flags == CLUSTER_FLAG_FREE); To prevent the BUG_ON(), call free_cluster() for free cluster to move the cluster to tail of list. Check cluster is not free before calling free_cluster() in relocate_cluster() to avoid BUG_ON(). Link: https://lkml.kernel.org/r/20250222160850.505274-4-shikemeng@huaweicloud.com Fixes: 3b644773eefd ("mm, swap: reduce contention on device lock") Signed-off-by: Kemeng Shi Reviewed-by: Kairui Song Signed-off-by: Andrew Morton --- mm/swapfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 6460b6cb36c9..df7c4e8b089c 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -653,7 +653,8 @@ static void relocate_cluster(struct swap_info_struct *si, return; if (!ci->count) { - free_cluster(si, ci); + if (ci->flags != CLUSTER_FLAG_FREE) + free_cluster(si, ci); } else if (ci->count != SWAPFILE_CLUSTER) { if (ci->flags != CLUSTER_FLAG_FRAG) move_cluster(si, ci, &si->frag_clusters[ci->order], From ce6d9c1c2b5cc785016faa11b48b6cd317eb367e Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Mon, 24 Feb 2025 21:20:02 -0500 Subject: [PATCH 0688/1090] NFS: fix nfs_release_folio() to not deadlock via kcompactd writeback Add PF_KCOMPACTD flag and current_is_kcompactd() helper to check for it so nfs_release_folio() can skip calling nfs_wb_folio() from kcompactd. Otherwise NFS can deadlock waiting for kcompactd enduced writeback which recurses back to NFS (which triggers writeback to NFSD via NFS loopback mount on the same host, NFSD blocks waiting for XFS's call to __filemap_get_folio): 6070.550357] INFO: task kcompactd0:58 blocked for more than 4435 seconds. {--- [58] "kcompactd0" [<0>] folio_wait_bit+0xe8/0x200 [<0>] folio_wait_writeback+0x2b/0x80 [<0>] nfs_wb_folio+0x80/0x1b0 [nfs] [<0>] nfs_release_folio+0x68/0x130 [nfs] [<0>] split_huge_page_to_list_to_order+0x362/0x840 [<0>] migrate_pages_batch+0x43d/0xb90 [<0>] migrate_pages_sync+0x9a/0x240 [<0>] migrate_pages+0x93c/0x9f0 [<0>] compact_zone+0x8e2/0x1030 [<0>] compact_node+0xdb/0x120 [<0>] kcompactd+0x121/0x2e0 [<0>] kthread+0xcf/0x100 [<0>] ret_from_fork+0x31/0x40 [<0>] ret_from_fork_asm+0x1a/0x30 ---} [akpm@linux-foundation.org: fix build] Link: https://lkml.kernel.org/r/20250225022002.26141-1-snitzer@kernel.org Fixes: 96780ca55e3c ("NFS: fix up nfs_release_folio() to try to release the page") Signed-off-by: Mike Snitzer Cc: Anna Schumaker Cc: Trond Myklebust Cc: Signed-off-by: Andrew Morton --- fs/nfs/file.c | 3 ++- include/linux/compaction.h | 5 +++++ include/linux/sched.h | 2 +- mm/compaction.c | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1bb646752e46..033feeab8c34 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -457,7 +458,7 @@ static bool nfs_release_folio(struct folio *folio, gfp_t gfp) /* If the private flag is set, then the folio is not freeable */ if (folio_test_private(folio)) { if ((current_gfp_context(gfp) & GFP_KERNEL) != GFP_KERNEL || - current_is_kswapd()) + current_is_kswapd() || current_is_kcompactd()) return false; if (nfs_wb_folio(folio->mapping->host, folio) < 0) return false; diff --git a/include/linux/compaction.h b/include/linux/compaction.h index e94776496049..7bf0c521db63 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -80,6 +80,11 @@ static inline unsigned long compact_gap(unsigned int order) return 2UL << order; } +static inline int current_is_kcompactd(void) +{ + return current->flags & PF_KCOMPACTD; +} + #ifdef CONFIG_COMPACTION extern unsigned int extfrag_for_order(struct zone *zone, unsigned int order); diff --git a/include/linux/sched.h b/include/linux/sched.h index 9632e3318e0d..9c15365a30c0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1701,7 +1701,7 @@ extern struct pid *cad_pid; #define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */ #define PF_USER_WORKER 0x00004000 /* Kernel thread cloned from userspace thread */ #define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */ -#define PF__HOLE__00010000 0x00010000 +#define PF_KCOMPACTD 0x00010000 /* I am kcompactd */ #define PF_KSWAPD 0x00020000 /* I am kswapd */ #define PF_MEMALLOC_NOFS 0x00040000 /* All allocations inherit GFP_NOFS. See memalloc_nfs_save() */ #define PF_MEMALLOC_NOIO 0x00080000 /* All allocations inherit GFP_NOIO. See memalloc_noio_save() */ diff --git a/mm/compaction.c b/mm/compaction.c index 12ed8425fa17..a3203d97123e 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -3181,6 +3181,7 @@ static int kcompactd(void *p) long default_timeout = msecs_to_jiffies(HPAGE_FRAG_CHECK_INTERVAL_MSEC); long timeout = default_timeout; + current->flags |= PF_KCOMPACTD; set_freezable(); pgdat->kcompactd_max_order = 0; @@ -3237,6 +3238,8 @@ static int kcompactd(void *p) pgdat->proactive_compact_trigger = false; } + current->flags &= ~PF_KCOMPACTD; + return 0; } From c29564d8b46f64f5e6e6f1c9c02f7761b7b90963 Mon Sep 17 00:00:00 2001 From: Su Hui Date: Fri, 21 Feb 2025 15:16:25 +0800 Subject: [PATCH 0689/1090] include/linux/log2.h: mark is_power_of_2() with __always_inline When building kernel with randconfig, there is an error: In function `kvm_is_cr4_bit_set',inlined from `kvm_update_cpuid_runtime' at arch/x86/kvm/cpuid.c:310:9: include/linux/compiler_types.h:542:38: error: call to `__compiletime_assert_380' declared with attribute error: BUILD_BUG_ON failed: !is_power_of_2(cr4_bit). '!is_power_of_2(X86_CR4_OSXSAVE)' is False, but gcc treats is_power_of_2() as non-inline function and a compilation error happens. Fix this by marking is_power_of_2() with __always_inline. Link: https://lkml.kernel.org/r/20250221071624.1356899-1-suhui@nfschina.com Signed-off-by: Su Hui Cc: Binbin Wu Cc: Paolo Bonzini Cc: Sean Christopherson Signed-off-by: Andrew Morton --- include/linux/log2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/log2.h b/include/linux/log2.h index 9f30d087a128..1366cb688a6d 100644 --- a/include/linux/log2.h +++ b/include/linux/log2.h @@ -41,7 +41,7 @@ int __ilog2_u64(u64 n) * *not* considered a power of two. * Return: true if @n is a power of 2, otherwise false. */ -static inline __attribute__((const)) +static __always_inline __attribute__((const)) bool is_power_of_2(unsigned long n) { return (n != 0 && ((n & (n - 1)) == 0)); From 1c684d77dfbcf926e0dd28f6d260e8fdd8a58e85 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 25 Feb 2025 14:23:31 -0800 Subject: [PATCH 0690/1090] selftests/damon/damos_quota: make real expectation of quota exceeds Patch series "selftests/damon: three fixes for false results". Fix three DAMON selftest bugs that cause two and one false positive failures and successes. This patch (of 3): damos_quota.py assumes the quota will always exceeded. But whether quota will be exceeded or not depend on the monitoring results. Actually the monitored workload has chaning access pattern and hence sometimes the quota may not really be exceeded. As a result, false positive test failures happen. Expect how much time the quota will be exceeded by checking the monitoring results, and use it instead of the naive assumption. Link: https://lkml.kernel.org/r/20250225222333.505646-1-sj@kernel.org Link: https://lkml.kernel.org/r/20250225222333.505646-2-sj@kernel.org Fixes: 51f58c9da14b ("selftests/damon: add a test for DAMOS quota") Signed-off-by: SeongJae Park Cc: Shuah Khan Cc: Signed-off-by: Andrew Morton --- tools/testing/selftests/damon/damos_quota.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/damon/damos_quota.py b/tools/testing/selftests/damon/damos_quota.py index 7d4c6bb2e3cd..57c4937aaed2 100755 --- a/tools/testing/selftests/damon/damos_quota.py +++ b/tools/testing/selftests/damon/damos_quota.py @@ -51,16 +51,19 @@ def main(): nr_quota_exceeds = scheme.stats.qt_exceeds wss_collected.sort() + nr_expected_quota_exceeds = 0 for wss in wss_collected: if wss > sz_quota: print('quota is not kept: %s > %s' % (wss, sz_quota)) print('collected samples are as below') print('\n'.join(['%d' % wss for wss in wss_collected])) exit(1) + if wss == sz_quota: + nr_expected_quota_exceeds += 1 - if nr_quota_exceeds < len(wss_collected): - print('quota is not always exceeded: %d > %d' % - (len(wss_collected), nr_quota_exceeds)) + if nr_quota_exceeds < nr_expected_quota_exceeds: + print('quota is exceeded less than expected: %d < %d' % + (nr_quota_exceeds, nr_expected_quota_exceeds)) exit(1) if __name__ == '__main__': From 695469c07a65547acb6e229b3fdf6aaa881817e3 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 25 Feb 2025 14:23:32 -0800 Subject: [PATCH 0691/1090] selftests/damon/damon_nr_regions: set ops update for merge results check to 100ms damon_nr_regions.py updates max_nr_regions to a number smaller than expected number of real regions and confirms DAMON respect the harsh limit. To give time for DAMON to make changes for the regions, 3 aggregation intervals (300 milliseconds) are given. The internal mechanism works with not only the max_nr_regions, but also sz_limit, though. It avoids merging region if that casn make region of size larger than sz_limit. In the test, sz_limit is set too small to achive the new max_nr_regions, unless it is updated for the new min_nr_regions. But the update is done only once per operations set update interval, which is one second by default. Hence, the test randomly incurs false positive failures. Fix it by setting the ops interval same to aggregation interval, to make sure sz_limit is updated by the time of the check. Link: https://lkml.kernel.org/r/20250225222333.505646-3-sj@kernel.org Fixes: 8bf890c81612 ("selftests/damon/damon_nr_regions: test online-tuned max_nr_regions") Signed-off-by: SeongJae Park Cc: Shuah Khan Cc: Signed-off-by: Andrew Morton --- tools/testing/selftests/damon/damon_nr_regions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/damon/damon_nr_regions.py b/tools/testing/selftests/damon/damon_nr_regions.py index 2e8a74aff543..6f1c1d88e309 100755 --- a/tools/testing/selftests/damon/damon_nr_regions.py +++ b/tools/testing/selftests/damon/damon_nr_regions.py @@ -109,6 +109,7 @@ def main(): attrs = kdamonds.kdamonds[0].contexts[0].monitoring_attrs attrs.min_nr_regions = 3 attrs.max_nr_regions = 7 + attrs.update_us = 100000 err = kdamonds.kdamonds[0].commit() if err is not None: proc.terminate() From 582ccf78f6090d88b1c7066b1e90b3d9ec952d08 Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 25 Feb 2025 14:23:33 -0800 Subject: [PATCH 0692/1090] selftests/damon/damon_nr_regions: sort collected regiosn before checking with min/max boundaries damon_nr_regions.py starts DAMON, periodically collect number of regions in snapshots, and see if it is in the requested range. The check code assumes the numbers are sorted on the collection list, but there is no such guarantee. Hence this can result in false positive test success. Sort the list before doing the check. Link: https://lkml.kernel.org/r/20250225222333.505646-4-sj@kernel.org Fixes: 781497347d1b ("selftests/damon: implement test for min/max_nr_regions") Signed-off-by: SeongJae Park Cc: Shuah Khan Cc: Signed-off-by: Andrew Morton --- tools/testing/selftests/damon/damon_nr_regions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/damon/damon_nr_regions.py b/tools/testing/selftests/damon/damon_nr_regions.py index 6f1c1d88e309..58f3291fed12 100755 --- a/tools/testing/selftests/damon/damon_nr_regions.py +++ b/tools/testing/selftests/damon/damon_nr_regions.py @@ -65,6 +65,7 @@ def test_nr_regions(real_nr_regions, min_nr_regions, max_nr_regions): test_name = 'nr_regions test with %d/%d/%d real/min/max nr_regions' % ( real_nr_regions, min_nr_regions, max_nr_regions) + collected_nr_regions.sort() if (collected_nr_regions[0] < min_nr_regions or collected_nr_regions[-1] > max_nr_regions): print('fail %s' % test_name) From c50f8e6053b0503375c2975bf47f182445aebb4c Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 26 Feb 2025 13:14:00 +1300 Subject: [PATCH 0693/1090] mm: fix kernel BUG when userfaultfd_move encounters swapcache userfaultfd_move() checks whether the PTE entry is present or a swap entry. - If the PTE entry is present, move_present_pte() handles folio migration by setting: src_folio->index = linear_page_index(dst_vma, dst_addr); - If the PTE entry is a swap entry, move_swap_pte() simply copies the PTE to the new dst_addr. This approach is incorrect because, even if the PTE is a swap entry, it can still reference a folio that remains in the swap cache. This creates a race window between steps 2 and 4. 1. add_to_swap: The folio is added to the swapcache. 2. try_to_unmap: PTEs are converted to swap entries. 3. pageout: The folio is written back. 4. Swapcache is cleared. If userfaultfd_move() occurs in the window between steps 2 and 4, after the swap PTE has been moved to the destination, accessing the destination triggers do_swap_page(), which may locate the folio in the swapcache. However, since the folio's index has not been updated to match the destination VMA, do_swap_page() will detect a mismatch. This can result in two critical issues depending on the system configuration. If KSM is disabled, both small and large folios can trigger a BUG during the add_rmap operation due to: page_pgoff(folio, page) != linear_page_index(vma, address) [ 13.336953] page: refcount:6 mapcount:1 mapping:00000000f43db19c index:0xffffaf150 pfn:0x4667c [ 13.337520] head: order:2 mapcount:1 entire_mapcount:0 nr_pages_mapped:1 pincount:0 [ 13.337716] memcg:ffff00000405f000 [ 13.337849] anon flags: 0x3fffc0000020459(locked|uptodate|dirty|owner_priv_1|head|swapbacked|node=0|zone=0|lastcpupid=0xffff) [ 13.338630] raw: 03fffc0000020459 ffff80008507b538 ffff80008507b538 ffff000006260361 [ 13.338831] raw: 0000000ffffaf150 0000000000004000 0000000600000000 ffff00000405f000 [ 13.339031] head: 03fffc0000020459 ffff80008507b538 ffff80008507b538 ffff000006260361 [ 13.339204] head: 0000000ffffaf150 0000000000004000 0000000600000000 ffff00000405f000 [ 13.339375] head: 03fffc0000000202 fffffdffc0199f01 ffffffff00000000 0000000000000001 [ 13.339546] head: 0000000000000004 0000000000000000 00000000ffffffff 0000000000000000 [ 13.339736] page dumped because: VM_BUG_ON_PAGE(page_pgoff(folio, page) != linear_page_index(vma, address)) [ 13.340190] ------------[ cut here ]------------ [ 13.340316] kernel BUG at mm/rmap.c:1380! [ 13.340683] Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP [ 13.340969] Modules linked in: [ 13.341257] CPU: 1 UID: 0 PID: 107 Comm: a.out Not tainted 6.14.0-rc3-gcf42737e247a-dirty #299 [ 13.341470] Hardware name: linux,dummy-virt (DT) [ 13.341671] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 13.341815] pc : __page_check_anon_rmap+0xa0/0xb0 [ 13.341920] lr : __page_check_anon_rmap+0xa0/0xb0 [ 13.342018] sp : ffff80008752bb20 [ 13.342093] x29: ffff80008752bb20 x28: fffffdffc0199f00 x27: 0000000000000001 [ 13.342404] x26: 0000000000000000 x25: 0000000000000001 x24: 0000000000000001 [ 13.342575] x23: 0000ffffaf0d0000 x22: 0000ffffaf0d0000 x21: fffffdffc0199f00 [ 13.342731] x20: fffffdffc0199f00 x19: ffff000006210700 x18: 00000000ffffffff [ 13.342881] x17: 6c203d2120296567 x16: 6170202c6f696c6f x15: 662866666f67705f [ 13.343033] x14: 6567617028454741 x13: 2929737365726464 x12: ffff800083728ab0 [ 13.343183] x11: ffff800082996bf8 x10: 0000000000000fd7 x9 : ffff80008011bc40 [ 13.343351] x8 : 0000000000017fe8 x7 : 00000000fffff000 x6 : ffff8000829eebf8 [ 13.343498] x5 : c0000000fffff000 x4 : 0000000000000000 x3 : 0000000000000000 [ 13.343645] x2 : 0000000000000000 x1 : ffff0000062db980 x0 : 000000000000005f [ 13.343876] Call trace: [ 13.344045] __page_check_anon_rmap+0xa0/0xb0 (P) [ 13.344234] folio_add_anon_rmap_ptes+0x22c/0x320 [ 13.344333] do_swap_page+0x1060/0x1400 [ 13.344417] __handle_mm_fault+0x61c/0xbc8 [ 13.344504] handle_mm_fault+0xd8/0x2e8 [ 13.344586] do_page_fault+0x20c/0x770 [ 13.344673] do_translation_fault+0xb4/0xf0 [ 13.344759] do_mem_abort+0x48/0xa0 [ 13.344842] el0_da+0x58/0x130 [ 13.344914] el0t_64_sync_handler+0xc4/0x138 [ 13.345002] el0t_64_sync+0x1ac/0x1b0 [ 13.345208] Code: aa1503e0 f000f801 910f6021 97ff5779 (d4210000) [ 13.345504] ---[ end trace 0000000000000000 ]--- [ 13.345715] note: a.out[107] exited with irqs disabled [ 13.345954] note: a.out[107] exited with preempt_count 2 If KSM is enabled, Peter Xu also discovered that do_swap_page() may trigger an unexpected CoW operation for small folios because ksm_might_need_to_copy() allocates a new folio when the folio index does not match linear_page_index(vma, addr). This patch also checks the swapcache when handling swap entries. If a match is found in the swapcache, it processes it similarly to a present PTE. However, there are some differences. For example, the folio is no longer exclusive because folio_try_share_anon_rmap_pte() is performed during unmapping. Furthermore, in the case of swapcache, the folio has already been unmapped, eliminating the risk of concurrent rmap walks and removing the need to acquire src_folio's anon_vma or lock. Note that for large folios, in the swapcache handling path, we directly return -EBUSY since split_folio() will return -EBUSY regardless if the folio is under writeback or unmapped. This is not an urgent issue, so a follow-up patch may address it separately. [v-songbaohua@oppo.com: minor cleanup according to Peter Xu] Link: https://lkml.kernel.org/r/20250226024411.47092-1-21cnbao@gmail.com Link: https://lkml.kernel.org/r/20250226001400.9129-1-21cnbao@gmail.com Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Barry Song Acked-by: Peter Xu Reviewed-by: Suren Baghdasaryan Cc: Andrea Arcangeli Cc: Al Viro Cc: Axel Rasmussen Cc: Brian Geffon Cc: Christian Brauner Cc: David Hildenbrand Cc: Hugh Dickins Cc: Jann Horn Cc: Kalesh Singh Cc: Liam R. Howlett Cc: Lokesh Gidra Cc: Matthew Wilcox (Oracle) Cc: Michal Hocko Cc: Mike Rapoport (IBM) Cc: Nicolas Geoffray Cc: Ryan Roberts Cc: Shuah Khan Cc: ZhangPeng Cc: Tangquan Zheng Cc: Signed-off-by: Andrew Morton --- mm/userfaultfd.c | 74 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index af3dfc3633db..c45b672e10d1 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -18,6 +18,7 @@ #include #include #include "internal.h" +#include "swap.h" static __always_inline bool validate_dst_vma(struct vm_area_struct *dst_vma, unsigned long dst_end) @@ -1076,16 +1077,14 @@ out: return err; } -static int move_swap_pte(struct mm_struct *mm, +static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma, unsigned long dst_addr, unsigned long src_addr, pte_t *dst_pte, pte_t *src_pte, pte_t orig_dst_pte, pte_t orig_src_pte, pmd_t *dst_pmd, pmd_t dst_pmdval, - spinlock_t *dst_ptl, spinlock_t *src_ptl) + spinlock_t *dst_ptl, spinlock_t *src_ptl, + struct folio *src_folio) { - if (!pte_swp_exclusive(orig_src_pte)) - return -EBUSY; - double_pt_lock(dst_ptl, src_ptl); if (!is_pte_pages_stable(dst_pte, src_pte, orig_dst_pte, orig_src_pte, @@ -1094,6 +1093,16 @@ static int move_swap_pte(struct mm_struct *mm, return -EAGAIN; } + /* + * The src_folio resides in the swapcache, requiring an update to its + * index and mapping to align with the dst_vma, where a swap-in may + * occur and hit the swapcache after moving the PTE. + */ + if (src_folio) { + folio_move_anon_rmap(src_folio, dst_vma); + src_folio->index = linear_page_index(dst_vma, dst_addr); + } + orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte); set_pte_at(mm, dst_addr, dst_pte, orig_src_pte); double_pt_unlock(dst_ptl, src_ptl); @@ -1141,6 +1150,7 @@ static int move_pages_pte(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, __u64 mode) { swp_entry_t entry; + struct swap_info_struct *si = NULL; pte_t orig_src_pte, orig_dst_pte; pte_t src_folio_pte; spinlock_t *src_ptl, *dst_ptl; @@ -1322,6 +1332,8 @@ retry: orig_dst_pte, orig_src_pte, dst_pmd, dst_pmdval, dst_ptl, src_ptl, src_folio); } else { + struct folio *folio = NULL; + entry = pte_to_swp_entry(orig_src_pte); if (non_swap_entry(entry)) { if (is_migration_entry(entry)) { @@ -1335,9 +1347,53 @@ retry: goto out; } - err = move_swap_pte(mm, dst_addr, src_addr, dst_pte, src_pte, - orig_dst_pte, orig_src_pte, dst_pmd, - dst_pmdval, dst_ptl, src_ptl); + if (!pte_swp_exclusive(orig_src_pte)) { + err = -EBUSY; + goto out; + } + + si = get_swap_device(entry); + if (unlikely(!si)) { + err = -EAGAIN; + goto out; + } + /* + * Verify the existence of the swapcache. If present, the folio's + * index and mapping must be updated even when the PTE is a swap + * entry. The anon_vma lock is not taken during this process since + * the folio has already been unmapped, and the swap entry is + * exclusive, preventing rmap walks. + * + * For large folios, return -EBUSY immediately, as split_folio() + * also returns -EBUSY when attempting to split unmapped large + * folios in the swapcache. This issue needs to be resolved + * separately to allow proper handling. + */ + if (!src_folio) + folio = filemap_get_folio(swap_address_space(entry), + swap_cache_index(entry)); + if (!IS_ERR_OR_NULL(folio)) { + if (folio_test_large(folio)) { + err = -EBUSY; + folio_put(folio); + goto out; + } + src_folio = folio; + src_folio_pte = orig_src_pte; + if (!folio_trylock(src_folio)) { + pte_unmap(&orig_src_pte); + pte_unmap(&orig_dst_pte); + src_pte = dst_pte = NULL; + put_swap_device(si); + si = NULL; + /* now we can block and wait */ + folio_lock(src_folio); + goto retry; + } + } + err = move_swap_pte(mm, dst_vma, dst_addr, src_addr, dst_pte, src_pte, + orig_dst_pte, orig_src_pte, dst_pmd, dst_pmdval, + dst_ptl, src_ptl, src_folio); } out: @@ -1354,6 +1410,8 @@ out: if (src_pte) pte_unmap(src_pte); mmu_notifier_invalidate_range_end(&range); + if (si) + put_swap_device(si); return err; } From 058313515d5aab10d0a01dd634f92ed4a4e71d4c Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 25 Feb 2025 17:52:55 +0800 Subject: [PATCH 0694/1090] mm: shmem: fix potential data corruption during shmem swapin Alex and Kairui reported some issues (system hang or data corruption) when swapping out or swapping in large shmem folios. This is especially easy to reproduce when the tmpfs is mount with the 'huge=within_size' parameter. Thanks to Kairui's reproducer, the issue can be easily replicated. The root cause of the problem is that swap readahead may asynchronously swap in order 0 folios into the swap cache, while the shmem mapping can still store large swap entries. Then an order 0 folio is inserted into the shmem mapping without splitting the large swap entry, which overwrites the original large swap entry, leading to data corruption. When getting a folio from the swap cache, we should split the large swap entry stored in the shmem mapping if the orders do not match, to fix this issue. Link: https://lkml.kernel.org/r/2fe47c557e74e9df5fe2437ccdc6c9115fa1bf70.1740476943.git.baolin.wang@linux.alibaba.com Fixes: 809bc86517cc ("mm: shmem: support large folio swap out") Signed-off-by: Baolin Wang Reported-by: Alex Xu (Hello71) Reported-by: Kairui Song Closes: https://lore.kernel.org/all/1738717785.im3r5g2vxc.none@localhost/ Tested-by: Kairui Song Cc: David Hildenbrand Cc: Lance Yang Cc: Matthew Wilcow Cc: Hugh Dickins Cc: Signed-off-by: Andrew Morton --- mm/shmem.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 4ea6109a8043..cebbac97a221 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2253,7 +2253,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, struct folio *folio = NULL; bool skip_swapcache = false; swp_entry_t swap; - int error, nr_pages; + int error, nr_pages, order, split_order; VM_BUG_ON(!*foliop || !xa_is_value(*foliop)); swap = radix_to_swp_entry(*foliop); @@ -2272,10 +2272,9 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, /* Look it up and read it in.. */ folio = swap_cache_get_folio(swap, NULL, 0); + order = xa_get_order(&mapping->i_pages, index); if (!folio) { - int order = xa_get_order(&mapping->i_pages, index); bool fallback_order0 = false; - int split_order; /* Or update major stats only when swapin succeeds?? */ if (fault_type) { @@ -2339,6 +2338,29 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, error = -ENOMEM; goto failed; } + } else if (order != folio_order(folio)) { + /* + * Swap readahead may swap in order 0 folios into swapcache + * asynchronously, while the shmem mapping can still stores + * large swap entries. In such cases, we should split the + * large swap entry to prevent possible data corruption. + */ + split_order = shmem_split_large_entry(inode, index, swap, gfp); + if (split_order < 0) { + error = split_order; + goto failed; + } + + /* + * If the large swap entry has already been split, it is + * necessary to recalculate the new swap entry based on + * the old order alignment. + */ + if (split_order > 0) { + pgoff_t offset = index - round_down(index, 1 << split_order); + + swap = swp_entry(swp_type(swap), swp_offset(swap) + offset); + } } alloced: @@ -2346,7 +2368,8 @@ alloced: folio_lock(folio); if ((!skip_swapcache && !folio_test_swapcache(folio)) || folio->swap.val != swap.val || - !shmem_confirm_swap(mapping, index, swap)) { + !shmem_confirm_swap(mapping, index, swap) || + xa_get_order(&mapping->i_pages, index) != folio_order(folio)) { error = -EEXIST; goto unlock; } From ea6de4f8f8f32e54662118a97c441a6ad7b24345 Mon Sep 17 00:00:00 2001 From: Sun YangKai Date: Wed, 26 Feb 2025 23:32:43 +0800 Subject: [PATCH 0695/1090] mm: zswap: use ATOMIC_LONG_INIT to initialize zswap_stored_pages This is currently the only atomic_long_t variable initialized by ATOMIC_INIT macro found in the kernel by using `grep -r atomic_long_t | grep ATOMIC_INIT` This was introduced in 6e1fa555ec77, in which we modified the type of zswap_stored_pages to atomic_long_t, but didn't change the initialization. Link: https://lkml.kernel.org/r/20250226153253.19179-1-sunk67188@gmail.com Fixes: 6e1fa555ec77 ("mm: zswap: modify zswap_stored_pages to be atomic_long_t") Signed-off-by: Sun YangKai Acked-by: Yosry Ahmed Acked-by: David Hildenbrand Cc: Chengming Zhou Cc: Johannes Weiner Cc: Kanchana P Sridhar Cc: Nhat Pham Signed-off-by: Andrew Morton --- mm/zswap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/zswap.c b/mm/zswap.c index ac9d299e7d0c..23365e76a3ce 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -43,7 +43,7 @@ * statistics **********************************/ /* The number of compressed pages currently stored in zswap */ -atomic_long_t zswap_stored_pages = ATOMIC_INIT(0); +atomic_long_t zswap_stored_pages = ATOMIC_LONG_INIT(0); /* * The statistics below are not protected from concurrent access for From 37b338eed10581784e854d4262da05c8d960c748 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Wed, 26 Feb 2025 10:55:08 -0800 Subject: [PATCH 0696/1090] userfaultfd: do not block on locking a large folio with raised refcount Lokesh recently raised an issue about UFFDIO_MOVE getting into a deadlock state when it goes into split_folio() with raised folio refcount. split_folio() expects the reference count to be exactly mapcount + num_pages_in_folio + 1 (see can_split_folio()) and fails with EAGAIN otherwise. If multiple processes are trying to move the same large folio, they raise the refcount (all tasks succeed in that) then one of them succeeds in locking the folio, while others will block in folio_lock() while keeping the refcount raised. The winner of this race will proceed with calling split_folio() and will fail returning EAGAIN to the caller and unlocking the folio. The next competing process will get the folio locked and will go through the same flow. In the meantime the original winner will be retried and will block in folio_lock(), getting into the queue of waiting processes only to repeat the same path. All this results in a livelock. An easy fix would be to avoid waiting for the folio lock while holding folio refcount, similar to madvise_free_huge_pmd() where folio lock is acquired before raising the folio refcount. Since we lock and take a refcount of the folio while holding the PTE lock, changing the order of these operations should not break anything. Modify move_pages_pte() to try locking the folio first and if that fails and the folio is large then return EAGAIN without touching the folio refcount. If the folio is single-page then split_folio() is not called, so we don't have this issue. Lokesh has a reproducer [1] and I verified that this change fixes the issue. [1] https://github.com/lokeshgidra/uffd_move_ioctl_deadlock [akpm@linux-foundation.org: reflow comment to 80 cols, s/end/end up/] Link: https://lkml.kernel.org/r/20250226185510.2732648-2-surenb@google.com Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Suren Baghdasaryan Reported-by: Lokesh Gidra Reviewed-by: Peter Xu Acked-by: Liam R. Howlett Cc: Andrea Arcangeli Cc: Barry Song <21cnbao@gmail.com> Cc: Barry Song Cc: David Hildenbrand Cc: Hugh Dickins Cc: Jann Horn Cc: Kalesh Singh Cc: Lorenzo Stoakes Cc: Matthew Wilcow (Oracle) Cc: Signed-off-by: Andrew Morton --- mm/userfaultfd.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index c45b672e10d1..f5c6b3454f76 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1250,6 +1250,7 @@ retry: */ if (!src_folio) { struct folio *folio; + bool locked; /* * Pin the page while holding the lock to be sure the @@ -1269,12 +1270,26 @@ retry: goto out; } + locked = folio_trylock(folio); + /* + * We avoid waiting for folio lock with a raised + * refcount for large folios because extra refcounts + * will result in split_folio() failing later and + * retrying. If multiple tasks are trying to move a + * large folio we can end up livelocking. + */ + if (!locked && folio_test_large(folio)) { + spin_unlock(src_ptl); + err = -EAGAIN; + goto out; + } + folio_get(folio); src_folio = folio; src_folio_pte = orig_src_pte; spin_unlock(src_ptl); - if (!folio_trylock(src_folio)) { + if (!locked) { pte_unmap(&orig_src_pte); pte_unmap(&orig_dst_pte); src_pte = dst_pte = NULL; From 927e926d72d9155fde3264459fe9bfd7b5e40d28 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Wed, 26 Feb 2025 10:55:09 -0800 Subject: [PATCH 0697/1090] userfaultfd: fix PTE unmapping stack-allocated PTE copies Current implementation of move_pages_pte() copies source and destination PTEs in order to detect concurrent changes to PTEs involved in the move. However these copies are also used to unmap the PTEs, which will fail if CONFIG_HIGHPTE is enabled because the copies are allocated on the stack. Fix this by using the actual PTEs which were kmap()ed. Link: https://lkml.kernel.org/r/20250226185510.2732648-3-surenb@google.com Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Suren Baghdasaryan Reported-by: Peter Xu Reviewed-by: Peter Xu Cc: Andrea Arcangeli Cc: Barry Song <21cnbao@gmail.com> Cc: Barry Song Cc: David Hildenbrand Cc: Hugh Dickins Cc: Jann Horn Cc: Kalesh Singh Cc: Liam R. Howlett Cc: Lokesh Gidra Cc: Lorenzo Stoakes Cc: Matthew Wilcow (Oracle) Cc: Signed-off-by: Andrew Morton --- mm/userfaultfd.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index f5c6b3454f76..d06453fa8aba 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1290,8 +1290,8 @@ retry: spin_unlock(src_ptl); if (!locked) { - pte_unmap(&orig_src_pte); - pte_unmap(&orig_dst_pte); + pte_unmap(src_pte); + pte_unmap(dst_pte); src_pte = dst_pte = NULL; /* now we can block and wait */ folio_lock(src_folio); @@ -1307,8 +1307,8 @@ retry: /* at this point we have src_folio locked */ if (folio_test_large(src_folio)) { /* split_folio() can block */ - pte_unmap(&orig_src_pte); - pte_unmap(&orig_dst_pte); + pte_unmap(src_pte); + pte_unmap(dst_pte); src_pte = dst_pte = NULL; err = split_folio(src_folio); if (err) @@ -1333,8 +1333,8 @@ retry: goto out; } if (!anon_vma_trylock_write(src_anon_vma)) { - pte_unmap(&orig_src_pte); - pte_unmap(&orig_dst_pte); + pte_unmap(src_pte); + pte_unmap(dst_pte); src_pte = dst_pte = NULL; /* now we can block and wait */ anon_vma_lock_write(src_anon_vma); @@ -1352,8 +1352,8 @@ retry: entry = pte_to_swp_entry(orig_src_pte); if (non_swap_entry(entry)) { if (is_migration_entry(entry)) { - pte_unmap(&orig_src_pte); - pte_unmap(&orig_dst_pte); + pte_unmap(src_pte); + pte_unmap(dst_pte); src_pte = dst_pte = NULL; migration_entry_wait(mm, src_pmd, src_addr); err = -EAGAIN; @@ -1396,8 +1396,8 @@ retry: src_folio = folio; src_folio_pte = orig_src_pte; if (!folio_trylock(src_folio)) { - pte_unmap(&orig_src_pte); - pte_unmap(&orig_dst_pte); + pte_unmap(src_pte); + pte_unmap(dst_pte); src_pte = dst_pte = NULL; put_swap_device(si); si = NULL; From adae46ac1e38a288b14f0298e27412adcba83f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo=20Navarro?= Date: Wed, 26 Feb 2025 13:26:27 +0100 Subject: [PATCH 0698/1090] mm: shmem: remove unnecessary warning in shmem_writepage() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the scenario where shmem_writepage() is called with info->flags & VM_LOCKED is unlikely to happen, it's still possible, as evidenced by syzbot [1]. However, the warning in this case isn't necessary because the situation is already handled correctly [2]. [2] https://lore.kernel.org/lkml/8afe1f7f-31a2-4fc0-1fbd-f9ba8a116fe3@google.com/ Link: https://lkml.kernel.org/r/20250226-20250221-warning-in-shmem_writepage-v1-1-5ad19420e17e@igalia.com Fixes: 9a976f0c847b ("shmem: skip page split if we're not reclaiming") Signed-off-by: Ricardo Cañuelo Navarro Reported-by: Pengfei Xu Closes: https://lore.kernel.org/lkml/ZZ9PShXjKJkVelNm@xpf.sh.intel.com/ [1] Suggested-by: Hugh Dickins Reviewed-by: Baolin Wang Cc: Florent Revest Cc: Christian Brauner Cc: David Hildenbrand Cc: Davidlohr Bueso Cc: Florent Revest Cc: Luis Chamberalin Signed-off-by: Andrew Morton --- mm/shmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/shmem.c b/mm/shmem.c index cebbac97a221..3fcd1690eedd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1548,7 +1548,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) if (WARN_ON_ONCE(!wbc->for_reclaim)) goto redirty; - if (WARN_ON_ONCE((info->flags & VM_LOCKED) || sbinfo->noswap)) + if ((info->flags & VM_LOCKED) || sbinfo->noswap) goto redirty; if (!total_swap_pages) From 3685024edd270f7c791f993157d65d3c928f3d6e Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Wed, 26 Feb 2025 12:16:09 +0000 Subject: [PATCH 0699/1090] mm: don't skip arch_sync_kernel_mappings() in error paths Fix callers that previously skipped calling arch_sync_kernel_mappings() if an error occurred during a pgtable update. The call is still required to sync any pgtable updates that may have occurred prior to hitting the error condition. These are theoretical bugs discovered during code review. Link: https://lkml.kernel.org/r/20250226121610.2401743-1-ryan.roberts@arm.com Fixes: 2ba3e6947aed ("mm/vmalloc: track which page-table levels were modified") Fixes: 0c95cba49255 ("mm: apply_to_pte_range warn and fail if a large pte is encountered") Signed-off-by: Ryan Roberts Reviewed-by: Anshuman Khandual Reviewed-by: Catalin Marinas Cc: Christop Hellwig Cc: "Uladzislau Rezki (Sony)" Cc: Signed-off-by: Andrew Morton --- mm/memory.c | 6 ++++-- mm/vmalloc.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index b4d3d4893267..55d0d4954627 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3051,8 +3051,10 @@ static int __apply_to_page_range(struct mm_struct *mm, unsigned long addr, next = pgd_addr_end(addr, end); if (pgd_none(*pgd) && !create) continue; - if (WARN_ON_ONCE(pgd_leaf(*pgd))) - return -EINVAL; + if (WARN_ON_ONCE(pgd_leaf(*pgd))) { + err = -EINVAL; + break; + } if (!pgd_none(*pgd) && WARN_ON_ONCE(pgd_bad(*pgd))) { if (!create) continue; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index a6e7acebe9ad..61981ee1c9d2 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -586,13 +586,13 @@ static int vmap_small_pages_range_noflush(unsigned long addr, unsigned long end, mask |= PGTBL_PGD_MODIFIED; err = vmap_pages_p4d_range(pgd, addr, next, prot, pages, &nr, &mask); if (err) - return err; + break; } while (pgd++, addr = next, addr != end); if (mask & ARCH_PAGE_TABLE_SYNC_MASK) arch_sync_kernel_mappings(start, end); - return 0; + return err; } /* From 34b82f33cf3f03bc39e9a205a913d790e1520ade Mon Sep 17 00:00:00 2001 From: Brian Geffon Date: Wed, 26 Feb 2025 11:23:41 -0500 Subject: [PATCH 0700/1090] mm: fix finish_fault() handling for large folios When handling faults for anon shmem finish_fault() will attempt to install ptes for the entire folio. Unfortunately if it encounters a single non-pte_none entry in that range it will bail, even if the pte that triggered the fault is still pte_none. When this situation happens the fault will be retried endlessly never making forward progress. This patch fixes this behavior and if it detects that a pte in the range is not pte_none it will fall back to setting a single pte. [bgeffon@google.com: tweak whitespace] Link: https://lkml.kernel.org/r/20250227133236.1296853-1-bgeffon@google.com Link: https://lkml.kernel.org/r/20250226162341.915535-1-bgeffon@google.com Fixes: 43e027e41423 ("mm: memory: extend finish_fault() to support large folio") Signed-off-by: Brian Geffon Suggested-by: Baolin Wang Reported-by: Marek Maslanka Cc: Hugh Dickins Cc: David Hildenbrand Cc: Hugh Dickens Cc: Kefeng Wang Cc: Matthew Wilcow (Oracle) Cc: Suren Baghdasaryan Cc: Zi Yan Cc: Signed-off-by: Andrew Morton --- mm/memory.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 55d0d4954627..b9661ccfa64f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -5185,7 +5185,11 @@ vm_fault_t finish_fault(struct vm_fault *vmf) bool is_cow = (vmf->flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED); int type, nr_pages; - unsigned long addr = vmf->address; + unsigned long addr; + bool needs_fallback = false; + +fallback: + addr = vmf->address; /* Did we COW the page? */ if (is_cow) @@ -5224,7 +5228,8 @@ vm_fault_t finish_fault(struct vm_fault *vmf) * approach also applies to non-anonymous-shmem faults to avoid * inflating the RSS of the process. */ - if (!vma_is_anon_shmem(vma) || unlikely(userfaultfd_armed(vma))) { + if (!vma_is_anon_shmem(vma) || unlikely(userfaultfd_armed(vma)) || + unlikely(needs_fallback)) { nr_pages = 1; } else if (nr_pages > 1) { pgoff_t idx = folio_page_idx(folio, page); @@ -5260,9 +5265,9 @@ vm_fault_t finish_fault(struct vm_fault *vmf) ret = VM_FAULT_NOPAGE; goto unlock; } else if (nr_pages > 1 && !pte_range_none(vmf->pte, nr_pages)) { - update_mmu_tlb_range(vma, addr, vmf->pte, nr_pages); - ret = VM_FAULT_NOPAGE; - goto unlock; + needs_fallback = true; + pte_unmap_unlock(vmf->pte, vmf->ptl); + goto fallback; } folio_ref_add(folio, nr_pages - 1); From eae116d1f0449ade3269ca47a67432622f5c6438 Mon Sep 17 00:00:00 2001 From: Gabriel Krisman Bertazi Date: Tue, 25 Feb 2025 22:22:58 -0500 Subject: [PATCH 0701/1090] Revert "mm/page_alloc.c: don't show protection in zone's ->lowmem_reserve[] for empty zone" Commit 96a5c186efff ("mm/page_alloc.c: don't show protection in zone's ->lowmem_reserve[] for empty zone") removes the protection of lower zones from allocations targeting memory-less high zones. This had an unintended impact on the pattern of reclaims because it makes the high-zone-targeted allocation more likely to succeed in lower zones, which adds pressure to said zones. I.e, the following corresponding checks in zone_watermark_ok/zone_watermark_fast are less likely to trigger: if (free_pages <= min + z->lowmem_reserve[highest_zoneidx]) return false; As a result, we are observing an increase in reclaim and kswapd scans, due to the increased pressure. This was initially observed as increased latency in filesystem operations when benchmarking with fio on a machine with some memory-less zones, but it has since been associated with increased contention in locks related to memory reclaim. By reverting this patch, the original performance was recovered on that machine. The original commit was introduced as a clarification of the /proc/zoneinfo output, so it doesn't seem there are usecases depending on it, making the revert a simple solution. For reference, I collected vmstat with and without this patch on a freshly booted system running intensive randread io from an nvme for 5 minutes. I got: rpm-6.12.0-slfo.1.2 -> pgscan_kswapd 5629543865 Patched -> pgscan_kswapd 33580844 33M scans is similar to what we had in kernels predating this patch. These numbers is fairly representative of the workload on this machine, as measured in several runs. So we are talking about a 2-order of magnitude increase. Link: https://lkml.kernel.org/r/20250226032258.234099-1-krisman@suse.de Fixes: 96a5c186efff ("mm/page_alloc.c: don't show protection in zone's ->lowmem_reserve[] for empty zone") Signed-off-by: Gabriel Krisman Bertazi Reviewed-by: Vlastimil Babka Acked-by: Michal Hocko Acked-by: Mel Gorman Cc: Baoquan He Cc: Signed-off-by: Andrew Morton --- mm/page_alloc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 579789600a3c..fe986e6de7a0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5849,11 +5849,10 @@ static void setup_per_zone_lowmem_reserve(void) for (j = i + 1; j < MAX_NR_ZONES; j++) { struct zone *upper_zone = &pgdat->node_zones[j]; - bool empty = !zone_managed_pages(upper_zone); managed_pages += zone_managed_pages(upper_zone); - if (clear || empty) + if (clear) zone->lowmem_reserve[j] = 0; else zone->lowmem_reserve[j] = managed_pages / ratio; From 88f5a9a945bf25df1f90032baf95457370c2206e Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 27 Feb 2025 17:02:28 +0530 Subject: [PATCH 0702/1090] MAINTAINERS: .mailmap: update Sumit Garg's email address Update Sumit Garg's email address to @kernel.org. Link: https://lkml.kernel.org/r/20250227113228.1809449-1-sumit.garg@linaro.org Signed-off-by: Sumit Garg Cc: Herbert Xu Cc: Jarkko Sakkinen Cc: Jens Wiklander Signed-off-by: Andrew Morton --- .mailmap | 1 + MAINTAINERS | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.mailmap b/.mailmap index a897c16d3bae..4a93909286d8 100644 --- a/.mailmap +++ b/.mailmap @@ -689,6 +689,7 @@ Subbaraman Narayanamurthy Subhash Jadavani Sudarshan Rajagopalan Sudeep Holla Sudeep KarkadaNagesha +Sumit Garg Sumit Semwal Surabhi Vishnoi Sven Eckelmann diff --git a/MAINTAINERS b/MAINTAINERS index 4e17764cb6ed..5e1be7b25912 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12864,7 +12864,7 @@ F: include/keys/trusted_dcp.h F: security/keys/trusted-keys/trusted_dcp.c KEYS-TRUSTED-TEE -M: Sumit Garg +M: Sumit Garg L: linux-integrity@vger.kernel.org L: keyrings@vger.kernel.org S: Supported @@ -17658,7 +17658,7 @@ F: Documentation/ABI/testing/sysfs-bus-optee-devices F: drivers/tee/optee/ OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER -M: Sumit Garg +M: Sumit Garg L: op-tee@lists.trustedfirmware.org S: Maintained F: drivers/char/hw_random/optee-rng.c @@ -23268,7 +23268,7 @@ F: include/media/i2c/tw9910.h TEE SUBSYSTEM M: Jens Wiklander -R: Sumit Garg +R: Sumit Garg L: op-tee@lists.trustedfirmware.org S: Maintained F: Documentation/ABI/testing/sysfs-class-tee From b2ef51c74b0171fde7eb69b6152d3d2f743ef269 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Thu, 27 Feb 2025 15:34:09 +0800 Subject: [PATCH 0703/1090] rapidio: fix an API misues when rio_add_net() fails rio_add_net() calls device_register() and fails when device_register() fails. Thus, put_device() should be used rather than kfree(). Add "mport->net = NULL;" to avoid a use after free issue. Link: https://lkml.kernel.org/r/20250227073409.3696854-1-haoxiang_li2024@163.com Fixes: e8de370188d0 ("rapidio: add mport char device driver") Signed-off-by: Haoxiang Li Reviewed-by: Dan Carpenter Cc: Alexandre Bounine Cc: Matt Porter Cc: Yang Yingliang Cc: Signed-off-by: Andrew Morton --- drivers/rapidio/devices/rio_mport_cdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 27afbb9d544b..cbf531d0ba68 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -1742,7 +1742,8 @@ static int rio_mport_add_riodev(struct mport_cdev_priv *priv, err = rio_add_net(net); if (err) { rmcd_debug(RDEV, "failed to register net, err=%d", err); - kfree(net); + put_device(&net->dev); + mport->net = NULL; goto cleanup; } } From e842f9a1edf306bf36fe2a4d847a0b0d458770de Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Thu, 27 Feb 2025 12:11:31 +0800 Subject: [PATCH 0704/1090] rapidio: add check for rio_add_net() in rio_scan_alloc_net() The return value of rio_add_net() should be checked. If it fails, put_device() should be called to free the memory and give up the reference initialized in rio_add_net(). Link: https://lkml.kernel.org/r/20250227041131.3680761-1-haoxiang_li2024@163.com Fixes: e6b585ca6e81 ("rapidio: move net allocation into core code") Signed-off-by: Yang Yingliang Signed-off-by: Haoxiang Li Cc: Alexandre Bounine Cc: Matt Porter Cc: Dan Carpenter Cc: Signed-off-by: Andrew Morton --- drivers/rapidio/rio-scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index fdcf742b2adb..c12941f71e2c 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -871,7 +871,10 @@ static struct rio_net *rio_scan_alloc_net(struct rio_mport *mport, dev_set_name(&net->dev, "rnet_%d", net->id); net->dev.parent = &mport->dev; net->dev.release = rio_scan_release_dev; - rio_add_net(net); + if (rio_add_net(net)) { + put_device(&net->dev); + net = NULL; + } } return net; From 8fe9ed44dc29fba0786b7e956d2e87179e407582 Mon Sep 17 00:00:00 2001 From: Hao Zhang Date: Thu, 27 Feb 2025 11:41:29 +0800 Subject: [PATCH 0705/1090] mm/page_alloc: fix uninitialized variable The variable "compact_result" is not initialized in function __alloc_pages_slowpath(). It causes should_compact_retry() to use an uninitialized value. Initialize variable "compact_result" with the value COMPACT_SKIPPED. BUG: KMSAN: uninit-value in __alloc_pages_slowpath+0xee8/0x16c0 mm/page_alloc.c:4416 __alloc_pages_slowpath+0xee8/0x16c0 mm/page_alloc.c:4416 __alloc_frozen_pages_noprof+0xa4c/0xe00 mm/page_alloc.c:4752 alloc_pages_mpol+0x4cd/0x890 mm/mempolicy.c:2270 alloc_frozen_pages_noprof mm/mempolicy.c:2341 [inline] alloc_pages_noprof mm/mempolicy.c:2361 [inline] folio_alloc_noprof+0x1dc/0x350 mm/mempolicy.c:2371 filemap_alloc_folio_noprof+0xa6/0x440 mm/filemap.c:1019 __filemap_get_folio+0xb9a/0x1840 mm/filemap.c:1970 grow_dev_folio fs/buffer.c:1039 [inline] grow_buffers fs/buffer.c:1105 [inline] __getblk_slow fs/buffer.c:1131 [inline] bdev_getblk+0x2c9/0xab0 fs/buffer.c:1431 getblk_unmovable include/linux/buffer_head.h:369 [inline] ext4_getblk+0x3b7/0xe50 fs/ext4/inode.c:864 ext4_bread_batch+0x9f/0x7d0 fs/ext4/inode.c:933 __ext4_find_entry+0x1ebb/0x36c0 fs/ext4/namei.c:1627 ext4_lookup_entry fs/ext4/namei.c:1729 [inline] ext4_lookup+0x189/0xb40 fs/ext4/namei.c:1797 __lookup_slow+0x538/0x710 fs/namei.c:1793 lookup_slow+0x6a/0xd0 fs/namei.c:1810 walk_component fs/namei.c:2114 [inline] link_path_walk+0xf29/0x1420 fs/namei.c:2479 path_openat+0x30f/0x6250 fs/namei.c:3985 do_filp_open+0x268/0x600 fs/namei.c:4016 do_sys_openat2+0x1bf/0x2f0 fs/open.c:1428 do_sys_open fs/open.c:1443 [inline] __do_sys_openat fs/open.c:1459 [inline] __se_sys_openat fs/open.c:1454 [inline] __x64_sys_openat+0x2a1/0x310 fs/open.c:1454 x64_sys_call+0x36f5/0x3c30 arch/x86/include/generated/asm/syscalls_64.h:258 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Local variable compact_result created at: __alloc_pages_slowpath+0x66/0x16c0 mm/page_alloc.c:4218 __alloc_frozen_pages_noprof+0xa4c/0xe00 mm/page_alloc.c:4752 Link: https://lkml.kernel.org/r/tencent_ED1032321D6510B145CDBA8CBA0093178E09@qq.com Reported-by: syzbot+0cfd5e38e96a5596f2b6@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0cfd5e38e96a5596f2b6 Signed-off-by: Hao Zhang Reviewed-by: Vlastimil Babka Cc: Michal Hocko Cc: Mel Gorman Cc: Signed-off-by: Andrew Morton --- mm/page_alloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index fe986e6de7a0..94917c729120 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4243,6 +4243,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, restart: compaction_retries = 0; no_progress_loops = 0; + compact_result = COMPACT_SKIPPED; compact_priority = DEF_COMPACT_PRIORITY; cpuset_mems_cookie = read_mems_allowed_begin(); zonelist_iter_cookie = zonelist_iter_begin(); From 80da96d735094ea22985ced98bc57fe3a4422921 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 4 Mar 2025 14:41:57 +0100 Subject: [PATCH 0706/1090] drm/bochs: Fix DPMS regression The recent rewrite with the use of regular atomic helpers broke the DPMS unblanking on X11. Fix it by moving the call of bochs_hw_blank(false) from CRTC mode_set_nofb() to atomic_enable(). Fixes: 2037174993c8 ("drm/bochs: Use regular atomic helpers") Link: https://bugzilla.suse.com/show_bug.cgi?id=1238209 Signed-off-by: Takashi Iwai Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250304134203.20534-1-tiwai@suse.de --- drivers/gpu/drm/tiny/bochs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c index c67e1f906785..8706763af8fb 100644 --- a/drivers/gpu/drm/tiny/bochs.c +++ b/drivers/gpu/drm/tiny/bochs.c @@ -335,8 +335,6 @@ static void bochs_hw_setmode(struct bochs_device *bochs, struct drm_display_mode bochs->xres, bochs->yres, bochs->bpp, bochs->yres_virtual); - bochs_hw_blank(bochs, false); - bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, 0); bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP, bochs->bpp); bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES, bochs->xres); @@ -506,6 +504,9 @@ static int bochs_crtc_helper_atomic_check(struct drm_crtc *crtc, static void bochs_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { + struct bochs_device *bochs = to_bochs_device(crtc->dev); + + bochs_hw_blank(bochs, false); } static void bochs_crtc_helper_atomic_disable(struct drm_crtc *crtc, From d385c8bceb14665e935419334aa3d3fac2f10456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutn=C3=BD?= Date: Wed, 5 Mar 2025 15:58:49 +0100 Subject: [PATCH 0707/1090] pid: Do not set pid_max in new pid namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is already difficult for users to troubleshoot which of multiple pid limits restricts their workload. The per-(hierarchical-)NS pid_max would contribute to the confusion. Also, the implementation copies the limit upon creation from parent, this pattern showed cumbersome with some attributes in legacy cgroup controllers -- it's subject to race condition between parent's limit modification and children creation and once copied it must be changed in the descendant. Let's do what other places do (ucounts or cgroup limits) -- create new pid namespaces without any limit at all. The global limit (actually any ancestor's limit) is still effectively in place, we avoid the set/unshare race and bumps of global (ancestral) limit have the desired effect on pid namespace that do not care. Link: https://lore.kernel.org/r/20240408145819.8787-1-mkoutny@suse.com/ Link: https://lore.kernel.org/r/20250221170249.890014-1-mkoutny@suse.com/ Fixes: 7863dcc72d0f4 ("pid: allow pid_max to be set per pid namespace") Signed-off-by: Michal Koutný Link: https://lore.kernel.org/r/20250305145849.55491-1-mkoutny@suse.com Signed-off-by: Christian Brauner --- kernel/pid_namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 8f6cfec87555..7098ed44e717 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -107,7 +107,7 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns goto out_free_idr; ns->ns.ops = &pidns_operations; - ns->pid_max = parent_pid_ns->pid_max; + ns->pid_max = PID_MAX_LIMIT; err = register_pidns_sysctls(ns); if (err) goto out_free_inum; From 14672f059d83f591afb2ee1fff56858efe055e5a Mon Sep 17 00:00:00 2001 From: Shrikanth Hegde Date: Thu, 6 Mar 2025 10:59:53 +0530 Subject: [PATCH 0708/1090] sched/deadline: Use online cpus for validating runtime The ftrace selftest reported a failure because writing -1 to sched_rt_runtime_us returns -EBUSY. This happens when the possible CPUs are different from active CPUs. Active CPUs are part of one root domain, while remaining CPUs are part of def_root_domain. Since active cpumask is being used, this results in cpus=0 when a non active CPUs is used in the loop. Fix it by looping over the online CPUs instead for validating the bandwidth calculations. Signed-off-by: Shrikanth Hegde Signed-off-by: Ingo Molnar Reviewed-by: Juri Lelli Link: https://lore.kernel.org/r/20250306052954.452005-2-sshegde@linux.ibm.com --- kernel/sched/deadline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 38e4537790af..ff4df16b5186 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -3189,7 +3189,7 @@ int sched_dl_global_validate(void) * value smaller than the currently allocated bandwidth in * any of the root_domains. */ - for_each_possible_cpu(cpu) { + for_each_online_cpu(cpu) { rcu_read_lock_sched(); if (dl_bw_visited(cpu, gen)) From b1536481c81fb604074da799e4f2d2038a1663f7 Mon Sep 17 00:00:00 2001 From: Shrikanth Hegde Date: Thu, 6 Mar 2025 10:59:54 +0530 Subject: [PATCH 0709/1090] sched/rt: Update limit of sched_rt sysctl in documentation By default fair_server dl_server allocates 5% of the bandwidth to the root domain. Due to this writing any value less than 5% fails due to -EBUSY: $ cat /proc/sys/kernel/sched_rt_period_us 1000000 $ echo 49999 > /proc/sys/kernel/sched_rt_runtime_us -bash: echo: write error: Device or resource busy $ echo 50000 > /proc/sys/kernel/sched_rt_runtime_us $ Since the sched_rt_runtime_us allows -1 as the minimum, put this restriction in the documentation. One should check average of runtime/period in /sys/kernel/debug/sched/fair_server/cpuX/* for exact value. Signed-off-by: Shrikanth Hegde Signed-off-by: Ingo Molnar Reviewed-by: Juri Lelli Link: https://lore.kernel.org/r/20250306052954.452005-3-sshegde@linux.ibm.com --- Documentation/scheduler/sched-rt-group.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/scheduler/sched-rt-group.rst b/Documentation/scheduler/sched-rt-group.rst index 80b05a3009ea..ab464335d320 100644 --- a/Documentation/scheduler/sched-rt-group.rst +++ b/Documentation/scheduler/sched-rt-group.rst @@ -102,6 +102,9 @@ The system wide settings are configured under the /proc virtual file system: * sched_rt_period_us takes values from 1 to INT_MAX. * sched_rt_runtime_us takes values from -1 to sched_rt_period_us. * A run time of -1 specifies runtime == period, ie. no limit. + * sched_rt_runtime_us/sched_rt_period_us > 0.05 inorder to preserve + bandwidth for fair dl_server. For accurate value check average of + runtime/period in /sys/kernel/debug/sched/fair_server/cpuX/ 2.2 Default behaviour From cf7ee25e70c6edfac4553d6b671e8b19db1d9573 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 4 Mar 2025 13:59:51 +0800 Subject: [PATCH 0710/1090] mctp i3c: handle NULL header address daddr can be NULL if there is no neighbour table entry present, in that case the tx packet should be dropped. saddr will usually be set by MCTP core, but check for NULL in case a packet is transmitted by a different protocol. Signed-off-by: Matt Johnston Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver") Link: https://patch.msgid.link/20250304-mctp-i3c-null-v1-1-4416bbd56540@codeconstruct.com.au Signed-off-by: Paolo Abeni --- drivers/net/mctp/mctp-i3c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c index d247fe483c58..c1e72253063b 100644 --- a/drivers/net/mctp/mctp-i3c.c +++ b/drivers/net/mctp/mctp-i3c.c @@ -507,6 +507,9 @@ static int mctp_i3c_header_create(struct sk_buff *skb, struct net_device *dev, { struct mctp_i3c_internal_hdr *ihdr; + if (!daddr || !saddr) + return -EINVAL; + skb_push(skb, sizeof(struct mctp_i3c_internal_hdr)); skb_reset_mac_header(skb); ihdr = (void *)skb_mac_header(skb); From 0e7633d7b95b67f1758aea19f8e85621c5f506a3 Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Tue, 4 Mar 2025 19:10:39 +0100 Subject: [PATCH 0711/1090] net: ipv6: fix dst ref loop in ila lwtunnel This patch follows commit 92191dd10730 ("net: ipv6: fix dst ref loops in rpl, seg6 and ioam6 lwtunnels") and, on a second thought, the same patch is also needed for ila (even though the config that triggered the issue was pathological, but still, we don't want that to happen). Fixes: 79ff2fc31e0f ("ila: Cache a route to translated address") Cc: Tom Herbert Signed-off-by: Justin Iurman Link: https://patch.msgid.link/20250304181039.35951-1-justin.iurman@uliege.be Signed-off-by: Paolo Abeni --- net/ipv6/ila/ila_lwt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index ff7e734e335b..ac4bcc623603 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -88,7 +88,8 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) goto drop; } - if (ilwt->connected) { + /* cache only if we don't create a dst reference loop */ + if (ilwt->connected && orig_dst->lwtstate != dst->lwtstate) { local_bh_disable(); dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr); local_bh_enable(); From 5da15a9c11c1c47ef573e6805b60a7d8a1687a2a Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Wed, 5 Mar 2025 09:16:55 +0100 Subject: [PATCH 0712/1090] net: ipv6: fix missing dst ref drop in ila lwtunnel Add missing skb_dst_drop() to drop reference to the old dst before adding the new dst to the skb. Fixes: 79ff2fc31e0f ("ila: Cache a route to translated address") Cc: Tom Herbert Signed-off-by: Justin Iurman Link: https://patch.msgid.link/20250305081655.19032-1-justin.iurman@uliege.be Signed-off-by: Paolo Abeni --- net/ipv6/ila/ila_lwt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index ac4bcc623603..7d574f5132e2 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -96,6 +96,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) } } + skb_dst_drop(skb); skb_dst_set(skb, dst); return dst_output(net, sk, skb); From 9a665fe3d967fe46edb4fd2497c7a5cc2dac2f55 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 6 Mar 2025 11:44:41 +0100 Subject: [PATCH 0713/1090] USB: serial: option: match on interface class for Telit FN990B The device id entries for Telit FN990B ended up matching only on the interface protocol. While this works, the protocol is qualified by the interface class (and subclass) which should have been included. Switch to matching using USB_DEVICE_AND_INTERFACE_INFO() while keeping the entries sorted also by protocol for consistency. Link: https://lore.kernel.org/20250227110655.3647028-2-fabio.porcedda@gmail.com/ Cc: Fabio Porcedda Cc: Daniele Palmas Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 58bd54e8c483..1ea2870725ac 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1394,22 +1394,22 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x60) }, /* Telit FN990B (rmnet) */ - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x40) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x30), + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x30), /* Telit FN990B (rmnet) */ .driver_info = NCTRL(5) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x60) }, /* Telit FN990B (MBIM) */ - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x40) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x30), + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */ .driver_info = NCTRL(6) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x60) }, /* Telit FN990B (RNDIS) */ - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x40) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x30), + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x30), /* Telit FN990B (RNDIS) */ .driver_info = NCTRL(6) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x60) }, /* Telit FN990B (ECM) */ - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x40) }, - { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x30), + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x30), /* Telit FN990B (ECM) */ .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x60) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), From 4981bb50392b7515b765da28cf8768ce624c2670 Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Tue, 4 Mar 2025 10:19:38 +0100 Subject: [PATCH 0714/1090] USB: serial: option: add Telit Cinterion FE990B compositions Add the following Telit Cinterion FE990B40 compositions: 0x10b0: rmnet + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) + tty (diag) + DPL + QDSS (Qualcomm Debug SubSystem) + adb T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 7 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10b0 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=28c2595e C: #Ifs= 9 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10b1: MBIM + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) + tty (diag) + DPL + QDSS (Qualcomm Debug SubSystem) + adb T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10b1 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=28c2595e C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10b2: RNDIS + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) + tty (diag) + DPL + QDSS (Qualcomm Debug SubSystem) + adb T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 9 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10b2 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=28c2595e C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=ef(misc ) Sub=04 Prot=01 Driver=rndis_host E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10b3: ECM + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (AT) + tty (diag) + DPL + QDSS (Qualcomm Debug SubSystem) + adb T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 11 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10b3 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FE990 S: SerialNumber=28c2595e C: #Ifs=10 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 8 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=8d(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 9 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Cc: stable@vger.kernel.org Signed-off-by: Fabio Porcedda Reviewed-by: Daniele Palmas [ johan: use USB_DEVICE_AND_INTERFACE_INFO() and sort by protocol ] Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1ea2870725ac..aeb71d96a828 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1388,6 +1388,22 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x30), /* Telit FE990B (rmnet) */ + .driver_info = NCTRL(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x30), /* Telit FE990B (MBIM) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x30), /* Telit FE990B (RNDIS) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x60) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x30), /* Telit FE990B (ECM) */ + .driver_info = NCTRL(6) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x60) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */ From 6232f0d8e100a26275bbd773fc56a60af2c95322 Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Tue, 4 Mar 2025 10:19:39 +0100 Subject: [PATCH 0715/1090] USB: serial: option: fix Telit Cinterion FE990A name The correct name for FE990 is FE990A so use it in order to avoid confusion with FE990B. Cc: stable@vger.kernel.org Signed-off-by: Fabio Porcedda Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index aeb71d96a828..5cd26dac2069 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1368,13 +1368,13 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ .driver_info = RSVD(0) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990 (MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990 (RNDIS) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990A (RNDIS) */ .driver_info = NCTRL(2) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990A (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, From 9af152dcf1a06f589f44a74da4ad67e365d4db9a Mon Sep 17 00:00:00 2001 From: Ivan Abramov Date: Thu, 6 Mar 2025 14:20:45 +0300 Subject: [PATCH 0716/1090] drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data() Since pci_get_domain_bus_and_slot() can return NULL, add NULL check for pci_gfx_root in the mid_get_vbt_data(). This change is similar to the checks implemented in mid_get_fuse_settings() and mid_get_pci_revID(), which were introduced by commit 0cecdd818cd7 ("gma500: Final enables for Oaktrail") as "additional minor bulletproofing". Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: f910b411053f ("gma500: Add the glue to the various BIOS and firmware interfaces") Signed-off-by: Ivan Abramov Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20250306112046.17144-1-i.abramov@mt-integration.ru --- drivers/gpu/drm/gma500/mid_bios.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index 7e76790c6a81..cba97d7db131 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -279,6 +279,11 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv) 0, PCI_DEVFN(2, 0)); int ret = -1; + if (pci_gfx_root == NULL) { + WARN_ON(1); + return; + } + /* Get the address of the platform config vbt */ pci_read_config_dword(pci_gfx_root, 0xFC, &addr); pci_dev_put(pci_gfx_root); From b5e3956535466187657563b754ba0f1da8626c7f Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Thu, 6 Mar 2025 14:39:51 +0800 Subject: [PATCH 0717/1090] kbuild: install-extmod-build: Fix build when specifying KBUILD_OUTPUT Since commit 5f73e7d0386d ("kbuild: refactor cross-compiling linux-headers package"), the linux-headers pacman package fails to build when "O=" is set. The build system complains: /mnt/chroot/linux/scripts/Makefile.build:41: mnt/chroots/linux-mainline/pacman/linux-upstream/pkg/linux-upstream-headers/usr//lib/modules/6.14.0-rc3-00350-g771dba31fffc/build/scripts/Makefile: No such file or directory This is because the "srcroot" variable is set to "." and the "build" variable is set to the absolute path. This makes the "src" variables point to wrong directory. Change the "build" variable to a relative path to "." to fix build. Fixes: 5f73e7d0386d ("kbuild: refactor cross-compiling linux-headers package") Signed-off-by: Inochi Amaoto Signed-off-by: Masahiro Yamada --- scripts/package/install-extmod-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build index 2966473b4660..b96538787f3d 100755 --- a/scripts/package/install-extmod-build +++ b/scripts/package/install-extmod-build @@ -63,7 +63,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then # Clear VPATH and srcroot because the source files reside in the output # directory. # shellcheck disable=SC2016 # $(MAKE) and $(build) will be expanded by Make - "${MAKE}" run-command KBUILD_RUN_COMMAND='+$(MAKE) HOSTCC='"${CC}"' VPATH= srcroot=. $(build)='"${destdir}"/scripts + "${MAKE}" run-command KBUILD_RUN_COMMAND='+$(MAKE) HOSTCC='"${CC}"' VPATH= srcroot=. $(build)='"$(realpath --relative-base=. "${destdir}")"/scripts rm -f "${destdir}/scripts/Kbuild" fi From fb8286562ecfb585e26b033c5e32e6fb85efb0b3 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 6 Mar 2025 04:05:26 +0100 Subject: [PATCH 0718/1090] netfilter: nf_tables: make destruction work queue pernet The call to flush_work before tearing down a table from the netlink notifier was supposed to make sure that all earlier updates (e.g. rule add) that might reference that table have been processed. Unfortunately, flush_work() waits for the last queued instance. This could be an instance that is different from the one that we must wait for. This is because transactions are protected with a pernet mutex, but the work item is global, so holding the transaction mutex doesn't prevent another netns from queueing more work. Make the work item pernet so that flush_work() will wait for all transactions queued from this netns. A welcome side effect is that we no longer need to wait for transaction objects from foreign netns. The gc work queue is still global. This seems to be ok because nft_set structures are reference counted and each container structure owns a reference on the net namespace. The destroy_list is still protected by a global spinlock rather than pernet one but the hold time is very short anyway. v2: call cancel_work_sync before reaping the remaining tables (Pablo). Fixes: 9f6958ba2e90 ("netfilter: nf_tables: unconditionally flush pending work before notifier") Reported-by: syzbot+5d8c5789c8cb076b2c25@syzkaller.appspotmail.com Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 4 +++- net/netfilter/nf_tables_api.c | 24 ++++++++++++++---------- net/netfilter/nft_compat.c | 8 ++++---- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 60d5dcdb289c..803d5f1601f9 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1891,7 +1891,7 @@ void nft_chain_filter_fini(void); void __init nft_chain_route_init(void); void nft_chain_route_fini(void); -void nf_tables_trans_destroy_flush_work(void); +void nf_tables_trans_destroy_flush_work(struct net *net); int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result); __be64 nf_jiffies64_to_msecs(u64 input); @@ -1905,6 +1905,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re struct nftables_pernet { struct list_head tables; struct list_head commit_list; + struct list_head destroy_list; struct list_head commit_set_list; struct list_head binding_list; struct list_head module_list; @@ -1915,6 +1916,7 @@ struct nftables_pernet { unsigned int base_seq; unsigned int gc_seq; u8 validate_state; + struct work_struct destroy_work; }; extern unsigned int nf_tables_net_id; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index a34de9c17cf1..c2df81b7e950 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -34,7 +34,6 @@ unsigned int nf_tables_net_id __read_mostly; static LIST_HEAD(nf_tables_expressions); static LIST_HEAD(nf_tables_objects); static LIST_HEAD(nf_tables_flowtables); -static LIST_HEAD(nf_tables_destroy_list); static LIST_HEAD(nf_tables_gc_list); static DEFINE_SPINLOCK(nf_tables_destroy_list_lock); static DEFINE_SPINLOCK(nf_tables_gc_list_lock); @@ -125,7 +124,6 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s table->validate_state = new_validate_state; } static void nf_tables_trans_destroy_work(struct work_struct *w); -static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work); static void nft_trans_gc_work(struct work_struct *work); static DECLARE_WORK(trans_gc_work, nft_trans_gc_work); @@ -10006,11 +10004,12 @@ static void nft_commit_release(struct nft_trans *trans) static void nf_tables_trans_destroy_work(struct work_struct *w) { + struct nftables_pernet *nft_net = container_of(w, struct nftables_pernet, destroy_work); struct nft_trans *trans, *next; LIST_HEAD(head); spin_lock(&nf_tables_destroy_list_lock); - list_splice_init(&nf_tables_destroy_list, &head); + list_splice_init(&nft_net->destroy_list, &head); spin_unlock(&nf_tables_destroy_list_lock); if (list_empty(&head)) @@ -10024,9 +10023,11 @@ static void nf_tables_trans_destroy_work(struct work_struct *w) } } -void nf_tables_trans_destroy_flush_work(void) +void nf_tables_trans_destroy_flush_work(struct net *net) { - flush_work(&trans_destroy_work); + struct nftables_pernet *nft_net = nft_pernet(net); + + flush_work(&nft_net->destroy_work); } EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work); @@ -10484,11 +10485,11 @@ static void nf_tables_commit_release(struct net *net) trans->put_net = true; spin_lock(&nf_tables_destroy_list_lock); - list_splice_tail_init(&nft_net->commit_list, &nf_tables_destroy_list); + list_splice_tail_init(&nft_net->commit_list, &nft_net->destroy_list); spin_unlock(&nf_tables_destroy_list_lock); nf_tables_module_autoload_cleanup(net); - schedule_work(&trans_destroy_work); + schedule_work(&nft_net->destroy_work); mutex_unlock(&nft_net->commit_mutex); } @@ -11853,7 +11854,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event, gc_seq = nft_gc_seq_begin(nft_net); - nf_tables_trans_destroy_flush_work(); + nf_tables_trans_destroy_flush_work(net); again: list_for_each_entry(table, &nft_net->tables, list) { if (nft_table_has_owner(table) && @@ -11895,6 +11896,7 @@ static int __net_init nf_tables_init_net(struct net *net) INIT_LIST_HEAD(&nft_net->tables); INIT_LIST_HEAD(&nft_net->commit_list); + INIT_LIST_HEAD(&nft_net->destroy_list); INIT_LIST_HEAD(&nft_net->commit_set_list); INIT_LIST_HEAD(&nft_net->binding_list); INIT_LIST_HEAD(&nft_net->module_list); @@ -11903,6 +11905,7 @@ static int __net_init nf_tables_init_net(struct net *net) nft_net->base_seq = 1; nft_net->gc_seq = 0; nft_net->validate_state = NFT_VALIDATE_SKIP; + INIT_WORK(&nft_net->destroy_work, nf_tables_trans_destroy_work); return 0; } @@ -11931,14 +11934,17 @@ static void __net_exit nf_tables_exit_net(struct net *net) if (!list_empty(&nft_net->module_list)) nf_tables_module_autoload_cleanup(net); + cancel_work_sync(&nft_net->destroy_work); __nft_release_tables(net); nft_gc_seq_end(nft_net, gc_seq); mutex_unlock(&nft_net->commit_mutex); + WARN_ON_ONCE(!list_empty(&nft_net->tables)); WARN_ON_ONCE(!list_empty(&nft_net->module_list)); WARN_ON_ONCE(!list_empty(&nft_net->notify_list)); + WARN_ON_ONCE(!list_empty(&nft_net->destroy_list)); } static void nf_tables_exit_batch(struct list_head *net_exit_list) @@ -12029,10 +12035,8 @@ static void __exit nf_tables_module_exit(void) unregister_netdevice_notifier(&nf_tables_flowtable_notifier); nft_chain_filter_fini(); nft_chain_route_fini(); - nf_tables_trans_destroy_flush_work(); unregister_pernet_subsys(&nf_tables_net_ops); cancel_work_sync(&trans_gc_work); - cancel_work_sync(&trans_destroy_work); rcu_barrier(); rhltable_destroy(&nft_objname_ht); nf_tables_core_module_exit(); diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 7ca4f0d21fe2..72711d62fddf 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -228,7 +228,7 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv) return 0; } -static void nft_compat_wait_for_destructors(void) +static void nft_compat_wait_for_destructors(struct net *net) { /* xtables matches or targets can have side effects, e.g. * creation/destruction of /proc files. @@ -236,7 +236,7 @@ static void nft_compat_wait_for_destructors(void) * work queue. If we have pending invocations we thus * need to wait for those to finish. */ - nf_tables_trans_destroy_flush_work(); + nf_tables_trans_destroy_flush_work(net); } static int @@ -262,7 +262,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr, nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv); - nft_compat_wait_for_destructors(); + nft_compat_wait_for_destructors(ctx->net); ret = xt_check_target(&par, size, proto, inv); if (ret < 0) { @@ -515,7 +515,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr, nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv); - nft_compat_wait_for_destructors(); + nft_compat_wait_for_destructors(ctx->net); return xt_check_match(&par, size, proto, inv); } From 269b844239149a9bbaba66518db99ebb06554a15 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 6 Mar 2025 10:42:33 +0000 Subject: [PATCH 0719/1090] ASoC: dapm: Fix changes to DECLARE_ADAU17X1_DSP_MUX_CTRL The changes to DECLARE_ADAU17X1_DSP_MUX_CTRL did avoid the issue with a compiler not liking all the macro indirection. However it introduced a new issue with respect to the mux not being declared static: sound/soc/codecs/adau17x1.c:275:8: sparse: sparse: symbol 'adau17x1_dac_mux' was not declared. Should it be static? sound/soc/codecs/adau17x1.c:278:8: sparse: sparse: symbol 'adau17x1_capture_mux' was not declared. Should it be static? Fix this up by going back to the inline declaration of the soc_enum, but just call SOC_ENUM_EXT directly rather than indirecting through SOC_DAPM_ENUM_EXT. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202503061119.4QGlnOi6-lkp@intel.com/ Fixes: c951b20766f0 ("ASoC: dapm: Use ASoC control macros where possible") Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250306104233.1638625-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau17x1.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 2ebb5c90bdd9..0b6b0d2115eb 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -254,13 +254,11 @@ static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol, } #define DECLARE_ADAU17X1_DSP_MUX_CTRL(_name, _label, _stream, _text) \ - const struct soc_enum _name##_enum = \ - SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \ - ARRAY_SIZE(_text), _text); \ const struct snd_kcontrol_new _name = \ - SOC_DAPM_ENUM_EXT(_label, _name##_enum, \ - adau17x1_dsp_mux_enum_get, \ - adau17x1_dsp_mux_enum_put) + SOC_ENUM_EXT(_label, (const struct soc_enum)\ + SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \ + ARRAY_SIZE(_text), _text), \ + adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put) static const char * const adau17x1_dac_mux_text[] = { "DSP", From 2c2eadd07e747059ccd65e68cd1d1b23ca96b072 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 5 Mar 2025 18:27:32 +0100 Subject: [PATCH 0720/1090] ASoC: cs42l43: convert to SYSTEM_SLEEP_PM_OPS The custom suspend function causes a build warning when CONFIG_PM_SLEEP is disabled: sound/soc/codecs/cs42l43.c:2405:12: error: unused function 'cs42l43_codec_runtime_force_suspend' [-Werror,-Wunused-function] Change SET_SYSTEM_SLEEP_PM_OPS() to the newer SYSTEM_SLEEP_PM_OPS(), to avoid this. Fixes: 164b7dd4546b ("ASoC: cs42l43: Add jack delay debounce after suspend") Signed-off-by: Arnd Bergmann Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250305172738.3437513-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l43.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index 4257dbefe9dd..e0d630c262f6 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2417,7 +2417,7 @@ static int cs42l43_codec_runtime_force_suspend(struct device *dev) static const struct dev_pm_ops cs42l43_codec_pm_ops = { RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) }; static const struct platform_device_id cs42l43_codec_id_table[] = { From 35d99c68af40a8ca175babc5a89ef7e2226fb3ca Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Mon, 3 Mar 2025 10:42:33 +0800 Subject: [PATCH 0721/1090] btrfs: fix a leaked chunk map issue in read_one_chunk() Add btrfs_free_chunk_map() to free the memory allocated by btrfs_alloc_chunk_map() if btrfs_add_chunk_map() fails. Fixes: 7dc66abb5a47 ("btrfs: use a dedicated data structure for chunk maps") CC: stable@vger.kernel.org Reviewed-by: Qu Wenruo Reviewed-by: Filipe Manana Signed-off-by: Haoxiang Li Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f6ae76815e4b..6f8dcf59b525 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -7151,6 +7151,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf, btrfs_err(fs_info, "failed to add chunk map, start=%llu len=%llu: %d", map->start, map->chunk_len, ret); + btrfs_free_chunk_map(map); } return ret; From 391b41f983bf7ff853de44704d8e14e7cc648a9b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 5 Mar 2025 16:37:50 +0000 Subject: [PATCH 0722/1090] gpio: rcar: Fix missing of_node_put() call of_parse_phandle_with_fixed_args() requires its caller to call into of_node_put() on the node pointer from the output structure, but such a call is currently missing. Call into of_node_put() to rectify that. Fixes: 159f8a0209af ("gpio-rcar: Add DT support") Signed-off-by: Fabrizio Castro Reviewed-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20250305163753.34913-2-fabrizio.castro.jz@renesas.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-rcar.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 8e0544e92488..a7a1cdf7ac66 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -468,7 +468,12 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) p->info = *info; ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args); - *npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK; + if (ret) { + *npins = RCAR_MAX_GPIO_PER_BANK; + } else { + *npins = args.args[2]; + of_node_put(args.np); + } if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) { dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n", From 7a2ff0510c51462c0a979f5006d375a2b23d46e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Mar 2025 02:06:27 +0000 Subject: [PATCH 0723/1090] ASoC: soc-pcm: reuse dpcm_state_string() We already have dpcm_state_string(). Let's reuse it. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87y0xi52vx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index c2d4becf0c3d..1b9ae03e83d0 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -144,7 +144,6 @@ static inline const char *soc_codec_dai_name(struct snd_soc_pcm_runtime *rtd) return (rtd)->dai_link->num_codecs == 1 ? snd_soc_rtd_to_codec(rtd, 0)->name : "multicodec"; } -#ifdef CONFIG_DEBUG_FS static const char *dpcm_state_string(enum snd_soc_dpcm_state state) { switch (state) { @@ -173,6 +172,7 @@ static const char *dpcm_state_string(enum snd_soc_dpcm_state state) return "unknown"; } +#ifdef CONFIG_DEBUG_FS static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, int stream, char *buf, size_t size) { @@ -1636,9 +1636,9 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, continue; if (be->dpcm[stream].users == 0) { - dev_err(be->dev, "ASoC: no users %s at close - state %d\n", + dev_err(be->dev, "ASoC: no users %s at close - state %s\n", snd_pcm_direction_name(stream), - be->dpcm[stream].state); + dpcm_state_string(be->dpcm[stream].state)); continue; } @@ -1687,9 +1687,9 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) /* first time the dpcm is open ? */ if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) { - dev_err(be->dev, "ASoC: too many users %s at open %d\n", + dev_err(be->dev, "ASoC: too many users %s at open %s\n", snd_pcm_direction_name(stream), - be->dpcm[stream].state); + dpcm_state_string(be->dpcm[stream].state)); continue; } @@ -1708,9 +1708,9 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) if (err < 0) { be->dpcm[stream].users--; if (be->dpcm[stream].users < 0) - dev_err(be->dev, "ASoC: no users %s at unwind %d\n", + dev_err(be->dev, "ASoC: no users %s at unwind %s\n", snd_pcm_direction_name(stream), - be->dpcm[stream].state); + dpcm_state_string(be->dpcm[stream].state)); be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; goto unwind; @@ -2572,8 +2572,8 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) { - dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", - fe->dai_link->name, fe->dpcm[stream].state); + dev_err(fe->dev, "ASoC: FE %s is not ready %s\n", + fe->dai_link->name, dpcm_state_string(fe->dpcm[stream].state)); ret = -EINVAL; goto disconnect; } From 5d5eceb9bb1050774dadc6919a258729f276fd00 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 6 Mar 2025 01:59:25 +0000 Subject: [PATCH 0724/1090] ASoC: soc-dai: add snd_soc_dai_mute_is_ctrled_at_trigger() Adds snd_soc_dai_mute_is_ctrled_at_trigger() to judge dai->driver->ops->mute_unmute_on_trigger flags Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/871pva6hs2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-dai.c | 12 ++++++++++-- sound/soc/soc-pcm.c | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index c3a3ba4b0bb7..d19ab5572d2b 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -193,7 +193,7 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, /* Digital Audio Interface mute */ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, int direction); - +int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai); int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, unsigned int *tx_num, unsigned int *tx_slot, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 8f2b5b840bb0..a210089747d0 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -364,6 +364,14 @@ int snd_soc_dai_prepare(struct snd_soc_dai *dai, } EXPORT_SYMBOL_GPL(snd_soc_dai_prepare); +int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai) +{ + if (dai->driver->ops) + return dai->driver->ops->mute_unmute_on_trigger; + + return 0; +} + /** * snd_soc_dai_digital_mute - configure DAI system or master clock. * @dai: DAI @@ -620,7 +628,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, if (ret < 0) break; - if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger) + if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) snd_soc_dai_digital_mute(dai, 0, substream->stream); soc_dai_mark_push(dai, substream, trigger); @@ -633,7 +641,7 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, if (rollback && !soc_dai_mark_match(dai, substream, trigger)) continue; - if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger) + if (snd_soc_dai_mute_is_ctrled_at_trigger(dai)) snd_soc_dai_digital_mute(dai, 1, substream->stream); r = soc_dai_trigger(dai, substream, cmd); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1b9ae03e83d0..403edd2fd8cf 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -949,7 +949,7 @@ static int __soc_pcm_prepare(struct snd_soc_pcm_runtime *rtd, SND_SOC_DAPM_STREAM_START); for_each_rtd_dais(rtd, i, dai) { - if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger) + if (!snd_soc_dai_mute_is_ctrled_at_trigger(dai)) snd_soc_dai_digital_mute(dai, 0, substream->stream); } @@ -1007,7 +1007,7 @@ static int soc_pcm_hw_clean(struct snd_soc_pcm_runtime *rtd, soc_pcm_set_dai_params(dai, NULL); if (snd_soc_dai_stream_active(dai, substream->stream) == 1) { - if (dai->driver->ops && !dai->driver->ops->mute_unmute_on_trigger) + if (!snd_soc_dai_mute_is_ctrled_at_trigger(dai)) snd_soc_dai_digital_mute(dai, 1, substream->stream); } } From ff712188daa3fe3ce7e11e530b4dca3826dae14a Mon Sep 17 00:00:00 2001 From: Miao Li Date: Tue, 4 Mar 2025 15:07:57 +0800 Subject: [PATCH 0725/1090] usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader When used on Huawei hisi platforms, Prolific Mass Storage Card Reader which the VID:PID is in 067b:2731 might fail to enumerate at boot time and doesn't work well with LPM enabled, combination quirks: USB_QUIRK_DELAY_INIT + USB_QUIRK_NO_LPM fixed the problems. Signed-off-by: Miao Li Cc: stable Link: https://lore.kernel.org/r/20250304070757.139473-1-limiao870622@163.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index dfcfc142bd5e..8efbacc5bc34 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -341,6 +341,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* Prolific Single-LUN Mass Storage Card Reader */ + { USB_DEVICE(0x067b, 0x2731), .driver_info = USB_QUIRK_DELAY_INIT | + USB_QUIRK_NO_LPM }, + /* Saitek Cyborg Gold Joystick */ { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, From b13abcb7ddd8d38de769486db5bd917537b32ab1 Mon Sep 17 00:00:00 2001 From: Andrei Kuchynski Date: Wed, 5 Mar 2025 11:17:39 +0000 Subject: [PATCH 0726/1090] usb: typec: ucsi: Fix NULL pointer access Resources should be released only after all threads that utilize them have been destroyed. This commit ensures that resources are not released prematurely by waiting for the associated workqueue to complete before deallocating them. Cc: stable Fixes: b9aa02ca39a4 ("usb: typec: ucsi: Add polling mechanism for partner tasks like alt mode checking") Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250305111739.1489003-2-akuchynski@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 7a56d3f840d7..2a2915b0a645 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1825,11 +1825,11 @@ static int ucsi_init(struct ucsi *ucsi) err_unregister: for (con = connector; con->port; con++) { + if (con->wq) + destroy_workqueue(con->wq); ucsi_unregister_partner(con); ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); ucsi_unregister_port_psy(con); - if (con->wq) - destroy_workqueue(con->wq); usb_power_delivery_unregister_capabilities(con->port_sink_caps); con->port_sink_caps = NULL; @@ -2013,10 +2013,6 @@ void ucsi_unregister(struct ucsi *ucsi) for (i = 0; i < ucsi->cap.num_connectors; i++) { cancel_work_sync(&ucsi->connector[i].work); - ucsi_unregister_partner(&ucsi->connector[i]); - ucsi_unregister_altmodes(&ucsi->connector[i], - UCSI_RECIPIENT_CON); - ucsi_unregister_port_psy(&ucsi->connector[i]); if (ucsi->connector[i].wq) { struct ucsi_work *uwork; @@ -2032,6 +2028,11 @@ void ucsi_unregister(struct ucsi *ucsi) destroy_workqueue(ucsi->connector[i].wq); } + ucsi_unregister_partner(&ucsi->connector[i]); + ucsi_unregister_altmodes(&ucsi->connector[i], + UCSI_RECIPIENT_CON); + ucsi_unregister_port_psy(&ucsi->connector[i]); + usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_sink_caps); ucsi->connector[i].port_sink_caps = NULL; usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_source_caps); From 74d42bdb3a4673b1c10d1f457184e4d3c9cb0196 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Mar 2025 07:30:42 -1000 Subject: [PATCH 0727/1090] fs/pipe: express 'pipe_empty()' in terms of 'pipe_occupancy()' That's what 'pipe_full()' does, so it's more consistent. But more importantly it gets the type limits right when the pipe head and tail are no longer necessarily 'unsigned int'. Signed-off-by: Linus Torvalds --- include/linux/pipe_fs_i.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index e572e6fc4f81..4d0a2267e6ef 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -176,16 +176,6 @@ static inline bool pipe_has_watch_queue(const struct pipe_inode_info *pipe) #endif } -/** - * pipe_empty - Return true if the pipe is empty - * @head: The pipe ring head pointer - * @tail: The pipe ring tail pointer - */ -static inline bool pipe_empty(unsigned int head, unsigned int tail) -{ - return head == tail; -} - /** * pipe_occupancy - Return number of slots used in the pipe * @head: The pipe ring head pointer @@ -196,6 +186,16 @@ static inline unsigned int pipe_occupancy(unsigned int head, unsigned int tail) return (pipe_index_t)(head - tail); } +/** + * pipe_empty - Return true if the pipe is empty + * @head: The pipe ring head pointer + * @tail: The pipe ring tail pointer + */ +static inline bool pipe_empty(unsigned int head, unsigned int tail) +{ + return !pipe_occupancy(head, tail); +} + /** * pipe_full - Return true if the pipe is full * @head: The pipe ring head pointer From d810d4c27bf34c719243bab9feb0d843edc09fd7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Mar 2025 07:33:58 -1000 Subject: [PATCH 0728/1090] fs/pipe: do not open-code pipe head/tail logic in FIONREAD Rasmus points out that we do indeed have other cases of breakage from the type changes that were introduced on 32-bit targets in order to read the pipe head and tail values atomically (commit 3d252160b818: "fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex"). Fix it up by using the proper helper functions that now deal with the pipe buffer index types properly. This makes the code simpler and more obvious. The compiler does the CSE and loop hoisting of the pipe ring size masking that we used to do manually, so open-coding this was never a good idea. Reported-by: Rasmus Villemoes Link: https://lore.kernel.org/all/87cyeu5zgk.fsf@prevas.dk/ Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg Nesterov Cc: Mateusz Guzik Cc: K Prateek Nayak Cc: Swapnil Sapkal Signed-off-by: Linus Torvalds --- fs/pipe.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index e8e6698f3698..5c872775a6db 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -614,7 +614,7 @@ out: static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct pipe_inode_info *pipe = filp->private_data; - unsigned int count, head, tail, mask; + unsigned int count, head, tail; switch (cmd) { case FIONREAD: @@ -622,10 +622,9 @@ static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) count = 0; head = pipe->head; tail = pipe->tail; - mask = pipe->ring_size - 1; - while (tail != head) { - count += pipe->bufs[tail & mask].len; + while (!pipe_empty(head, tail)) { + count += pipe_buf(pipe, tail)->len; tail++; } mutex_unlock(&pipe->mutex); From ebb0f38bb47f74b29e267babdbcd2c47d5292aa8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Mar 2025 07:53:25 -1000 Subject: [PATCH 0729/1090] fs/pipe: fix pipe buffer index use in FUSE This was another case that Rasmus pointed out where the direct access to the pipe head and tail pointers broke on 32-bit configurations due to the type changes. As with the pipe FIONREAD case, fix it by using the appropriate helper functions that deal with the right pipe index sizing. Reported-by: Rasmus Villemoes Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/ Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > Cc: Mateusz Guzik Cc: K Prateek Nayak Cc: Swapnil Sapkal Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 2b2d1b755544..3c9caafca9e2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2107,7 +2107,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { - unsigned int head, tail, mask, count; + unsigned int head, tail, count; unsigned nbuf; unsigned idx; struct pipe_buffer *bufs; @@ -2124,8 +2124,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, head = pipe->head; tail = pipe->tail; - mask = pipe->ring_size - 1; - count = head - tail; + count = pipe_occupancy(head, tail); bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); if (!bufs) { @@ -2135,8 +2134,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, nbuf = 0; rem = 0; - for (idx = tail; idx != head && rem < len; idx++) - rem += pipe->bufs[idx & mask].len; + for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++) + rem += pipe_buf(pipe, idx)->len; ret = -EINVAL; if (rem < len) @@ -2147,10 +2146,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, struct pipe_buffer *ibuf; struct pipe_buffer *obuf; - if (WARN_ON(nbuf >= count || tail == head)) + if (WARN_ON(nbuf >= count || pipe_empty(head, tail))) goto out_free; - ibuf = &pipe->bufs[tail & mask]; + ibuf = pipe_buf(pipe, tail); obuf = &bufs[nbuf]; if (rem >= ibuf->len) { From 6933c1067fe6df8ddb34dd68bdb2aa172cbd08c8 Mon Sep 17 00:00:00 2001 From: Alban Kurti Date: Thu, 6 Feb 2025 21:07:54 +0000 Subject: [PATCH 0730/1090] rust: init: add missing newline to pr_info! calls Several pr_info! calls in rust/kernel/init.rs (both in code examples and macro documentation) were missing a newline, causing logs to run together. This commit updates these calls to include a trailing newline, improving readability and consistency with the C side. Fixes: 6841d45a3030 ("rust: init: add `stack_pin_init!` macro") Fixes: 7f8977a7fe6d ("rust: init: add `{pin_}chain` functions to `{Pin}Init`") Fixes: d0fdc3961270 ("rust: init: add `PinnedDrop` trait and macros") Fixes: 4af84c6a85c6 ("rust: init: update expanded macro explanation") Reported-by: Miguel Ojeda Link: https://github.com/Rust-for-Linux/linux/issues/1139 Signed-off-by: Alban Kurti Link: https://lore.kernel.org/r/20250206-printing_fix-v3-3-a85273b501ae@invicto.ai [ Replaced Closes with Link since it fixes part of the issue. Added one more Fixes tag (still same set of stable kernels). - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/init.rs | 12 ++++++------ rust/kernel/init/macros.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs index 8bbd5e3398fc..e25d047f3c82 100644 --- a/rust/kernel/init.rs +++ b/rust/kernel/init.rs @@ -259,7 +259,7 @@ pub mod macros; /// }, /// })); /// let foo: Pin<&mut Foo> = foo; -/// pr_info!("a: {}", &*foo.a.lock()); +/// pr_info!("a: {}\n", &*foo.a.lock()); /// ``` /// /// # Syntax @@ -319,7 +319,7 @@ macro_rules! stack_pin_init { /// }, GFP_KERNEL)?, /// })); /// let foo = foo.unwrap(); -/// pr_info!("a: {}", &*foo.a.lock()); +/// pr_info!("a: {}\n", &*foo.a.lock()); /// ``` /// /// ```rust,ignore @@ -352,7 +352,7 @@ macro_rules! stack_pin_init { /// x: 64, /// }, GFP_KERNEL)?, /// })); -/// pr_info!("a: {}", &*foo.a.lock()); +/// pr_info!("a: {}\n", &*foo.a.lock()); /// # Ok::<_, AllocError>(()) /// ``` /// @@ -882,7 +882,7 @@ pub unsafe trait PinInit: Sized { /// /// impl Foo { /// fn setup(self: Pin<&mut Self>) { - /// pr_info!("Setting up foo"); + /// pr_info!("Setting up foo\n"); /// } /// } /// @@ -986,7 +986,7 @@ pub unsafe trait Init: PinInit { /// /// impl Foo { /// fn setup(&mut self) { - /// pr_info!("Setting up foo"); + /// pr_info!("Setting up foo\n"); /// } /// } /// @@ -1336,7 +1336,7 @@ impl InPlaceWrite for UniqueArc> { /// #[pinned_drop] /// impl PinnedDrop for Foo { /// fn drop(self: Pin<&mut Self>) { -/// pr_info!("Foo is being dropped!"); +/// pr_info!("Foo is being dropped!\n"); /// } /// } /// ``` diff --git a/rust/kernel/init/macros.rs b/rust/kernel/init/macros.rs index 1fd146a83241..b7213962a6a5 100644 --- a/rust/kernel/init/macros.rs +++ b/rust/kernel/init/macros.rs @@ -45,7 +45,7 @@ //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { -//! pr_info!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped.\n"); //! } //! } //! @@ -412,7 +412,7 @@ //! #[pinned_drop] //! impl PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>) { -//! pr_info!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped.\n"); //! } //! } //! ``` @@ -423,7 +423,7 @@ //! // `unsafe`, full path and the token parameter are added, everything else stays the same. //! unsafe impl ::kernel::init::PinnedDrop for Foo { //! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) { -//! pr_info!("{self:p} is getting dropped."); +//! pr_info!("{self:p} is getting dropped.\n"); //! } //! } //! ``` From 50c3e77eb3712a039760345999709ee0fad83447 Mon Sep 17 00:00:00 2001 From: Alban Kurti Date: Thu, 6 Feb 2025 21:07:55 +0000 Subject: [PATCH 0731/1090] rust: sync: add missing newline in locked_by log example The pr_info! example in rust/kernel/sync/locked_by.rs was missing a newline. This patch appends the missing newline to ensure that log messages for locked resources display correctly. Fixes: 7b1f55e3a984 ("rust: sync: introduce `LockedBy`") Reported-by: Miguel Ojeda Link: https://github.com/Rust-for-Linux/linux/issues/1139 Signed-off-by: Alban Kurti Link: https://lore.kernel.org/r/20250206-printing_fix-v3-4-a85273b501ae@invicto.ai [ Replaced Closes with Link since it fixes part of the issue. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/sync/locked_by.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/sync/locked_by.rs b/rust/kernel/sync/locked_by.rs index a7b244675c2b..61f100a45b35 100644 --- a/rust/kernel/sync/locked_by.rs +++ b/rust/kernel/sync/locked_by.rs @@ -55,7 +55,7 @@ use core::{cell::UnsafeCell, mem::size_of, ptr}; /// fn print_bytes_used(dir: &Directory, file: &File) { /// let guard = dir.inner.lock(); /// let inner_file = file.inner.access(&guard); -/// pr_info!("{} {}", guard.bytes_used, inner_file.bytes_used); +/// pr_info!("{} {}\n", guard.bytes_used, inner_file.bytes_used); /// } /// /// /// Increments `bytes_used` for both the directory and file. From 0ea4c3906416cefd6ae7ae5e93af9f2ef1b8c39b Mon Sep 17 00:00:00 2001 From: Alban Kurti Date: Thu, 6 Feb 2025 21:07:56 +0000 Subject: [PATCH 0732/1090] rust: workqueue: add missing newline to pr_info! examples The documentation examples in rust/kernel/workqueue.rs use pr_info! calls that lack a trailing newline. To maintain consistency with kernel logging practices, this patch adds the newline to all affected examples. Fixes: 15b286d1fd05 ("rust: workqueue: add examples") Reported-by: Miguel Ojeda Link: https://github.com/Rust-for-Linux/linux/issues/1139 Signed-off-by: Alban Kurti Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20250206-printing_fix-v3-5-a85273b501ae@invicto.ai [ Replaced Closes with Link since it fixes part of the issue. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/workqueue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 0cd100d2aefb..b7be224cdf4b 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -60,7 +60,7 @@ //! type Pointer = Arc; //! //! fn run(this: Arc) { -//! pr_info!("The value is: {}", this.value); +//! pr_info!("The value is: {}\n", this.value); //! } //! } //! @@ -108,7 +108,7 @@ //! type Pointer = Arc; //! //! fn run(this: Arc) { -//! pr_info!("The value is: {}", this.value_1); +//! pr_info!("The value is: {}\n", this.value_1); //! } //! } //! @@ -116,7 +116,7 @@ //! type Pointer = Arc; //! //! fn run(this: Arc) { -//! pr_info!("The second value is: {}", this.value_2); +//! pr_info!("The second value is: {}\n", this.value_2); //! } //! } //! From c00b413a96261faef4ce22329153c6abd4acef25 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 6 Mar 2025 16:59:16 +0100 Subject: [PATCH 0733/1090] x86/boot: Sanitize boot params before parsing command line The 5-level paging code parses the command line to look for the 'no5lvl' string, and does so very early, before sanitize_boot_params() has been called and has been given the opportunity to wipe bogus data from the fields in boot_params that are not covered by struct setup_header, and are therefore supposed to be initialized to zero by the bootloader. This triggers an early boot crash when using syslinux-efi to boot a recent kernel built with CONFIG_X86_5LEVEL=y and CONFIG_EFI_STUB=n, as the 0xff padding that now fills the unused PE/COFF header is copied into boot_params by the bootloader, and interpreted as the top half of the command line pointer. Fix this by sanitizing the boot_params before use. Note that there is no harm in calling this more than once; subsequent invocations are able to spot that the boot_params have already been cleaned up. Signed-off-by: Ard Biesheuvel Signed-off-by: Ingo Molnar Cc: "H. Peter Anvin" Cc: Linus Torvalds Cc: # v6.1+ Link: https://lore.kernel.org/r/20250306155915.342465-2-ardb+git@google.com Closes: https://lore.kernel.org/all/202503041549.35913.ulrich.gemkow@ikr.uni-stuttgart.de --- arch/x86/boot/compressed/pgtable_64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c index c882e1f67af0..d8c5de40669d 100644 --- a/arch/x86/boot/compressed/pgtable_64.c +++ b/arch/x86/boot/compressed/pgtable_64.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "misc.h" #include +#include #include #include #include "pgtable.h" @@ -107,6 +108,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable) bool l5_required = false; /* Initialize boot_params. Required for cmdline_find_option_bool(). */ + sanitize_boot_params(bp); boot_params_ptr = bp; /* From 33255c161ac4be003ac87c434ebc49645d18a929 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 28 Feb 2025 20:07:58 -0500 Subject: [PATCH 0734/1090] bcachefs: Fix bch2_dev_journal_alloc() spuriously failing Previously, we fixed journal resize spuriousl failing with -BCH_ERR_open_buckets_empty, but initial journal allocation was missed because it didn't invoke the "block on allocator" loop at all. Factor out the "loop on allocator" code to fix that. Signed-off-by: Kent Overstreet --- fs/bcachefs/journal.c | 59 +++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 5dabbf3c0965..05b1250619ec 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -1021,8 +1021,8 @@ struct journal_buf *bch2_next_write_buffer_flush_journal_buf(struct journal *j, /* allocate journal on a device: */ -static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr, - bool new_fs, struct closure *cl) +static int bch2_set_nr_journal_buckets_iter(struct bch_dev *ca, unsigned nr, + bool new_fs, struct closure *cl) { struct bch_fs *c = ca->fs; struct journal_device *ja = &ca->journal; @@ -1150,26 +1150,20 @@ err_free: return ret; } -/* - * Allocate more journal space at runtime - not currently making use if it, but - * the code works: - */ -int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca, - unsigned nr) +static int bch2_set_nr_journal_buckets_loop(struct bch_fs *c, struct bch_dev *ca, + unsigned nr, bool new_fs) { struct journal_device *ja = &ca->journal; - struct closure cl; int ret = 0; + struct closure cl; closure_init_stack(&cl); - down_write(&c->state_lock); - /* don't handle reducing nr of buckets yet: */ if (nr < ja->nr) - goto unlock; + return 0; - while (ja->nr < nr) { + while (!ret && ja->nr < nr) { struct disk_reservation disk_res = { 0, 0, 0 }; /* @@ -1182,27 +1176,38 @@ int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca, * filesystem-wide allocation will succeed, this is a device * specific allocation - we can hang here: */ + if (!new_fs) { + ret = bch2_disk_reservation_get(c, &disk_res, + bucket_to_sector(ca, nr - ja->nr), 1, 0); + if (ret) + break; + } - ret = bch2_disk_reservation_get(c, &disk_res, - bucket_to_sector(ca, nr - ja->nr), 1, 0); - if (ret) - break; + ret = bch2_set_nr_journal_buckets_iter(ca, nr, new_fs, &cl); - ret = __bch2_set_nr_journal_buckets(ca, nr, false, &cl); + if (ret == -BCH_ERR_bucket_alloc_blocked || + ret == -BCH_ERR_open_buckets_empty) + ret = 0; /* wait and retry */ bch2_disk_reservation_put(c, &disk_res); - closure_sync(&cl); - - if (ret && - ret != -BCH_ERR_bucket_alloc_blocked && - ret != -BCH_ERR_open_buckets_empty) - break; } - bch_err_fn(c, ret); -unlock: + return ret; +} + +/* + * Allocate more journal space at runtime - not currently making use if it, but + * the code works: + */ +int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca, + unsigned nr) +{ + down_write(&c->state_lock); + int ret = bch2_set_nr_journal_buckets_loop(c, ca, nr, false); up_write(&c->state_lock); + + bch_err_fn(c, ret); return ret; } @@ -1228,7 +1233,7 @@ int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs) min(1 << 13, (1 << 24) / ca->mi.bucket_size)); - ret = __bch2_set_nr_journal_buckets(ca, nr, new_fs, NULL); + ret = bch2_set_nr_journal_buckets_loop(ca->fs, ca, nr, new_fs); err: bch_err_fn(ca, ret); return ret; From 8ba73f53dc5b7545776e09e6982115dcbcbabec4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 28 Feb 2025 11:34:41 -0500 Subject: [PATCH 0735/1090] bcachefs: copygc now skips non-rw devices There's no point in doing copygc on non-rw devices: the fragmentation doesn't matter if we're not writing to them, and we may not have anywhere to put the data on our other devices. Signed-off-by: Kent Overstreet --- fs/bcachefs/movinggc.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c index 21805509ab9e..6718dc37c5a3 100644 --- a/fs/bcachefs/movinggc.c +++ b/fs/bcachefs/movinggc.c @@ -74,20 +74,14 @@ static int bch2_bucket_is_movable(struct btree_trans *trans, struct move_bucket *b, u64 time) { struct bch_fs *c = trans->c; - struct btree_iter iter; - struct bkey_s_c k; - struct bch_alloc_v4 _a; - const struct bch_alloc_v4 *a; - int ret; - if (bch2_bucket_is_open(trans->c, - b->k.bucket.inode, - b->k.bucket.offset)) + if (bch2_bucket_is_open(c, b->k.bucket.inode, b->k.bucket.offset)) return 0; - k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_alloc, - b->k.bucket, BTREE_ITER_cached); - ret = bkey_err(k); + struct btree_iter iter; + struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_alloc, + b->k.bucket, BTREE_ITER_cached); + int ret = bkey_err(k); if (ret) return ret; @@ -95,13 +89,18 @@ static int bch2_bucket_is_movable(struct btree_trans *trans, if (!ca) goto out; - a = bch2_alloc_to_v4(k, &_a); + if (ca->mi.state != BCH_MEMBER_STATE_rw || + !bch2_dev_is_online(ca)) + goto out_put; + + struct bch_alloc_v4 _a; + const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a); b->k.gen = a->gen; b->sectors = bch2_bucket_sectors_dirty(*a); u64 lru_idx = alloc_lru_idx_fragmentation(*a, ca); ret = lru_idx && lru_idx <= time; - +out_put: bch2_dev_put(ca); out: bch2_trans_iter_exit(trans, &iter); From 115ef44a98220fddfab37a39a19370497cd718b9 Mon Sep 17 00:00:00 2001 From: Jun Yang Date: Wed, 5 Mar 2025 23:44:10 +0800 Subject: [PATCH 0736/1090] sched: address a potential NULL pointer dereference in the GRED scheduler. If kzalloc in gred_init returns a NULL pointer, the code follows the error handling path, invoking gred_destroy. This, in turn, calls gred_offload, where memset could receive a NULL pointer as input, potentially leading to a kernel crash. When table->opt is NULL in gred_init(), gred_change_table_def() is not called yet, so it is not necessary to call ->ndo_setup_tc() in gred_offload(). Signed-off-by: Jun Yang Reviewed-by: Cong Wang Fixes: f25c0515c521 ("net: sched: gred: dynamically allocate tc_gred_qopt_offload") Link: https://patch.msgid.link/20250305154410.3505642-1-juny24602@gmail.com Signed-off-by: Jakub Kicinski --- net/sched/sch_gred.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index ab6234b4fcd5..532fde548b88 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -913,7 +913,8 @@ static void gred_destroy(struct Qdisc *sch) for (i = 0; i < table->DPs; i++) gred_destroy_vq(table->tab[i]); - gred_offload(sch, TC_GRED_DESTROY); + if (table->opt) + gred_offload(sch, TC_GRED_DESTROY); kfree(table->opt); } From e7112524e5e885181cc5ae4d258f33b9dbe0b907 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 6 Mar 2025 08:27:51 -0800 Subject: [PATCH 0737/1090] block: Name the RQF flags enum Commit 5f89154e8e9e3445f9b59 ("block: Use enum to define RQF_x bit indexes") converted the RQF flags to an anonymous enum, which was a beneficial change. This patch goes one step further by naming the enum as "rqf_flags". This naming enables exporting these flags to BPF clients, eliminating the need to duplicate these flags in BPF code. Instead, BPF clients can now access the same kernel-side values through CO:RE (Compile Once, Run Everywhere), as shown in this example: rqf_stats = bpf_core_enum_value(enum rqf_flags, __RQF_STATS) Suggested-by: Yonghong Song Signed-off-by: Breno Leitao Link: https://lore.kernel.org/r/20250306-rqf_flags-v1-1-bbd64918b406@debian.org Signed-off-by: Jens Axboe --- include/linux/blk-mq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index fa2a76cc2f73..71f4f0cc3dac 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -28,7 +28,7 @@ typedef enum rq_end_io_ret (rq_end_io_fn)(struct request *, blk_status_t); typedef __u32 __bitwise req_flags_t; /* Keep rqf_name[] in sync with the definitions below */ -enum { +enum rqf_flags { /* drive already may have started this one */ __RQF_STARTED, /* request for flush sequence */ From 00a7d39898c8010bfd5ff62af31ca5db34421b38 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Mar 2025 18:25:35 -1000 Subject: [PATCH 0738/1090] fs/pipe: add simpler helpers for common cases The fix to atomically read the pipe head and tail state when not holding the pipe mutex has caused a number of headaches due to the size change of the involved types. It turns out that we don't have _that_ many places that access these fields directly and were affected, but we have more than we strictly should have, because our low-level helper functions have been designed to have intimate knowledge of how the pipes work. And as a result, that random noise of direct 'pipe->head' and 'pipe->tail' accesses makes it harder to pinpoint any actual potential problem spots remaining. For example, we didn't have a "is the pipe full" helper function, but instead had a "given these pipe buffer indexes and this pipe size, is the pipe full". That's because some low-level pipe code does actually want that much more complicated interface. But most other places literally just want a "is the pipe full" helper, and not having it meant that those places ended up being unnecessarily much too aware of this all. It would have been much better if only the very core pipe code that cared had been the one aware of this all. So let's fix it - better late than never. This just introduces the trivial wrappers for "is this pipe full or empty" and to get how many pipe buffers are used, so that instead of writing if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) the places that literally just want to know if a pipe is full can just say if (pipe_is_full(pipe)) instead. The existing trivial cases were converted with a 'sed' script. This cuts down on the places that access pipe->head and pipe->tail directly outside of the pipe code (and core splice code) quite a lot. The splice code in particular still revels in doing the direct low-level accesses, and the fuse fuse_dev_splice_write() code also seems a bit unnecessarily eager to go very low-level, but it's at least a bit better than it used to be. Signed-off-by: Linus Torvalds --- drivers/char/virtio_console.c | 4 ++-- fs/fuse/dev.c | 2 +- fs/pipe.c | 6 +++--- fs/splice.c | 20 ++++++++++---------- include/linux/pipe_fs_i.h | 27 +++++++++++++++++++++++++++ mm/filemap.c | 7 +++---- mm/shmem.c | 6 +++--- 7 files changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 24442485e73e..18f92dd44d45 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -923,14 +923,14 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, pipe_lock(pipe); ret = 0; - if (pipe_empty(pipe->head, pipe->tail)) + if (pipe_is_empty(pipe)) goto error_out; ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); if (ret < 0) goto error_out; - occupancy = pipe_occupancy(pipe->head, pipe->tail); + occupancy = pipe_buf_usage(pipe); buf = alloc_buf(port->portdev->vdev, 0, occupancy); if (!buf) { diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 3c9caafca9e2..2c3a4d09e500 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1457,7 +1457,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, if (ret < 0) goto out; - if (pipe_occupancy(pipe->head, pipe->tail) + cs.nr_segs > pipe->max_usage) { + if (pipe_buf_usage(pipe) + cs.nr_segs > pipe->max_usage) { ret = -EIO; goto out; } diff --git a/fs/pipe.c b/fs/pipe.c index 5c872775a6db..4d0799e4e719 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -394,7 +394,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to) wake_next_reader = true; mutex_lock(&pipe->mutex); } - if (pipe_empty(pipe->head, pipe->tail)) + if (pipe_is_empty(pipe)) wake_next_reader = false; mutex_unlock(&pipe->mutex); @@ -577,11 +577,11 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe)); mutex_lock(&pipe->mutex); - was_empty = pipe_empty(pipe->head, pipe->tail); + was_empty = pipe_is_empty(pipe); wake_next_writer = true; } out: - if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) + if (pipe_is_full(pipe)) wake_next_writer = false; mutex_unlock(&pipe->mutex); diff --git a/fs/splice.c b/fs/splice.c index 28cfa63aa236..23fa5561b944 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -331,7 +331,7 @@ ssize_t copy_splice_read(struct file *in, loff_t *ppos, int i; /* Work out how much data we can actually add into the pipe */ - used = pipe_occupancy(pipe->head, pipe->tail); + used = pipe_buf_usage(pipe); npages = max_t(ssize_t, pipe->max_usage - used, 0); len = min_t(size_t, len, npages * PAGE_SIZE); npages = DIV_ROUND_UP(len, PAGE_SIZE); @@ -527,7 +527,7 @@ static int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_des return -ERESTARTSYS; repeat: - while (pipe_empty(pipe->head, pipe->tail)) { + while (pipe_is_empty(pipe)) { if (!pipe->writers) return 0; @@ -820,7 +820,7 @@ ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, if (signal_pending(current)) break; - while (pipe_empty(pipe->head, pipe->tail)) { + while (pipe_is_empty(pipe)) { ret = 0; if (!pipe->writers) goto out; @@ -968,7 +968,7 @@ static ssize_t do_splice_read(struct file *in, loff_t *ppos, return 0; /* Don't try to read more the pipe has space for. */ - p_space = pipe->max_usage - pipe_occupancy(pipe->head, pipe->tail); + p_space = pipe->max_usage - pipe_buf_usage(pipe); len = min_t(size_t, len, p_space << PAGE_SHIFT); if (unlikely(len > MAX_RW_COUNT)) @@ -1080,7 +1080,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, more = sd->flags & SPLICE_F_MORE; sd->flags |= SPLICE_F_MORE; - WARN_ON_ONCE(!pipe_empty(pipe->head, pipe->tail)); + WARN_ON_ONCE(!pipe_is_empty(pipe)); while (len) { size_t read_len; @@ -1268,7 +1268,7 @@ static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags) send_sig(SIGPIPE, current, 0); return -EPIPE; } - if (!pipe_full(pipe->head, pipe->tail, pipe->max_usage)) + if (!pipe_is_full(pipe)) return 0; if (flags & SPLICE_F_NONBLOCK) return -EAGAIN; @@ -1652,13 +1652,13 @@ static int ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) * Check the pipe occupancy without the inode lock first. This function * is speculative anyways, so missing one is ok. */ - if (!pipe_empty(pipe->head, pipe->tail)) + if (!pipe_is_empty(pipe)) return 0; ret = 0; pipe_lock(pipe); - while (pipe_empty(pipe->head, pipe->tail)) { + while (pipe_is_empty(pipe)) { if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -1688,13 +1688,13 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) * Check pipe occupancy without the inode lock first. This function * is speculative anyways, so missing one is ok. */ - if (!pipe_full(pipe->head, pipe->tail, pipe->max_usage)) + if (!pipe_is_full(pipe)) return 0; ret = 0; pipe_lock(pipe); - while (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) { + while (pipe_is_full(pipe)) { if (!pipe->readers) { send_sig(SIGPIPE, current, 0); ret = -EPIPE; diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 4d0a2267e6ef..b698758000f8 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -208,6 +208,33 @@ static inline bool pipe_full(unsigned int head, unsigned int tail, return pipe_occupancy(head, tail) >= limit; } +/** + * pipe_is_full - Return true if the pipe is full + * @pipe: the pipe + */ +static inline bool pipe_is_full(const struct pipe_inode_info *pipe) +{ + return pipe_full(pipe->head, pipe->tail, pipe->max_usage); +} + +/** + * pipe_is_empty - Return true if the pipe is empty + * @pipe: the pipe + */ +static inline bool pipe_is_empty(const struct pipe_inode_info *pipe) +{ + return pipe_empty(pipe->head, pipe->tail); +} + +/** + * pipe_buf_usage - Return how many pipe buffers are in use + * @pipe: the pipe + */ +static inline unsigned int pipe_buf_usage(const struct pipe_inode_info *pipe) +{ + return pipe_occupancy(pipe->head, pipe->tail); +} + /** * pipe_buf - Return the pipe buffer for the specified slot in the pipe ring * @pipe: The pipe to access diff --git a/mm/filemap.c b/mm/filemap.c index d4564a79eb35..2974691fdfad 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2897,8 +2897,7 @@ size_t splice_folio_into_pipe(struct pipe_inode_info *pipe, size = min(size, folio_size(folio) - offset); offset %= PAGE_SIZE; - while (spliced < size && - !pipe_full(pipe->head, pipe->tail, pipe->max_usage)) { + while (spliced < size && !pipe_is_full(pipe)) { struct pipe_buffer *buf = pipe_head_buf(pipe); size_t part = min_t(size_t, PAGE_SIZE - offset, size - spliced); @@ -2955,7 +2954,7 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos, iocb.ki_pos = *ppos; /* Work out how much data we can actually add into the pipe */ - used = pipe_occupancy(pipe->head, pipe->tail); + used = pipe_buf_usage(pipe); npages = max_t(ssize_t, pipe->max_usage - used, 0); len = min_t(size_t, len, npages * PAGE_SIZE); @@ -3015,7 +3014,7 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos, total_spliced += n; *ppos += n; in->f_ra.prev_pos = *ppos; - if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) + if (pipe_is_full(pipe)) goto out; } diff --git a/mm/shmem.c b/mm/shmem.c index 4ea6109a8043..20032a333d80 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3487,7 +3487,7 @@ static size_t splice_zeropage_into_pipe(struct pipe_inode_info *pipe, size = min_t(size_t, size, PAGE_SIZE - offset); - if (!pipe_full(pipe->head, pipe->tail, pipe->max_usage)) { + if (!pipe_is_full(pipe)) { struct pipe_buffer *buf = pipe_head_buf(pipe); *buf = (struct pipe_buffer) { @@ -3514,7 +3514,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, int error = 0; /* Work out how much data we can actually add into the pipe */ - used = pipe_occupancy(pipe->head, pipe->tail); + used = pipe_buf_usage(pipe); npages = max_t(ssize_t, pipe->max_usage - used, 0); len = min_t(size_t, len, npages * PAGE_SIZE); @@ -3601,7 +3601,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, total_spliced += n; *ppos += n; in->f_ra.prev_pos = *ppos; - if (pipe_full(pipe->head, pipe->tail, pipe->max_usage)) + if (pipe_is_full(pipe)) break; cond_resched(); From d048c84bc1d6b831ca4e3381a16fb616ad96d8db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Mar 2025 09:28:26 +0100 Subject: [PATCH 0739/1090] wifi: rework MAINTAINERS entries a bit Since I really don't want to be CC'ed on every patch add X: entries for all the drivers that are otherwise covered. In some cases, add a bit more to drivers that have other entries, mostly for the vendor directories, but for libertas also add libertas_tf. While at it, also add all nl80211-related (vendor) UAPI header files to the nl80211 entry. Link: https://patch.msgid.link/20250306092831.f7fdfe7df7b2.I7c86da443038af32e9bcbaa5f53b1e4128a0d1f9@changeid Signed-off-by: Johannes Berg --- MAINTAINERS | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 73a6c3469274..e989ca218d37 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -124,6 +124,7 @@ F: include/net/ieee80211_radiotap.h F: include/net/iw_handler.h F: include/net/wext.h F: include/uapi/linux/nl80211.h +N: include/uapi/linux/nl80211-.* F: include/uapi/linux/wireless.h F: net/wireless/ @@ -514,7 +515,7 @@ F: drivers/hwmon/adm1029.c ADM8211 WIRELESS DRIVER L: linux-wireless@vger.kernel.org S: Orphan -F: drivers/net/wireless/admtek/adm8211.* +F: drivers/net/wireless/admtek/ ADP1050 HARDWARE MONITOR DRIVER M: Radu Sabau @@ -6195,7 +6196,7 @@ F: Documentation/process/cve.rst CW1200 WLAN driver S: Orphan -F: drivers/net/wireless/st/cw1200/ +F: drivers/net/wireless/st/ F: include/linux/platform_data/net-cw1200.h CX18 VIDEO4LINUX DRIVER @@ -13983,6 +13984,7 @@ MARVELL LIBERTAS WIRELESS DRIVER L: libertas-dev@lists.infradead.org S: Orphan F: drivers/net/wireless/marvell/libertas/ +F: drivers/net/wireless/marvell/libertas_tf/ MARVELL MACCHIATOBIN SUPPORT M: Russell King @@ -15652,7 +15654,7 @@ M: Ajay Singh M: Claudiu Beznea L: linux-wireless@vger.kernel.org S: Supported -F: drivers/net/wireless/microchip/wilc1000/ +F: drivers/net/wireless/microchip/ MICROSEMI MIPS SOCS M: Alexandre Belloni @@ -16438,6 +16440,23 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git F: Documentation/devicetree/bindings/net/wireless/ F: drivers/net/wireless/ +X: drivers/net/wireless/ath/ +X: drivers/net/wireless/broadcom/ +X: drivers/net/wireless/intel/ +X: drivers/net/wireless/intersil/ +X: drivers/net/wireless/marvell/ +X: drivers/net/wireless/mediatek/mt76/ +X: drivers/net/wireless/mediatek/mt7601u/ +X: drivers/net/wireless/microchip/ +X: drivers/net/wireless/purelifi/ +X: drivers/net/wireless/quantenna/ +X: drivers/net/wireless/ralink/ +X: drivers/net/wireless/realtek/ +X: drivers/net/wireless/rsi/ +X: drivers/net/wireless/silabs/ +X: drivers/net/wireless/st/ +X: drivers/net/wireless/ti/ +X: drivers/net/wireless/zydas/ NETWORKING [DSA] M: Andrew Lunn @@ -17822,7 +17841,7 @@ M: Christian Lamparter L: linux-wireless@vger.kernel.org S: Maintained W: https://wireless.wiki.kernel.org/en/users/Drivers/p54 -F: drivers/net/wireless/intersil/p54/ +F: drivers/net/wireless/intersil/ PACKET SOCKETS M: Willem de Bruijn @@ -19099,7 +19118,7 @@ PURELIFI PLFXLC DRIVER M: Srinivasan Raju L: linux-wireless@vger.kernel.org S: Supported -F: drivers/net/wireless/purelifi/plfxlc/ +F: drivers/net/wireless/purelifi/ PVRUSB2 VIDEO4LINUX DRIVER M: Mike Isely @@ -19650,7 +19669,7 @@ M: Igor Mitsyanko R: Sergey Matyukevich L: linux-wireless@vger.kernel.org S: Maintained -F: drivers/net/wireless/quantenna +F: drivers/net/wireless/quantenna/ RADEON and AMDGPU DRM DRIVERS M: Alex Deucher @@ -19731,7 +19750,7 @@ RALINK RT2X00 WIRELESS LAN DRIVER M: Stanislaw Gruszka L: linux-wireless@vger.kernel.org S: Maintained -F: drivers/net/wireless/ralink/rt2x00/ +F: drivers/net/wireless/ralink/ RAMDISK RAM BLOCK DEVICE DRIVER M: Jens Axboe @@ -21698,7 +21717,7 @@ SILICON LABS WIRELESS DRIVERS (for WFxxx series) M: Jérôme Pouiller S: Supported F: Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml -F: drivers/net/wireless/silabs/wfx/ +F: drivers/net/wireless/silabs/ SILICON MOTION SM712 FRAME BUFFER DRIVER M: Sudip Mukherjee @@ -26198,7 +26217,7 @@ F: mm/zbud.c ZD1211RW WIRELESS DRIVER L: linux-wireless@vger.kernel.org S: Orphan -F: drivers/net/wireless/zydas/zd1211rw/ +F: drivers/net/wireless/zydas/ ZD1301 MEDIA DRIVER L: linux-media@vger.kernel.org From bbb18f7e23a3f5f56d5c8b4ee0f78f00edb3b1b2 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 6 Mar 2025 12:25:46 +0200 Subject: [PATCH 0740/1090] wifi: iwlwifi: pcie: Fix TSO preparation The allocation of the scatter gather data structure should be done based on the number of memory chunks that need to be mapped, and it is not dependent on the overall payload length. Fix it. In addition, as the skb_to_sgvec() function returns an 'int' do not assign it to an 'unsigned int' as otherwise the error check would be useless. Fixes: 7f5e3038f029 ("wifi: iwlwifi: map entire SKB when sending AMSDUs") Signed-off-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250306122425.8c0e23a3d583.I3cb4d6768c9d28ce3da6cd0a6c65466176cfc1ee@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 7b6071a59b69..7c1dd5cc084a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1869,12 +1869,12 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, unsigned int offset) { struct sg_table *sgt; - unsigned int n_segments; + unsigned int n_segments = skb_shinfo(skb)->nr_frags + 1; + int orig_nents; if (WARN_ON_ONCE(skb_has_frag_list(skb))) return NULL; - n_segments = DIV_ROUND_UP(skb->len - offset, skb_shinfo(skb)->gso_size); *hdr = iwl_pcie_get_page_hdr(trans, hdr_room + __alignof__(struct sg_table) + sizeof(struct sg_table) + @@ -1889,11 +1889,12 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, sg_init_table(sgt->sgl, n_segments); /* Only map the data, not the header (it is copied to the TSO page) */ - sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, offset, - skb->len - offset); - if (WARN_ON_ONCE(sgt->orig_nents <= 0)) + orig_nents = skb_to_sgvec(skb, sgt->sgl, offset, skb->len - offset); + if (WARN_ON_ONCE(orig_nents <= 0)) return NULL; + sgt->orig_nents = orig_nents; + /* And map the entire SKB */ if (dma_map_sgtable(trans->dev, sgt, DMA_TO_DEVICE, 0) < 0) return NULL; From b8c8a03e9b7bfc06f366b75daf3d0812400e7123 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 6 Mar 2025 12:25:47 +0200 Subject: [PATCH 0741/1090] wifi: iwlwifi: mvm: fix PNVM timeout for non-MSI-X platforms When MSI-X is not enabled, we mask all the interrupts in the interrupt handler and re-enable them when the interrupt thread runs. If STATUS_INT_ENABLED is not set, we won't re-enable in the thread. In order to get the ALIVE interrupt, we allow the ALIVE interrupt itself, and RX as well in order to receive the ALIVE notification (which is received as an RX from the firmware. The problem is that STATUS_INT_ENABLED is clear until the op_mode calls trans_fw_alive which means that until trans_fw_alive is called, any notification from the firmware will not be received. This became a problem when we inserted the pnvm_load exactly between the ALIVE and trans_fw_alive. Fix that by calling trans_fw_alive before loading the PNVM. This will allow to get the notification from the firmware about PNVM load being complete and continue the flow normally. This didn't happen on MSI-X because we don't disable the interrupts in the ISR when MSI-X is available. The error in the log looks like this: iwlwifi 0000:00:03.0: Timeout waiting for PNVM load! iwlwifi 0000:00:03.0: Failed to start RT ucode: -110 iwlwifi 0000:00:03.0: WRT: Collecting data: ini trigger 13 fired (delay=0ms). Fixes: 70d3ca86b025 ("iwlwifi: mvm: ring the doorbell and wait for PNVM load completion") Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250306122425.0f2cf207aae1.I025d8f724b44f52eadf6c19069352eb9275613a8@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index df49dd2e2026..d10877856049 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2024 Intel Corporation + * Copyright (C) 2012-2014, 2018-2025 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -422,6 +422,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, /* if reached this point, Alive notification was received */ iwl_mei_alive_notif(true); + iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr); + ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait, &mvm->fw->ucode_capa); if (ret) { @@ -430,8 +432,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, return ret; } - iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr); - /* * Note: all the queues are enabled as part of the interface * initialization, but in firmware restart scenarios they From 1801a94299a5c7fc1a6825e92e1ce0dc7099faa9 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 6 Mar 2025 12:25:48 +0200 Subject: [PATCH 0742/1090] wifi: iwlwifi: trans: cancel restart work on op mode leave If the restart work happens to run after the opmode left (i.e. called iwl_trans_op_mode_leave), then the opmode memory (including its mutex) is likely to be freed already, and trans->opmode is NULL. Although the hw is stopped in that stage, which means that this restart got aborted (i.e. STATUS_RESET_PENDING will be cleared), it still can access trans->opmode (NULL pointer dereference) or the opmodes memory (which is freed). Fix this by canceling the restart wk in iwl_trans_op_mode_leave. Also make sure that the restart wk is really aborted. Fixes: 7391b2a4f7db ("wifi: iwlwifi: rework firmware error handling") Signed-off-by: Miri Korenblit Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20250306122425.801301ba1b8b.I6f6143f550b6335b699920c5d4b2b78449607a96@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 49c8507d1a6b..47854a36413e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -403,6 +403,8 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans) iwl_trans_pcie_op_mode_leave(trans); + cancel_work_sync(&trans->restart.wk); + trans->op_mode = NULL; trans->state = IWL_TRANS_NO_FW; From 43e04077170799d0e6289f3e928f727e401b3d79 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 6 Mar 2025 12:37:55 +0200 Subject: [PATCH 0743/1090] wifi: mac80211: flush the station before moving it to UN-AUTHORIZED state We first want to flush the station to make sure we no longer have any frames being Tx by the station before the station is moved to un-authorized state. Failing to do that will lead to races: a frame may be sent after the station's state has been changed. Since the API clearly states that the driver can't fail the sta_state() transition down the list of state, we can easily flush the station first, and only then call the driver's sta_state(). Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250306123626.450bc40e8b04.I636ba96843c77f13309c15c9fd6eb0c5a52a7976@changeid Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f83268fa9f92..caa3d0236b5e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -4,7 +4,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2023 Intel Corporation + * Copyright (C) 2018-2024 Intel Corporation */ #include @@ -1335,9 +1335,13 @@ static int _sta_info_move_state(struct sta_info *sta, sta->sta.addr, new_state); /* notify the driver before the actual changes so it can - * fail the transition + * fail the transition if the state is increasing. + * The driver is required not to fail when the transition + * is decreasing the state, so first, do all the preparation + * work and only then, notify the driver. */ - if (test_sta_flag(sta, WLAN_STA_INSERTED)) { + if (new_state > sta->sta_state && + test_sta_flag(sta, WLAN_STA_INSERTED)) { int err = drv_sta_state(sta->local, sta->sdata, sta, sta->sta_state, new_state); if (err) @@ -1413,6 +1417,16 @@ static int _sta_info_move_state(struct sta_info *sta, break; } + if (new_state < sta->sta_state && + test_sta_flag(sta, WLAN_STA_INSERTED)) { + int err = drv_sta_state(sta->local, sta->sdata, sta, + sta->sta_state, new_state); + + WARN_ONCE(err, + "Driver is not allowed to fail if the sta_state is transitioning down the list: %d\n", + err); + } + sta->sta_state = new_state; return 0; From 20d5a0b9cd0ccb32e886cf6baecf14936325bf10 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 6 Mar 2025 12:37:56 +0200 Subject: [PATCH 0744/1090] wifi: mac80211: don't queue sdata::work for a non-running sdata The worker really shouldn't be queued for a non-running interface. Also, if ieee80211_setup_sdata is called between queueing and executing the wk, it will be initialized, which will corrupt wiphy_work_list. Fixes: f8891461a277 ("mac80211: do not start any work during reconfigure flow") Signed-off-by: Miri Korenblit Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20250306123626.1e02caf82640.I4949e71ed56e7186ed4968fa9ddff477473fa2f4@changeid Signed-off-by: Johannes Berg --- net/mac80211/util.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 7f02bd5891eb..fdda14c08e2b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -6,7 +6,7 @@ * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * utilities for mac80211 */ @@ -2193,8 +2193,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) ieee80211_reconfig_roc(local); /* Requeue all works */ - list_for_each_entry(sdata, &local->interfaces, list) - wiphy_work_queue(local->hw.wiphy, &sdata->work); + list_for_each_entry(sdata, &local->interfaces, list) { + if (ieee80211_sdata_running(sdata)) + wiphy_work_queue(local->hw.wiphy, &sdata->work); + } } ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, From 2e85829ac7fbbd57b93f6cd334b6d448c9ce9db3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Mar 2025 12:37:57 +0200 Subject: [PATCH 0745/1090] wifi: nl80211: fix assoc link handling The refactoring of the assoc link handling in order to support multi-link reconfiguration broke the setting of the assoc link ID, and thus resulted in the wrong BSS "use_for" value being selected. Fix that for both association and ML reconfiguration. Fixes: 720fa448f5a7 ("wifi: nl80211: Split the links handling of an association request") Signed-off-by: Johannes Berg Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250306123626.7b233d769c32.I62fd04a8667dd55cedb9a1c0414cc92dd098da75@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e87267fbb442..aac0e7298dc7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -11123,6 +11123,7 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device static int nl80211_process_links(struct cfg80211_registered_device *rdev, struct cfg80211_assoc_link *links, + int assoc_link_id, const u8 *ssid, int ssid_len, struct genl_info *info) { @@ -11153,7 +11154,7 @@ static int nl80211_process_links(struct cfg80211_registered_device *rdev, } links[link_id].bss = nl80211_assoc_bss(rdev, ssid, ssid_len, attrs, - link_id, link_id); + assoc_link_id, link_id); if (IS_ERR(links[link_id].bss)) { err = PTR_ERR(links[link_id].bss); links[link_id].bss = NULL; @@ -11350,8 +11351,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]); ap_addr = req.ap_mld_addr; - err = nl80211_process_links(rdev, req.links, ssid, ssid_len, - info); + err = nl80211_process_links(rdev, req.links, req.link_id, + ssid, ssid_len, info); if (err) goto free; @@ -16506,7 +16507,10 @@ static int nl80211_assoc_ml_reconf(struct sk_buff *skb, struct genl_info *info) add_links = 0; if (info->attrs[NL80211_ATTR_MLO_LINKS]) { - err = nl80211_process_links(rdev, links, NULL, 0, info); + err = nl80211_process_links(rdev, links, + /* mark as MLO, but not assoc */ + IEEE80211_MLD_MAX_NUM_LINKS, + NULL, 0, info); if (err) return err; From 9a267ce4a3fca93a34a8881046f97bcf472228c8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Mar 2025 12:37:58 +0200 Subject: [PATCH 0746/1090] wifi: mac80211: fix SA Query processing in MLO When MLO is used and SA Query processing isn't done by userspace (e.g. wpa_supplicant w/o CONFIG_OCV), then the mac80211 code kicks in but uses the wrong addresses. Fix them. Signed-off-by: Johannes Berg Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20250306123626.bab48bb49061.I9391b22f1360d20ac8c4e92604de23f27696ba8f@changeid Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1e28efe4203c..0659ec892ec6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -6,7 +6,7 @@ * Copyright 2007-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation */ #include @@ -3329,8 +3329,8 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, return; } - if (!ether_addr_equal(mgmt->sa, sdata->deflink.u.mgd.bssid) || - !ether_addr_equal(mgmt->bssid, sdata->deflink.u.mgd.bssid)) { + if (!ether_addr_equal(mgmt->sa, sdata->vif.cfg.ap_addr) || + !ether_addr_equal(mgmt->bssid, sdata->vif.cfg.ap_addr)) { /* Not from the current AP or not associated yet. */ return; } @@ -3346,9 +3346,9 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, skb_reserve(skb, local->hw.extra_tx_headroom); resp = skb_put_zero(skb, 24); - memcpy(resp->da, mgmt->sa, ETH_ALEN); + memcpy(resp->da, sdata->vif.cfg.ap_addr, ETH_ALEN); memcpy(resp->sa, sdata->vif.addr, ETH_ALEN); - memcpy(resp->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN); + memcpy(resp->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN); resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query)); From 72d520476a2fab6f3489e8388ab524985d6c4b90 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Thu, 6 Mar 2025 12:37:59 +0200 Subject: [PATCH 0747/1090] wifi: cfg80211: cancel wiphy_work before freeing wiphy A wiphy_work can be queued from the moment the wiphy is allocated and initialized (i.e. wiphy_new_nm). When a wiphy_work is queued, the rdev::wiphy_work is getting queued. If wiphy_free is called before the rdev::wiphy_work had a chance to run, the wiphy memory will be freed, and then when it eventally gets to run it'll use invalid memory. Fix this by canceling the work before freeing the wiphy. Fixes: a3ee4dc84c4e ("wifi: cfg80211: add a work abstraction with special semantics") Signed-off-by: Miri Korenblit Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20250306123626.efd1d19f6e07.I48229f96f4067ef73f5b87302335e2fd750136c9@changeid Signed-off-by: Johannes Berg --- net/wireless/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/wireless/core.c b/net/wireless/core.c index 12b780de8779..828e29872633 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1191,6 +1191,13 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) { struct cfg80211_internal_bss *scan, *tmp; struct cfg80211_beacon_registration *reg, *treg; + unsigned long flags; + + spin_lock_irqsave(&rdev->wiphy_work_lock, flags); + WARN_ON(!list_empty(&rdev->wiphy_work_list)); + spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags); + cancel_work_sync(&rdev->wiphy_work); + rfkill_destroy(rdev->wiphy.rfkill); list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { list_del(®->list); From 502843396ec2a3eb4f58a2e4618a4a85fc5e0f46 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 3 Mar 2025 19:40:29 +0200 Subject: [PATCH 0748/1090] thunderbolt: Prevent use-after-free in resume from hibernate Kenneth noticed that his laptop crashes randomly when resuming from hibernate if there is device connected and display tunneled. I was able to reproduce this as well with the following steps: 1. Boot the system up, nothing connected. 2. Connect Thunderbolt 4 dock to the host. 3. Connect monitor to the Thunderbolt 4 dock. 4. Verify that there is picture on the screen. 5. Enter hibernate. 6. Exit hibernate. 7. Wait for the system to resume. Expectation: System resumes just fine, the connected monitor still shows screen. Actual result: There is crash during resume, screen is blank. What happens is that during resume from hibernate we tear down any existing tunnels created by the boot kernel and this ends up calling tb_dp_dprx_stop() which calls tb_tunnel_put() dropping the reference count to zero even though we never called tb_dp_dprx_start() for it (we never do that for discovery). This makes the discovered DP tunnel memory to be released and any access after that causes use-after-free and possible crash. Fix this so that we only stop DPRX flow if it has been started in the first place. Reported-by: Kenneth Crudup Closes: https://lore.kernel.org/linux-usb/8e175721-806f-45d6-892a-bd3356af80c9@panix.com/ Cc: stable@vger.kernel.org Fixes: d6d458d42e1e ("thunderbolt: Handle DisplayPort tunnel activation asynchronously") Reviewed-by: Yehezkel Bernat Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tunnel.c | 11 ++++++++--- drivers/thunderbolt/tunnel.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 8229a6fbda5a..717b31d78728 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -1009,6 +1009,8 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunnel) */ tb_tunnel_get(tunnel); + tunnel->dprx_started = true; + if (tunnel->callback) { tunnel->dprx_timeout = dprx_timeout_to_ktime(dprx_timeout); queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0); @@ -1021,9 +1023,12 @@ static int tb_dp_dprx_start(struct tb_tunnel *tunnel) static void tb_dp_dprx_stop(struct tb_tunnel *tunnel) { - tunnel->dprx_canceled = true; - cancel_delayed_work(&tunnel->dprx_work); - tb_tunnel_put(tunnel); + if (tunnel->dprx_started) { + tunnel->dprx_started = false; + tunnel->dprx_canceled = true; + cancel_delayed_work(&tunnel->dprx_work); + tb_tunnel_put(tunnel); + } } static int tb_dp_activate(struct tb_tunnel *tunnel, bool active) diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h index 7f6d3a18a41e..8a0a0cb21a89 100644 --- a/drivers/thunderbolt/tunnel.h +++ b/drivers/thunderbolt/tunnel.h @@ -63,6 +63,7 @@ enum tb_tunnel_state { * @allocated_down: Allocated downstream bandwidth (only for USB3) * @bw_mode: DP bandwidth allocation mode registers can be used to * determine consumed and allocated bandwidth + * @dprx_started: DPRX negotiation was started (tb_dp_dprx_start() was called for it) * @dprx_canceled: Was DPRX capabilities read poll canceled * @dprx_timeout: If set DPRX capabilities read poll work will timeout after this passes * @dprx_work: Worker that is scheduled to poll completion of DPRX capabilities read @@ -100,6 +101,7 @@ struct tb_tunnel { int allocated_up; int allocated_down; bool bw_mode; + bool dprx_started; bool dprx_canceled; ktime_t dprx_timeout; struct delayed_work dprx_work; From 14cb5d83068ecf15d2da6f7d0e9ea9edbcbc0457 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Fri, 7 Mar 2025 00:28:46 +0000 Subject: [PATCH 0749/1090] x86/amd_nb: Use rdmsr_safe() in amd_get_mmconfig_range() Xen doesn't offer MSR_FAM10H_MMIO_CONF_BASE to all guests. This results in the following warning: unchecked MSR access error: RDMSR from 0xc0010058 at rIP: 0xffffffff8101d19f (xen_do_read_msr+0x7f/0xa0) Call Trace: xen_read_msr+0x1e/0x30 amd_get_mmconfig_range+0x2b/0x80 quirk_amd_mmconfig_area+0x28/0x100 pnp_fixup_device+0x39/0x50 __pnp_add_device+0xf/0x150 pnp_add_device+0x3d/0x100 pnpacpi_add_device_handler+0x1f9/0x280 acpi_ns_get_device_callback+0x104/0x1c0 acpi_ns_walk_namespace+0x1d0/0x260 acpi_get_devices+0x8a/0xb0 pnpacpi_init+0x50/0x80 do_one_initcall+0x46/0x2e0 kernel_init_freeable+0x1da/0x2f0 kernel_init+0x16/0x1b0 ret_from_fork+0x30/0x50 ret_from_fork_asm+0x1b/0x30 based on quirks for a "PNP0c01" device. Treating MMCFG as disabled is the right course of action, so no change is needed there. This was most likely exposed by fixing the Xen MSR accessors to not be silently-safe. Fixes: 3fac3734c43a ("xen/pv: support selecting safe/unsafe msr accesses") Signed-off-by: Andrew Cooper Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20250307002846.3026685-1-andrew.cooper3@citrix.com --- arch/x86/kernel/amd_nb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 11fac09e3a8c..67e773744edb 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c @@ -143,7 +143,6 @@ bool __init early_is_amd_nb(u32 device) struct resource *amd_get_mmconfig_range(struct resource *res) { - u32 address; u64 base, msr; unsigned int segn_busn_bits; @@ -151,13 +150,11 @@ struct resource *amd_get_mmconfig_range(struct resource *res) boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) return NULL; - /* assume all cpus from fam10h have mmconfig */ - if (boot_cpu_data.x86 < 0x10) + /* Assume CPUs from Fam10h have mmconfig, although not all VMs do */ + if (boot_cpu_data.x86 < 0x10 || + rdmsrl_safe(MSR_FAM10H_MMIO_CONF_BASE, &msr)) return NULL; - address = MSR_FAM10H_MMIO_CONF_BASE; - rdmsrl(address, msr); - /* mmconfig is not enabled */ if (!(msr & FAM10H_MMIO_CONF_ENABLE)) return NULL; From ac7c06acaa3738b38e83815ac0f07140ad320f13 Mon Sep 17 00:00:00 2001 From: Nikunj A Dadhania Date: Thu, 6 Mar 2025 19:17:21 +1100 Subject: [PATCH 0750/1090] virt: sev-guest: Allocate request data dynamically Commit ae596615d93d ("virt: sev-guest: Reduce the scope of SNP command mutex") narrowed the command mutex scope to snp_send_guest_request(). However, GET_REPORT, GET_DERIVED_KEY, and GET_EXT_REPORT share the req structure in snp_guest_dev. Without the mutex protection, concurrent requests can overwrite each other's data. Fix it by dynamically allocating the request structure. Fixes: ae596615d93d ("virt: sev-guest: Reduce the scope of SNP command mutex") Closes: https://github.com/AMDESE/AMDSEV/issues/265 Reported-by: andreas.stuehrk@yaxi.tech Signed-off-by: Nikunj A Dadhania Signed-off-by: Alexey Kardashevskiy Signed-off-by: Borislav Petkov (AMD) Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250307013700.437505-2-aik@amd.com --- drivers/virt/coco/sev-guest/sev-guest.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 264b6523fe52..23ac177472be 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -38,12 +38,6 @@ struct snp_guest_dev { struct miscdevice misc; struct snp_msg_desc *msg_desc; - - union { - struct snp_report_req report; - struct snp_derived_key_req derived_key; - struct snp_ext_report_req ext_report; - } req; }; /* @@ -71,7 +65,7 @@ struct snp_req_resp { static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) { - struct snp_report_req *report_req = &snp_dev->req.report; + struct snp_report_req *report_req __free(kfree) = NULL; struct snp_msg_desc *mdesc = snp_dev->msg_desc; struct snp_report_resp *report_resp; struct snp_guest_req req = {}; @@ -80,6 +74,10 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io if (!arg->req_data || !arg->resp_data) return -EINVAL; + report_req = kzalloc(sizeof(*report_req), GFP_KERNEL_ACCOUNT); + if (!report_req) + return -ENOMEM; + if (copy_from_user(report_req, (void __user *)arg->req_data, sizeof(*report_req))) return -EFAULT; @@ -116,7 +114,7 @@ e_free: static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) { - struct snp_derived_key_req *derived_key_req = &snp_dev->req.derived_key; + struct snp_derived_key_req *derived_key_req __free(kfree) = NULL; struct snp_derived_key_resp derived_key_resp = {0}; struct snp_msg_desc *mdesc = snp_dev->msg_desc; struct snp_guest_req req = {}; @@ -136,6 +134,10 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque if (sizeof(buf) < resp_len) return -ENOMEM; + derived_key_req = kzalloc(sizeof(*derived_key_req), GFP_KERNEL_ACCOUNT); + if (!derived_key_req) + return -ENOMEM; + if (copy_from_user(derived_key_req, (void __user *)arg->req_data, sizeof(*derived_key_req))) return -EFAULT; @@ -168,7 +170,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques struct snp_req_resp *io) { - struct snp_ext_report_req *report_req = &snp_dev->req.ext_report; + struct snp_ext_report_req *report_req __free(kfree) = NULL; struct snp_msg_desc *mdesc = snp_dev->msg_desc; struct snp_report_resp *report_resp; struct snp_guest_req req = {}; @@ -178,6 +180,10 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data)) return -EINVAL; + report_req = kzalloc(sizeof(*report_req), GFP_KERNEL_ACCOUNT); + if (!report_req) + return -ENOMEM; + if (copy_from_sockptr(report_req, io->req_data, sizeof(*report_req))) return -EFAULT; From 3e385c0d6ce88ac9916dcf84267bd5855d830748 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Fri, 7 Mar 2025 12:37:00 +1100 Subject: [PATCH 0751/1090] virt: sev-guest: Move SNP Guest Request data pages handling under snp_cmd_mutex Compared to the SNP Guest Request, the "Extended" version adds data pages for receiving certificates. If not enough pages provided, the HV can report to the VM how much is needed so the VM can reallocate and repeat. Commit ae596615d93d ("virt: sev-guest: Reduce the scope of SNP command mutex") moved handling of the allocated/desired pages number out of scope of said mutex and create a possibility for a race (multiple instances trying to trigger Extended request in a VM) as there is just one instance of snp_msg_desc per /dev/sev-guest and no locking other than snp_cmd_mutex. Fix the issue by moving the data blob/size and the GHCB input struct (snp_req_data) into snp_guest_req which is allocated on stack now and accessed by the GHCB caller under that mutex. Stop allocating SEV_FW_BLOB_MAX_SIZE in snp_msg_alloc() as only one of four callers needs it. Free the received blob in get_ext_report() right after it is copied to the userspace. Possible future users of snp_send_guest_request() are likely to have different ideas about the buffer size anyways. Fixes: ae596615d93d ("virt: sev-guest: Reduce the scope of SNP command mutex") Signed-off-by: Alexey Kardashevskiy Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Nikunj A Dadhania Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250307013700.437505-3-aik@amd.com --- arch/x86/coco/sev/core.c | 23 ++++++----------- arch/x86/include/asm/sev.h | 6 ++--- drivers/virt/coco/sev-guest/sev-guest.c | 34 ++++++++++++++++++++----- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 82492efc5d94..96c7bc698e6b 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -2853,19 +2853,8 @@ struct snp_msg_desc *snp_msg_alloc(void) if (!mdesc->response) goto e_free_request; - mdesc->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE); - if (!mdesc->certs_data) - goto e_free_response; - - /* initial the input address for guest request */ - mdesc->input.req_gpa = __pa(mdesc->request); - mdesc->input.resp_gpa = __pa(mdesc->response); - mdesc->input.data_gpa = __pa(mdesc->certs_data); - return mdesc; -e_free_response: - free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg)); e_free_request: free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg)); e_unmap: @@ -2885,7 +2874,6 @@ void snp_msg_free(struct snp_msg_desc *mdesc) kfree(mdesc->ctx); free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg)); free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg)); - free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE); iounmap((__force void __iomem *)mdesc->secrets); memset(mdesc, 0, sizeof(*mdesc)); @@ -3054,7 +3042,7 @@ retry_request: * sequence number must be incremented or the VMPCK must be deleted to * prevent reuse of the IV. */ - rc = snp_issue_guest_request(req, &mdesc->input, rio); + rc = snp_issue_guest_request(req, &req->input, rio); switch (rc) { case -ENOSPC: /* @@ -3064,7 +3052,7 @@ retry_request: * order to increment the sequence number and thus avoid * IV reuse. */ - override_npages = mdesc->input.data_npages; + override_npages = req->input.data_npages; req->exit_code = SVM_VMGEXIT_GUEST_REQUEST; /* @@ -3120,7 +3108,7 @@ retry_request: } if (override_npages) - mdesc->input.data_npages = override_npages; + req->input.data_npages = override_npages; return rc; } @@ -3158,6 +3146,11 @@ int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_guest_req *req */ memcpy(mdesc->request, &mdesc->secret_request, sizeof(mdesc->secret_request)); + /* Initialize the input address for guest request */ + req->input.req_gpa = __pa(mdesc->request); + req->input.resp_gpa = __pa(mdesc->response); + req->input.data_gpa = req->certs_data ? __pa(req->certs_data) : 0; + rc = __handle_guest_request(mdesc, req, rio); if (rc) { if (rc == -EIO && diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 1581246491b5..ba7999f66abe 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -203,6 +203,9 @@ struct snp_guest_req { unsigned int vmpck_id; u8 msg_version; u8 msg_type; + + struct snp_req_data input; + void *certs_data; }; /* @@ -263,9 +266,6 @@ struct snp_msg_desc { struct snp_guest_msg secret_request, secret_response; struct snp_secrets_page *secrets; - struct snp_req_data input; - - void *certs_data; struct aesgcm_ctx *ctx; diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 23ac177472be..70fbc9a3e703 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -176,6 +176,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques struct snp_guest_req req = {}; int ret, npages = 0, resp_len; sockptr_t certs_address; + struct page *page; if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data)) return -EINVAL; @@ -209,8 +210,20 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques * the host. If host does not supply any certs in it, then copy * zeros to indicate that certificate data was not provided. */ - memset(mdesc->certs_data, 0, report_req->certs_len); npages = report_req->certs_len >> PAGE_SHIFT; + page = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO, + get_order(report_req->certs_len)); + if (!page) + return -ENOMEM; + + req.certs_data = page_address(page); + ret = set_memory_decrypted((unsigned long)req.certs_data, npages); + if (ret) { + pr_err("failed to mark page shared, ret=%d\n", ret); + __free_pages(page, get_order(report_req->certs_len)); + return -EFAULT; + } + cmd: /* * The intermediate response buffer is used while decrypting the @@ -219,10 +232,12 @@ cmd: */ resp_len = sizeof(report_resp->data) + mdesc->ctx->authsize; report_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT); - if (!report_resp) - return -ENOMEM; + if (!report_resp) { + ret = -ENOMEM; + goto e_free_data; + } - mdesc->input.data_npages = npages; + req.input.data_npages = npages; req.msg_version = arg->msg_version; req.msg_type = SNP_MSG_REPORT_REQ; @@ -237,7 +252,7 @@ cmd: /* If certs length is invalid then copy the returned length */ if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) { - report_req->certs_len = mdesc->input.data_npages << PAGE_SHIFT; + report_req->certs_len = req.input.data_npages << PAGE_SHIFT; if (copy_to_sockptr(io->req_data, report_req, sizeof(*report_req))) ret = -EFAULT; @@ -246,7 +261,7 @@ cmd: if (ret) goto e_free; - if (npages && copy_to_sockptr(certs_address, mdesc->certs_data, report_req->certs_len)) { + if (npages && copy_to_sockptr(certs_address, req.certs_data, report_req->certs_len)) { ret = -EFAULT; goto e_free; } @@ -256,6 +271,13 @@ cmd: e_free: kfree(report_resp); +e_free_data: + if (npages) { + if (set_memory_encrypted((unsigned long)req.certs_data, npages)) + WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n"); + else + __free_pages(page, get_order(report_req->certs_len)); + } return ret; } From 986c2e9ca818b0b74cfc737517549fd0b80ff15d Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sun, 2 Mar 2025 00:16:01 +0100 Subject: [PATCH 0752/1090] drm/panic: use `div_ceil` to clean Clippy warning Starting with the upcoming Rust 1.86.0 (to be released 2025-04-03), Clippy warns: error: manually reimplementing `div_ceil` --> drivers/gpu/drm/drm_panic_qr.rs:548:26 | 548 | let pad_offset = (offset + 7) / 8; | ^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `offset.div_ceil(8)` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil And similarly for `stride`. Thus apply the suggestion to both. The behavior (and thus codegen) is not exactly equivalent [1][2], since `div_ceil()` returns the right value for the values that currently would overflow. Link: https://github.com/rust-lang/rust-clippy/issues/14333 [1] Link: https://godbolt.org/z/dPq6nGnv3 [2] Signed-off-by: Miguel Ojeda Fixes: cb5164ac43d0 ("drm/panic: Add a QR code panic screen") Cc: stable@vger.kernel.org # Needed in 6.12.y and 6.13.y only (Rust is pinned in older LTSs). Reviewed-by: Alice Ryhl Reviewed-by: Jocelyn Falempe Signed-off-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250301231602.917580-1-ojeda@kernel.org --- drivers/gpu/drm/drm_panic_qr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index ef2d490965ba..56692c6be219 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -545,7 +545,7 @@ impl EncodedMsg<'_> { } self.push(&mut offset, (MODE_STOP, 4)); - let pad_offset = (offset + 7) / 8; + let pad_offset = offset.div_ceil(8); for i in pad_offset..self.version.max_data() { self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)]; } @@ -659,7 +659,7 @@ struct QrImage<'a> { impl QrImage<'_> { fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> { let width = em.version.width(); - let stride = (width + 7) / 8; + let stride = width.div_ceil(8); let data = qrdata; let mut qr_image = QrImage { From cba3b86974a3388b12130654809e50cd19294849 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sun, 2 Mar 2025 00:16:02 +0100 Subject: [PATCH 0753/1090] drm/panic: fix overindented list items in documentation Starting with the upcoming Rust 1.86.0 (to be released 2025-04-03), Clippy warns: error: doc list item overindented --> drivers/gpu/drm/drm_panic_qr.rs:914:5 | 914 | /// will be encoded as binary segment, otherwise it will be encoded | ^^^ help: try using ` ` (2 spaces) | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_overindented_list_items The overindentation is slightly hard to notice, since all the items start with a backquote that makes it look OK, but it is there. Thus fix it. Signed-off-by: Miguel Ojeda Fixes: cb5164ac43d0 ("drm/panic: Add a QR code panic screen") Cc: stable@vger.kernel.org # Needed in 6.12.y and 6.13.y only (Rust is pinned in older LTSs). Reviewed-by: Jocelyn Falempe Reviewed-by: Alice Ryhl Signed-off-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250301231602.917580-2-ojeda@kernel.org --- drivers/gpu/drm/drm_panic_qr.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index 56692c6be219..08b31d75c24a 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -911,16 +911,16 @@ impl QrImage<'_> { /// /// * `url`: The base URL of the QR code. It will be encoded as Binary segment. /// * `data`: A pointer to the binary data, to be encoded. if URL is NULL, it -/// will be encoded as binary segment, otherwise it will be encoded -/// efficiently as a numeric segment, and appended to the URL. +/// will be encoded as binary segment, otherwise it will be encoded +/// efficiently as a numeric segment, and appended to the URL. /// * `data_len`: Length of the data, that needs to be encoded, must be less -/// than data_size. +/// than data_size. /// * `data_size`: Size of data buffer, it should be at least 4071 bytes to hold -/// a V40 QR code. It will then be overwritten with the QR code image. +/// a V40 QR code. It will then be overwritten with the QR code image. /// * `tmp`: A temporary buffer that the QR code encoder will use, to write the -/// segments and ECC. +/// segments and ECC. /// * `tmp_size`: Size of the temporary buffer, it must be at least 3706 bytes -/// long for V40. +/// long for V40. /// /// # Safety /// From 75ddcd5ad40ecd9fbc9f5a7a2ed0e1e74921db3c Mon Sep 17 00:00:00 2001 From: Hsin-chen Chuang Date: Fri, 28 Feb 2025 01:14:10 +0800 Subject: [PATCH 0754/1090] Bluetooth: btusb: Configure altsetting for HCI_USER_CHANNEL Automatically configure the altsetting for HCI_USER_CHANNEL when a SCO is connected. The motivation is to enable the HCI_USER_CHANNEL user to send out SCO data through USB Bluetooth chips, which is mainly used for bidirectional audio transfer (voice call). This was not capable because: - Per Bluetooth Core Spec v5, Vol 4, Part B, 2.1, the corresponding alternate setting should be set based on the air mode in order to transfer SCO data, but - The Linux Bluetooth HCI_USER_CHANNEL exposes the Bluetooth Host Controller Interface to the user space, which is something above the USB layer. The user space is not able to configure the USB alt while keeping the channel open. This patch intercepts the HCI_EV_SYNC_CONN_COMPLETE packets in btusb, extracts the air mode, and configures the alt setting in btusb. This patch is tested on ChromeOS devices. The USB Bluetooth models (CVSD, TRANS alt3 and alt6) could work without a customized kernel. Fixes: b16b327edb4d ("Bluetooth: btusb: add sysfs attribute to control USB alt setting") Signed-off-by: Hsin-chen Chuang Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/Kconfig | 12 ++++++++++++ drivers/bluetooth/btusb.c | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 4ab32abf0f48..7771edf54fb3 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -56,6 +56,18 @@ config BT_HCIBTUSB_POLL_SYNC Say Y here to enable USB poll_sync for Bluetooth USB devices by default. +config BT_HCIBTUSB_AUTO_ISOC_ALT + bool "Automatically adjust alternate setting for Isoc endpoints" + depends on BT_HCIBTUSB + default y if CHROME_PLATFORMS + help + Say Y here to automatically adjusting the alternate setting for + HCI_USER_CHANNEL whenever a SCO link is established. + + When enabled, btusb intercepts the HCI_EV_SYNC_CONN_COMPLETE packets + and configures isoc endpoint alternate setting automatically when + HCI_USER_CHANNEL is in use. + config BT_HCIBTUSB_BCM bool "Broadcom protocol support" depends on BT_HCIBTUSB diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2a8d91963c63..a0fc465458b2 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -34,6 +34,7 @@ static bool force_scofix; static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND); static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC); static bool reset = true; +static bool auto_isoc_alt = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT); static struct usb_driver btusb_driver; @@ -1085,6 +1086,42 @@ static inline void btusb_free_frags(struct btusb_data *data) spin_unlock_irqrestore(&data->rxlock, flags); } +static void btusb_sco_connected(struct btusb_data *data, struct sk_buff *skb) +{ + struct hci_event_hdr *hdr = (void *) skb->data; + struct hci_ev_sync_conn_complete *ev = + (void *) skb->data + sizeof(*hdr); + struct hci_dev *hdev = data->hdev; + unsigned int notify_air_mode; + + if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT) + return; + + if (skb->len < sizeof(*hdr) || hdr->evt != HCI_EV_SYNC_CONN_COMPLETE) + return; + + if (skb->len != sizeof(*hdr) + sizeof(*ev) || ev->status) + return; + + switch (ev->air_mode) { + case BT_CODEC_CVSD: + notify_air_mode = HCI_NOTIFY_ENABLE_SCO_CVSD; + break; + + case BT_CODEC_TRANSPARENT: + notify_air_mode = HCI_NOTIFY_ENABLE_SCO_TRANSP; + break; + + default: + return; + } + + bt_dev_info(hdev, "enabling SCO with air mode %u", ev->air_mode); + data->sco_num = 1; + data->air_mode = notify_air_mode; + schedule_work(&data->work); +} + static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb) { if (data->intr_interval) { @@ -1092,6 +1129,10 @@ static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb) schedule_delayed_work(&data->rx_work, 0); } + /* Configure altsetting for HCI_USER_CHANNEL on SCO connected */ + if (auto_isoc_alt && hci_dev_test_flag(data->hdev, HCI_USER_CHANNEL)) + btusb_sco_connected(data, skb); + return data->recv_event(data->hdev, skb); } From 8d74c9106be8da051b22f0cd81e665f17d51ba5d Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 27 Feb 2025 23:28:15 +0200 Subject: [PATCH 0755/1090] Bluetooth: SCO: fix sco_conn refcounting on sco_conn_ready sco_conn refcount shall not be incremented a second time if the sk already owns the refcount, so hold only when adding new chan. Add sco_conn_hold() for clarity, as refcnt is never zero here due to the sco_conn_add(). Fixes SCO socket shutdown not actually closing the SCO connection. Fixes: ed9588554943 ("Bluetooth: SCO: remove the redundant sco_conn_put") Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/sco.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index aa7bfe26cb40..ed6846864ea9 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -107,6 +107,14 @@ static void sco_conn_put(struct sco_conn *conn) kref_put(&conn->ref, sco_conn_free); } +static struct sco_conn *sco_conn_hold(struct sco_conn *conn) +{ + BT_DBG("conn %p refcnt %u", conn, kref_read(&conn->ref)); + + kref_get(&conn->ref); + return conn; +} + static struct sco_conn *sco_conn_hold_unless_zero(struct sco_conn *conn) { if (!conn) @@ -1353,6 +1361,7 @@ static void sco_conn_ready(struct sco_conn *conn) bacpy(&sco_pi(sk)->src, &conn->hcon->src); bacpy(&sco_pi(sk)->dst, &conn->hcon->dst); + sco_conn_hold(conn); hci_conn_hold(conn->hcon); __sco_chan_add(conn, sk, parent); @@ -1411,8 +1420,10 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) struct sco_conn *conn; conn = sco_conn_add(hcon); - if (conn) + if (conn) { sco_conn_ready(conn); + sco_conn_put(conn); + } } else sco_conn_del(hcon, bt_to_errno(status)); } From 0bdd88971519cfa8a76d1a4dde182e74cfbd5d5c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 28 Feb 2025 13:12:54 -0500 Subject: [PATCH 0756/1090] Bluetooth: hci_event: Fix enabling passive scanning Passive scanning shall only be enabled when disconnecting LE links, otherwise it may start result in triggering scanning when e.g. an ISO link disconnects: > HCI Event: LE Meta Event (0x3e) plen 29 LE Connected Isochronous Stream Established (0x19) Status: Success (0x00) Connection Handle: 257 CIG Synchronization Delay: 0 us (0x000000) CIS Synchronization Delay: 0 us (0x000000) Central to Peripheral Latency: 10000 us (0x002710) Peripheral to Central Latency: 10000 us (0x002710) Central to Peripheral PHY: LE 2M (0x02) Peripheral to Central PHY: LE 2M (0x02) Number of Subevents: 1 Central to Peripheral Burst Number: 1 Peripheral to Central Burst Number: 1 Central to Peripheral Flush Timeout: 2 Peripheral to Central Flush Timeout: 2 Central to Peripheral MTU: 320 Peripheral to Central MTU: 160 ISO Interval: 10.00 msec (0x0008) ... > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 257 Reason: Remote User Terminated Connection (0x13) < HCI Command: LE Set Extended Scan Enable (0x08|0x0042) plen 6 Extended scan: Enabled (0x01) Filter duplicates: Enabled (0x01) Duration: 0 msec (0x0000) Period: 0.00 sec (0x0000) Fixes: 9fcb18ef3acb ("Bluetooth: Introduce LE auto connect options") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2cc7a9306350..903b0b52692a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3391,23 +3391,30 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data, hci_update_scan(hdev); } - params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); - if (params) { - switch (params->auto_connect) { - case HCI_AUTO_CONN_LINK_LOSS: - if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) + /* Re-enable passive scanning if disconnected device is marked + * as auto-connectable. + */ + if (conn->type == LE_LINK) { + params = hci_conn_params_lookup(hdev, &conn->dst, + conn->dst_type); + if (params) { + switch (params->auto_connect) { + case HCI_AUTO_CONN_LINK_LOSS: + if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) + break; + fallthrough; + + case HCI_AUTO_CONN_DIRECT: + case HCI_AUTO_CONN_ALWAYS: + hci_pend_le_list_del_init(params); + hci_pend_le_list_add(params, + &hdev->pend_le_conns); + hci_update_passive_scan(hdev); break; - fallthrough; - case HCI_AUTO_CONN_DIRECT: - case HCI_AUTO_CONN_ALWAYS: - hci_pend_le_list_del_init(params); - hci_pend_le_list_add(params, &hdev->pend_le_conns); - hci_update_passive_scan(hdev); - break; - - default: - break; + default: + break; + } } } From ab6ab707a4d060a51c45fc13e3b2228d5f7c0b87 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 4 Mar 2025 10:06:10 -0500 Subject: [PATCH 0757/1090] Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context" This reverts commit 4d94f05558271654670d18c26c912da0c1c15549 which has problems (see [1]) and is no longer needed since 581dd2dc168f ("Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating") has reworked the code where the original bug has been found. [1] Link: https://lore.kernel.org/linux-bluetooth/877c55ci1r.wl-tiwai@suse.de/T/#t Fixes: 4d94f0555827 ("Bluetooth: hci_core: Fix sleeping function called from invalid context") Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 108 +++++++++++-------------------- net/bluetooth/hci_core.c | 10 ++- net/bluetooth/iso.c | 6 -- net/bluetooth/l2cap_core.c | 12 ++-- net/bluetooth/rfcomm/core.c | 6 -- net/bluetooth/sco.c | 12 ++-- 6 files changed, 57 insertions(+), 97 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f756fac95488..6281063cbd8e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -804,6 +804,7 @@ struct hci_conn_params { extern struct list_head hci_dev_list; extern struct list_head hci_cb_list; extern rwlock_t hci_dev_list_lock; +extern struct mutex hci_cb_list_lock; #define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags) #define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags) @@ -2010,47 +2011,24 @@ struct hci_cb { char *name; - bool (*match) (struct hci_conn *conn); void (*connect_cfm) (struct hci_conn *conn, __u8 status); void (*disconn_cfm) (struct hci_conn *conn, __u8 status); void (*security_cfm) (struct hci_conn *conn, __u8 status, - __u8 encrypt); + __u8 encrypt); void (*key_change_cfm) (struct hci_conn *conn, __u8 status); void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); }; -static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list) -{ - struct hci_cb *cb, *cpy; - - rcu_read_lock(); - list_for_each_entry_rcu(cb, &hci_cb_list, list) { - if (cb->match && cb->match(conn)) { - cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC); - if (!cpy) - break; - - *cpy = *cb; - INIT_LIST_HEAD(&cpy->list); - list_add_rcu(&cpy->list, list); - } - } - rcu_read_unlock(); -} - static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) { - struct list_head list; - struct hci_cb *cb, *tmp; + struct hci_cb *cb; - INIT_LIST_HEAD(&list); - hci_cb_lookup(conn, &list); - - list_for_each_entry_safe(cb, tmp, &list, list) { + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { if (cb->connect_cfm) cb->connect_cfm(conn, status); - kfree(cb); } + mutex_unlock(&hci_cb_list_lock); if (conn->connect_cfm_cb) conn->connect_cfm_cb(conn, status); @@ -2058,43 +2036,22 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason) { - struct list_head list; - struct hci_cb *cb, *tmp; + struct hci_cb *cb; - INIT_LIST_HEAD(&list); - hci_cb_lookup(conn, &list); - - list_for_each_entry_safe(cb, tmp, &list, list) { + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { if (cb->disconn_cfm) cb->disconn_cfm(conn, reason); - kfree(cb); } + mutex_unlock(&hci_cb_list_lock); if (conn->disconn_cfm_cb) conn->disconn_cfm_cb(conn, reason); } -static inline void hci_security_cfm(struct hci_conn *conn, __u8 status, - __u8 encrypt) -{ - struct list_head list; - struct hci_cb *cb, *tmp; - - INIT_LIST_HEAD(&list); - hci_cb_lookup(conn, &list); - - list_for_each_entry_safe(cb, tmp, &list, list) { - if (cb->security_cfm) - cb->security_cfm(conn, status, encrypt); - kfree(cb); - } - - if (conn->security_cfm_cb) - conn->security_cfm_cb(conn, status); -} - static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) { + struct hci_cb *cb; __u8 encrypt; if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) @@ -2102,11 +2059,20 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; - hci_security_cfm(conn, status, encrypt); + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { + if (cb->security_cfm) + cb->security_cfm(conn, status, encrypt); + } + mutex_unlock(&hci_cb_list_lock); + + if (conn->security_cfm_cb) + conn->security_cfm_cb(conn, status); } static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status) { + struct hci_cb *cb; __u8 encrypt; if (conn->state == BT_CONFIG) { @@ -2133,38 +2099,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status) conn->sec_level = conn->pending_sec_level; } - hci_security_cfm(conn, status, encrypt); + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { + if (cb->security_cfm) + cb->security_cfm(conn, status, encrypt); + } + mutex_unlock(&hci_cb_list_lock); + + if (conn->security_cfm_cb) + conn->security_cfm_cb(conn, status); } static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) { - struct list_head list; - struct hci_cb *cb, *tmp; + struct hci_cb *cb; - INIT_LIST_HEAD(&list); - hci_cb_lookup(conn, &list); - - list_for_each_entry_safe(cb, tmp, &list, list) { + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { if (cb->key_change_cfm) cb->key_change_cfm(conn, status); - kfree(cb); } + mutex_unlock(&hci_cb_list_lock); } static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role) { - struct list_head list; - struct hci_cb *cb, *tmp; + struct hci_cb *cb; - INIT_LIST_HEAD(&list); - hci_cb_lookup(conn, &list); - - list_for_each_entry_safe(cb, tmp, &list, list) { + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { if (cb->role_switch_cfm) cb->role_switch_cfm(conn, status, role); - kfree(cb); } + mutex_unlock(&hci_cb_list_lock); } static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e7ec12437c8b..012fc107901a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -57,6 +57,7 @@ DEFINE_RWLOCK(hci_dev_list_lock); /* HCI callback list */ LIST_HEAD(hci_cb_list); +DEFINE_MUTEX(hci_cb_list_lock); /* HCI ID Numbering */ static DEFINE_IDA(hci_index_ida); @@ -2972,7 +2973,9 @@ int hci_register_cb(struct hci_cb *cb) { BT_DBG("%p name %s", cb, cb->name); - list_add_tail_rcu(&cb->list, &hci_cb_list); + mutex_lock(&hci_cb_list_lock); + list_add_tail(&cb->list, &hci_cb_list); + mutex_unlock(&hci_cb_list_lock); return 0; } @@ -2982,8 +2985,9 @@ int hci_unregister_cb(struct hci_cb *cb) { BT_DBG("%p name %s", cb, cb->name); - list_del_rcu(&cb->list); - synchronize_rcu(); + mutex_lock(&hci_cb_list_lock); + list_del(&cb->list); + mutex_unlock(&hci_cb_list_lock); return 0; } diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 44acddf58a0c..0cb52a3308ba 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -2187,11 +2187,6 @@ done: return HCI_LM_ACCEPT; } -static bool iso_match(struct hci_conn *hcon) -{ - return hcon->type == ISO_LINK || hcon->type == LE_LINK; -} - static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) { if (hcon->type != ISO_LINK) { @@ -2373,7 +2368,6 @@ drop: static struct hci_cb iso_cb = { .name = "ISO", - .match = iso_match, .connect_cfm = iso_connect_cfm, .disconn_cfm = iso_disconn_cfm, }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b22078b67972..c27ea70f71e1 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -7182,11 +7182,6 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, return NULL; } -static bool l2cap_match(struct hci_conn *hcon) -{ - return hcon->type == ACL_LINK || hcon->type == LE_LINK; -} - static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) { struct hci_dev *hdev = hcon->hdev; @@ -7194,6 +7189,9 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) struct l2cap_chan *pchan; u8 dst_type; + if (hcon->type != ACL_LINK && hcon->type != LE_LINK) + return; + BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); if (status) { @@ -7258,6 +7256,9 @@ int l2cap_disconn_ind(struct hci_conn *hcon) static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) { + if (hcon->type != ACL_LINK && hcon->type != LE_LINK) + return; + BT_DBG("hcon %p reason %d", hcon, reason); l2cap_conn_del(hcon, bt_to_errno(reason)); @@ -7565,7 +7566,6 @@ unlock: static struct hci_cb l2cap_cb = { .name = "L2CAP", - .match = l2cap_match, .connect_cfm = l2cap_connect_cfm, .disconn_cfm = l2cap_disconn_cfm, .security_cfm = l2cap_security_cfm, diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4c56ca5a216c..ad5177e3a69b 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -2134,11 +2134,6 @@ static int rfcomm_run(void *unused) return 0; } -static bool rfcomm_match(struct hci_conn *hcon) -{ - return hcon->type == ACL_LINK; -} - static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) { struct rfcomm_session *s; @@ -2185,7 +2180,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) static struct hci_cb rfcomm_cb = { .name = "RFCOMM", - .match = rfcomm_match, .security_cfm = rfcomm_security_cfm }; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index ed6846864ea9..5d1bc0d6aee0 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1407,13 +1407,11 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) return lm; } -static bool sco_match(struct hci_conn *hcon) -{ - return hcon->type == SCO_LINK || hcon->type == ESCO_LINK; -} - static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) { + if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) + return; + BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status); if (!status) { @@ -1430,6 +1428,9 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) { + if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) + return; + BT_DBG("hcon %p reason %d", hcon, reason); sco_conn_del(hcon, bt_to_errno(reason)); @@ -1455,7 +1456,6 @@ drop: static struct hci_cb sco_cb = { .name = "SCO", - .match = sco_match, .connect_cfm = sco_connect_cfm, .disconn_cfm = sco_disconn_cfm, }; From 6914f7e2e25fac9d1d2b62c208eaa5f2bf810fe9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 6 Mar 2025 23:00:16 +0100 Subject: [PATCH 0758/1090] x86/mm: Define PTRS_PER_PMD for assembly code too Andy reported the following build warning from head_32.S: In file included from arch/x86/kernel/head_32.S:29: arch/x86/include/asm/pgtable_32.h:59:5: error: "PTRS_PER_PMD" is not defined, evaluates to 0 [-Werror=undef] 59 | #if PTRS_PER_PMD > 1 The reason is that on 2-level i386 paging the folded in PMD's PTRS_PER_PMD constant is not defined in assembly headers, only in generic MM C headers. Instead of trying to fish out the definition from the generic headers, just define it - it even has a comment for it already... Reported-by: Andy Shevchenko Tested-by: Andy Shevchenko Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/Z8oa8AUVyi2HWfo9@gmail.com --- arch/x86/include/asm/pgtable-2level_types.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable-2level_types.h b/arch/x86/include/asm/pgtable-2level_types.h index 7f6ccff0ba72..4a12c276b181 100644 --- a/arch/x86/include/asm/pgtable-2level_types.h +++ b/arch/x86/include/asm/pgtable-2level_types.h @@ -23,17 +23,17 @@ typedef union { #define ARCH_PAGE_TABLE_SYNC_MASK PGTBL_PMD_MODIFIED /* - * traditional i386 two-level paging structure: + * Traditional i386 two-level paging structure: */ #define PGDIR_SHIFT 22 #define PTRS_PER_PGD 1024 - /* - * the i386 is two-level, so we don't really have any - * PMD directory physically. + * The i386 is two-level, so we don't really have any + * PMD directory physically: */ +#define PTRS_PER_PMD 1 #define PTRS_PER_PTE 1024 From 966944f3711665db13e214fef6d02982c49bb972 Mon Sep 17 00:00:00 2001 From: Mitchell Levy Date: Fri, 7 Mar 2025 15:27:00 -0800 Subject: [PATCH 0759/1090] rust: lockdep: Remove support for dynamically allocated LockClassKeys Currently, dynamically allocated LockCLassKeys can be used from the Rust side without having them registered. This is a soundness issue, so remove them. Fixes: 6ea5aa08857a ("rust: sync: introduce `LockClassKey`") Suggested-by: Alice Ryhl Signed-off-by: Mitchell Levy Signed-off-by: Boqun Feng Signed-off-by: Ingo Molnar Reviewed-by: Benno Lossin Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250307232717.1759087-11-boqun.feng@gmail.com --- rust/kernel/sync.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 3498fb344dc9..16eab9138b2b 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -30,28 +30,20 @@ pub struct LockClassKey(Opaque); unsafe impl Sync for LockClassKey {} impl LockClassKey { - /// Creates a new lock class key. - pub const fn new() -> Self { - Self(Opaque::uninit()) - } - pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { self.0.get() } } -impl Default for LockClassKey { - fn default() -> Self { - Self::new() - } -} - /// Defines a new static lock class and returns a pointer to it. #[doc(hidden)] #[macro_export] macro_rules! static_lock_class { () => {{ - static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new(); + static CLASS: $crate::sync::LockClassKey = + // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated + // lock_class_key + unsafe { ::core::mem::MaybeUninit::uninit().assume_init() }; &CLASS }}; } From b3c5ec8b79bf6bc49cc4850d0949d712830283d7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 7 Mar 2025 15:26:51 -0800 Subject: [PATCH 0760/1090] locking/rtmutex: Use the 'struct' keyword in kernel-doc comment Add the "struct" keyword to prevent a kernel-doc warning: rtmutex_common.h:67: warning: cannot understand function prototype: 'struct rt_wake_q_head ' Signed-off-by: Randy Dunlap Signed-off-by: Boqun Feng Signed-off-by: Ingo Molnar Acked-by: Waiman Long Link: https://lore.kernel.org/r/20250307232717.1759087-2-boqun.feng@gmail.com --- kernel/locking/rtmutex_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h index c38a2d2d4a7e..78dd3d8c6554 100644 --- a/kernel/locking/rtmutex_common.h +++ b/kernel/locking/rtmutex_common.h @@ -59,8 +59,8 @@ struct rt_mutex_waiter { }; /** - * rt_wake_q_head - Wrapper around regular wake_q_head to support - * "sleeping" spinlocks on RT + * struct rt_wake_q_head - Wrapper around regular wake_q_head to support + * "sleeping" spinlocks on RT * @head: The regular wake_q_head for sleeping lock variants * @rtlock_task: Task pointer for RT lock (spin/rwlock) wakeups */ From 85b2b9c16d053364e2004883140538e73b333cdb Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Fri, 7 Mar 2025 15:26:52 -0800 Subject: [PATCH 0761/1090] locking/semaphore: Use wake_q to wake up processes outside lock critical section A circular lock dependency splat has been seen involving down_trylock(): ====================================================== WARNING: possible circular locking dependency detected 6.12.0-41.el10.s390x+debug ------------------------------------------------------ dd/32479 is trying to acquire lock: 0015a20accd0d4f8 ((console_sem).lock){-.-.}-{2:2}, at: down_trylock+0x26/0x90 but task is already holding lock: 000000017e461698 (&zone->lock){-.-.}-{2:2}, at: rmqueue_bulk+0xac/0x8f0 the existing dependency chain (in reverse order) is: -> #4 (&zone->lock){-.-.}-{2:2}: -> #3 (hrtimer_bases.lock){-.-.}-{2:2}: -> #2 (&rq->__lock){-.-.}-{2:2}: -> #1 (&p->pi_lock){-.-.}-{2:2}: -> #0 ((console_sem).lock){-.-.}-{2:2}: The console_sem -> pi_lock dependency is due to calling try_to_wake_up() while holding the console_sem raw_spinlock. This dependency can be broken by using wake_q to do the wakeup instead of calling try_to_wake_up() under the console_sem lock. This will also make the semaphore's raw_spinlock become a terminal lock without taking any further locks underneath it. The hrtimer_bases.lock is a raw_spinlock while zone->lock is a spinlock. The hrtimer_bases.lock -> zone->lock dependency happens via the debug_objects_fill_pool() helper function in the debugobjects code. -> #4 (&zone->lock){-.-.}-{2:2}: __lock_acquire+0xe86/0x1cc0 lock_acquire.part.0+0x258/0x630 lock_acquire+0xb8/0xe0 _raw_spin_lock_irqsave+0xb4/0x120 rmqueue_bulk+0xac/0x8f0 __rmqueue_pcplist+0x580/0x830 rmqueue_pcplist+0xfc/0x470 rmqueue.isra.0+0xdec/0x11b0 get_page_from_freelist+0x2ee/0xeb0 __alloc_pages_noprof+0x2c2/0x520 alloc_pages_mpol_noprof+0x1fc/0x4d0 alloc_pages_noprof+0x8c/0xe0 allocate_slab+0x320/0x460 ___slab_alloc+0xa58/0x12b0 __slab_alloc.isra.0+0x42/0x60 kmem_cache_alloc_noprof+0x304/0x350 fill_pool+0xf6/0x450 debug_object_activate+0xfe/0x360 enqueue_hrtimer+0x34/0x190 __run_hrtimer+0x3c8/0x4c0 __hrtimer_run_queues+0x1b2/0x260 hrtimer_interrupt+0x316/0x760 do_IRQ+0x9a/0xe0 do_irq_async+0xf6/0x160 Normally a raw_spinlock to spinlock dependency is not legitimate and will be warned if CONFIG_PROVE_RAW_LOCK_NESTING is enabled, but debug_objects_fill_pool() is an exception as it explicitly allows this dependency for non-PREEMPT_RT kernel without causing PROVE_RAW_LOCK_NESTING lockdep splat. As a result, this dependency is legitimate and not a bug. Anyway, semaphore is the only locking primitive left that is still using try_to_wake_up() to do wakeup inside critical section, all the other locking primitives had been migrated to use wake_q to do wakeup outside of the critical section. It is also possible that there are other circular locking dependencies involving printk/console_sem or other existing/new semaphores lurking somewhere which may show up in the future. Let just do the migration now to wake_q to avoid headache like this. Reported-by: yzbot+ed801a886dfdbfe7136d@syzkaller.appspotmail.com Signed-off-by: Waiman Long Signed-off-by: Boqun Feng Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250307232717.1759087-3-boqun.feng@gmail.com --- kernel/locking/semaphore.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/locking/semaphore.c b/kernel/locking/semaphore.c index 34bfae72f295..de9117c0e671 100644 --- a/kernel/locking/semaphore.c +++ b/kernel/locking/semaphore.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ static noinline void __down(struct semaphore *sem); static noinline int __down_interruptible(struct semaphore *sem); static noinline int __down_killable(struct semaphore *sem); static noinline int __down_timeout(struct semaphore *sem, long timeout); -static noinline void __up(struct semaphore *sem); +static noinline void __up(struct semaphore *sem, struct wake_q_head *wake_q); /** * down - acquire the semaphore @@ -183,13 +184,16 @@ EXPORT_SYMBOL(down_timeout); void __sched up(struct semaphore *sem) { unsigned long flags; + DEFINE_WAKE_Q(wake_q); raw_spin_lock_irqsave(&sem->lock, flags); if (likely(list_empty(&sem->wait_list))) sem->count++; else - __up(sem); + __up(sem, &wake_q); raw_spin_unlock_irqrestore(&sem->lock, flags); + if (!wake_q_empty(&wake_q)) + wake_up_q(&wake_q); } EXPORT_SYMBOL(up); @@ -269,11 +273,12 @@ static noinline int __sched __down_timeout(struct semaphore *sem, long timeout) return __down_common(sem, TASK_UNINTERRUPTIBLE, timeout); } -static noinline void __sched __up(struct semaphore *sem) +static noinline void __sched __up(struct semaphore *sem, + struct wake_q_head *wake_q) { struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list, struct semaphore_waiter, list); list_del(&waiter->list); waiter->up = true; - wake_up_process(waiter->task); + wake_q_add(wake_q, waiter->task); } From f3600c867c99a2cc8038680ecf211089c50e7971 Mon Sep 17 00:00:00 2001 From: Mina Almasry Date: Thu, 6 Mar 2025 21:55:20 +0000 Subject: [PATCH 0762/1090] netmem: prevent TX of unreadable skbs Currently on stable trees we have support for netmem/devmem RX but not TX. It is not safe to forward/redirect an RX unreadable netmem packet into the device's TX path, as the device may call dma-mapping APIs on dma addrs that should not be passed to it. Fix this by preventing the xmit of unreadable skbs. Tested by configuring tc redirect: sudo tc qdisc add dev eth1 ingress sudo tc filter add dev eth1 ingress protocol ip prio 1 flower ip_proto \ tcp src_ip 192.168.1.12 action mirred egress redirect dev eth1 Before, I see unreadable skbs in the driver's TX path passed to dma mapping APIs. After, I don't see unreadable skbs in the driver's TX path passed to dma mapping APIs. Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags") Suggested-by: Jakub Kicinski Cc: stable@vger.kernel.org Signed-off-by: Mina Almasry Link: https://patch.msgid.link/20250306215520.1415465-1-almasrymina@google.com Signed-off-by: Jakub Kicinski --- net/core/dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 30da277c5a6f..2f7f5fd9ffec 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3872,6 +3872,9 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device { netdev_features_t features; + if (!skb_frags_readable(skb)) + goto out_kfree_skb; + features = netif_skb_features(skb); skb = validate_xmit_vlan(skb, features); if (unlikely(!skb)) From d749d901b2168389f060b654fdaa08acf6b367d2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 6 Mar 2025 23:25:29 +0200 Subject: [PATCH 0763/1090] net/mlx5: Fill out devlink dev info only for PFs Firmware version query is supported on the PFs. Due to this following kernel warning log is observed: [ 188.590344] mlx5_core 0000:08:00.2: mlx5_fw_version_query:816:(pid 1453): fw query isn't supported by the FW Fix it by restricting the query and devlink info to the PF. Fixes: 8338d9378895 ("net/mlx5: Added devlink info callback") Signed-off-by: Jiri Pirko Reviewed-by: Kalesh AP Signed-off-by: Tariq Toukan Reviewed-by: Parav Pandit Link: https://patch.msgid.link/20250306212529.429329-1-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 98d4306929f3..a2cf3e79693d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -46,6 +46,9 @@ mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, u32 running_fw, stored_fw; int err; + if (!mlx5_core_is_pf(dev)) + return 0; + err = devlink_info_version_fixed_put(req, "fw.psid", dev->board_id); if (err) return err; From dc5340c3133a3ebe54853fd299116149e528cfaa Mon Sep 17 00:00:00 2001 From: Joseph Huang Date: Thu, 6 Mar 2025 12:23:05 -0500 Subject: [PATCH 0764/1090] net: dsa: mv88e6xxx: Verify after ATU Load ops ATU Load operations could fail silently if there's not enough space on the device to hold the new entry. When this happens, the symptom depends on the unknown flood settings. If unknown multicast flood is disabled, the multicast packets are dropped when the ATU table is full. If unknown multicast flood is enabled, the multicast packets will be flooded to all ports. Either way, IGMP snooping is broken when the ATU Load operation fails silently. Do a Read-After-Write verification after each fdb/mdb add operation to make sure that the operation was really successful, and return -ENOSPC otherwise. Fixes: defb05b9b9b4 ("net: dsa: mv88e6xxx: Add support for fdb_add, fdb_del, and fdb_getnext") Signed-off-by: Joseph Huang Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250306172306.3859214-1-Joseph.Huang@garmin.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/chip.c | 59 ++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 68d1e891752b..5db96ca52505 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2208,13 +2208,11 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, return err; } -static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, - const unsigned char *addr, u16 vid, - u8 state) +static int mv88e6xxx_port_db_get(struct mv88e6xxx_chip *chip, + const unsigned char *addr, u16 vid, + u16 *fid, struct mv88e6xxx_atu_entry *entry) { - struct mv88e6xxx_atu_entry entry; struct mv88e6xxx_vtu_entry vlan; - u16 fid; int err; /* Ports have two private address databases: one for when the port is @@ -2225,7 +2223,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, * VLAN ID into the port's database used for VLAN-unaware bridging. */ if (vid == 0) { - fid = MV88E6XXX_FID_BRIDGED; + *fid = MV88E6XXX_FID_BRIDGED; } else { err = mv88e6xxx_vtu_get(chip, vid, &vlan); if (err) @@ -2235,14 +2233,39 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, if (!vlan.valid) return -EOPNOTSUPP; - fid = vlan.fid; + *fid = vlan.fid; } - entry.state = 0; - ether_addr_copy(entry.mac, addr); - eth_addr_dec(entry.mac); + entry->state = 0; + ether_addr_copy(entry->mac, addr); + eth_addr_dec(entry->mac); - err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry); + return mv88e6xxx_g1_atu_getnext(chip, *fid, entry); +} + +static bool mv88e6xxx_port_db_find(struct mv88e6xxx_chip *chip, + const unsigned char *addr, u16 vid) +{ + struct mv88e6xxx_atu_entry entry; + u16 fid; + int err; + + err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry); + if (err) + return false; + + return entry.state && ether_addr_equal(entry.mac, addr); +} + +static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, + const unsigned char *addr, u16 vid, + u8 state) +{ + struct mv88e6xxx_atu_entry entry; + u16 fid; + int err; + + err = mv88e6xxx_port_db_get(chip, addr, vid, &fid, &entry); if (err) return err; @@ -2846,6 +2869,13 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, addr, vid, MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC); + if (err) + goto out; + + if (!mv88e6xxx_port_db_find(chip, addr, vid)) + err = -ENOSPC; + +out: mv88e6xxx_reg_unlock(chip); return err; @@ -6614,6 +6644,13 @@ static int mv88e6xxx_port_mdb_add(struct dsa_switch *ds, int port, mv88e6xxx_reg_lock(chip); err = mv88e6xxx_port_db_load_purge(chip, port, mdb->addr, mdb->vid, MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC); + if (err) + goto out; + + if (!mv88e6xxx_port_db_find(chip, mdb->addr, mdb->vid)) + err = -ENOSPC; + +out: mv88e6xxx_reg_unlock(chip); return err; From 26db9c9ee19c36a97dbb1cfef007a3c189c4c874 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 6 Mar 2025 18:24:18 +0800 Subject: [PATCH 0765/1090] net: mctp i3c: Copy headers if cloned Use skb_cow_head() prior to modifying the tx skb. This is necessary when the skb has been cloned, to avoid modifying other shared clones. Signed-off-by: Matt Johnston Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver") Link: https://patch.msgid.link/20250306-matt-i3c-cow-head-v1-1-d5e6a5495227@codeconstruct.com.au Signed-off-by: Jakub Kicinski --- drivers/net/mctp/mctp-i3c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c index c1e72253063b..c678f79aa356 100644 --- a/drivers/net/mctp/mctp-i3c.c +++ b/drivers/net/mctp/mctp-i3c.c @@ -506,10 +506,15 @@ static int mctp_i3c_header_create(struct sk_buff *skb, struct net_device *dev, const void *saddr, unsigned int len) { struct mctp_i3c_internal_hdr *ihdr; + int rc; if (!daddr || !saddr) return -EINVAL; + rc = skb_cow_head(skb, sizeof(struct mctp_i3c_internal_hdr)); + if (rc) + return rc; + skb_push(skb, sizeof(struct mctp_i3c_internal_hdr)); skb_reset_mac_header(skb); ihdr = (void *)skb_mac_header(skb); From df8ce77ba8b7c012a3edd1ca7368b46831341466 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 6 Mar 2025 10:33:20 +0800 Subject: [PATCH 0766/1090] net: mctp i2c: Copy headers if cloned Use skb_cow_head() prior to modifying the TX SKB. This is necessary when the SKB has been cloned, to avoid modifying other shared clones. Signed-off-by: Matt Johnston Fixes: f5b8abf9fc3d ("mctp i2c: MCTP I2C binding driver") Link: https://patch.msgid.link/20250306-matt-mctp-i2c-cow-v1-1-293827212681@codeconstruct.com.au Signed-off-by: Jakub Kicinski --- drivers/net/mctp/mctp-i2c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c index e3dcdeacc12c..d74d47dd6e04 100644 --- a/drivers/net/mctp/mctp-i2c.c +++ b/drivers/net/mctp/mctp-i2c.c @@ -583,6 +583,7 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev, struct mctp_i2c_hdr *hdr; struct mctp_hdr *mhdr; u8 lldst, llsrc; + int rc; if (len > MCTP_I2C_MAXMTU) return -EMSGSIZE; @@ -593,6 +594,10 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev, lldst = *((u8 *)daddr); llsrc = *((u8 *)saddr); + rc = skb_cow_head(skb, sizeof(struct mctp_i2c_hdr)); + if (rc) + return rc; + skb_push(skb, sizeof(struct mctp_i2c_hdr)); skb_reset_mac_header(skb); hdr = (void *)skb_mac_header(skb); From a07364b394697d2e0baffeb517f41385259aa484 Mon Sep 17 00:00:00 2001 From: Andrei Botila Date: Tue, 4 Mar 2025 18:06:13 +0200 Subject: [PATCH 0767/1090] net: phy: nxp-c45-tja11xx: add TJA112X PHY configuration errata The most recent sillicon versions of TJA1120 and TJA1121 can achieve full silicon performance by putting the PHY in managed mode. It is necessary to apply these PHY writes before link gets established. Application of this fix is required after restart of device and wakeup from sleep. Cc: stable@vger.kernel.org Fixes: f1fe5dff2b8a ("net: phy: nxp-c45-tja11xx: add TJA1120 support") Signed-off-by: Andrei Botila Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250304160619.181046-2-andrei.botila@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 34231b5b9175..709d6c9f7cba 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -22,6 +22,11 @@ #define PHY_ID_TJA_1103 0x001BB010 #define PHY_ID_TJA_1120 0x001BB031 +#define VEND1_DEVICE_ID3 0x0004 +#define TJA1120_DEV_ID3_SILICON_VERSION GENMASK(15, 12) +#define TJA1120_DEV_ID3_SAMPLE_TYPE GENMASK(11, 8) +#define DEVICE_ID3_SAMPLE_TYPE_R 0x9 + #define VEND1_DEVICE_CONTROL 0x0040 #define DEVICE_CONTROL_RESET BIT(15) #define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14) @@ -1593,6 +1598,50 @@ static int nxp_c45_set_phy_mode(struct phy_device *phydev) return 0; } +/* Errata: ES_TJA1120 and ES_TJA1121 Rev. 1.0 — 28 November 2024 Section 3.1 */ +static void nxp_c45_tja1120_errata(struct phy_device *phydev) +{ + int silicon_version, sample_type; + bool macsec_ability; + int phy_abilities; + int ret = 0; + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_DEVICE_ID3); + if (ret < 0) + return; + + sample_type = FIELD_GET(TJA1120_DEV_ID3_SAMPLE_TYPE, ret); + if (sample_type != DEVICE_ID3_SAMPLE_TYPE_R) + return; + + silicon_version = FIELD_GET(TJA1120_DEV_ID3_SILICON_VERSION, ret); + + phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1, + VEND1_PORT_ABILITIES); + macsec_ability = !!(phy_abilities & MACSEC_ABILITY); + if ((!macsec_ability && silicon_version == 2) || + (macsec_ability && silicon_version == 1)) { + /* TJA1120/TJA1121 PHY configuration errata workaround. + * Apply PHY writes sequence before link up. + */ + if (!macsec_ability) { + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x4b95); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0xf3cd); + } else { + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x89c7); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0x0893); + } + + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x0476, 0x58a0); + + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, 0x8921, 0xa3a); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, 0x89F1, 0x16c1); + + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0x0); + } +} + static int nxp_c45_config_init(struct phy_device *phydev) { int ret; @@ -1609,6 +1658,9 @@ static int nxp_c45_config_init(struct phy_device *phydev) phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); + if (phy_id_compare(phydev->phy_id, PHY_ID_TJA_1120, GENMASK(31, 4))) + nxp_c45_tja1120_errata(phydev); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, PHY_CONFIG_AUTO); From 48939523843e4813e78920f54937944a8787134b Mon Sep 17 00:00:00 2001 From: Andrei Botila Date: Tue, 4 Mar 2025 18:06:14 +0200 Subject: [PATCH 0768/1090] net: phy: nxp-c45-tja11xx: add TJA112XB SGMII PCS restart errata TJA1120B/TJA1121B can achieve a stable operation of SGMII after a startup event by putting the SGMII PCS into power down mode and restart afterwards. It is necessary to put the SGMII PCS into power down mode and back up. Cc: stable@vger.kernel.org Fixes: f1fe5dff2b8a ("net: phy: nxp-c45-tja11xx: add TJA1120 support") Signed-off-by: Andrei Botila Link: https://patch.msgid.link/20250304160619.181046-3-andrei.botila@oss.nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/nxp-c45-tja11xx.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 709d6c9f7cba..e9fc54517449 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -114,6 +114,9 @@ #define MII_BASIC_CONFIG_RMII 0x5 #define MII_BASIC_CONFIG_MII 0x4 +#define VEND1_SGMII_BASIC_CONTROL 0xB000 +#define SGMII_LPM BIT(11) + #define VEND1_SYMBOL_ERROR_CNT_XTD 0x8351 #define EXTENDED_CNT_EN BIT(15) #define VEND1_MONITOR_STATUS 0xAC80 @@ -1598,11 +1601,11 @@ static int nxp_c45_set_phy_mode(struct phy_device *phydev) return 0; } -/* Errata: ES_TJA1120 and ES_TJA1121 Rev. 1.0 — 28 November 2024 Section 3.1 */ +/* Errata: ES_TJA1120 and ES_TJA1121 Rev. 1.0 — 28 November 2024 Section 3.1 & 3.2 */ static void nxp_c45_tja1120_errata(struct phy_device *phydev) { + bool macsec_ability, sgmii_ability; int silicon_version, sample_type; - bool macsec_ability; int phy_abilities; int ret = 0; @@ -1619,6 +1622,7 @@ static void nxp_c45_tja1120_errata(struct phy_device *phydev) phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PORT_ABILITIES); macsec_ability = !!(phy_abilities & MACSEC_ABILITY); + sgmii_ability = !!(phy_abilities & SGMII_ABILITY); if ((!macsec_ability && silicon_version == 2) || (macsec_ability && silicon_version == 1)) { /* TJA1120/TJA1121 PHY configuration errata workaround. @@ -1639,6 +1643,18 @@ static void nxp_c45_tja1120_errata(struct phy_device *phydev) phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 0x0); phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 0x0); + + if (sgmii_ability) { + /* TJA1120B/TJA1121B SGMII PCS restart errata workaround. + * Put SGMII PCS into power down mode and back up. + */ + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_SGMII_BASIC_CONTROL, + SGMII_LPM); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + VEND1_SGMII_BASIC_CONTROL, + SGMII_LPM); + } } } From 505ead7ab77f289f12d8a68ac83da068e4d4408b Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 6 Mar 2025 05:16:18 -0800 Subject: [PATCH 0769/1090] netpoll: hold rcu read lock in __netpoll_send_skb() The function __netpoll_send_skb() is being invoked without holding the RCU read lock. This oversight triggers a warning message when CONFIG_PROVE_RCU_LIST is enabled: net/core/netpoll.c:330 suspicious rcu_dereference_check() usage! netpoll_send_skb netpoll_send_udp write_ext_msg console_flush_all console_unlock vprintk_emit To prevent npinfo from disappearing unexpectedly, ensure that __netpoll_send_skb() is protected with the RCU read lock. Fixes: 2899656b494dcd1 ("netpoll: take rcu_read_lock_bh() in netpoll_send_skb_on_dev()") Signed-off-by: Breno Leitao Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306-netpoll_rcu_v2-v2-1-bc4f5c51742a@debian.org Signed-off-by: Jakub Kicinski --- net/core/netpoll.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 62b4041aae1a..0ab722d95a2d 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -319,6 +319,7 @@ static int netpoll_owner_active(struct net_device *dev) static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) { netdev_tx_t status = NETDEV_TX_BUSY; + netdev_tx_t ret = NET_XMIT_DROP; struct net_device *dev; unsigned long tries; /* It is up to the caller to keep npinfo alive. */ @@ -327,11 +328,12 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) lockdep_assert_irqs_disabled(); dev = np->dev; + rcu_read_lock(); npinfo = rcu_dereference_bh(dev->npinfo); if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { dev_kfree_skb_irq(skb); - return NET_XMIT_DROP; + goto out; } /* don't get messages out of order, and no recursion */ @@ -370,7 +372,10 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) skb_queue_tail(&npinfo->txq, skb); schedule_delayed_work(&npinfo->tx_work,0); } - return NETDEV_TX_OK; + ret = NETDEV_TX_OK; +out: + rcu_read_unlock(); + return ret; } netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) From da64a2359092ceec4f9dea5b329d0aef20104217 Mon Sep 17 00:00:00 2001 From: Tiezhu Yang Date: Sat, 8 Mar 2025 13:50:45 +0800 Subject: [PATCH 0770/1090] LoongArch: Convert unreachable() to BUG() When compiling on LoongArch, there exists the following objtool warning in arch/loongarch/kernel/machine_kexec.o: kexec_reboot() falls through to next function crash_shutdown_secondary() Avoid using unreachable() as it can (and will in the absence of UBSAN) generate fall-through code. Use BUG() so we get a "break BRK_BUG" trap (with unreachable annotation). Cc: stable@vger.kernel.org # 6.12+ Acked-by: Josh Poimboeuf Signed-off-by: Tiezhu Yang Signed-off-by: Huacai Chen --- arch/loongarch/kernel/machine_kexec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c index 8ae641dc53bb..f9381800e291 100644 --- a/arch/loongarch/kernel/machine_kexec.c +++ b/arch/loongarch/kernel/machine_kexec.c @@ -126,14 +126,14 @@ void kexec_reboot(void) /* All secondary cpus go to kexec_smp_wait */ if (smp_processor_id() > 0) { relocated_kexec_smp_wait(NULL); - unreachable(); + BUG(); } #endif do_kexec = (void *)reboot_code_buffer; do_kexec(efi_boot, cmdline_ptr, systable_ptr, start_addr, first_ind_entry); - unreachable(); + BUG(); } From a0d3c8bcb9206ac207c7ad3182027c6b0a1319bb Mon Sep 17 00:00:00 2001 From: Yuli Wang Date: Sat, 8 Mar 2025 13:51:32 +0800 Subject: [PATCH 0771/1090] LoongArch: Eliminate superfluous get_numa_distances_cnt() In LoongArch, get_numa_distances_cnt() isn't in use, resulting in a compiler warning. Fix follow errors with clang-18 when W=1e: arch/loongarch/kernel/acpi.c:259:28: error: unused function 'get_numa_distances_cnt' [-Werror,-Wunused-function] 259 | static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit) | ^~~~~~~~~~~~~~~~~~~~~~ 1 error generated. Link: https://lore.kernel.org/all/Z7bHPVUH4lAezk0E@kernel.org/ Signed-off-by: Yuli Wang Signed-off-by: Huacai Chen --- arch/loongarch/kernel/acpi.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 382a09a7152c..1120ac2824f6 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -249,18 +249,6 @@ static __init int setup_node(int pxm) return acpi_map_pxm_to_node(pxm); } -/* - * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for - * I/O localities since SRAT does not list them. I/O localities are - * not supported at this point. - */ -unsigned int numa_distance_cnt; - -static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit) -{ - return slit->locality_count; -} - void __init numa_set_distance(int from, int to, int distance) { if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) { From c9117434c8f7523f0b77db4c5766f5011cc94677 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sat, 8 Mar 2025 13:51:32 +0800 Subject: [PATCH 0772/1090] LoongArch: Use polling play_dead() when resuming from hibernation When CONFIG_RANDOM_KMALLOC_CACHES or other randomization infrastructrue enabled, the idle_task's stack may different between the booting kernel and target kernel. So when resuming from hibernation, an ACTION_BOOT_CPU IPI wakeup the idle instruction in arch_cpu_idle_dead() and jump to the interrupt handler. But since the stack pointer is changed, the interrupt handler cannot restore correct context. So rename the current arch_cpu_idle_dead() to idle_play_dead(), make it as the default version of play_dead(), and the new arch_cpu_idle_dead() call play_dead() directly. For hibernation, implement an arch-specific hibernate_resume_nonboot_cpu_disable() to use the polling version (idle instruction is replace by nop, and irq is disabled) of play_dead(), i.e. poll_play_dead(), to avoid IPI handler corrupting the idle_task's stack when resuming from hibernation. This solution is a little similar to commit 406f992e4a372dafbe3c ("x86 / hibernate: Use hlt_play_dead() when resuming from hibernation"). Cc: stable@vger.kernel.org Tested-by: Erpeng Xu Tested-by: Yuli Wang Signed-off-by: Huacai Chen --- arch/loongarch/kernel/smp.c | 47 ++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index fbf747447f13..4b24589c0b56 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -423,7 +424,7 @@ void loongson_cpu_die(unsigned int cpu) mb(); } -void __noreturn arch_cpu_idle_dead(void) +static void __noreturn idle_play_dead(void) { register uint64_t addr; register void (*init_fn)(void); @@ -447,6 +448,50 @@ void __noreturn arch_cpu_idle_dead(void) BUG(); } +#ifdef CONFIG_HIBERNATION +static void __noreturn poll_play_dead(void) +{ + register uint64_t addr; + register void (*init_fn)(void); + + idle_task_exit(); + __this_cpu_write(cpu_state, CPU_DEAD); + + __smp_mb(); + do { + __asm__ __volatile__("nop\n\t"); + addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0); + } while (addr == 0); + + init_fn = (void *)TO_CACHE(addr); + iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR); + + init_fn(); + BUG(); +} +#endif + +static void (*play_dead)(void) = idle_play_dead; + +void __noreturn arch_cpu_idle_dead(void) +{ + play_dead(); + BUG(); /* play_dead() doesn't return */ +} + +#ifdef CONFIG_HIBERNATION +int hibernate_resume_nonboot_cpu_disable(void) +{ + int ret; + + play_dead = poll_play_dead; + ret = suspend_disable_secondary_cpus(); + play_dead = idle_play_dead; + + return ret; +} +#endif + #endif /* From c8477bb0a8e7f6b2e47952b403c5cb67a6929e55 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Sat, 8 Mar 2025 13:51:32 +0800 Subject: [PATCH 0773/1090] LoongArch: Set max_pfn with the PFN of the last page The current max_pfn equals to zero. In this case, it causes user cannot get some page information through /proc filesystem such as kpagecount. The following message is displayed by stress-ng test suite with command "stress-ng --verbose --physpage 1 -t 1". # stress-ng --verbose --physpage 1 -t 1 stress-ng: error: [1691] physpage: cannot read page count for address 0x134ac000 in /proc/kpagecount, errno=22 (Invalid argument) stress-ng: error: [1691] physpage: cannot read page count for address 0x7ffff207c3a8 in /proc/kpagecount, errno=22 (Invalid argument) stress-ng: error: [1691] physpage: cannot read page count for address 0x134b0000 in /proc/kpagecount, errno=22 (Invalid argument) ... After applying this patch, the kernel can pass the test. # stress-ng --verbose --physpage 1 -t 1 stress-ng: debug: [1701] physpage: [1701] started (instance 0 on CPU 3) stress-ng: debug: [1701] physpage: [1701] exited (instance 0 on CPU 3) stress-ng: debug: [1700] physpage: [1701] terminated (success) Cc: stable@vger.kernel.org # 6.8+ Fixes: ff6c3d81f2e8 ("NUMA: optimize detection of memory with no node id assigned by firmware") Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/kernel/setup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index edcfdfcad7d2..90cb3ca96f08 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -387,6 +387,9 @@ static void __init check_kernel_sections_mem(void) */ static void __init arch_mem_init(char **cmdline_p) { + /* Recalculate max_low_pfn for "mem=xxx" */ + max_pfn = max_low_pfn = PHYS_PFN(memblock_end_of_DRAM()); + if (usermem) pr_info("User-defined physical RAM map overwrite\n"); From 3109d5ff484b7bc7b955f166974c6776d91f247b Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Sat, 8 Mar 2025 13:51:32 +0800 Subject: [PATCH 0774/1090] LoongArch: Set hugetlb mmap base address aligned with pmd size With ltp test case "testcases/bin/hugefork02", there is a dmesg error report message such as: kernel BUG at mm/hugetlb.c:5550! Oops - BUG[#1]: CPU: 0 UID: 0 PID: 1517 Comm: hugefork02 Not tainted 6.14.0-rc2+ #241 Hardware name: QEMU QEMU Virtual Machine, BIOS unknown 2/2/2022 pc 90000000004eaf1c ra 9000000000485538 tp 900000010edbc000 sp 900000010edbf940 a0 900000010edbfb00 a1 9000000108d20280 a2 00007fffe9474000 a3 00007ffff3474000 a4 0000000000000000 a5 0000000000000003 a6 00000000003cadd3 a7 0000000000000000 t0 0000000001ffffff t1 0000000001474000 t2 900000010ecd7900 t3 00007fffe9474000 t4 00007fffe9474000 t5 0000000000000040 t6 900000010edbfb00 t7 0000000000000001 t8 0000000000000005 u0 90000000004849d0 s9 900000010edbfa00 s0 9000000108d20280 s1 00007fffe9474000 s2 0000000002000000 s3 9000000108d20280 s4 9000000002b38b10 s5 900000010edbfb00 s6 00007ffff3474000 s7 0000000000000406 s8 900000010edbfa08 ra: 9000000000485538 unmap_vmas+0x130/0x218 ERA: 90000000004eaf1c __unmap_hugepage_range+0x6f4/0x7d0 PRMD: 00000004 (PPLV0 +PIE -PWE) EUEN: 00000007 (+FPE +SXE +ASXE -BTE) ECFG: 00071c1d (LIE=0,2-4,10-12 VS=7) ESTAT: 000c0000 [BRK] (IS= ECode=12 EsubCode=0) PRID: 0014c010 (Loongson-64bit, Loongson-3A5000) Process hugefork02 (pid: 1517, threadinfo=00000000a670eaf4, task=000000007a95fc64) Call Trace: [<90000000004eaf1c>] __unmap_hugepage_range+0x6f4/0x7d0 [<9000000000485534>] unmap_vmas+0x12c/0x218 [<9000000000494068>] exit_mmap+0xe0/0x308 [<900000000025fdc4>] mmput+0x74/0x180 [<900000000026a284>] do_exit+0x294/0x898 [<900000000026aa30>] do_group_exit+0x30/0x98 [<900000000027bed4>] get_signal+0x83c/0x868 [<90000000002457b4>] arch_do_signal_or_restart+0x54/0xfa0 [<90000000015795e8>] irqentry_exit_to_user_mode+0xb8/0x138 [<90000000002572d0>] tlb_do_page_fault_1+0x114/0x1b4 The problem is that base address allocated from hugetlbfs is not aligned with pmd size. Here add a checking for hugetlbfs and align base address with pmd size. After this patch the test case "testcases/bin/hugefork02" passes to run. This is similar to the commit 7f24cbc9c4d42db8a3c8484d1 ("mm/mmap: teach generic_get_unmapped_area{_topdown} to handle hugetlb mappings"). Cc: stable@vger.kernel.org # 6.13+ Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/mm/mmap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c index 914e82ff3f65..1df9e99582cc 100644 --- a/arch/loongarch/mm/mmap.c +++ b/arch/loongarch/mm/mmap.c @@ -3,6 +3,7 @@ * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ #include +#include #include #include #include @@ -63,8 +64,11 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, } info.length = len; - info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0; info.align_offset = pgoff << PAGE_SHIFT; + if (filp && is_file_hugepages(filp)) + info.align_mask = huge_page_mask_align(filp); + else + info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0; if (dir == DOWN) { info.flags = VM_UNMAPPED_AREA_TOPDOWN; From 6fb1867d5a44b0a061cf39d2492d23d314bcb8ce Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Sat, 8 Mar 2025 13:51:59 +0800 Subject: [PATCH 0775/1090] LoongArch: KVM: Add interrupt checking for AVEC There is a newly added macro INT_AVEC with CSR ESTAT register, which is bit 14 used for LoongArch AVEC support. AVEC interrupt status bit 14 is supported with macro CSR_ESTAT_IS, so here replace the hard-coded value 0x1fff with macro CSR_ESTAT_IS so that the AVEC interrupt status is also supported by KVM. Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/kvm/vcpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 20f941af3e9e..9e1a9b4aa4c6 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -311,7 +311,7 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) { int ret = RESUME_GUEST; unsigned long estat = vcpu->arch.host_estat; - u32 intr = estat & 0x1fff; /* Ignore NMI */ + u32 intr = estat & CSR_ESTAT_IS; u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT; vcpu->mode = OUTSIDE_GUEST_MODE; From 78d7bc5a02e1468df53896df354fa80727f35b7d Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Sat, 8 Mar 2025 13:52:01 +0800 Subject: [PATCH 0776/1090] LoongArch: KVM: Reload guest CSR registers after sleep On host, the HW guest CSR registers are lost after suspend and resume operation. Since last_vcpu of boot CPU still records latest vCPU pointer so that the guest CSR register skips to reload when boot CPU resumes and vCPU is scheduled. Here last_vcpu is cleared so that guest CSR registers will reload from scheduled vCPU context after suspend and resume. Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/kvm/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c index f6d3242b9234..b6864d6e5ec8 100644 --- a/arch/loongarch/kvm/main.c +++ b/arch/loongarch/kvm/main.c @@ -317,6 +317,13 @@ int kvm_arch_enable_virtualization_cpu(void) kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx", read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc()); + /* + * HW Guest CSR registers are lost after CPU suspend and resume. + * Clear last_vcpu so that Guest CSR registers forced to reload + * from vCPU SW state. + */ + this_cpu_ptr(vmcs)->last_vcpu = NULL; + return 0; } From 6bdbb73dc8d99fbb77f5db79dbb6f108708090b4 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Sat, 8 Mar 2025 13:52:04 +0800 Subject: [PATCH 0777/1090] LoongArch: KVM: Fix GPA size issue about VM Physical address space is 48 bit on Loongson-3A5000 physical machine, however it is 47 bit for VM on Loongson-3A5000 system. Size of physical address space of VM is the same with the size of virtual user space (a half) of physical machine. Variable cpu_vabits represents user address space, kernel address space is not included (user space and kernel space are both a half of total). Here cpu_vabits, rather than cpu_vabits - 1, is to represent the size of guest physical address space. Also there is strict checking about page fault GPA address, inject error if it is larger than maximum GPA address of VM. Cc: stable@vger.kernel.org Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/kvm/exit.c | 6 ++++++ arch/loongarch/kvm/vm.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c index c1e8ec5b941b..ea321403644a 100644 --- a/arch/loongarch/kvm/exit.c +++ b/arch/loongarch/kvm/exit.c @@ -669,6 +669,12 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write) struct kvm_run *run = vcpu->run; unsigned long badv = vcpu->arch.badv; + /* Inject ADE exception if exceed max GPA size */ + if (unlikely(badv >= vcpu->kvm->arch.gpa_size)) { + kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEM); + return RESUME_GUEST; + } + ret = kvm_handle_mm_fault(vcpu, badv, write); if (ret) { /* Treat as MMIO */ diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c index b8b3e1972d6e..edccfc8c9cd8 100644 --- a/arch/loongarch/kvm/vm.c +++ b/arch/loongarch/kvm/vm.c @@ -48,7 +48,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) if (kvm_pvtime_supported()) kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); - kvm->arch.gpa_size = BIT(cpu_vabits - 1); + /* + * cpu_vabits means user address space only (a half of total). + * GPA size of VM is the same with the size of user address space. + */ + kvm->arch.gpa_size = BIT(cpu_vabits); kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1; kvm->arch.invalid_ptes[0] = 0; kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table; From 69823334200029767de785d30acf74e4872a11d3 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:09 +0200 Subject: [PATCH 0778/1090] ASoC: SOF: Intel: mtl: Split up dsp_ops setup code Move the sof_mtl_ops and sof_mtl_ops_init() to pci-mtl.c as local static and add a 'generic' sof_mtl_set_ops() function as replacement exported function to fill the dsp_ops structure. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 2 -- sound/soc/sof/intel/mtl.c | 44 +++++++++++++++++------------------ sound/soc/sof/intel/mtl.h | 2 ++ sound/soc/sof/intel/pci-mtl.c | 8 +++++++ 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index ee4ccc1a5490..92b7402e752e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -913,8 +913,6 @@ extern struct snd_sof_dsp_ops sof_tgl_ops; int sof_tgl_ops_init(struct snd_sof_dev *sdev); extern struct snd_sof_dsp_ops sof_icl_ops; int sof_icl_ops_init(struct snd_sof_dev *sdev); -extern struct snd_sof_dsp_ops sof_mtl_ops; -int sof_mtl_ops_init(struct snd_sof_dev *sdev); extern struct snd_sof_dsp_ops sof_lnl_ops; int sof_lnl_ops_init(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 4a6b1d56171e..ec563214dd1a 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -712,43 +712,40 @@ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) } EXPORT_SYMBOL_NS(mtl_dsp_core_put, "SND_SOC_SOF_INTEL_MTL"); -/* Meteorlake ops */ -struct snd_sof_dsp_ops sof_mtl_ops; - -int sof_mtl_ops_init(struct snd_sof_dev *sdev) +int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) { struct sof_ipc4_fw_data *ipc4_data; /* common defaults */ - memcpy(&sof_mtl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); + memcpy(dsp_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); /* shutdown */ - sof_mtl_ops.shutdown = hda_dsp_shutdown; + dsp_ops->shutdown = hda_dsp_shutdown; /* doorbell */ - sof_mtl_ops.irq_thread = mtl_ipc_irq_thread; + dsp_ops->irq_thread = mtl_ipc_irq_thread; /* ipc */ - sof_mtl_ops.send_msg = mtl_ipc_send_msg; - sof_mtl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset; - sof_mtl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset; + dsp_ops->send_msg = mtl_ipc_send_msg; + dsp_ops->get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset; + dsp_ops->get_window_offset = mtl_dsp_ipc_get_window_offset; /* debug */ - sof_mtl_ops.debug_map = mtl_dsp_debugfs; - sof_mtl_ops.debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs); - sof_mtl_ops.dbg_dump = mtl_dsp_dump; - sof_mtl_ops.ipc_dump = mtl_ipc_dump; + dsp_ops->debug_map = mtl_dsp_debugfs; + dsp_ops->debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs); + dsp_ops->dbg_dump = mtl_dsp_dump; + dsp_ops->ipc_dump = mtl_ipc_dump; /* pre/post fw run */ - sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run; - sof_mtl_ops.post_fw_run = mtl_dsp_post_fw_run; + dsp_ops->pre_fw_run = mtl_dsp_pre_fw_run; + dsp_ops->post_fw_run = mtl_dsp_post_fw_run; /* parse platform specific extended manifest */ - sof_mtl_ops.parse_platform_ext_manifest = NULL; + dsp_ops->parse_platform_ext_manifest = NULL; /* dsp core get/put */ - sof_mtl_ops.core_get = mtl_dsp_core_get; - sof_mtl_ops.core_put = mtl_dsp_core_put; + dsp_ops->core_get = mtl_dsp_core_get; + dsp_ops->core_put = mtl_dsp_core_put; sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); if (!sdev->private) @@ -764,13 +761,14 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) /* External library loading support */ ipc4_data->load_library = hda_dsp_ipc4_load_library; - /* set DAI ops */ - hda_set_dai_drv_ops(sdev, &sof_mtl_ops); + dsp_ops->set_power_state = hda_dsp_set_power_state_ipc4; - sof_mtl_ops.set_power_state = hda_dsp_set_power_state_ipc4; + /* set DAI ops */ + hda_set_dai_drv_ops(sdev, dsp_ops); return 0; -}; +} +EXPORT_SYMBOL_NS(sof_mtl_set_ops, "SND_SOC_SOF_INTEL_MTL"); const struct sof_intel_dsp_desc mtl_chip_info = { .cores_num = 3, diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 9ab4b21c960e..4d098dae2973 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -145,3 +145,5 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev); int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core); int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core); + +int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index 71f711cf8599..c5048a4a56be 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -20,6 +20,14 @@ #include "hda.h" #include "mtl.h" +/* Meteorlake ops */ +static struct snd_sof_dsp_ops sof_mtl_ops; + +static int sof_mtl_ops_init(struct snd_sof_dev *sdev) +{ + return sof_mtl_set_ops(sdev, &sof_mtl_ops); +} + static const struct sof_dev_desc mtl_desc = { .use_acpi_target_states = true, .machines = snd_soc_acpi_intel_mtl_machines, From 0d2d276f53ea3ba1686619cde503d9748f58a834 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:10 +0200 Subject: [PATCH 0779/1090] ASoC: SOF: Intel: lnl/ptl: Only set dsp_ops which differs from MTL LunarLake is a next generation in ACE architecture and most of the dsp_ops are the same as it is in previous generation. Use the sof_mtl_set_ops() to get the ops used for mtl and update the ones that needs different functions for LNL. Update pci-ptl at the same time to use the LNL dsp_ops as before. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.h | 2 - sound/soc/sof/intel/lnl.c | 86 +++++++---------------------------- sound/soc/sof/intel/lnl.h | 2 + sound/soc/sof/intel/pci-lnl.c | 12 +++-- sound/soc/sof/intel/pci-ptl.c | 15 ++++-- 5 files changed, 38 insertions(+), 79 deletions(-) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 92b7402e752e..76154627fc17 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -913,8 +913,6 @@ extern struct snd_sof_dsp_ops sof_tgl_ops; int sof_tgl_ops_init(struct snd_sof_dev *sdev); extern struct snd_sof_dsp_ops sof_icl_ops; int sof_icl_ops_init(struct snd_sof_dev *sdev); -extern struct snd_sof_dsp_ops sof_lnl_ops; -int sof_lnl_ops_init(struct snd_sof_dev *sdev); extern const struct sof_intel_dsp_desc skl_chip_info; extern const struct sof_intel_dsp_desc apl_chip_info; diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 793d8539821d..ffda39ca3606 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -20,17 +20,6 @@ #include "lnl.h" #include -/* LunarLake ops */ -struct snd_sof_dsp_ops sof_lnl_ops; -EXPORT_SYMBOL_NS(sof_lnl_ops, "SND_SOC_SOF_INTEL_LNL"); - -static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = { - {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, - {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, - {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, - {"fw_regs", HDA_DSP_BAR, MTL_SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY}, -}; - /* this helps allows the DSP to setup DMIC/SSP */ static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus, bool enable) { @@ -111,78 +100,32 @@ static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev) return 0; } -int sof_lnl_ops_init(struct snd_sof_dev *sdev) +int sof_lnl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) { - struct sof_ipc4_fw_data *ipc4_data; + int ret; - /* common defaults */ - memcpy(&sof_lnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); + ret = sof_mtl_set_ops(sdev, dsp_ops); + if (ret) + return ret; /* probe/remove */ if (!sdev->dspless_mode_selected) { - sof_lnl_ops.probe = lnl_hda_dsp_probe; - sof_lnl_ops.remove = lnl_hda_dsp_remove; + dsp_ops->probe = lnl_hda_dsp_probe; + dsp_ops->remove = lnl_hda_dsp_remove; } - /* shutdown */ - sof_lnl_ops.shutdown = hda_dsp_shutdown; - - /* doorbell */ - sof_lnl_ops.irq_thread = mtl_ipc_irq_thread; - - /* ipc */ - sof_lnl_ops.send_msg = mtl_ipc_send_msg; - sof_lnl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset; - sof_lnl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset; - - /* debug */ - sof_lnl_ops.debug_map = lnl_dsp_debugfs; - sof_lnl_ops.debug_map_count = ARRAY_SIZE(lnl_dsp_debugfs); - sof_lnl_ops.dbg_dump = mtl_dsp_dump; - sof_lnl_ops.ipc_dump = mtl_ipc_dump; - - /* pre/post fw run */ - sof_lnl_ops.pre_fw_run = mtl_dsp_pre_fw_run; - sof_lnl_ops.post_fw_run = lnl_dsp_post_fw_run; - - /* parse platform specific extended manifest */ - sof_lnl_ops.parse_platform_ext_manifest = NULL; - - /* dsp core get/put */ - /* TODO: add core_get and core_put */ + /* post fw run */ + dsp_ops->post_fw_run = lnl_dsp_post_fw_run; /* PM */ if (!sdev->dspless_mode_selected) { - sof_lnl_ops.resume = lnl_hda_dsp_resume; - sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume; + dsp_ops->resume = lnl_hda_dsp_resume; + dsp_ops->runtime_resume = lnl_hda_dsp_runtime_resume; } - /* dsp core get/put */ - sof_lnl_ops.core_get = mtl_dsp_core_get; - sof_lnl_ops.core_put = mtl_dsp_core_put; - - sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL); - if (!sdev->private) - return -ENOMEM; - - ipc4_data = sdev->private; - ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET; - - ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2; - - ipc4_data->fw_context_save = true; - - /* External library loading support */ - ipc4_data->load_library = hda_dsp_ipc4_load_library; - - /* set DAI ops */ - hda_set_dai_drv_ops(sdev, &sof_lnl_ops); - - sof_lnl_ops.set_power_state = hda_dsp_set_power_state_ipc4; - return 0; -}; -EXPORT_SYMBOL_NS(sof_lnl_ops_init, "SND_SOC_SOF_INTEL_LNL"); +} +EXPORT_SYMBOL_NS(sof_lnl_set_ops, "SND_SOC_SOF_INTEL_LNL"); /* Check if an SDW IRQ occurred */ static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) @@ -262,3 +205,6 @@ const struct sof_intel_dsp_desc ptl_chip_info = { .hw_ip_version = SOF_INTEL_ACE_3_0, }; EXPORT_SYMBOL_NS(ptl_chip_info, "SND_SOC_SOF_INTEL_LNL"); + +MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); +MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h index 79101af84b2e..e585b93d2b63 100644 --- a/sound/soc/sof/intel/lnl.h +++ b/sound/soc/sof/intel/lnl.h @@ -12,4 +12,6 @@ #define LNL_DSP_REG_HFDSC 0x160200 /* DSP core0 status */ #define LNL_DSP_REG_HFDEC 0x160204 /* DSP core0 error */ +int sof_lnl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); + #endif /* __SOF_INTEL_LNL_H */ diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index 8d4d74ac4398..91b9cff8c4ca 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -18,7 +18,15 @@ /* platform specific devices */ #include "hda.h" -#include "mtl.h" +#include "lnl.h" + +/* LunarLake ops */ +static struct snd_sof_dsp_ops sof_lnl_ops; + +static int sof_lnl_ops_init(struct snd_sof_dev *sdev) +{ + return sof_lnl_set_ops(sdev, &sof_lnl_ops); +} static const struct sof_dev_desc lnl_desc = { .use_acpi_target_states = true, @@ -73,6 +81,4 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF support for LunarLake platforms"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); -MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV"); diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index c4fb6a2441b7..32f93723ee66 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -16,7 +16,15 @@ /* platform specific devices */ #include "hda.h" -#include "mtl.h" +#include "lnl.h" + +/* PantherLake ops */ +static struct snd_sof_dsp_ops sof_ptl_ops; + +static int sof_ptl_ops_init(struct snd_sof_dev *sdev) +{ + return sof_lnl_set_ops(sdev, &sof_ptl_ops); +} static const struct sof_dev_desc ptl_desc = { .use_acpi_target_states = true, @@ -43,8 +51,8 @@ static const struct sof_dev_desc ptl_desc = { [SOF_IPC_TYPE_4] = "sof-ptl.ri", }, .nocodec_tplg_filename = "sof-ptl-nocodec.tplg", - .ops = &sof_lnl_ops, - .ops_init = sof_lnl_ops_init, + .ops = &sof_ptl_ops, + .ops_init = sof_ptl_ops_init, }; /* PCI IDs */ @@ -73,6 +81,5 @@ MODULE_DESCRIPTION("SOF support for PantherLake platforms"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV"); From 80416226920c21e806f93bd0930d67557f41600f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:11 +0200 Subject: [PATCH 0780/1090] ASoC: SOF: Intel: mtl: Stop exporting dsp_ops callback functions There is no need to export individual dsp_ops functions anymore as the callbacks are filled now by sof_mtl_set_ops() Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 30 ++++++++++-------------------- sound/soc/sof/intel/mtl.h | 15 --------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index ec563214dd1a..2242c96bfa51 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -96,7 +96,7 @@ static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) return false; } -int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; struct sof_ipc4_msg *msg_data = msg->msg_data; @@ -122,7 +122,6 @@ int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } -EXPORT_SYMBOL_NS(mtl_ipc_send_msg, "SND_SOC_SOF_INTEL_MTL"); void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) { @@ -238,7 +237,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) EXPORT_SYMBOL_NS(mtl_enable_interrupts, "SND_SOC_SOF_INTEL_MTL"); /* pre fw run operations */ -int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) +static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; u32 dsphfpwrsts; @@ -298,9 +297,8 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) return ret; } -EXPORT_SYMBOL_NS(mtl_dsp_pre_fw_run, "SND_SOC_SOF_INTEL_MTL"); -int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) +static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) { int ret; @@ -325,9 +323,8 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) hda_sdw_int_enable(sdev, true); return 0; } -EXPORT_SYMBOL_NS(mtl_dsp_post_fw_run, "SND_SOC_SOF_INTEL_MTL"); -void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) +static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) { char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; u32 fwsts; @@ -343,7 +340,6 @@ void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) sof_ipc4_intel_dump_telemetry_state(sdev, flags); } -EXPORT_SYMBOL_NS(mtl_dsp_dump, "SND_SOC_SOF_INTEL_MTL"); static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev) { @@ -559,7 +555,7 @@ err: } EXPORT_SYMBOL_NS(mtl_dsp_cl_init, "SND_SOC_SOF_INTEL_MTL"); -irqreturn_t mtl_ipc_irq_thread(int irq, void *context) +static irqreturn_t mtl_ipc_irq_thread(int irq, void *context) { struct sof_ipc4_msg notification_data = {{ 0 }}; struct snd_sof_dev *sdev = context; @@ -641,21 +637,18 @@ irqreturn_t mtl_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } -EXPORT_SYMBOL_NS(mtl_ipc_irq_thread, "SND_SOC_SOF_INTEL_MTL"); -int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) +static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { return MTL_DSP_MBOX_UPLINK_OFFSET; } -EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_mailbox_offset, "SND_SOC_SOF_INTEL_MTL"); -int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) +static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) { return MTL_SRAM_WINDOW_OFFSET(id); } -EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_window_offset, "SND_SOC_SOF_INTEL_MTL"); -void mtl_ipc_dump(struct snd_sof_dev *sdev) +static void mtl_ipc_dump(struct snd_sof_dev *sdev) { u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl; @@ -671,7 +664,6 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev) "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); } -EXPORT_SYMBOL_NS(mtl_ipc_dump, "SND_SOC_SOF_INTEL_MTL"); static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) { @@ -680,7 +672,7 @@ static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) return mtl_enable_interrupts(sdev, false); } -int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) +static int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) { const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; @@ -692,9 +684,8 @@ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) return 0; } -EXPORT_SYMBOL_NS(mtl_dsp_core_get, "SND_SOC_SOF_INTEL_MTL"); -int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) +static int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) { const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; int ret; @@ -710,7 +701,6 @@ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) return 0; } -EXPORT_SYMBOL_NS(mtl_dsp_core_put, "SND_SOC_SOF_INTEL_MTL"); int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) { diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 4d098dae2973..e01a1536709e 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -122,28 +122,13 @@ #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0) bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev); -int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg); void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev); void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev); int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable); -int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev); -int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev); -void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags); - int mtl_power_down_dsp(struct snd_sof_dev *sdev); int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); -irqreturn_t mtl_ipc_irq_thread(int irq, void *context); - -int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev); -int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); - -void mtl_ipc_dump(struct snd_sof_dev *sdev); - -int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core); -int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core); - int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); From 8aeb7d2c3fc315e629d252cd601598a5af74bbb0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:12 +0200 Subject: [PATCH 0781/1090] ASoC: SOF: Intel: Create ptl.c as placeholder for Panther Lake features Create a minimal placeholder to make it possible to add code to handle the new features of Panther Lake compared to MTL/LNL. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/lnl.c | 33 ++++------------------ sound/soc/sof/intel/lnl.h | 4 +++ sound/soc/sof/intel/pci-ptl.c | 6 ++-- sound/soc/sof/intel/ptl.c | 52 +++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/ptl.h | 14 ++++++++++ 6 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 sound/soc/sof/intel/ptl.c create mode 100644 sound/soc/sof/intel/ptl.h diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index f40daa616803..675f9fc92dde 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -34,7 +34,7 @@ snd-sof-pci-intel-icl-y := pci-icl.o icl.o snd-sof-pci-intel-tgl-y := pci-tgl.o tgl.o snd-sof-pci-intel-mtl-y := pci-mtl.o mtl.o snd-sof-pci-intel-lnl-y := pci-lnl.o lnl.o -snd-sof-pci-intel-ptl-y := pci-ptl.o +snd-sof-pci-intel-ptl-y := pci-ptl.o ptl.o obj-$(CONFIG_SND_SOC_SOF_MERRIFIELD) += snd-sof-pci-intel-tng.o obj-$(CONFIG_SND_SOC_SOF_INTEL_SKL) += snd-sof-pci-intel-skl.o diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index ffda39ca3606..2f3222040f98 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -128,20 +128,22 @@ int sof_lnl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) EXPORT_SYMBOL_NS(sof_lnl_set_ops, "SND_SOC_SOF_INTEL_LNL"); /* Check if an SDW IRQ occurred */ -static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) +bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); return hdac_bus_eml_check_interrupt(bus, true, AZX_REG_ML_LEPTR_ID_SDW); } +EXPORT_SYMBOL_NS(lnl_dsp_check_sdw_irq, "SND_SOC_SOF_INTEL_LNL"); -static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev) +int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev) { mtl_disable_ipc_interrupts(sdev); return mtl_enable_interrupts(sdev, false); } +EXPORT_SYMBOL_NS(lnl_dsp_disable_interrupts, "SND_SOC_SOF_INTEL_LNL"); -static bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) +bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) { struct hdac_bus *bus = sof_to_bus(sdev); u16 wake_sts; @@ -157,6 +159,7 @@ static bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) /* filter out the range of SDIs that can be set for SoundWire */ return wake_sts & GENMASK(SDW_MAX_DEVICES, SDW_INTEL_DEV_NUM_IDA_MIN); } +EXPORT_SYMBOL_NS(lnl_sdw_check_wakeen_irq, "SND_SOC_SOF_INTEL_LNL"); const struct sof_intel_dsp_desc lnl_chip_info = { .cores_num = 5, @@ -182,29 +185,5 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .hw_ip_version = SOF_INTEL_ACE_2_0, }; -const struct sof_intel_dsp_desc ptl_chip_info = { - .cores_num = 5, - .init_core_mask = BIT(0), - .host_managed_cores_mask = BIT(0), - .ipc_req = MTL_DSP_REG_HFIPCXIDR, - .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, - .ipc_ack = MTL_DSP_REG_HFIPCXIDA, - .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, - .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = LNL_DSP_REG_HFDSC, - .rom_init_timeout = 300, - .ssp_count = MTL_SSP_COUNT, - .d0i3_offset = MTL_HDA_VS_D0I3C, - .read_sdw_lcount = hda_sdw_check_lcount_ext, - .check_sdw_irq = lnl_dsp_check_sdw_irq, - .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, - .check_ipc_irq = mtl_dsp_check_ipc_irq, - .cl_init = mtl_dsp_cl_init, - .power_down_dsp = mtl_power_down_dsp, - .disable_interrupts = lnl_dsp_disable_interrupts, - .hw_ip_version = SOF_INTEL_ACE_3_0, -}; -EXPORT_SYMBOL_NS(ptl_chip_info, "SND_SOC_SOF_INTEL_LNL"); - MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h index e585b93d2b63..2837f818ac51 100644 --- a/sound/soc/sof/intel/lnl.h +++ b/sound/soc/sof/intel/lnl.h @@ -14,4 +14,8 @@ int sof_lnl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); +bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev); +int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev); +bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev); + #endif /* __SOF_INTEL_LNL_H */ diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index 32f93723ee66..3812ab6d99c0 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -16,14 +16,14 @@ /* platform specific devices */ #include "hda.h" -#include "lnl.h" +#include "ptl.h" /* PantherLake ops */ static struct snd_sof_dsp_ops sof_ptl_ops; static int sof_ptl_ops_init(struct snd_sof_dev *sdev) { - return sof_lnl_set_ops(sdev, &sof_ptl_ops); + return sof_ptl_set_ops(sdev, &sof_ptl_ops); } static const struct sof_dev_desc ptl_desc = { @@ -80,6 +80,4 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF support for PantherLake platforms"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC"); MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON"); -MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL"); -MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV"); diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c new file mode 100644 index 000000000000..ae8e9e08ad2a --- /dev/null +++ b/sound/soc/sof/intel/ptl.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// Copyright(c) 2025 Intel Corporation + +/* + * Hardware interface for audio DSP on PantherLake. + */ + +#include +#include +#include +#include "../ipc4-priv.h" +#include "../ops.h" +#include "hda.h" +#include "hda-ipc.h" +#include "../sof-audio.h" +#include "mtl.h" +#include "lnl.h" +#include "ptl.h" + +int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) +{ + return sof_lnl_set_ops(sdev, dsp_ops); +} +EXPORT_SYMBOL_NS(sof_ptl_set_ops, "SND_SOC_SOF_INTEL_PTL"); + +const struct sof_intel_dsp_desc ptl_chip_info = { + .cores_num = 5, + .init_core_mask = BIT(0), + .host_managed_cores_mask = BIT(0), + .ipc_req = MTL_DSP_REG_HFIPCXIDR, + .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, + .rom_status_reg = LNL_DSP_REG_HFDSC, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .d0i3_offset = MTL_HDA_VS_D0I3C, + .read_sdw_lcount = hda_sdw_check_lcount_ext, + .check_sdw_irq = lnl_dsp_check_sdw_irq, + .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, + .check_ipc_irq = mtl_dsp_check_ipc_irq, + .cl_init = mtl_dsp_cl_init, + .power_down_dsp = mtl_power_down_dsp, + .disable_interrupts = lnl_dsp_disable_interrupts, + .hw_ip_version = SOF_INTEL_ACE_3_0, +}; + +MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); +MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL"); +MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK"); diff --git a/sound/soc/sof/intel/ptl.h b/sound/soc/sof/intel/ptl.h new file mode 100644 index 000000000000..186f7c835acb --- /dev/null +++ b/sound/soc/sof/intel/ptl.h @@ -0,0 +1,14 @@ +/* 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. + * + * Copyright(c) 2025 Intel Corporation + */ + +#ifndef __SOF_INTEL_PTL_H +#define __SOF_INTEL_PTL_H + +int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); + +#endif /* __SOF_INTEL_PTL_H */ From eea84a7f0cdb693c261a7cf84bd4b3d81479c9a6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:13 +0200 Subject: [PATCH 0782/1090] ASoC: SOF: ipc4: Add support for Intel HW managed mic privacy messaging ACE3 (Panther Lake) introduced support for microphone privacy feature which can - in hardware - mute incoming audio data based on a state of a physical switch. The change in the privacy state is delivered through interface IP blocks and can only be handled by the link owner. In Intel platforms Soundwire is for example host owned, so the interrupt can only be handled by the host. Since the input stream is going to be muted by hardware, the host needs to send a message to firmware about the change in privacy so it can execute a fade out/in to enhance user experience. The support for microphone privacy can be queried from the HW_CONFIG data under the INTEL_MIC_PRIVACY_CAP tuple. This is Intel specific data, the core will pass it to platform code if the intel_configure_mic_privacy() callback is provided. Platform code can call sof_ipc4_mic_privacy_state_change() to send the IPC message to the firmware on state change. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof/ipc4/header.h | 13 +++++++++++++ sound/soc/sof/ipc4-loader.c | 33 +++++++++++++++++++++++++++++++++ sound/soc/sof/ipc4-priv.h | 5 +++++ sound/soc/sof/ipc4.c | 18 ++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h index 0c0cf47946b1..f71d04736d17 100644 --- a/include/sound/sof/ipc4/header.h +++ b/include/sound/sof/ipc4/header.h @@ -396,6 +396,7 @@ enum sof_ipc4_base_fw_params { SOF_IPC4_FW_PARAM_MODULES_INFO_GET, SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16, SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20, + SOF_IPC4_FW_PARAM_MIC_PRIVACY_STATE_CHANGE = 35, }; enum sof_ipc4_fw_config_params { @@ -446,6 +447,18 @@ struct sof_ipc4_dx_state_info { uint32_t dx_mask; } __packed __aligned(4); +enum sof_ipc4_hw_config_params { + SOF_IPC4_HW_CFG_INTEL_MIC_PRIVACY_CAPS = 11, +}; + +#define SOF_IPC_INTEL_MIC_PRIVACY_VERSION_PTL 1 + +struct sof_ipc4_intel_mic_privacy_cap { + uint32_t version; + uint32_t capabilities_length; + uint32_t capabilities[]; +} __packed; + /* Reply messages */ /* diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index 6ad1ef0e53e8..d2f534d65edf 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -502,6 +502,39 @@ int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev) offset += sizeof(*tuple) + tuple->size; } + /* Get the hardware configuration */ + msg.primary = SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg.primary |= SOF_IPC4_MOD_ID(SOF_IPC4_MOD_INIT_BASEFW_MOD_ID); + msg.primary |= SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID); + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_HW_CONFIG_GET); + + msg.data_size = sdev->ipc->max_payload_size; + + ret = iops->set_get_data(sdev, &msg, msg.data_size, false); + if (ret) + goto out; + + offset = 0; + while (offset < msg.data_size) { + tuple = (struct sof_ipc4_tuple *)((u8 *)msg.data_ptr + offset); + + switch (tuple->type) { + case SOF_IPC4_HW_CFG_INTEL_MIC_PRIVACY_CAPS: + if (ipc4_data->intel_configure_mic_privacy) { + struct sof_ipc4_intel_mic_privacy_cap *caps; + + caps = (struct sof_ipc4_intel_mic_privacy_cap *)tuple->value; + ipc4_data->intel_configure_mic_privacy(sdev, caps); + } + break; + default: + break; + } + + offset += sizeof(*tuple) + tuple->size; + } + out: kfree(msg.data_ptr); diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index b798810eff91..58b032820683 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -11,6 +11,7 @@ #include #include +#include #include "sof-priv.h" /* The DSP window indices are fixed */ @@ -89,6 +90,8 @@ struct sof_ipc4_fw_data { int (*load_library)(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload); + void (*intel_configure_mic_privacy)(struct snd_sof_dev *sdev, + struct sof_ipc4_intel_mic_privacy_cap *caps); struct mutex pipeline_state_mutex; /* protect pipeline triggers, ref counts and states */ }; @@ -118,4 +121,6 @@ void sof_ipc4_update_cpc_from_manifest(struct snd_sof_dev *sdev, size_t sof_ipc4_find_debug_slot_offset_by_type(struct snd_sof_dev *sdev, u32 slot_type); +void sof_ipc4_mic_privacy_state_change(struct snd_sof_dev *sdev, bool state); + #endif diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index 2ed0c52fb2f1..37e837b22ac8 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -851,3 +851,21 @@ const struct sof_ipc_ops ipc4_ops = { .pcm = &ipc4_pcm_ops, .fw_tracing = &ipc4_mtrace_ops, }; + +void sof_ipc4_mic_privacy_state_change(struct snd_sof_dev *sdev, bool state) +{ + struct sof_ipc4_msg msg; + u32 data = state; + + msg.primary = SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); + msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); + msg.primary |= SOF_IPC4_MOD_ID(SOF_IPC4_MOD_INIT_BASEFW_MOD_ID); + msg.primary |= SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID); + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_MIC_PRIVACY_STATE_CHANGE); + + msg.data_size = sizeof(data); + msg.data_ptr = &data; + + sof_ipc4_set_get_data(sdev, &msg, msg.data_size, true); +} +EXPORT_SYMBOL(sof_ipc4_mic_privacy_state_change); From 0978e8207b61ac6d51280e5d28ccfff75d653363 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:14 +0200 Subject: [PATCH 0783/1090] ASoC: SOF: Intel: hda-mlink: Add support for mic privacy in VS SHIM registers New register has been introduced with PTL in the vendor specific SHIM registers, outside of the IPs itself for microphone privacy status handling. Via the PVCCS register the current microphone privacy status can be checked and the interrupt generation on status change can be enabled/disabled. The status change interrupt is routed to the owner of the interface (DSP/host). The PVCCS is provided for each sublink under the IP to make it possible to control the interrupt generation per sublink. On status change the MDSTSCHG bit needs to be cleared for all sublink of the interface to be able to detect future changes in privacy. The status bit (MDSTS) is volatile in all PVCCS register, it reflects the current state of the GPIO signal. Microphone privacy is a hardware feature (if enabled and configured that way), the host has only passive, monitoring role. The added functions are generic to be future proof if the mic privacy support is extended beyond Soundwire and DMIC links. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- include/sound/hda-mlink.h | 25 +++++++ sound/soc/sof/intel/hda-mlink.c | 127 ++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 6774f4b9e5fc..4327317be6af 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -62,6 +62,12 @@ struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid); int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); +/* microphone privacy specific function supported by ACE3+ architecture */ +void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, + unsigned long mask); +bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid); +bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid); + #else static inline int @@ -185,4 +191,23 @@ hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enabl { return 0; } + +static inline void +hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, + unsigned long mask) +{ +} + +static inline bool +hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid) +{ + return false; +} + +static inline bool +hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid) +{ + return false; +} + #endif /* CONFIG_SND_SOC_SOF_HDA_MLINK */ diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index fe627bcb0531..ce561fe52bd5 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -16,6 +16,7 @@ #include #include +#include #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK) @@ -42,6 +43,7 @@ * @shim_offset: offset to SHIM register base * @ip_offset: offset to IP register base * @shim_vs_offset: offset to vendor-specific (VS) SHIM base + * @mic_privacy_mask: bitmask of sublinks where mic privacy is applied */ struct hdac_ext2_link { struct hdac_ext_link hext_link; @@ -65,6 +67,8 @@ struct hdac_ext2_link { u32 shim_offset; u32 ip_offset; u32 shim_vs_offset; + + unsigned long mic_privacy_mask; }; #define hdac_ext_link_to_ext2(h) container_of(h, struct hdac_ext2_link, hext_link) @@ -90,6 +94,13 @@ struct hdac_ext2_link { #define AZX_REG_INTEL_UAOL_IP_OFFSET 0x100 #define AZX_REG_INTEL_UAOL_VS_SHIM_OFFSET 0xC00 +/* Microphone privacy */ +#define AZX_REG_INTEL_VS_SHIM_PVCCS 0x10 +#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE BIT(0) +#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHG BIT(8) +#define AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS BIT(9) +#define AZX_REG_INTEL_VS_SHIM_PVCCS_FMDIS BIT(10) + /* HDAML section - this part follows sequences in the hardware specification, * including naming conventions and the use of the hdaml_ prefix. * The code is intentionally minimal with limited dependencies on frameworks or @@ -696,6 +707,20 @@ static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, } ret = hdaml_link_init(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); + if ((h2link->mic_privacy_mask & BIT(sublink)) && !ret) { + u16 __iomem *pvccs = h2link->base_ptr + + h2link->shim_vs_offset + + sublink * h2link->instance_offset + + AZX_REG_INTEL_VS_SHIM_PVCCS; + u16 val = readw(pvccs); + + writew(val | AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE, pvccs); + + if (val & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS) + dev_dbg(bus->dev, + "sublink %d (%d:%d): Mic privacy is enabled\n", + sublink, alt, elid); + } skip_init: if (eml_lock) @@ -742,6 +767,16 @@ static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid if (--h2link->sublink_ref_count[sublink] > 0) goto skip_shutdown; } + + if (h2link->mic_privacy_mask & BIT(sublink)) { + u16 __iomem *pvccs = h2link->base_ptr + + h2link->shim_vs_offset + + sublink * h2link->instance_offset + + AZX_REG_INTEL_VS_SHIM_PVCCS; + + writew(readw(pvccs) & ~AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHGIE, pvccs); + } + ret = hdaml_link_shutdown(hlink->ml_addr + AZX_REG_ML_LCTL, sublink); skip_shutdown: @@ -987,6 +1022,98 @@ int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool e } EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, "SND_SOC_SOF_HDA_MLINK"); +void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, + unsigned long mask) +{ + struct hdac_ext2_link *h2link; + + if (!mask) + return; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return; + + if (__fls(mask) > h2link->slcount) { + dev_warn(bus->dev, + "%s: invalid sublink mask for %d:%d, slcount %d: %#lx\n", + __func__, alt, elid, h2link->slcount, mask); + return; + } + + dev_dbg(bus->dev, "sublink mask for %d:%d, slcount %d: %#lx\n", alt, + elid, h2link->slcount, mask); + + h2link->mic_privacy_mask = mask; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_set_mic_privacy_mask, "SND_SOC_SOF_HDA_MLINK"); + +bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + bool changed = false; + u16 __iomem *pvccs; + int i; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return false; + + /* The change in privacy state needs to be acked for each link */ + for_each_set_bit(i, &h2link->mic_privacy_mask, h2link->slcount) { + u16 val; + + if (h2link->sublink_ref_count[i] == 0) + continue; + + pvccs = h2link->base_ptr + + h2link->shim_vs_offset + + i * h2link->instance_offset + + AZX_REG_INTEL_VS_SHIM_PVCCS; + + val = readw(pvccs); + if (val & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTSCHG) { + writew(val, pvccs); + changed = true; + } + } + + return changed; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_is_mic_privacy_changed, "SND_SOC_SOF_HDA_MLINK"); + +bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid) +{ + struct hdac_ext2_link *h2link; + u16 __iomem *pvccs; + bool state; + int i; + + h2link = find_ext2_link(bus, alt, elid); + if (!h2link) + return false; + + for_each_set_bit(i, &h2link->mic_privacy_mask, h2link->slcount) { + if (h2link->sublink_ref_count[i] == 0) + continue; + + /* Return the privacy state from the first active link */ + pvccs = h2link->base_ptr + + h2link->shim_vs_offset + + i * h2link->instance_offset + + AZX_REG_INTEL_VS_SHIM_PVCCS; + + state = readw(pvccs) & AZX_REG_INTEL_VS_SHIM_PVCCS_MDSTS; + dev_dbg(bus->dev, "alt: %d, elid: %d: Mic privacy is %s\n", alt, + elid, str_enabled_disabled(state)); + + return state; + } + + return false; +} +EXPORT_SYMBOL_NS(hdac_bus_eml_get_mic_privacy_state, "SND_SOC_SOF_HDA_MLINK"); + #endif MODULE_LICENSE("Dual BSD/GPL"); From a0db661e7d8e084e9cf3b9cdca7c6e4e66f2e849 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:15 +0200 Subject: [PATCH 0784/1090] ASoC: SOF: hda/shim: Add callbacks to handle mic privacy change for sdw Add generic callback definitions for checking the mic privacy interrupt and status. Implement wrappers for mic privacy reported via the Soundwire interrupt and its vendor specific SHIM registers. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 34 ++++++++++++++++++++++++++++++++++ sound/soc/sof/intel/shim.h | 2 ++ 2 files changed, 36 insertions(+) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a1ccd95da8bb..6b1ada566476 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -352,6 +352,27 @@ void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev) } EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, "SND_SOC_SOF_INTEL_HDA_GENERIC"); +static bool hda_dsp_sdw_check_mic_privacy_irq(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->check_mic_privacy_irq) + return chip->check_mic_privacy_irq(sdev, true, + AZX_REG_ML_LEPTR_ID_SDW); + + return false; +} + +static void hda_dsp_sdw_process_mic_privacy(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->process_mic_privacy) + chip->process_mic_privacy(sdev, true, AZX_REG_ML_LEPTR_ID_SDW); +} + #else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */ static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) { @@ -383,6 +404,13 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) return false; } +static inline bool hda_dsp_sdw_check_mic_privacy_irq(struct snd_sof_dev *sdev) +{ + return false; +} + +static inline void hda_dsp_sdw_process_mic_privacy(struct snd_sof_dev *sdev) { } + #endif /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */ /* pre fw run operations */ @@ -678,7 +706,13 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) if (hda_dsp_check_sdw_irq(sdev)) { trace_sof_intel_hda_irq(sdev, "sdw"); + hda_dsp_sdw_thread(irq, hdev->sdw); + + if (hda_dsp_sdw_check_mic_privacy_irq(sdev)) { + trace_sof_intel_hda_irq(sdev, "mic privacy"); + hda_dsp_sdw_process_mic_privacy(sdev); + } } if (hda_sdw_check_wakeen_irq(sdev)) { diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 8709b750a11e..d4372f0bff7e 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -193,6 +193,8 @@ struct sof_intel_dsp_desc { bool (*check_sdw_wakeen_irq)(struct snd_sof_dev *sdev); void (*sdw_process_wakeen)(struct snd_sof_dev *sdev); bool (*check_ipc_irq)(struct snd_sof_dev *sdev); + bool (*check_mic_privacy_irq)(struct snd_sof_dev *sdev, bool alt, int elid); + void (*process_mic_privacy)(struct snd_sof_dev *sdev, bool alt, int elid); int (*power_down_dsp)(struct snd_sof_dev *sdev); int (*disable_interrupts)(struct snd_sof_dev *sdev); int (*cl_init)(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); From 4a43c3241ec3465a501825ecaf051e5a1d85a60b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2025 13:28:16 +0200 Subject: [PATCH 0785/1090] ASoC: SOF: Intel: ptl: Add support for mic privacy Implement the three callbacks that is needed to enable support for reporting the mic privacy change via soundwire. In PTL the mic privacy reporting is supported via soundwire and DMIC and the soundwire is owned by the host, it's interrupt is routed there. To enable the interrupt, the sublink mask needs to be passed to the multilink layer, the check_mic_privacy_irq/process_mic_privacy callbacks needs to be implemented to check and report the mic privacy change. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Liam Girdwood Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20250307112816.1495-9-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/ptl.c | 58 +++++++++++++++++++++++++++++++++++++-- sound/soc/sof/intel/ptl.h | 5 ++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c index ae8e9e08ad2a..8fa4bdceedd9 100644 --- a/sound/soc/sof/intel/ptl.c +++ b/sound/soc/sof/intel/ptl.c @@ -18,10 +18,62 @@ #include "lnl.h" #include "ptl.h" +static bool sof_ptl_check_mic_privacy_irq(struct snd_sof_dev *sdev, bool alt, + int elid) +{ + if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW) + return false; + + return hdac_bus_eml_is_mic_privacy_changed(sof_to_bus(sdev), alt, elid); +} + +static void sof_ptl_process_mic_privacy(struct snd_sof_dev *sdev, bool alt, + int elid) +{ + bool state; + + if (!alt || elid != AZX_REG_ML_LEPTR_ID_SDW) + return; + + state = hdac_bus_eml_get_mic_privacy_state(sof_to_bus(sdev), alt, elid); + + sof_ipc4_mic_privacy_state_change(sdev, state); +} + +static void sof_ptl_set_mic_privacy(struct snd_sof_dev *sdev, + struct sof_ipc4_intel_mic_privacy_cap *caps) +{ + u32 micpvcp; + + if (!caps || !caps->capabilities_length) + return; + + micpvcp = caps->capabilities[0]; + + /* No need to set the mic privacy if it is not enabled or forced */ + if (!(micpvcp & PTL_MICPVCP_DDZE_ENABLED) || + micpvcp & PTL_MICPVCP_DDZE_FORCED) + return; + + hdac_bus_eml_set_mic_privacy_mask(sof_to_bus(sdev), true, + AZX_REG_ML_LEPTR_ID_SDW, + PTL_MICPVCP_GET_SDW_MASK(micpvcp)); +} + int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops) { - return sof_lnl_set_ops(sdev, dsp_ops); -} + struct sof_ipc4_fw_data *ipc4_data; + int ret; + + ret = sof_lnl_set_ops(sdev, dsp_ops); + if (ret) + return ret; + + ipc4_data = sdev->private; + ipc4_data->intel_configure_mic_privacy = sof_ptl_set_mic_privacy; + + return 0; +}; EXPORT_SYMBOL_NS(sof_ptl_set_ops, "SND_SOC_SOF_INTEL_PTL"); const struct sof_intel_dsp_desc ptl_chip_info = { @@ -41,6 +93,8 @@ const struct sof_intel_dsp_desc ptl_chip_info = { .check_sdw_irq = lnl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, .check_ipc_irq = mtl_dsp_check_ipc_irq, + .check_mic_privacy_irq = sof_ptl_check_mic_privacy_irq, + .process_mic_privacy = sof_ptl_process_mic_privacy, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, .disable_interrupts = lnl_dsp_disable_interrupts, diff --git a/sound/soc/sof/intel/ptl.h b/sound/soc/sof/intel/ptl.h index 186f7c835acb..6a7ef11f411e 100644 --- a/sound/soc/sof/intel/ptl.h +++ b/sound/soc/sof/intel/ptl.h @@ -9,6 +9,11 @@ #ifndef __SOF_INTEL_PTL_H #define __SOF_INTEL_PTL_H +#define PTL_MICPVCP_DDZE_FORCED BIT(16) +#define PTL_MICPVCP_DDZE_ENABLED BIT(17) +#define PTL_MICPVCP_DDZLS_SDW GENMASK(26, 20) +#define PTL_MICPVCP_GET_SDW_MASK(x) (((x) & PTL_MICPVCP_DDZLS_SDW) >> 20) + int sof_ptl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops); #endif /* __SOF_INTEL_PTL_H */ From a8fed0bddf8fa239fc71dc5c035d2e078c597369 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 6 Mar 2025 18:18:39 +0100 Subject: [PATCH 0786/1090] ASoC: dt-bindings: add regulator support to dmic codec Add optional vref-supply property to describe the regulator supplying the digital microphones. Signed-off-by: Olivier Moysan Acked-by: "Rob Herring (Arm)" Link: https://patch.msgid.link/20250306171840.593443-2-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/dmic-codec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/dmic-codec.yaml b/Documentation/devicetree/bindings/sound/dmic-codec.yaml index 59ef0cf6b6e5..cc3c84dd4c26 100644 --- a/Documentation/devicetree/bindings/sound/dmic-codec.yaml +++ b/Documentation/devicetree/bindings/sound/dmic-codec.yaml @@ -19,6 +19,9 @@ properties: '#sound-dai-cells': const: 0 + vref-supply: + description: Phandle to the digital microphone reference supply + dmicen-gpios: description: GPIO specifier for DMIC to control start and stop maxItems: 1 From d3321a20b5111a66f3e68798959a347acfccbd44 Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Thu, 6 Mar 2025 18:18:40 +0100 Subject: [PATCH 0787/1090] ASoC: dmic: add regulator support Allow management of the regulator that may be used to supply the digital microphone. Signed-off-by: Olivier Moysan Link: https://patch.msgid.link/20250306171840.593443-3-olivier.moysan@foss.st.com Signed-off-by: Mark Brown --- sound/soc/codecs/dmic.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index 0388f115470c..5d3c3f17c6d8 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ module_param(wakeup_delay, uint, 0644); struct dmic { struct gpio_desc *gpio_en; + struct regulator *vref; int wakeup_delay; /* Delay after DMIC mode switch */ int modeswitch_delay; @@ -55,22 +57,33 @@ static int dmic_aif_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct dmic *dmic = snd_soc_component_get_drvdata(component); + int ret = 0; switch (event) { case SND_SOC_DAPM_POST_PMU: if (dmic->gpio_en) gpiod_set_value_cansleep(dmic->gpio_en, 1); + if (dmic->vref) { + ret = regulator_enable(dmic->vref); + if (ret) + return ret; + } + if (dmic->wakeup_delay) msleep(dmic->wakeup_delay); break; case SND_SOC_DAPM_POST_PMD: if (dmic->gpio_en) gpiod_set_value_cansleep(dmic->gpio_en, 0); + + if (dmic->vref) + ret = regulator_disable(dmic->vref); + break; } - return 0; + return ret; } static struct snd_soc_dai_driver dmic_dai = { @@ -100,6 +113,10 @@ static int dmic_component_probe(struct snd_soc_component *component) if (!dmic) return -ENOMEM; + dmic->vref = devm_regulator_get_optional(component->dev, "vref"); + if (IS_ERR(dmic->vref) && PTR_ERR(dmic->vref) != -ENODEV) + return dev_err_probe(component->dev, PTR_ERR(dmic->vref), "Failed to get vref\n"); + dmic->gpio_en = devm_gpiod_get_optional(component->dev, "dmicen", GPIOD_OUT_LOW); if (IS_ERR(dmic->gpio_en)) From db91ad81a2545eb82aa47d0306bc3e1adb05e336 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 6 Mar 2025 13:31:38 +0800 Subject: [PATCH 0788/1090] ASoC: dt-bindings: fsl,imx-asrc: Document audio graph port This device can be used in conjunction with audio-graph-card to provide an endpoint for binding with the other side of the audio link. Signed-off-by: Shengjiu Wang Reviewed-by: Frank Li Reviewed-by: "Rob Herring (Arm)" Link: https://patch.msgid.link/20250306053138.1914956-1-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,imx-asrc.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml index abac5084d63b..85799f83e65f 100644 --- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml @@ -77,6 +77,10 @@ properties: power-domains: maxItems: 1 + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + fsl,asrc-rate: $ref: /schemas/types.yaml#/definitions/uint32 description: The mutual sample rate used by DPCM Back Ends @@ -174,4 +178,12 @@ examples: "txa", "txb", "txc"; fsl,asrc-rate = <48000>; fsl,asrc-width = <16>; + + port { + playback-only; + + asrc_endpoint: endpoint { + remote-endpoint = <&fe00_ep>; + }; + }; }; From 058a6bec37c6c3b826158f6d26b75de43816a880 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Fri, 7 Mar 2025 23:02:56 +0100 Subject: [PATCH 0789/1090] x86/microcode/AMD: Add some forgotten models to the SHA check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some more forgotten models to the SHA check. Fixes: 50cef76d5cb0 ("x86/microcode/AMD: Load only SHA256-checksummed patches") Reported-by: Toralf Förster Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar Tested-by: Toralf Förster Link: https://lore.kernel.org/r/20250307220256.11816-1-bp@kernel.org --- arch/x86/kernel/cpu/microcode/amd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 95ac1c6a84fb..c69b1bc45483 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -175,23 +175,29 @@ static bool need_sha_check(u32 cur_rev) { switch (cur_rev >> 8) { case 0x80012: return cur_rev <= 0x800126f; break; + case 0x80082: return cur_rev <= 0x800820f; break; case 0x83010: return cur_rev <= 0x830107c; break; case 0x86001: return cur_rev <= 0x860010e; break; case 0x86081: return cur_rev <= 0x8608108; break; case 0x87010: return cur_rev <= 0x8701034; break; case 0x8a000: return cur_rev <= 0x8a0000a; break; + case 0xa0010: return cur_rev <= 0xa00107a; break; case 0xa0011: return cur_rev <= 0xa0011da; break; case 0xa0012: return cur_rev <= 0xa001243; break; + case 0xa0082: return cur_rev <= 0xa00820e; break; case 0xa1011: return cur_rev <= 0xa101153; break; case 0xa1012: return cur_rev <= 0xa10124e; break; case 0xa1081: return cur_rev <= 0xa108109; break; case 0xa2010: return cur_rev <= 0xa20102f; break; case 0xa2012: return cur_rev <= 0xa201212; break; + case 0xa4041: return cur_rev <= 0xa404109; break; + case 0xa5000: return cur_rev <= 0xa500013; break; case 0xa6012: return cur_rev <= 0xa60120a; break; case 0xa7041: return cur_rev <= 0xa704109; break; case 0xa7052: return cur_rev <= 0xa705208; break; case 0xa7080: return cur_rev <= 0xa708009; break; case 0xa70c0: return cur_rev <= 0xa70C009; break; + case 0xaa001: return cur_rev <= 0xaa00116; break; case 0xaa002: return cur_rev <= 0xaa00218; break; default: break; } From 80e54e84911a923c40d7bee33a34c1b4be148d7a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 9 Mar 2025 13:45:25 -1000 Subject: [PATCH 0790/1090] Linux 6.14-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6a8e5be6b004..1d6a9ec8a2ac 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Baby Opossum Posse # *DOCUMENTATION* From aed709355fd05ef747e1af24a1d5d78cd7feb81e Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Mon, 10 Feb 2025 11:34:41 -0800 Subject: [PATCH 0791/1090] drm/hyperv: Fix address space leak when Hyper-V DRM device is removed When a Hyper-V DRM device is probed, the driver allocates MMIO space for the vram, and maps it cacheable. If the device removed, or in the error path for device probing, the MMIO space is released but no unmap is done. Consequently the kernel address space for the mapping is leaked. Fix this by adding iounmap() calls in the device removal path, and in the error path during device probing. Fixes: f1f63cbb705d ("drm/hyperv: Fix an error handling path in hyperv_vmbus_probe()") Fixes: a0ab5abced55 ("drm/hyperv : Removing the restruction of VRAM allocation with PCI bar size") Signed-off-by: Michael Kelley Reviewed-by: Saurabh Sengar Tested-by: Saurabh Sengar Link: https://lore.kernel.org/r/20250210193441.2414-1-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20250210193441.2414-1-mhklinux@outlook.com> --- drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c index f59abfa7622a..0d49f168a919 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c @@ -154,6 +154,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev, return 0; err_free_mmio: + iounmap(hv->vram); vmbus_free_mmio(hv->mem->start, hv->fb_size); err_vmbus_close: vmbus_close(hdev->channel); @@ -172,6 +173,7 @@ static void hyperv_vmbus_remove(struct hv_device *hdev) vmbus_close(hdev->channel); hv_set_drvdata(hdev, NULL); + iounmap(hv->vram); vmbus_free_mmio(hv->mem->start, hv->fb_size); } From 304386373007aaca9236a3f36afac0bbedcd2bf0 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Tue, 18 Feb 2025 15:01:30 -0800 Subject: [PATCH 0792/1090] fbdev: hyperv_fb: Fix hang in kdump kernel when on Hyper-V Gen 2 VMs Gen 2 Hyper-V VMs boot via EFI and have a standard EFI framebuffer device. When the kdump kernel runs in such a VM, loading the efifb driver may hang because of accessing the framebuffer at the wrong memory address. The scenario occurs when the hyperv_fb driver in the original kernel moves the framebuffer to a different MMIO address because of conflicts with an already-running efifb or simplefb driver. The hyperv_fb driver then informs Hyper-V of the change, which is allowed by the Hyper-V FB VMBus device protocol. However, when the kexec command loads the kdump kernel into crash memory via the kexec_file_load() system call, the system call doesn't know the framebuffer has moved, and it sets up the kdump screen_info using the original framebuffer address. The transition to the kdump kernel does not go through the Hyper-V host, so Hyper-V does not reset the framebuffer address like it would do on a reboot. When efifb tries to run, it accesses a non-existent framebuffer address, which traps to the Hyper-V host. After many such accesses, the Hyper-V host thinks the guest is being malicious, and throttles the guest to the point that it runs very slowly or appears to have hung. When the kdump kernel is loaded into crash memory via the kexec_load() system call, the problem does not occur. In this case, the kexec command builds the screen_info table itself in user space from data returned by the FBIOGET_FSCREENINFO ioctl against /dev/fb0, which gives it the new framebuffer location. This problem was originally reported in 2020 [1], resulting in commit 3cb73bc3fa2a ("hyperv_fb: Update screen_info after removing old framebuffer"). This commit solved the problem by setting orig_video_isVGA to 0, so the kdump kernel was unaware of the EFI framebuffer. The efifb driver did not try to load, and no hang occurred. But in 2024, commit c25a19afb81c ("fbdev/hyperv_fb: Do not clear global screen_info") effectively reverted 3cb73bc3fa2a. Commit c25a19afb81c has no reference to 3cb73bc3fa2a, so perhaps it was done without knowing the implications that were reported with 3cb73bc3fa2a. In any case, as of commit c25a19afb81c, the original problem came back again. Interestingly, the hyperv_drm driver does not have this problem because it never moves the framebuffer. The difference is that the hyperv_drm driver removes any conflicting framebuffers *before* allocating an MMIO address, while the hyperv_fb drivers removes conflicting framebuffers *after* allocating an MMIO address. With the "after" ordering, hyperv_fb may encounter a conflict and move the framebuffer to a different MMIO address. But the conflict is essentially bogus because it is removed a few lines of code later. Rather than fix the problem with the approach from 2020 in commit 3cb73bc3fa2a, instead slightly reorder the steps in hyperv_fb so conflicting framebuffers are removed before allocating an MMIO address. Then the default framebuffer MMIO address should always be available, and there's never any confusion about which framebuffer address the kdump kernel should use -- it's always the original address provided by the Hyper-V host. This approach is already used by the hyperv_drm driver, and is consistent with the usage guidelines at the head of the module with the function aperture_remove_conflicting_devices(). This approach also solves a related minor problem when kexec_load() is used to load the kdump kernel. With current code, unbinding and rebinding the hyperv_fb driver could result in the framebuffer moving back to the default framebuffer address, because on the rebind there are no conflicts. If such a move is done after the kdump kernel is loaded with the new framebuffer address, at kdump time it could again have the wrong address. This problem and fix are described in terms of the kdump kernel, but it can also occur with any kernel started via kexec. See extensive discussion of the problem and solution at [2]. [1] https://lore.kernel.org/linux-hyperv/20201014092429.1415040-1-kasong@redhat.com/ [2] https://lore.kernel.org/linux-hyperv/BLAPR10MB521793485093FDB448F7B2E5FDE92@BLAPR10MB5217.namprd10.prod.outlook.com/ Reported-by: Thomas Tai Fixes: c25a19afb81c ("fbdev/hyperv_fb: Do not clear global screen_info") Signed-off-by: Michael Kelley Link: https://lore.kernel.org/r/20250218230130.3207-1-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20250218230130.3207-1-mhklinux@outlook.com> --- drivers/video/fbdev/hyperv_fb.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 363e4ccfcdb7..ce23d0ef5702 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -989,6 +989,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) base = pci_resource_start(pdev, 0); size = pci_resource_len(pdev, 0); + aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME); /* * For Gen 1 VM, we can directly use the contiguous memory @@ -1010,11 +1011,21 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) goto getmem_done; } pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n"); + } else { + aperture_remove_all_conflicting_devices(KBUILD_MODNAME); } /* - * Cannot use the contiguous physical memory. - * Allocate mmio space for framebuffer. + * Cannot use contiguous physical memory, so allocate MMIO space for + * the framebuffer. At this point in the function, conflicting devices + * that might have claimed the framebuffer MMIO space based on + * screen_info.lfb_base must have already been removed so that + * vmbus_allocate_mmio() does not allocate different MMIO space. If the + * kdump image were to be loaded using kexec_file_load(), the + * framebuffer location in the kdump image would be set from + * screen_info.lfb_base at the time that kdump is enabled. If the + * framebuffer has moved elsewhere, this could be the wrong location, + * causing kdump to hang when efifb (for example) loads. */ dio_fb_size = screen_width * screen_height * screen_depth / 8; @@ -1051,11 +1062,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) info->screen_size = dio_fb_size; getmem_done: - if (base && size) - aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME); - else - aperture_remove_all_conflicting_devices(KBUILD_MODNAME); - if (!gen2vm) pci_dev_put(pdev); From f5e728a50bb17336a20803dde488515b833ecd1d Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Sat, 1 Mar 2025 08:16:30 -0800 Subject: [PATCH 0793/1090] fbdev: hyperv_fb: Simplify hvfb_putmem The device object required in 'hvfb_release_phymem' function for 'dma_free_coherent' can also be obtained from the 'info' pointer, making 'hdev' parameter in 'hvfb_putmem' redundant. Remove the unnecessary 'hdev' argument from 'hvfb_putmem'. Signed-off-by: Saurabh Sengar Reviewed-by: Michael Kelley Tested-by: Michael Kelley Link: https://lore.kernel.org/r/1740845791-19977-2-git-send-email-ssengar@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <1740845791-19977-2-git-send-email-ssengar@linux.microsoft.com> --- drivers/video/fbdev/hyperv_fb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index ce23d0ef5702..9798a34ac571 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -952,7 +952,7 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev, } /* Release contiguous physical memory */ -static void hvfb_release_phymem(struct hv_device *hdev, +static void hvfb_release_phymem(struct device *device, phys_addr_t paddr, unsigned int size) { unsigned int order = get_order(size); @@ -960,7 +960,7 @@ static void hvfb_release_phymem(struct hv_device *hdev, if (order <= MAX_PAGE_ORDER) __free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order); else - dma_free_coherent(&hdev->device, + dma_free_coherent(device, round_up(size, PAGE_SIZE), phys_to_virt(paddr), paddr); @@ -1080,7 +1080,7 @@ err1: } /* Release the framebuffer */ -static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info) +static void hvfb_putmem(struct fb_info *info) { struct hvfb_par *par = info->par; @@ -1089,7 +1089,7 @@ static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info) iounmap(par->mmio_vp); vmbus_free_mmio(par->mem->start, screen_fb_size); } else { - hvfb_release_phymem(hdev, info->fix.smem_start, + hvfb_release_phymem(info->device, info->fix.smem_start, screen_fb_size); } @@ -1203,7 +1203,7 @@ static int hvfb_probe(struct hv_device *hdev, error: fb_deferred_io_cleanup(info); - hvfb_putmem(hdev, info); + hvfb_putmem(info); error2: vmbus_close(hdev->channel); error1: @@ -1232,7 +1232,7 @@ static void hvfb_remove(struct hv_device *hdev) vmbus_close(hdev->channel); hv_set_drvdata(hdev, NULL); - hvfb_putmem(hdev, info); + hvfb_putmem(info); framebuffer_release(info); } From ea2f45ab0e53b255f72c85ccd99e2b394fc5fceb Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Sat, 1 Mar 2025 08:16:31 -0800 Subject: [PATCH 0794/1090] fbdev: hyperv_fb: Allow graceful removal of framebuffer When a Hyper-V framebuffer device is unbind, hyperv_fb driver tries to release the framebuffer forcefully. If this framebuffer is in use it produce the following WARN and hence this framebuffer is never released. [ 44.111220] WARNING: CPU: 35 PID: 1882 at drivers/video/fbdev/core/fb_info.c:70 framebuffer_release+0x2c/0x40 < snip > [ 44.111289] Call Trace: [ 44.111290] [ 44.111291] ? show_regs+0x6c/0x80 [ 44.111295] ? __warn+0x8d/0x150 [ 44.111298] ? framebuffer_release+0x2c/0x40 [ 44.111300] ? report_bug+0x182/0x1b0 [ 44.111303] ? handle_bug+0x6e/0xb0 [ 44.111306] ? exc_invalid_op+0x18/0x80 [ 44.111308] ? asm_exc_invalid_op+0x1b/0x20 [ 44.111311] ? framebuffer_release+0x2c/0x40 [ 44.111313] ? hvfb_remove+0x86/0xa0 [hyperv_fb] [ 44.111315] vmbus_remove+0x24/0x40 [hv_vmbus] [ 44.111323] device_remove+0x40/0x80 [ 44.111325] device_release_driver_internal+0x20b/0x270 [ 44.111327] ? bus_find_device+0xb3/0xf0 Fix this by moving the release of framebuffer and assosiated memory to fb_ops.fb_destroy function, so that framebuffer framework handles it gracefully. While we fix this, also replace manual registrations/unregistration of framebuffer with devm_register_framebuffer. Fixes: 68a2d20b79b1 ("drivers/video: add Hyper-V Synthetic Video Frame Buffer Driver") Signed-off-by: Saurabh Sengar Reviewed-by: Michael Kelley Tested-by: Michael Kelley Link: https://lore.kernel.org/r/1740845791-19977-3-git-send-email-ssengar@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <1740845791-19977-3-git-send-email-ssengar@linux.microsoft.com> --- drivers/video/fbdev/hyperv_fb.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 9798a34ac571..75338ffc703f 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -282,6 +282,8 @@ static uint screen_depth; static uint screen_fb_size; static uint dio_fb_size; /* FB size for deferred IO */ +static void hvfb_putmem(struct fb_info *info); + /* Send message to Hyper-V host */ static inline int synthvid_send(struct hv_device *hdev, struct synthvid_msg *msg) @@ -862,6 +864,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, hvfb_ondemand_refresh_throttle(par, x, y, width, height); } +/* + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end + * of unregister_framebuffer() or fb_release(). Do any cleanup related to + * framebuffer here. + */ +static void hvfb_destroy(struct fb_info *info) +{ + hvfb_putmem(info); + framebuffer_release(info); +} + /* * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases. @@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = { .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, .fb_blank = hvfb_blank, + .fb_destroy = hvfb_destroy, }; /* Get options from kernel paramenter "video=" */ @@ -1178,7 +1192,7 @@ static int hvfb_probe(struct hv_device *hdev, if (ret) goto error; - ret = register_framebuffer(info); + ret = devm_register_framebuffer(&hdev->device, info); if (ret) { pr_err("Unable to register framebuffer\n"); goto error; @@ -1226,14 +1240,10 @@ static void hvfb_remove(struct hv_device *hdev) fb_deferred_io_cleanup(info); - unregister_framebuffer(info); cancel_delayed_work_sync(&par->dwork); vmbus_close(hdev->channel); hv_set_drvdata(hdev, NULL); - - hvfb_putmem(info); - framebuffer_release(info); } static int hvfb_suspend(struct hv_device *hdev) From 09beefefb57bbc3a06d98f319d85db4d719d7bcb Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Wed, 26 Feb 2025 12:06:06 -0800 Subject: [PATCH 0795/1090] x86/hyperv: Fix output argument to hypercall that changes page visibility The hypercall in hv_mark_gpa_visibility() is invoked with an input argument and an output argument. The output argument ostensibly returns the number of pages that were processed. But in fact, the hypercall does not provide any output, so the output argument is spurious. The spurious argument is harmless because Hyper-V ignores it, but in the interest of correctness and to avoid the potential for future problems, remove it. Signed-off-by: Michael Kelley Reviewed-by: Nuno Das Neves Link: https://lore.kernel.org/r/20250226200612.2062-2-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20250226200612.2062-2-mhklinux@outlook.com> --- arch/x86/hyperv/ivm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index dd68d9ad9b22..ec7880271cf9 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -464,7 +464,6 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], enum hv_mem_host_visibility visibility) { struct hv_gpa_range_for_visibility *input; - u16 pages_processed; u64 hv_status; unsigned long flags; @@ -493,7 +492,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn)); hv_status = hv_do_rep_hypercall( HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count, - 0, input, &pages_processed); + 0, input, NULL); local_irq_restore(flags); if (hv_result_success(hv_status)) From a2add513311b48cc924a699a8174db2c61ed5e8a Mon Sep 17 00:00:00 2001 From: Jeff LaBundy Date: Sun, 9 Mar 2025 20:29:59 -0500 Subject: [PATCH 0796/1090] Input: iqs7222 - preserve system status register Some register groups reserve a byte at the end of their continuous address space. Depending on the variant of silicon, this field may share the same memory space as the lower byte of the system status register (0x10). In these cases, caching the reserved byte and writing it later may effectively reset the device depending on what happened in between the read and write operations. Solve this problem by avoiding any access to this last byte within offending register groups. This method replaces a workaround which attempted to write the reserved byte with up-to-date contents, but left a small window in which updates by the device could have been clobbered. Now that the driver does not touch these reserved bytes, the order in which the device's registers are written no longer matters, and they can be written in their natural order. The new method is also much more generic, and can be more easily extended to new variants of silicon with different register maps. As part of this change, the register read and write functions must be gently updated to support byte access instead of word access. Fixes: 2e70ef525b73 ("Input: iqs7222 - acknowledge reset before writing registers") Signed-off-by: Jeff LaBundy Link: https://lore.kernel.org/r/Z85Alw+d9EHKXx2e@nixie71 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/iqs7222.c | 50 ++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index 22022d11470d..80b917944b51 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -100,11 +100,11 @@ enum iqs7222_reg_key_id { enum iqs7222_reg_grp_id { IQS7222_REG_GRP_STAT, - IQS7222_REG_GRP_FILT, IQS7222_REG_GRP_CYCLE, IQS7222_REG_GRP_GLBL, IQS7222_REG_GRP_BTN, IQS7222_REG_GRP_CHAN, + IQS7222_REG_GRP_FILT, IQS7222_REG_GRP_SLDR, IQS7222_REG_GRP_TPAD, IQS7222_REG_GRP_GPIO, @@ -286,6 +286,7 @@ static const struct iqs7222_event_desc iqs7222_tp_events[] = { struct iqs7222_reg_grp_desc { u16 base; + u16 val_len; int num_row; int num_col; }; @@ -342,6 +343,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAC00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -400,6 +402,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAC00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -454,6 +457,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xC400, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -496,6 +500,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xC400, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -543,6 +548,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAA00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -600,6 +606,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAA00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -656,6 +663,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -712,6 +720,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -768,6 +777,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -1604,7 +1614,7 @@ static int iqs7222_force_comms(struct iqs7222_private *iqs7222) } static int iqs7222_read_burst(struct iqs7222_private *iqs7222, - u16 reg, void *val, u16 num_val) + u16 reg, void *val, u16 val_len) { u8 reg_buf[sizeof(__be16)]; int ret, i; @@ -1619,7 +1629,7 @@ static int iqs7222_read_burst(struct iqs7222_private *iqs7222, { .addr = client->addr, .flags = I2C_M_RD, - .len = num_val * sizeof(__le16), + .len = val_len, .buf = (u8 *)val, }, }; @@ -1675,7 +1685,7 @@ static int iqs7222_read_word(struct iqs7222_private *iqs7222, u16 reg, u16 *val) __le16 val_buf; int error; - error = iqs7222_read_burst(iqs7222, reg, &val_buf, 1); + error = iqs7222_read_burst(iqs7222, reg, &val_buf, sizeof(val_buf)); if (error) return error; @@ -1685,10 +1695,9 @@ static int iqs7222_read_word(struct iqs7222_private *iqs7222, u16 reg, u16 *val) } static int iqs7222_write_burst(struct iqs7222_private *iqs7222, - u16 reg, const void *val, u16 num_val) + u16 reg, const void *val, u16 val_len) { int reg_len = reg > U8_MAX ? sizeof(reg) : sizeof(u8); - int val_len = num_val * sizeof(__le16); int msg_len = reg_len + val_len; int ret, i; struct i2c_client *client = iqs7222->client; @@ -1747,7 +1756,7 @@ static int iqs7222_write_word(struct iqs7222_private *iqs7222, u16 reg, u16 val) { __le16 val_buf = cpu_to_le16(val); - return iqs7222_write_burst(iqs7222, reg, &val_buf, 1); + return iqs7222_write_burst(iqs7222, reg, &val_buf, sizeof(val_buf)); } static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222) @@ -1831,30 +1840,14 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) /* * Acknowledge reset before writing any registers in case the device - * suffers a spurious reset during initialization. Because this step - * may change the reserved fields of the second filter beta register, - * its cache must be updated. - * - * Writing the second filter beta register, in turn, may clobber the - * system status register. As such, the filter beta register pair is - * written first to protect against this hazard. + * suffers a spurious reset during initialization. */ if (dir == WRITE) { - u16 reg = dev_desc->reg_grps[IQS7222_REG_GRP_FILT].base + 1; - u16 filt_setup; - error = iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP, iqs7222->sys_setup[0] | IQS7222_SYS_SETUP_ACK_RESET); if (error) return error; - - error = iqs7222_read_word(iqs7222, reg, &filt_setup); - if (error) - return error; - - iqs7222->filt_setup[1] &= GENMASK(7, 0); - iqs7222->filt_setup[1] |= (filt_setup & ~GENMASK(7, 0)); } /* @@ -1883,6 +1876,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) int num_col = dev_desc->reg_grps[i].num_col; u16 reg = dev_desc->reg_grps[i].base; __le16 *val_buf; + u16 val_len = dev_desc->reg_grps[i].val_len ? : num_col * sizeof(*val_buf); u16 *val; if (!num_col) @@ -1900,7 +1894,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) switch (dir) { case READ: error = iqs7222_read_burst(iqs7222, reg, - val_buf, num_col); + val_buf, val_len); for (k = 0; k < num_col; k++) val[k] = le16_to_cpu(val_buf[k]); break; @@ -1909,7 +1903,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) for (k = 0; k < num_col; k++) val_buf[k] = cpu_to_le16(val[k]); error = iqs7222_write_burst(iqs7222, reg, - val_buf, num_col); + val_buf, val_len); break; default: @@ -1962,7 +1956,7 @@ static int iqs7222_dev_info(struct iqs7222_private *iqs7222) int error, i; error = iqs7222_read_burst(iqs7222, IQS7222_PROD_NUM, dev_id, - ARRAY_SIZE(dev_id)); + sizeof(dev_id)); if (error) return error; @@ -2915,7 +2909,7 @@ static int iqs7222_report(struct iqs7222_private *iqs7222) __le16 status[IQS7222_MAX_COLS_STAT]; error = iqs7222_read_burst(iqs7222, IQS7222_SYS_STATUS, status, - num_stat); + num_stat * sizeof(*status)); if (error) return error; From 823869e1e61607ab0d433de3c8abed221dc80a5e Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 6 Mar 2025 08:46:57 +0000 Subject: [PATCH 0797/1090] afs: Fix afs_atcell_get_link() to handle RCU pathwalk The ->get_link() method may be entered under RCU pathwalk conditions (in which case, the dentry pointer is NULL). This is not taken account of by afs_atcell_get_link() and lockdep will complain when it tries to lock an rwsem. Fix this by marking net->ws_cell as __rcu and using RCU access macros on it and by making afs_atcell_get_link() just return a pointer to the name in RCU pathwalk without taking net->cells_lock or a ref on the cell as RCU will protect the name storage (the cell is already freed via call_rcu()). Fixes: 30bca65bbbae ("afs: Make /afs/@cell and /afs/.@cell symlinks") Reported-by: Alexander Viro Signed-off-by: David Howells cc: Marc Dionne cc: linux-afs@lists.infradead.org cc: linux-fsdevel@vger.kernel.org Link: https://lore.kernel.org/r/20250310094206.801057-2-dhowells@redhat.com/ # v4 --- fs/afs/cell.c | 11 ++++++----- fs/afs/dynroot.c | 15 +++++++++++++-- fs/afs/internal.h | 2 +- fs/afs/proc.c | 4 ++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/fs/afs/cell.c b/fs/afs/cell.c index cee42646736c..96a6781f3653 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -64,7 +64,8 @@ static struct afs_cell *afs_find_cell_locked(struct afs_net *net, return ERR_PTR(-ENAMETOOLONG); if (!name) { - cell = net->ws_cell; + cell = rcu_dereference_protected(net->ws_cell, + lockdep_is_held(&net->cells_lock)); if (!cell) return ERR_PTR(-EDESTADDRREQ); goto found; @@ -388,8 +389,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell) /* install the new cell */ down_write(&net->cells_lock); afs_see_cell(new_root, afs_cell_trace_see_ws); - old_root = net->ws_cell; - net->ws_cell = new_root; + old_root = rcu_replace_pointer(net->ws_cell, new_root, + lockdep_is_held(&net->cells_lock)); up_write(&net->cells_lock); afs_unuse_cell(net, old_root, afs_cell_trace_unuse_ws); @@ -945,8 +946,8 @@ void afs_cell_purge(struct afs_net *net) _enter(""); down_write(&net->cells_lock); - ws = net->ws_cell; - net->ws_cell = NULL; + ws = rcu_replace_pointer(net->ws_cell, NULL, + lockdep_is_held(&net->cells_lock)); up_write(&net->cells_lock); afs_unuse_cell(net, ws, afs_cell_trace_unuse_ws); diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index d8bf52f77d93..008698d706ca 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -314,12 +314,23 @@ static const char *afs_atcell_get_link(struct dentry *dentry, struct inode *inod const char *name; bool dotted = vnode->fid.vnode == 3; - if (!net->ws_cell) + if (!dentry) { + /* We're in RCU-pathwalk. */ + cell = rcu_dereference(net->ws_cell); + if (dotted) + name = cell->name - 1; + else + name = cell->name; + /* Shouldn't need to set a delayed call. */ + return name; + } + + if (!rcu_access_pointer(net->ws_cell)) return ERR_PTR(-ENOENT); down_read(&net->cells_lock); - cell = net->ws_cell; + cell = rcu_dereference_protected(net->ws_cell, lockdep_is_held(&net->cells_lock)); if (dotted) name = cell->name - 1; else diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 90f407774a9a..df30bd62da79 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -287,7 +287,7 @@ struct afs_net { /* Cell database */ struct rb_root cells; - struct afs_cell *ws_cell; + struct afs_cell __rcu *ws_cell; struct work_struct cells_manager; struct timer_list cells_timer; atomic_t cells_outstanding; diff --git a/fs/afs/proc.c b/fs/afs/proc.c index e7614f4f30c2..12c88d8be3fe 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -206,7 +206,7 @@ static int afs_proc_rootcell_show(struct seq_file *m, void *v) net = afs_seq2net_single(m); down_read(&net->cells_lock); - cell = net->ws_cell; + cell = rcu_dereference_protected(net->ws_cell, lockdep_is_held(&net->cells_lock)); if (cell) seq_printf(m, "%s\n", cell->name); up_read(&net->cells_lock); @@ -242,7 +242,7 @@ static int afs_proc_rootcell_write(struct file *file, char *buf, size_t size) ret = -EEXIST; inode_lock(file_inode(file)); - if (!net->ws_cell) + if (!rcu_access_pointer(net->ws_cell)) ret = afs_cell_init(net, buf); else printk("busy\n"); From 65be5c95d08eedda570a6c888a12384c77fe7614 Mon Sep 17 00:00:00 2001 From: Vladis Dronov Date: Sun, 9 Mar 2025 18:22:16 +0100 Subject: [PATCH 0798/1090] x86/sgx: Warn explicitly if X86_FEATURE_SGX_LC is not enabled The kernel requires X86_FEATURE_SGX_LC to be able to create SGX enclaves, not just X86_FEATURE_SGX. There is quite a number of hardware which has X86_FEATURE_SGX but not X86_FEATURE_SGX_LC. A kernel running on such hardware does not create the /dev/sgx_enclave file and does so silently. Explicitly warn if X86_FEATURE_SGX_LC is not enabled to properly notify users that the kernel disabled the SGX driver. The X86_FEATURE_SGX_LC, a.k.a. SGX Launch Control, is a CPU feature that enables LE (Launch Enclave) hash MSRs to be writable (with additional opt-in required in the 'feature control' MSR) when running enclaves, i.e. using a custom root key rather than the Intel proprietary key for enclave signing. I've hit this issue myself and have spent some time researching where my /dev/sgx_enclave file went on SGX-enabled hardware. Related links: https://github.com/intel/linux-sgx/issues/837 https://patchwork.kernel.org/project/platform-driver-x86/patch/20180827185507.17087-3-jarkko.sakkinen@linux.intel.com/ [ mingo: Made the error message a bit more verbose, and added other cases where the kernel fails to create the /dev/sgx_enclave device node. ] Signed-off-by: Vladis Dronov Signed-off-by: Ingo Molnar Acked-by: Kai Huang Cc: Jarkko Sakkinen Cc: Andy Lutomirski Cc: Sean Christopherson Cc: Linus Torvalds Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20250309172215.21777-2-vdronov@redhat.com --- arch/x86/kernel/cpu/sgx/driver.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/driver.c b/arch/x86/kernel/cpu/sgx/driver.c index 22b65a5f5ec6..7f8d1e11dbee 100644 --- a/arch/x86/kernel/cpu/sgx/driver.c +++ b/arch/x86/kernel/cpu/sgx/driver.c @@ -150,13 +150,15 @@ int __init sgx_drv_init(void) u64 xfrm_mask; int ret; - if (!cpu_feature_enabled(X86_FEATURE_SGX_LC)) + if (!cpu_feature_enabled(X86_FEATURE_SGX_LC)) { + pr_info("SGX disabled: SGX launch control CPU feature is not available, /dev/sgx_enclave disabled.\n"); return -ENODEV; + } cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx); if (!(eax & 1)) { - pr_err("SGX disabled: SGX1 instruction support not available.\n"); + pr_info("SGX disabled: SGX1 instruction support not available, /dev/sgx_enclave disabled.\n"); return -ENODEV; } @@ -173,8 +175,10 @@ int __init sgx_drv_init(void) } ret = misc_register(&sgx_dev_enclave); - if (ret) + if (ret) { + pr_info("SGX disabled: Unable to register the /dev/sgx_enclave driver (%d).\n", ret); return ret; + } return 0; } From f3fa0e40df175acd60b71036b9a1fd62310aec03 Mon Sep 17 00:00:00 2001 From: Yafang Shao Date: Wed, 5 Feb 2025 11:24:38 +0800 Subject: [PATCH 0799/1090] sched/clock: Don't define sched_clock_irqtime as static key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sched_clock_irqtime was defined as a static key in: 8722903cbb8f ("sched: Define sched_clock_irqtime as static key") However, this change introduces a 'sleeping in atomic context' warning: arch/x86/kernel/tsc.c:1214 mark_tsc_unstable() warn: sleeping in atomic context As analyzed by Dan, the affected code path is as follows: vcpu_load() <- disables preempt -> kvm_arch_vcpu_load() -> mark_tsc_unstable() <- sleeps virt/kvm/kvm_main.c 166 void vcpu_load(struct kvm_vcpu *vcpu) 167 { 168 int cpu = get_cpu(); ^^^^^^^^^^ This get_cpu() disables preemption. 169 170 __this_cpu_write(kvm_running_vcpu, vcpu); 171 preempt_notifier_register(&vcpu->preempt_notifier); 172 kvm_arch_vcpu_load(vcpu, cpu); 173 put_cpu(); 174 } arch/x86/kvm/x86.c 4979 if (unlikely(vcpu->cpu != cpu) || kvm_check_tsc_unstable()) { 4980 s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 : 4981 rdtsc() - vcpu->arch.last_host_tsc; 4982 if (tsc_delta < 0) 4983 mark_tsc_unstable("KVM discovered backwards TSC"); arch/x86/kernel/tsc.c 1206 void mark_tsc_unstable(char *reason) 1207 { 1208 if (tsc_unstable) 1209 return; 1210 1211 tsc_unstable = 1; 1212 if (using_native_sched_clock()) 1213 clear_sched_clock_stable(); --> 1214 disable_sched_clock_irqtime(); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ kernel/jump_label.c 245 void static_key_disable(struct static_key *key) 246 { 247 cpus_read_lock(); ^^^^^^^^^^^^^^^^ This lock has a might_sleep() in it which triggers the static checker warning. 248 static_key_disable_cpuslocked(key); 249 cpus_read_unlock(); 250 } Let revert this change for now as {disable,enable}_sched_clock_irqtime are used in many places, as pointed out by Sean, including the following: The code path in clocksource_watchdog(): clocksource_watchdog() | -> spin_lock(&watchdog_lock); | -> __clocksource_unstable() | -> clocksource.mark_unstable() == tsc_cs_mark_unstable() | -> disable_sched_clock_irqtime() And the code path in sched_clock_register(): /* Cannot register a sched_clock with interrupts on */ local_irq_save(flags); ... /* Enable IRQ time accounting if we have a fast enough sched_clock() */ if (irqtime > 0 || (irqtime == -1 && rate >= 1000000)) enable_sched_clock_irqtime(); local_irq_restore(flags); [ lkp@intel.com: reported a build error in the prev version ] [ mingo: cherry-picked it over into sched/urgent ] Closes: https://lore.kernel.org/kvm/37a79ba3-9ce0-479c-a5b0-2bd75d573ed3@stanley.mountain/ Fixes: 8722903cbb8f ("sched: Define sched_clock_irqtime as static key") Reported-by: Dan Carpenter Debugged-by: Dan Carpenter Debugged-by: Sean Christopherson Debugged-by: Michal Koutný Signed-off-by: Yafang Shao Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Reviewed-by: Vincent Guittot Link: https://lkml.kernel.org/r/20250205032438.14668-1-laoar.shao@gmail.com --- kernel/sched/cputime.c | 8 ++++---- kernel/sched/sched.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index 5d9143dd0879..6dab4854c6c0 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -9,8 +9,6 @@ #ifdef CONFIG_IRQ_TIME_ACCOUNTING -DEFINE_STATIC_KEY_FALSE(sched_clock_irqtime); - /* * There are no locks covering percpu hardirq/softirq time. * They are only modified in vtime_account, on corresponding CPU @@ -24,14 +22,16 @@ DEFINE_STATIC_KEY_FALSE(sched_clock_irqtime); */ DEFINE_PER_CPU(struct irqtime, cpu_irqtime); +int sched_clock_irqtime; + void enable_sched_clock_irqtime(void) { - static_branch_enable(&sched_clock_irqtime); + sched_clock_irqtime = 1; } void disable_sched_clock_irqtime(void) { - static_branch_disable(&sched_clock_irqtime); + sched_clock_irqtime = 0; } static void irqtime_account_delta(struct irqtime *irqtime, u64 delta, diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c8512a9fb022..023b844159c9 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -3259,11 +3259,11 @@ struct irqtime { }; DECLARE_PER_CPU(struct irqtime, cpu_irqtime); -DECLARE_STATIC_KEY_FALSE(sched_clock_irqtime); +extern int sched_clock_irqtime; static inline int irqtime_enabled(void) { - return static_branch_likely(&sched_clock_irqtime); + return sched_clock_irqtime; } /* From e3e89178a9f4a80092578af3ff3c8478f9187d59 Mon Sep 17 00:00:00 2001 From: Florent Revest Date: Mon, 10 Mar 2025 15:42:43 +0100 Subject: [PATCH 0800/1090] x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes Currently, load_microcode_amd() iterates over all NUMA nodes, retrieves their CPU masks and unconditionally accesses per-CPU data for the first CPU of each mask. According to Documentation/admin-guide/mm/numaperf.rst: "Some memory may share the same node as a CPU, and others are provided as memory only nodes." Therefore, some node CPU masks may be empty and wouldn't have a "first CPU". On a machine with far memory (and therefore CPU-less NUMA nodes): - cpumask_of_node(nid) is 0 - cpumask_first(0) is CONFIG_NR_CPUS - cpu_data(CONFIG_NR_CPUS) accesses the cpu_info per-CPU array at an index that is 1 out of bounds This does not have any security implications since flashing microcode is a privileged operation but I believe this has reliability implications by potentially corrupting memory while flashing a microcode update. When booting with CONFIG_UBSAN_BOUNDS=y on an AMD machine that flashes a microcode update. I get the following splat: UBSAN: array-index-out-of-bounds in arch/x86/kernel/cpu/microcode/amd.c:X:Y index 512 is out of range for type 'unsigned long[512]' [...] Call Trace: dump_stack __ubsan_handle_out_of_bounds load_microcode_amd request_microcode_amd reload_store kernfs_fop_write_iter vfs_write ksys_write do_syscall_64 entry_SYSCALL_64_after_hwframe Change the loop to go over only NUMA nodes which have CPUs before determining whether the first CPU on the respective node needs microcode update. [ bp: Massage commit message, fix typo. ] Fixes: 7ff6edf4fef3 ("x86/microcode/AMD: Fix mixed steppings support") Signed-off-by: Florent Revest Signed-off-by: Borislav Petkov (AMD) Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250310144243.861978-1-revest@chromium.org --- arch/x86/kernel/cpu/microcode/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index c69b1bc45483..138689b8e1d8 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -1074,7 +1074,7 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz if (ret != UCODE_OK) return ret; - for_each_node(nid) { + for_each_node_with_cpus(nid) { cpu = cpumask_first(cpumask_of_node(nid)); c = &cpu_data(cpu); From ad5a0970f86d82e39ebd06d45a1f7aa48a1316f8 Mon Sep 17 00:00:00 2001 From: Vitaliy Shevtsov Date: Tue, 4 Mar 2025 16:56:37 +0500 Subject: [PATCH 0801/1090] ASoC: cs35l41: check the return value from spi_setup() Currently the return value from spi_setup() is not checked for a failure. It is unlikely it will ever fail in this particular case but it is still better to add this check for the sake of completeness and correctness. This is cheap since it is performed once when the device is being probed. Handle spi_setup() return value. Found by Linux Verification Center (linuxtesting.org) with Svace. Fixes: 872fc0b6bde8 ("ASoC: cs35l41: Set the max SPI speed for the whole device") Signed-off-by: Vitaliy Shevtsov Link: https://patch.msgid.link/20250304115643.2748-1-v.shevtsov@mt-integration.ru Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41-spi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c index a6db44520c06..f9b6bf7bea9c 100644 --- a/sound/soc/codecs/cs35l41-spi.c +++ b/sound/soc/codecs/cs35l41-spi.c @@ -32,13 +32,16 @@ static int cs35l41_spi_probe(struct spi_device *spi) const struct regmap_config *regmap_config = &cs35l41_regmap_spi; struct cs35l41_hw_cfg *hw_cfg = dev_get_platdata(&spi->dev); struct cs35l41_private *cs35l41; + int ret; cs35l41 = devm_kzalloc(&spi->dev, sizeof(struct cs35l41_private), GFP_KERNEL); if (!cs35l41) return -ENOMEM; spi->max_speed_hz = CS35L41_SPI_MAX_FREQ; - spi_setup(spi); + ret = spi_setup(spi); + if (ret < 0) + return ret; spi_set_drvdata(spi, cs35l41); cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config); From 89be3c15a58b2ccf31e969223c8ac93ca8932d81 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Fri, 28 Feb 2025 16:14:30 +0000 Subject: [PATCH 0802/1090] ASoC: qcom: sm8250: explicitly set format in sm8250_be_hw_params_fixup() Setting format to s16le is required for compressed playback on compatible soundcards. Cc: Srinivas Kandagatla Signed-off-by: Alexey Klimov Link: https://patch.msgid.link/20250228161430.373961-1-alexey.klimov@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/sm8250.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index 45e0c33fc3f3..9039107972e2 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,11 @@ static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); rate->min = rate->max = 48000; channels->min = channels->max = 2; + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); return 0; } From 10c7988418d8f759ba70c4a558961e0bfa74647f Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Thu, 6 Mar 2025 18:42:11 +0530 Subject: [PATCH 0803/1090] drm/xe: Release guc ids before cancelling work A GT resets can be occurring in parallel while cancelling work in async call which can requeue these workers. to avoid that, lets first release guc ids and then cancel work so they don't requeued. Fixes: 8ae8a2e8dd21 ("drm/xe: Long running job update") Fixes: 12c2f962fe71 ("drm/xe: cancel pending job timer before freeing scheduler") Signed-off-by: Tejas Upadhyay Suggested-by: Matthew Brost Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250306131211.975503-1-tejas.upadhyay@intel.com Signed-off-by: Lucas De Marchi (cherry picked from commit 8e8d76f62329127b31c64a034b052fb9e30e92af) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_submit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index b6a2dd742ebd..1a5fe4822a62 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1246,11 +1246,11 @@ static void __guc_exec_queue_fini_async(struct work_struct *w) xe_pm_runtime_get(guc_to_xe(guc)); trace_xe_exec_queue_destroy(q); + release_guc_id(guc, q); if (xe_exec_queue_is_lr(q)) cancel_work_sync(&ge->lr_tdr); /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&ge->sched.base.work_tdr); - release_guc_id(guc, q); xe_sched_entity_fini(&ge->entity); xe_sched_fini(&ge->sched); From 9106713bd2ab0cacd380cda0d3f0219f2e488086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 7 Mar 2025 11:01:09 +0100 Subject: [PATCH 0804/1090] drm/xe/userptr: Fix an incorrect assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The assert incorrectly checks the total length processed which can in fact be greater than the number of pages. Fix. Fixes: 0a98219bcc96 ("drm/xe/hmm: Don't dereference struct page pointers without notifier lock") Cc: Matthew Auld Cc: Matthew Brost Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20250307100109.21397-1-thomas.hellstrom@linux.intel.com (cherry picked from commit 70e5043ba85eae199b232e39921abd706b5c1fa4) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_hmm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c index 392102515f3d..c3cc0fa105e8 100644 --- a/drivers/gpu/drm/xe/xe_hmm.c +++ b/drivers/gpu/drm/xe/xe_hmm.c @@ -138,13 +138,17 @@ static int xe_build_sg(struct xe_device *xe, struct hmm_range *range, i += size; if (unlikely(j == st->nents - 1)) { + xe_assert(xe, i >= npages); if (i > npages) size -= (i - npages); + sg_mark_end(sgl); + } else { + xe_assert(xe, i < npages); } + sg_set_page(sgl, page, size << PAGE_SHIFT, 0); } - xe_assert(xe, i == npages); return dma_map_sgtable(dev, st, write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_NO_KERNEL_MAPPING); From 6266f4a78131c795631440ea9c7b66cdfd399484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 18 Feb 2025 23:18:55 +0200 Subject: [PATCH 0805/1090] drm/i915/cdclk: Do cdclk post plane programming later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently call intel_set_cdclk_post_plane_update() far too early. When pipes are active during the reprogramming the current spot only works for the cd2x divider update case, as that is synchronize to the pipe's vblank. Squashing and crawling are not synchronized in any way, so doing the programming while the pipes/planes are potentially still using the old hardware state could lead to underruns. Move the post plane reprgramming to a spot where we know that the pipes/planes have switched over the new hardware state. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250218211913.27867-2-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai (cherry picked from commit fb64f5568c0e0b5730733d70a012ae26b1a55815) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 41128469f12a..c9dcf2bbd4c7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7830,9 +7830,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_program_dpkgc_latency(state); - if (state->modeset) - intel_set_cdclk_post_plane_update(state); - intel_wait_for_vblank_workers(state); /* FIXME: We should call drm_atomic_helper_commit_hw_done() here @@ -7906,6 +7903,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_verify_planes(state); intel_sagv_post_plane_update(state); + if (state->modeset) + intel_set_cdclk_post_plane_update(state); intel_pmdemand_post_plane_update(state); drm_atomic_helper_commit_hw_done(&state->base); From 3e331a6715ee26f2fabc59dad6bb36d810707028 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 7 Mar 2025 19:56:35 -0500 Subject: [PATCH 0806/1090] drm/xe/pm: Temporarily disable D3Cold on BMG Currently, many instability cases related to D3Cold -> D0 transition on BMG are under investigation. Among them some bad cases where the device is lost after 1 to 3 transitions from D3Cold to D0 on the runtime pm, with pcieport upstream bridge port link retrain failure. In other cases, it works fine, but with some sudden random memory corruptions after D3cold, that could be 0xffff missed ack on GT forcewake or GuC reload related failures. In some other cases though, D3Cold -> D0 works pretty reliably. It looks like it is a combination of GPU cards and Host boards at this point. So, there is no possible/available quirk at this time. This patch disables the D3Cold by default on BMG by reducing the vram_d3cold_threshold to 0. Users and developers who wants to enable it are still able to via $ echo 300 > /sys/bus/pci/devices//vram_d3cold_threshold Fixes: 3adcf970dc7e ("drm/xe/bmg: Drop force_probe requirement") Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4037 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4395 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4396 Cc: Karthik Poosa Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20250308005636.1475420-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi (cherry picked from commit d945cc876277851053c0cf37927c8d7bd9d0e880) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_pm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index c9cc0c091dfd..89fd2c043136 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -267,6 +267,15 @@ int xe_pm_init_early(struct xe_device *xe) } ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */ +static u32 vram_threshold_value(struct xe_device *xe) +{ + /* FIXME: D3Cold temporarily disabled by default on BMG */ + if (xe->info.platform == XE_BATTLEMAGE) + return 0; + + return DEFAULT_VRAM_THRESHOLD; +} + /** * xe_pm_init - Initialize Xe Power Management * @xe: xe device instance @@ -277,6 +286,7 @@ ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */ */ int xe_pm_init(struct xe_device *xe) { + u32 vram_threshold; int err; /* For now suspend/resume is only allowed with GuC */ @@ -290,7 +300,8 @@ int xe_pm_init(struct xe_device *xe) if (err) return err; - err = xe_pm_set_vram_threshold(xe, DEFAULT_VRAM_THRESHOLD); + vram_threshold = vram_threshold_value(xe); + err = xe_pm_set_vram_threshold(xe, vram_threshold); if (err) return err; } From c605acb53f449f6289f042790307d7dc9e62d03d Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 7 Mar 2025 11:03:07 -0500 Subject: [PATCH 0807/1090] drm/xe/guc_pc: Retry and wait longer for GuC PC start In a rare situation of thermal limit during resume, GuC can be slow and run into delays like this: xe 0000:00:02.0: [drm] GT1: excessive init time: 667ms! \ [status = 0x8002F034, timeouts = 0] xe 0000:00:02.0: [drm] GT1: excessive init time: \ [freq = 100MHz (req = 800MHz), before = 100MHz, \ perf_limit_reasons = 0x1C001000] xe 0000:00:02.0: [drm] *ERROR* GT1: GuC PC Start failed ------------[ cut here ]------------ xe 0000:00:02.0: [drm] GT1: Failed to start GuC PC: -EIO When this happens, it will block entirely the GPU to be used. So, let's try and with a huge timeout in the hope it comes back. Also, let's collect some information on how long it is usually taking on situations like this, so perhaps the time can be tuned later. Cc: Vinay Belgaumkar Cc: Jonathan Cavitt Cc: John Harrison Reviewed-by: Jonathan Cavitt Link: https://patchwork.freedesktop.org/patch/msgid/20250307160307.1093391-1-rodrigo.vivi@intel.com Signed-off-by: Rodrigo Vivi (cherry picked from commit b4b05e53b550a886b4754b87fd0dd2b304579e85) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_guc_pc.c | 53 +++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index df7f130fb663..b995d1d51aed 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -6,6 +6,7 @@ #include "xe_guc_pc.h" #include +#include #include #include @@ -19,6 +20,7 @@ #include "xe_gt.h" #include "xe_gt_idle.h" #include "xe_gt_printk.h" +#include "xe_gt_throttle.h" #include "xe_gt_types.h" #include "xe_guc.h" #include "xe_guc_ct.h" @@ -49,6 +51,9 @@ #define LNL_MERT_FREQ_CAP 800 #define BMG_MERT_FREQ_CAP 2133 +#define SLPC_RESET_TIMEOUT_MS 5 /* roughly 5ms, but no need for precision */ +#define SLPC_RESET_EXTENDED_TIMEOUT_MS 1000 /* To be used only at pc_start */ + /** * DOC: GuC Power Conservation (PC) * @@ -113,9 +118,10 @@ static struct iosys_map *pc_to_maps(struct xe_guc_pc *pc) FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, count)) static int wait_for_pc_state(struct xe_guc_pc *pc, - enum slpc_global_state state) + enum slpc_global_state state, + int timeout_ms) { - int timeout_us = 5000; /* rought 5ms, but no need for precision */ + int timeout_us = 1000 * timeout_ms; int slept, wait = 10; xe_device_assert_mem_access(pc_to_xe(pc)); @@ -164,7 +170,8 @@ static int pc_action_query_task_state(struct xe_guc_pc *pc) }; int ret; - if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, + SLPC_RESET_TIMEOUT_MS)) return -EAGAIN; /* Blocking here to ensure the results are ready before reading them */ @@ -187,7 +194,8 @@ static int pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value) }; int ret; - if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, + SLPC_RESET_TIMEOUT_MS)) return -EAGAIN; ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0); @@ -208,7 +216,8 @@ static int pc_action_unset_param(struct xe_guc_pc *pc, u8 id) struct xe_guc_ct *ct = &pc_to_guc(pc)->ct; int ret; - if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, + SLPC_RESET_TIMEOUT_MS)) return -EAGAIN; ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0); @@ -440,6 +449,15 @@ u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc) return freq; } +static u32 get_cur_freq(struct xe_gt *gt) +{ + u32 freq; + + freq = xe_mmio_read32(>->mmio, RPNSWREQ); + freq = REG_FIELD_GET(REQ_RATIO_MASK, freq); + return decode_freq(freq); +} + /** * xe_guc_pc_get_cur_freq - Get Current requested frequency * @pc: The GuC PC @@ -463,10 +481,7 @@ int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq) return -ETIMEDOUT; } - *freq = xe_mmio_read32(>->mmio, RPNSWREQ); - - *freq = REG_FIELD_GET(REQ_RATIO_MASK, *freq); - *freq = decode_freq(*freq); + *freq = get_cur_freq(gt); xe_force_wake_put(gt_to_fw(gt), fw_ref); return 0; @@ -1002,6 +1017,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) struct xe_gt *gt = pc_to_gt(pc); u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); unsigned int fw_ref; + ktime_t earlier; int ret; xe_gt_assert(gt, xe_device_uc_enabled(xe)); @@ -1026,14 +1042,25 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) memset(pc->bo->vmap.vaddr, 0, size); slpc_shared_data_write(pc, header.size, size); + earlier = ktime_get(); ret = pc_action_reset(pc); if (ret) goto out; - if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) { - xe_gt_err(gt, "GuC PC Start failed\n"); - ret = -EIO; - goto out; + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, + SLPC_RESET_TIMEOUT_MS)) { + xe_gt_warn(gt, "GuC PC start taking longer than normal [freq = %dMHz (req = %dMHz), perf_limit_reasons = 0x%08X]\n", + xe_guc_pc_get_act_freq(pc), get_cur_freq(gt), + xe_gt_throttle_get_limit_reasons(gt)); + + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING, + SLPC_RESET_EXTENDED_TIMEOUT_MS)) { + xe_gt_err(gt, "GuC PC Start failed: Dynamic GT frequency control and GT sleep states are now disabled.\n"); + goto out; + } + + xe_gt_warn(gt, "GuC PC excessive start time: %lldms", + ktime_ms_delta(ktime_get(), earlier)); } ret = pc_init_freqs(pc); From 3f674e7b670b7b7d9261935820e4eba3c059f835 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 6 Mar 2025 14:25:57 -0800 Subject: [PATCH 0808/1090] nvme-pci: fix stuck reset on concurrent DPC and HP The PCIe error handling has the nvme driver quiesce the device, attempt to restart it, then wait for that restart to complete. A PCIe DPC event also toggles the PCIe link. If the slot doesn't have out-of-band presence detection, this will trigger a pciehp re-enumeration. The error handling that calls nvme_error_resume is holding the device lock while this happens. This lock blocks pciehp's request to disconnect the driver from proceeding. Meanwhile the nvme's reset can't make forward progress because its device isn't there anymore with outstanding IO, and the timeout handler won't do anything to fix it because the device is undergoing error handling. End result: deadlocked. Fix this by having the timeout handler short cut the disabling for a disconnected PCIe device. The downside is that we're relying on an IO timeout to clean up this mess, which could be a minute by default. Tested-by: Nilay Shroff Reviewed-by: Nilay Shroff Signed-off-by: Keith Busch --- drivers/nvme/host/pci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 640590b21728..e59aad269abf 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1411,9 +1411,20 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) struct nvme_dev *dev = nvmeq->dev; struct request *abort_req; struct nvme_command cmd = { }; + struct pci_dev *pdev = to_pci_dev(dev->dev); u32 csts = readl(dev->bar + NVME_REG_CSTS); u8 opcode; + /* + * Shutdown the device immediately if we see it is disconnected. This + * unblocks PCIe error handling if the nvme driver is waiting in + * error_resume for a device that has been removed. We can't unbind the + * driver while the driver's error callback is waiting to complete, so + * we're relying on a timeout to break that deadlock if a removal + * occurs while reset work is running. + */ + if (pci_dev_is_disconnected(pdev)) + nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING); if (nvme_state_terminal(&dev->ctrl)) goto disable; @@ -1421,7 +1432,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) * the recovery mechanism will surely fail. */ mb(); - if (pci_channel_offline(to_pci_dev(dev->dev))) + if (pci_channel_offline(pdev)) return BLK_EH_RESET_TIMER; /* From de93ddf88088f7624b589d0ff3af9effb87e8f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 19 Feb 2025 18:02:39 +0200 Subject: [PATCH 0809/1090] drm/atomic: Filter out redundant DPMS calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Video players (eg. mpv) do periodic XResetScreenSaver() calls to keep the screen on while the video playing. The modesetting ddx plumbs these straight through into the kernel as DPMS setproperty ioctls, without any filtering whatsoever. When implemented via atomic these end up as empty commits on the crtc (which will nonetheless take one full frame), which leads to a dropped frame every time XResetScreenSaver() is called. Let's just filter out redundant DPMS property changes in the kernel to avoid this issue. v2: Explain the resulting commits a bit better (Sima) Document the behaviour in uapi docs (Sima) Cc: stable@vger.kernel.org Testcase: igt/kms_flip/flip-vs-dpms-on-nop Reviewed-by: Simona Vetter Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250219160239.17502-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_atomic_uapi.c | 4 ++++ drivers/gpu/drm/drm_connector.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 370dc676e3aa..fd36b8fd54e9 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -956,6 +956,10 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; + + if (connector->dpms == mode) + goto out; + connector->dpms = mode; crtc = connector->state->crtc; diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 5f24d6b41cc6..48b08c9611a7 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1427,6 +1427,10 @@ EXPORT_SYMBOL(drm_hdmi_connector_get_output_format_name); * callback. For atomic drivers the remapping to the "ACTIVE" property is * implemented in the DRM core. * + * On atomic drivers any DPMS setproperty ioctl where the value does not + * change is completely skipped, otherwise a full atomic commit will occur. + * On legacy drivers the exact behavior is driver specific. + * * Note that this property cannot be set through the MODE_ATOMIC ioctl, * userspace must use "ACTIVE" on the CRTC instead. * From 73fe9073c0cc28056cb9de0c8a516dac070f1d1f Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Sun, 9 Mar 2025 20:52:08 -0700 Subject: [PATCH 0810/1090] Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio() The VMBus driver manages the MMIO space it owns via the hyperv_mmio resource tree. Because the synthetic video framebuffer portion of the MMIO space is initially setup by the Hyper-V host for each guest, the VMBus driver does an early reserve of that portion of MMIO space in the hyperv_mmio resource tree. It saves a pointer to that resource in fb_mmio. When a VMBus driver requests MMIO space and passes "true" for the "fb_overlap_ok" argument, the reserved framebuffer space is used if possible. In that case it's not necessary to do another request against the "shadow" hyperv_mmio resource tree because that resource was already requested in the early reserve steps. However, the vmbus_free_mmio() function currently does no special handling for the fb_mmio resource. When a framebuffer device is removed, or the driver is unbound, the current code for vmbus_free_mmio() releases the reserved resource, leaving fb_mmio pointing to memory that has been freed. If the same or another driver is subsequently bound to the device, vmbus_allocate_mmio() checks against fb_mmio, and potentially gets garbage. Furthermore a second unbind operation produces this "nonexistent resource" error because of the unbalanced behavior between vmbus_allocate_mmio() and vmbus_free_mmio(): [ 55.499643] resource: Trying to free nonexistent resource <0x00000000f0000000-0x00000000f07fffff> Fix this by adding logic to vmbus_free_mmio() to recognize when MMIO space in the fb_mmio reserved area would be released, and don't release it. This filtering ensures the fb_mmio resource always exists, and makes vmbus_free_mmio() more parallel with vmbus_allocate_mmio(). Fixes: be000f93e5d7 ("drivers:hv: Track allocations of children of hv_vmbus in private resource tree") Signed-off-by: Michael Kelley Tested-by: Saurabh Sengar Reviewed-by: Saurabh Sengar Link: https://lore.kernel.org/r/20250310035208.275764-1-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20250310035208.275764-1-mhklinux@outlook.com> --- drivers/hv/vmbus_drv.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0f6cd44fff29..6e55a1a2613d 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2262,12 +2262,25 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size) struct resource *iter; mutex_lock(&hyperv_mmio_lock); + + /* + * If all bytes of the MMIO range to be released are within the + * special case fb_mmio shadow region, skip releasing the shadow + * region since no corresponding __request_region() was done + * in vmbus_allocate_mmio(). + */ + if (fb_mmio && start >= fb_mmio->start && + (start + size - 1 <= fb_mmio->end)) + goto skip_shadow_release; + for (iter = hyperv_mmio; iter; iter = iter->sibling) { if ((iter->start >= start + size) || (iter->end <= start)) continue; __release_region(iter, start, size); } + +skip_shadow_release: release_mem_region(start, size); mutex_unlock(&hyperv_mmio_lock); From 6fbafe1cbed10e53b3cf236a8a1987425206dd8e Mon Sep 17 00:00:00 2001 From: Panagiotis Foliadis Date: Sat, 8 Mar 2025 16:49:05 +0000 Subject: [PATCH 0811/1090] rust: task: fix `SAFETY` comment in `Task::wake_up` The `SAFETY` comment inside the `wake_up` method references erroneously the `signal_pending` C function instead of the `wake_up_process` which is actually called. Fix the comment to reference the correct C function. Fixes: fe95f58320e6 ("rust: task: adjust safety comments in Task methods") Signed-off-by: Panagiotis Foliadis Reviewed-by: Charalampos Mitrodimas Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20250308-comment-fix-v1-1-4bba709fd36d@posteo.net [ Slightly reworded. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/task.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 07bc22a7645c..38da555a2bdb 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -320,7 +320,7 @@ impl Task { /// Wakes up the task. pub fn wake_up(&self) { - // SAFETY: It's always safe to call `signal_pending` on a valid task, even if the task + // SAFETY: It's always safe to call `wake_up_process` on a valid task, even if the task // running. unsafe { bindings::wake_up_process(self.as_ptr()) }; } From bf9b8020a80d32f6aa80591297a087d0519dc931 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 6 Mar 2025 17:55:48 +0900 Subject: [PATCH 0812/1090] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created The function nvmet_pci_epf_create_sq() use test_and_set_bit() to check that a submission queue is not already live and if not, set the NVMET_PCI_EPF_Q_LIVE queue flag to declare the sq live (ready to use). However, this is done on entry to the function, before the submission queue is actually fully initialized and ready to use. This creates a race situation with the function nvmet_pci_epf_poll_sqs_work() which looks at the NVMET_PCI_EPF_Q_LIVE queue flag to poll the submission queue when it is live. This race can lead to invalid DMA transfers if nvmet_pci_epf_poll_sqs_work() runs after the NVMET_PCI_EPF_Q_LIVE flag is set but before setting the sq pci address and doorbell ofset. Avoid this race by only testing the NVMET_PCI_EPF_Q_LIVE flag on entry to nvmet_pci_epf_create_sq() and setting it after the submission queue is fully setup before nvmet_pci_epf_create_sq() returns success. Since the function nvmet_pci_epf_create_cq() also has the same racy flag setting pattern, also make a similar change in that function. Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/target/pci-epf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c index 565d2bd36dcd..d55ad334670c 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c @@ -1265,7 +1265,7 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid]; u16 status; - if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags)) + if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags)) return NVME_SC_QID_INVALID | NVME_STATUS_DNR; if (!(flags & NVME_QUEUE_PHYS_CONTIG)) @@ -1300,6 +1300,8 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, if (status != NVME_SC_SUCCESS) goto err; + set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); + dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n", cqid, qsize, cq->qes, cq->vector); @@ -1307,7 +1309,6 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, err: clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags); - clear_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags); return status; } @@ -1333,7 +1334,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl, struct nvmet_pci_epf_queue *sq = &ctrl->sq[sqid]; u16 status; - if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags)) + if (test_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags)) return NVME_SC_QID_INVALID | NVME_STATUS_DNR; if (!(flags & NVME_QUEUE_PHYS_CONTIG)) @@ -1355,7 +1356,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl, status = nvmet_sq_create(tctrl, &sq->nvme_sq, sqid, sq->depth); if (status != NVME_SC_SUCCESS) - goto out_clear_bit; + return status; sq->iod_wq = alloc_workqueue("sq%d_wq", WQ_UNBOUND, min_t(int, sq->depth, WQ_MAX_ACTIVE), sqid); @@ -1365,6 +1366,8 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl, goto out_destroy_sq; } + set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags); + dev_dbg(ctrl->dev, "SQ[%u]: %u entries of %zu B\n", sqid, qsize, sq->qes); @@ -1372,8 +1375,6 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl, out_destroy_sq: nvmet_sq_destroy(&sq->nvme_sq); -out_clear_bit: - clear_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags); return status; } From 39393f5c5c795992507aa5005a9d58396a5b07f1 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 6 Mar 2025 17:55:49 +0900 Subject: [PATCH 0813/1090] nvmet: pci-epf: Do not add an IRQ vector if not needed The function nvmet_pci_epf_create_cq() always unconditionally calls nvmet_pci_epf_add_irq_vector() to add an IRQ vector for a completion queue. But this is not correct if the host requested the creation of a completion queue for polling, without an IRQ vector specified (i.e. the flag NVME_CQ_IRQ_ENABLED is not set). Fix this by calling nvmet_pci_epf_add_irq_vector() and setting the queue flag NVMET_PCI_EPF_Q_IRQ_ENABLED for the cq only if NVME_CQ_IRQ_ENABLED is set. While at it, also fix the error path to add the missing removal of the added IRQ vector if nvmet_cq_create() fails. Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver") Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/target/pci-epf.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c index d55ad334670c..b1e31483f157 100644 --- a/drivers/nvme/target/pci-epf.c +++ b/drivers/nvme/target/pci-epf.c @@ -1271,9 +1271,6 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, if (!(flags & NVME_QUEUE_PHYS_CONTIG)) return NVME_SC_INVALID_QUEUE | NVME_STATUS_DNR; - if (flags & NVME_CQ_IRQ_ENABLED) - set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags); - cq->pci_addr = pci_addr; cq->qid = cqid; cq->depth = qsize + 1; @@ -1290,10 +1287,11 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, cq->qes = ctrl->io_cqes; cq->pci_size = cq->qes * cq->depth; - cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector); - if (!cq->iv) { - status = NVME_SC_INTERNAL | NVME_STATUS_DNR; - goto err; + if (flags & NVME_CQ_IRQ_ENABLED) { + cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector); + if (!cq->iv) + return NVME_SC_INTERNAL | NVME_STATUS_DNR; + set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags); } status = nvmet_cq_create(tctrl, &cq->nvme_cq, cqid, cq->depth); @@ -1308,7 +1306,8 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl, return NVME_SC_SUCCESS; err: - clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags); + if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags)) + nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector); return status; } From bb39ed47065455604729404729d9116868638d31 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 5 Mar 2025 21:21:43 +0900 Subject: [PATCH 0814/1090] ksmbd: fix use-after-free in ksmbd_free_work_struct ->interim_entry of ksmbd_work could be deleted after oplock is freed. We don't need to manage it with linked list. The interim request could be immediately sent whenever a oplock break wait is needed. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/ksmbd_work.c | 3 --- fs/smb/server/ksmbd_work.h | 1 - fs/smb/server/oplock.c | 37 +++++++++++++++---------------------- fs/smb/server/oplock.h | 1 - 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c index 4af2e6007c29..72b00ca6e455 100644 --- a/fs/smb/server/ksmbd_work.c +++ b/fs/smb/server/ksmbd_work.c @@ -26,7 +26,6 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void) INIT_LIST_HEAD(&work->request_entry); INIT_LIST_HEAD(&work->async_request_entry); INIT_LIST_HEAD(&work->fp_entry); - INIT_LIST_HEAD(&work->interim_entry); INIT_LIST_HEAD(&work->aux_read_list); work->iov_alloc_cnt = 4; work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec), @@ -56,8 +55,6 @@ void ksmbd_free_work_struct(struct ksmbd_work *work) kfree(work->tr_buf); kvfree(work->request_buf); kfree(work->iov); - if (!list_empty(&work->interim_entry)) - list_del(&work->interim_entry); if (work->async_id) ksmbd_release_id(&work->conn->async_ida, work->async_id); diff --git a/fs/smb/server/ksmbd_work.h b/fs/smb/server/ksmbd_work.h index 8ca2c813246e..d36393ff8310 100644 --- a/fs/smb/server/ksmbd_work.h +++ b/fs/smb/server/ksmbd_work.h @@ -89,7 +89,6 @@ struct ksmbd_work { /* List head at conn->async_requests */ struct list_head async_request_entry; struct list_head fp_entry; - struct list_head interim_entry; }; /** diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 3a3fe4afbdf0..2febd1c8e278 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -46,7 +46,6 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work, opinfo->fid = id; opinfo->Tid = Tid; INIT_LIST_HEAD(&opinfo->op_entry); - INIT_LIST_HEAD(&opinfo->interim_list); init_waitqueue_head(&opinfo->oplock_q); init_waitqueue_head(&opinfo->oplock_brk); atomic_set(&opinfo->refcount, 1); @@ -803,7 +802,6 @@ out: static int smb2_lease_break_noti(struct oplock_info *opinfo) { struct ksmbd_conn *conn = opinfo->conn; - struct list_head *tmp, *t; struct ksmbd_work *work; struct lease_break_info *br_info; struct lease *lease = opinfo->o_lease; @@ -831,16 +829,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) work->sess = opinfo->sess; if (opinfo->op_state == OPLOCK_ACK_WAIT) { - list_for_each_safe(tmp, t, &opinfo->interim_list) { - struct ksmbd_work *in_work; - - in_work = list_entry(tmp, struct ksmbd_work, - interim_entry); - setup_async_work(in_work, NULL, NULL); - smb2_send_interim_resp(in_work, STATUS_PENDING); - list_del_init(&in_work->interim_entry); - release_async_work(in_work); - } INIT_WORK(&work->work, __smb2_lease_break_noti); ksmbd_queue_work(work); wait_for_break_ack(opinfo); @@ -871,7 +859,8 @@ static void wait_lease_breaking(struct oplock_info *opinfo) } } -static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) +static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level, + struct ksmbd_work *in_work) { int err = 0; @@ -914,9 +903,15 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) } if (lease->state & (SMB2_LEASE_WRITE_CACHING_LE | - SMB2_LEASE_HANDLE_CACHING_LE)) + SMB2_LEASE_HANDLE_CACHING_LE)) { + if (in_work) { + setup_async_work(in_work, NULL, NULL); + smb2_send_interim_resp(in_work, STATUS_PENDING); + release_async_work(in_work); + } + brk_opinfo->op_state = OPLOCK_ACK_WAIT; - else + } else atomic_dec(&brk_opinfo->breaking_cnt); } else { err = oplock_break_pending(brk_opinfo, req_op_level); @@ -1116,7 +1111,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, if (ksmbd_conn_releasing(opinfo->conn)) continue; - oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); + oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); opinfo_put(opinfo); } } @@ -1152,7 +1147,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) if (ksmbd_conn_releasing(opinfo->conn)) continue; - oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); + oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); opinfo_put(opinfo); } } @@ -1252,8 +1247,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, goto op_break_not_needed; } - list_add(&work->interim_entry, &prev_opinfo->interim_list); - err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II); + err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II, work); opinfo_put(prev_opinfo); if (err == -ENOENT) goto set_lev; @@ -1322,8 +1316,7 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work, } brk_opinfo->open_trunc = is_trunc; - list_add(&work->interim_entry, &brk_opinfo->interim_list); - oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II); + oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II, work); opinfo_put(brk_opinfo); } @@ -1386,7 +1379,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, SMB2_LEASE_KEY_SIZE)) goto next; brk_op->open_trunc = is_trunc; - oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE); + oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE, NULL); next: opinfo_put(brk_op); rcu_read_lock(); diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h index 72bc88a63a40..3f64f0787263 100644 --- a/fs/smb/server/oplock.h +++ b/fs/smb/server/oplock.h @@ -67,7 +67,6 @@ struct oplock_info { bool is_lease; bool open_trunc; /* truncate on open */ struct lease *o_lease; - struct list_head interim_list; struct list_head op_entry; struct list_head lease_entry; wait_queue_head_t oplock_q; /* Other server threads */ From 3aa660c059240e0c795217182cf7df32909dd917 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 6 Mar 2025 14:14:58 +0900 Subject: [PATCH 0815/1090] ksmbd: prevent connection release during oplock break notification ksmbd_work could be freed when after connection release. Increment r_count of ksmbd_conn to indicate that requests are not finished yet and to not release the connection. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/connection.c | 20 ++++++++++++++++++++ fs/smb/server/connection.h | 2 ++ fs/smb/server/oplock.c | 6 ++++++ fs/smb/server/server.c | 14 ++------------ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c index f8a40f65db6a..c1f22c129111 100644 --- a/fs/smb/server/connection.c +++ b/fs/smb/server/connection.c @@ -433,6 +433,26 @@ void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops) default_conn_ops.terminate_fn = ops->terminate_fn; } +void ksmbd_conn_r_count_inc(struct ksmbd_conn *conn) +{ + atomic_inc(&conn->r_count); +} + +void ksmbd_conn_r_count_dec(struct ksmbd_conn *conn) +{ + /* + * Checking waitqueue to dropping pending requests on + * disconnection. waitqueue_active is safe because it + * uses atomic operation for condition. + */ + atomic_inc(&conn->refcnt); + if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q)) + wake_up(&conn->r_count_q); + + if (atomic_dec_and_test(&conn->refcnt)) + kfree(conn); +} + int ksmbd_conn_transport_init(void) { int ret; diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h index b379ae4fdcdf..91c2318639e7 100644 --- a/fs/smb/server/connection.h +++ b/fs/smb/server/connection.h @@ -168,6 +168,8 @@ int ksmbd_conn_transport_init(void); void ksmbd_conn_transport_destroy(void); void ksmbd_conn_lock(struct ksmbd_conn *conn); void ksmbd_conn_unlock(struct ksmbd_conn *conn); +void ksmbd_conn_r_count_inc(struct ksmbd_conn *conn); +void ksmbd_conn_r_count_dec(struct ksmbd_conn *conn); /* * WARNING diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 2febd1c8e278..28886ff1ee57 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -634,6 +634,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) { struct smb2_oplock_break *rsp = NULL; struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); + struct ksmbd_conn *conn = work->conn; struct oplock_break_info *br_info = work->request_buf; struct smb2_hdr *rsp_hdr; struct ksmbd_file *fp; @@ -689,6 +690,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) out: ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); } /** @@ -723,6 +725,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) work->sess = opinfo->sess; if (opinfo->op_state == OPLOCK_ACK_WAIT) { + ksmbd_conn_r_count_inc(conn); INIT_WORK(&work->work, __smb2_oplock_break_noti); ksmbd_queue_work(work); @@ -744,6 +747,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) { struct smb2_lease_break *rsp = NULL; struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); + struct ksmbd_conn *conn = work->conn; struct lease_break_info *br_info = work->request_buf; struct smb2_hdr *rsp_hdr; @@ -790,6 +794,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) out: ksmbd_free_work_struct(work); + ksmbd_conn_r_count_dec(conn); } /** @@ -829,6 +834,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) work->sess = opinfo->sess; if (opinfo->op_state == OPLOCK_ACK_WAIT) { + ksmbd_conn_r_count_inc(conn); INIT_WORK(&work->work, __smb2_lease_break_noti); ksmbd_queue_work(work); wait_for_break_ack(opinfo); diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c index 601e7fcbcf1e..ab533c602987 100644 --- a/fs/smb/server/server.c +++ b/fs/smb/server/server.c @@ -270,17 +270,7 @@ static void handle_ksmbd_work(struct work_struct *wk) ksmbd_conn_try_dequeue_request(work); ksmbd_free_work_struct(work); - /* - * Checking waitqueue to dropping pending requests on - * disconnection. waitqueue_active is safe because it - * uses atomic operation for condition. - */ - atomic_inc(&conn->refcnt); - if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q)) - wake_up(&conn->r_count_q); - - if (atomic_dec_and_test(&conn->refcnt)) - kfree(conn); + ksmbd_conn_r_count_dec(conn); } /** @@ -310,7 +300,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn) conn->request_buf = NULL; ksmbd_conn_enqueue_request(work); - atomic_inc(&conn->r_count); + ksmbd_conn_r_count_inc(conn); /* update activity on connection */ conn->last_active = jiffies; INIT_WORK(&work->work, handle_ksmbd_work); From fd10709e28d2fa9015667aee56d92099fc97aa0d Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 7 Mar 2025 15:37:32 +0100 Subject: [PATCH 0816/1090] MAINTAINERS: Remove myself from the goodix touchscreen maintainers Haven't authored any commits to that driver in 10 years, and haven't had supported hardware for nearly as long. Signed-off-by: Bastien Nocera Link: https://lore.kernel.org/r/20250307143740.960328-1-hadess@hadess.net Signed-off-by: Dmitry Torokhov --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index baf0eeb9a355..ca8945fd98bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9729,7 +9729,6 @@ S: Maintained F: drivers/media/usb/go7007/ GOODIX TOUCHSCREEN -M: Bastien Nocera M: Hans de Goede L: linux-input@vger.kernel.org S: Maintained From f5d4e81774c42d9c2ea3980e570f3330ff2ed5d2 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Mon, 3 Mar 2025 08:49:41 +0800 Subject: [PATCH 0817/1090] drm/xe: remove redundant check in xe_vm_create_ioctl() The check for args->extensions is repeated twice in xe_vm_create_ioctl(). This commit removes the redundant check to streamline the code. Fixes: 7224788f6756 ("drm/xe: Kill XE_VM_PROPERTY_BIND_OP_ERROR_CAPTURE_ADDRESS extension") Cc: Rodrigo Vivi Signed-off-by: Xin Wang Reviewed-by: Tejas Upadhyay Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20250303004942.951699-1-x.wang@intel.com Signed-off-by: Rodrigo Vivi (cherry picked from commit 8da8aecf1f2d89c2b8188bcf7aa252ec146ddd12) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_vm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index ec6ec18ab3fa..5956631c0d40 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1809,9 +1809,6 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE)) return -EINVAL; - if (XE_IOCTL_DBG(xe, args->extensions)) - return -EINVAL; - if (args->flags & DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE) flags |= XE_VM_FLAG_SCRATCH_PAGE; if (args->flags & DRM_XE_VM_CREATE_FLAG_LR_MODE) From df1e82e7acd3c50b65ca0e2e09089b78382d14ab Mon Sep 17 00:00:00 2001 From: David Rosca Date: Thu, 13 Feb 2025 15:30:37 +0100 Subject: [PATCH 0818/1090] drm/amdgpu/display: Allow DCC for video formats on GFX12 We advertise DCC as supported for NV12/P010 formats on GFX12, but it would fail on this check on atomic commit. Signed-off-by: David Rosca Reviewed-by: Ruijing Dong Signed-off-by: Alex Deucher (cherry picked from commit ba795235a2b99ba9bbef647ab003b2f3145d9bbb) Cc: stable@vger.kernel.org # 6.12.x --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 774cc3f4f3fd..92472109f84a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -277,8 +277,11 @@ static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev, if (!dcc->enable) return 0; - if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || - !dc->cap_funcs.get_dcc_compression_cap) + if (adev->family < AMDGPU_FAMILY_GC_12_0_0 && + format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return -EINVAL; + + if (!dc->cap_funcs.get_dcc_compression_cap) return -EINVAL; input.format = format; From e204aab79e01bc8ff750645666993ed8b719de57 Mon Sep 17 00:00:00 2001 From: Aliaksei Urbanski Date: Thu, 6 Mar 2025 13:36:03 +0300 Subject: [PATCH 0819/1090] drm/amd/display: fix missing .is_two_pixels_per_container Starting from 6.11, AMDGPU driver, while being loaded with amdgpu.dc=1, due to lack of .is_two_pixels_per_container function in dce60_tg_funcs, causes a NULL pointer dereference on PCs with old GPUs, such as R9 280X. So this fix adds missing .is_two_pixels_per_container to dce60_tg_funcs. Reported-by: Rosen Penev Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3942 Fixes: e6a901a00822 ("drm/amd/display: use even ODM slice width for two pixels per container") Signed-off-by: Aliaksei Urbanski Signed-off-by: Alex Deucher (cherry picked from commit bd4b125eb949785c6f8a53b0494e32795421209d) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c index e5fb0e8333e4..e691a1cf3356 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c @@ -239,6 +239,7 @@ static const struct timing_generator_funcs dce60_tg_funcs = { dce60_timing_generator_enable_advanced_request, .configure_crc = dce60_configure_crc, .get_crc = dce110_get_crc, + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, }; void dce60_timing_generator_construct( From 4afacc9948e1f8fdbca401d259ae65ad93d298c0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 6 Mar 2025 12:51:24 -0600 Subject: [PATCH 0820/1090] drm/amd: Keep display off while going into S4 When userspace invokes S4 the flow is: 1) amdgpu_pmops_prepare() 2) amdgpu_pmops_freeze() 3) Create hibernation image 4) amdgpu_pmops_thaw() 5) Write out image to disk 6) Turn off system Then on resume amdgpu_pmops_restore() is called. This flow has a problem that because amdgpu_pmops_thaw() is called it will call amdgpu_device_resume() which will resume all of the GPU. This includes turning the display hardware back on and discovering connectors again. This is an unexpected experience for the display to turn back on. Adjust the flow so that during the S4 sequence display hardware is not turned back on. Reported-by: Xaver Hugl Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2038 Cc: Muhammad Usama Anjum Tested-by: Muhammad Usama Anjum Acked-by: Alex Deucher Acked-by: Harry Wentland Link: https://lore.kernel.org/r/20250306185124.44780-1-mario.limonciello@amd.com Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher (cherry picked from commit 68bfdc8dc0a1a7fdd9ab61e69907ae71a6fd3d91) --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 11 +++++++++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 95a05b03f799..c0ddbe7d6f0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2555,7 +2555,6 @@ static int amdgpu_pmops_freeze(struct device *dev) int r; r = amdgpu_device_suspend(drm_dev, true); - adev->in_s4 = false; if (r) return r; @@ -2567,8 +2566,13 @@ static int amdgpu_pmops_freeze(struct device *dev) static int amdgpu_pmops_thaw(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + int r; - return amdgpu_device_resume(drm_dev, true); + r = amdgpu_device_resume(drm_dev, true); + adev->in_s4 = false; + + return r; } static int amdgpu_pmops_poweroff(struct device *dev) @@ -2581,6 +2585,9 @@ static int amdgpu_pmops_poweroff(struct device *dev) static int amdgpu_pmops_restore(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); + + adev->in_s4 = false; return amdgpu_device_resume(drm_dev, true); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9d9645a2d18e..f4fed93f2915 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3373,6 +3373,11 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) return 0; } + + /* leave display off for S4 sequence */ + if (adev->in_s4) + return 0; + /* Recreate dc_state - DC invalidates it when setting power state to S3. */ dc_state_release(dm_state->context); dm_state->context = dc_state_create(dm->dc, NULL); From 40b8c14936bd2726354c856251f6baed9869e760 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 20 Feb 2025 16:20:26 -0500 Subject: [PATCH 0821/1090] drm/amd/display: Disable unneeded hpd interrupts during dm_init [Why] It seems HPD interrupts are enabled by default for all connectors, even if the hpd source isn't valid. An eDP for example, does not have a valid hpd source (but does have a valid hpdrx source; see construct_phy()). Thus, eDPs should have their hpd interrupt disabled. In the past, this wasn't really an issue. Although the driver gets interrupted, then acks by writing to hw registers, there weren't any subscribed handlers that did anything meaningful (see register_hpd_handlers()). But things changed with the introduction of IPS. s2idle requires that the driver allows IPS for DMUB fw to put hw to sleep. Since register access requires hw to be awake, the driver will block IPS entry to do so. And no IPS means no hw sleep during s2idle. This was the observation on DCN35 systems with an eDP. During suspend, the eDP toggled its hpd pin as part of the panel power down sequence. The driver was then interrupted, and acked by writing to registers, blocking IPS entry. [How] Since DC marks eDP connections as having invalid hpd sources (see construct_phy()), DM should disable them at the hw level. Do so in amdgpu_dm_hpd_init() by disabling all hpd ints first, then selectively enabling ones for connectors that have valid hpd sources. Cc: Mario Limonciello Cc: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Leo Li Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 7b1ba19eb15f88e70782642ce2d934211269337b) Cc: stable@vger.kernel.org --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index c4a7fd453e5f..a215234151ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -894,8 +894,16 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; + int irq_type; int i; + /* First, clear all hpd and hpdrx interrupts */ + for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++) { + if (!dc_interrupt_set(adev->dm.dc, i, false)) + drm_err(dev, "Failed to clear hpd(rx) source=%d on init\n", + i); + } + drm_connector_list_iter_begin(dev, &iter); drm_for_each_connector_iter(connector, &iter) { struct amdgpu_dm_connector *amdgpu_dm_connector; @@ -908,10 +916,31 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) dc_link = amdgpu_dm_connector->dc_link; + /* + * Get a base driver irq reference for hpd ints for the lifetime + * of dm. Note that only hpd interrupt types are registered with + * base driver; hpd_rx types aren't. IOW, amdgpu_irq_get/put on + * hpd_rx isn't available. DM currently controls hpd_rx + * explicitly with dc_interrupt_set() + */ if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) { - dc_interrupt_set(adev->dm.dc, - dc_link->irq_source_hpd, - true); + irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1; + /* + * TODO: There's a mismatch between mode_info.num_hpd + * and what bios reports as the # of connectors with hpd + * sources. Since the # of hpd source types registered + * with base driver == mode_info.num_hpd, we have to + * fallback to dc_interrupt_set for the remaining types. + */ + if (irq_type < adev->mode_info.num_hpd) { + if (amdgpu_irq_get(adev, &adev->hpd_irq, irq_type)) + drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", + dc_link->irq_source_hpd); + } else { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd, + true); + } } if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) { @@ -921,12 +950,6 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) } } drm_connector_list_iter_end(&iter); - - /* Update reference counts for HPDs */ - for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) { - if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1)) - drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i); - } } /** @@ -942,7 +965,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; - int i; + int irq_type; drm_connector_list_iter_begin(dev, &iter); drm_for_each_connector_iter(connector, &iter) { @@ -956,9 +979,18 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) dc_link = amdgpu_dm_connector->dc_link; if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) { - dc_interrupt_set(adev->dm.dc, - dc_link->irq_source_hpd, - false); + irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1; + + /* TODO: See same TODO in amdgpu_dm_hpd_init() */ + if (irq_type < adev->mode_info.num_hpd) { + if (amdgpu_irq_put(adev, &adev->hpd_irq, irq_type)) + drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", + dc_link->irq_source_hpd); + } else { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd, + false); + } } if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) { @@ -968,10 +1000,4 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) } } drm_connector_list_iter_end(&iter); - - /* Update reference counts for HPDs */ - for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) { - if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1)) - drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i); - } } From b5a981e1b34e44f94a5967f730fff4166f2101e8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Sat, 22 Feb 2025 23:37:32 -0600 Subject: [PATCH 0822/1090] drm/amd/display: fix default brightness [Why] To avoid flickering during boot default brightness level set by BIOS should be maintained for as much of the boot as feasible. commit 2fe87f54abdc ("drm/amd/display: Set default brightness according to ACPI") attempted to set the right levels for AC vs DC, but brightness still got reset to maximum level in initialization code for setup_backlight_device(). [How] Remove the hardcoded initialization in setup_backlight_device() and instead program brightness value to match BIOS (AC or DC). This avoids a brightness flicker from kernel changing the value. Userspace may however still change it during boot. Fixes: 2fe87f54abdc ("drm/amd/display: Set default brightness according to ACPI") Acked-by: Wayne Lin Signed-off-by: Mario Limonciello Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 0747acf3311229e22009bec4a9e7fc30c879e842) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f4fed93f2915..4bd7f82c582d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4911,6 +4911,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) dm->backlight_dev[aconnector->bl_idx] = backlight_device_register(bl_name, aconnector->base.kdev, dm, &amdgpu_dm_backlight_ops, &props); + dm->brightness[aconnector->bl_idx] = props.brightness; if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) { DRM_ERROR("DM: Backlight registration failed!\n"); @@ -4978,7 +4979,6 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm, aconnector->bl_idx = bl_idx; amdgpu_dm_update_backlight_caps(dm, bl_idx); - dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; dm->backlight_link[bl_idx] = link; dm->num_of_edps++; From 5760388d9681ac743038b846b9082b9023969551 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Sun, 23 Feb 2025 00:04:35 -0600 Subject: [PATCH 0823/1090] drm/amd/display: Restore correct backlight brightness after a GPU reset [Why] GPU reset will attempt to restore cached state, but brightness doesn't get restored. It will come back at 100% brightness, but userspace thinks it's the previous value. [How] When running resume sequence if GPU is in reset restore brightness to previous value. Acked-by: Wayne Lin Signed-off-by: Mario Limonciello Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 5e19e2b57b6bb640d68dfc7991e1e182922cf867) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4bd7f82c582d..74ad0d1240fe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -245,6 +245,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector); static void handle_hpd_rx_irq(void *param); +static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm, + int bl_idx, + u32 user_brightness); + static bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state, struct drm_crtc_state *new_crtc_state); @@ -3371,6 +3375,12 @@ static int dm_resume(struct amdgpu_ip_block *ip_block) mutex_unlock(&dm->dc_lock); + /* set the backlight after a reset */ + for (i = 0; i < dm->num_of_edps; i++) { + if (dm->backlight_dev[i]) + amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]); + } + return 0; } From 79e31396fdd7037c503e6add15af7cb00633ea92 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 27 Feb 2025 16:36:25 -0700 Subject: [PATCH 0824/1090] drm/amd/display: Assign normalized_pix_clk when color depth = 14 [WHY & HOW] A warning message "WARNING: CPU: 4 PID: 459 at ... /dc_resource.c:3397 calculate_phy_pix_clks+0xef/0x100 [amdgpu]" occurs because the display_color_depth == COLOR_DEPTH_141414 is not handled. This is observed in Radeon RX 6600 XT. It is fixed by assigning pix_clk * (14 * 3) / 24 - same as the rests. Also fixes the indentation in get_norm_pix_clk. Reviewed-by: Harry Wentland Signed-off-by: Alex Hung Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 274a87eb389f58eddcbc5659ab0b180b37e92775) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a45037cb4cc0..298668e9729c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3389,10 +3389,13 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) break; case COLOR_DEPTH_121212: normalized_pix_clk = (pix_clk * 36) / 24; - break; + break; + case COLOR_DEPTH_141414: + normalized_pix_clk = (pix_clk * 42) / 24; + break; case COLOR_DEPTH_161616: normalized_pix_clk = (pix_clk * 48) / 24; - break; + break; default: ASSERT(0); break; From e65e7bea220c3ce8c4c793b4ba35557f4994ab2b Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 28 Feb 2025 13:18:14 -0600 Subject: [PATCH 0825/1090] drm/amd/display: Fix slab-use-after-free on hdcp_work [Why] A slab-use-after-free is reported when HDCP is destroyed but the property_validate_dwork queue is still running. [How] Cancel the delayed work when destroying workqueue. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4006 Fixes: da3fd7ac0bcf ("drm/amd/display: Update CP property based on HW query") Cc: Alex Deucher Reviewed-by: Alex Hung Signed-off-by: Mario Limonciello Signed-off-by: Tom Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 725a04ba5a95e89c89633d4322430cfbca7ce128) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index e339c7a8d541..c0dc23244049 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -455,6 +455,7 @@ void hdcp_destroy(struct kobject *kobj, struct hdcp_workqueue *hdcp_work) for (i = 0; i < hdcp_work->max_link; i++) { cancel_delayed_work_sync(&hdcp_work[i].callback_dwork); cancel_delayed_work_sync(&hdcp_work[i].watchdog_timer_dwork); + cancel_delayed_work_sync(&hdcp_work[i].property_validate_dwork); } sysfs_remove_bin_file(kobj, &hdcp_work[0].attr); From ded6ad4c6e2005e959ea09abba16c451433dd34b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 9 Mar 2025 12:26:50 -0400 Subject: [PATCH 0826/1090] drm/amdgpu/vce2: fix ip block reference Need to use the correct IP block type. VCE vs VCN. Fixes mclk issues on Hawaii. Suggested by selendym. Fixes: 82ae6619a450 ("drm/amdgpu: update the handle ptr in wait_for_idle") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3997 Reviewed-by: Boyuan Zhang Cc: Sunil Khatri Signed-off-by: Alex Deucher (cherry picked from commit 02438acd252395628d74cfac692efbb676d21521) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index c633b7ff2943..09fd6ef99b3d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -284,7 +284,7 @@ static int vce_v2_0_stop(struct amdgpu_device *adev) return 0; } - ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCN); + ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE); if (!ip_block) return -EINVAL; From 366fef794bd2b7c2e9df933f6828dd9739bfba84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 10 Mar 2025 14:21:58 +0200 Subject: [PATCH 0827/1090] : Allow the passing of both iomem and non-iomem pointers to no_free_ptr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling no_free_ptr() for an __iomem pointer results in Sparse complaining about the types: warning: incorrect type in argument 1 (different address spaces) expected void const volatile *val got void [noderef] __iomem *__val [ The example is from drivers/platform/x86/intel/pmc/core_ssram.c:283 ] The problem is caused by the signature of __must_check_fn() added in: 85be6d842447 ("cleanup: Make no_free_ptr() __must_check") ... to enforce that the return value is always used. Use __force to allow both iomem and non-iomem pointers to be given for no_free_ptr(). Reported-by: kernel test robot Signed-off-by: Ilpo Järvinen Signed-off-by: Ingo Molnar Reviewed-by: Andy Shevchenko Reviewed-by: Dan Williams Cc: "H. Peter Anvin" Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250310122158.20966-1-ilpo.jarvinen@linux.intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202403050547.qnZtuNlN-lkp@intel.com/ --- include/linux/cleanup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h index ec00e3f7af2b..ee2614adb785 100644 --- a/include/linux/cleanup.h +++ b/include/linux/cleanup.h @@ -212,7 +212,7 @@ const volatile void * __must_check_fn(const volatile void *val) { return val; } #define no_free_ptr(p) \ - ((typeof(p)) __must_check_fn(__get_and_null(p, NULL))) + ((typeof(p)) __must_check_fn((__force const volatile void *)__get_and_null(p, NULL))) #define return_ptr(p) return no_free_ptr(p) From eab0396353be1c778eba1c0b5180176f04dd21ce Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Fri, 7 Mar 2025 10:18:20 +0800 Subject: [PATCH 0828/1090] net/mlx5: handle errors in mlx5_chains_create_table() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In mlx5_chains_create_table(), the return value of mlx5_get_fdb_sub_ns() and mlx5_get_flow_namespace() must be checked to prevent NULL pointer dereferences. If either function fails, the function should log error message with mlx5_core_warn() and return error pointer. Fixes: 39ac237ce009 ("net/mlx5: E-Switch, Refactor chains and priorities") Signed-off-by: Wentao Liang Reviewed-by: Tariq Toukan Link: https://patch.msgid.link/20250307021820.2646-1-vulab@iscas.ac.cn Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c index a80ecb672f33..711d14dea248 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c @@ -196,6 +196,11 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains, ns = mlx5_get_flow_namespace(chains->dev, chains->ns); } + if (!ns) { + mlx5_core_warn(chains->dev, "Failed to get flow namespace\n"); + return ERR_PTR(-EOPNOTSUPP); + } + ft_attr.autogroup.num_reserved_entries = 2; ft_attr.autogroup.max_num_groups = chains->group_num; ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); From d0a4a1b36d7a71b45972ef33762c3fc082bec1db Mon Sep 17 00:00:00 2001 From: Kory Maincent Date: Fri, 7 Mar 2025 10:12:55 +0100 Subject: [PATCH 0829/1090] net: ethtool: tsinfo: Fix dump command Fix missing initialization of ts_info->phc_index in the dump command, which could cause a netdev interface to incorrectly display a PTP provider at index 0 instead of "none". Fix it by initializing the phc_index to -1. In the same time, restore missing initialization of ts_info.cmd for the IOCTL case, as it was before the transition from ethnl_default_dumpit to custom ethnl_tsinfo_dumpit. Also, remove unnecessary zeroing of ts_info, as it is embedded within reply_data, which is fully zeroed two lines earlier. Fixes: b9e3f7dc9ed95 ("net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology") Signed-off-by: Kory Maincent Reviewed-by: Vadim Fedorenko Link: https://patch.msgid.link/20250307091255.463559-1-kory.maincent@bootlin.com Signed-off-by: Jakub Kicinski --- net/ethtool/tsinfo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c index 691be6c445b3..ad3866c5a902 100644 --- a/net/ethtool/tsinfo.c +++ b/net/ethtool/tsinfo.c @@ -290,7 +290,8 @@ static void *ethnl_tsinfo_prepare_dump(struct sk_buff *skb, reply_data = ctx->reply_data; memset(reply_data, 0, sizeof(*reply_data)); reply_data->base.dev = dev; - memset(&reply_data->ts_info, 0, sizeof(reply_data->ts_info)); + reply_data->ts_info.cmd = ETHTOOL_GET_TS_INFO; + reply_data->ts_info.phc_index = -1; return ehdr; } From cfa693bf9d5361608e2963f5dae053b3695af8eb Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 7 Mar 2025 11:12:23 +0100 Subject: [PATCH 0830/1090] net: usb: lan78xx: Sanitize return values of register read/write functions usb_control_msg() returns the number of transferred bytes or a negative error code. The current implementation propagates the transferred byte count, which is unintended. This affects code paths that assume a boolean success/failure check, such as the EEPROM detection logic. Fix this by ensuring lan78xx_read_reg() and lan78xx_write_reg() return only 0 on success and preserve negative error codes. This approach is consistent with existing usage, as the transferred byte count is not explicitly checked elsewhere. Fixes: 8b1b2ca83b20 ("net: usb: lan78xx: Improve error handling in EEPROM and OTP operations") Reported-by: Mark Brown Closes: https://lore.kernel.org/all/ac965de8-f320-430f-80f6-b16f4e1ba06d@sirena.org.uk Signed-off-by: Oleksij Rempel Tested-by: Mark Brown Link: https://patch.msgid.link/20250307101223.3025632-1-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/usb/lan78xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index a91bf9c7e31d..137adf6d5b08 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -627,7 +627,7 @@ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) kfree(buf); - return ret; + return ret < 0 ? ret : 0; } static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data) @@ -658,7 +658,7 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data) kfree(buf); - return ret; + return ret < 0 ? ret : 0; } static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask, From 9f7b2aa5034e24d3c49db73d5f760c0435fe31c2 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:12 +0000 Subject: [PATCH 0831/1090] eth: bnxt: fix truesize for mb-xdp-pass case When mb-xdp is set and return is XDP_PASS, packet is converted from xdp_buff to sk_buff with xdp_update_skb_shared_info() in bnxt_xdp_build_skb(). bnxt_xdp_build_skb() passes incorrect truesize argument to xdp_update_skb_shared_info(). The truesize is calculated as BNXT_RX_PAGE_SIZE * sinfo->nr_frags but the skb_shared_info was wiped by napi_build_skb() before. So it stores sinfo->nr_frags before bnxt_xdp_build_skb() and use it instead of getting skb_shared_info from xdp_get_shared_info_from_buff(). Splat looks like: ------------[ cut here ]------------ WARNING: CPU: 2 PID: 0 at net/core/skbuff.c:6072 skb_try_coalesce+0x504/0x590 Modules linked in: xt_nat xt_tcpudp veth af_packet xt_conntrack nft_chain_nat xt_MASQUERADE nf_conntrack_netlink xfrm_user xt_addrtype nft_coms CPU: 2 UID: 0 PID: 0 Comm: swapper/2 Not tainted 6.14.0-rc2+ #3 RIP: 0010:skb_try_coalesce+0x504/0x590 Code: 4b fd ff ff 49 8b 34 24 40 80 e6 40 0f 84 3d fd ff ff 49 8b 74 24 48 40 f6 c6 01 0f 84 2e fd ff ff 48 8d 4e ff e9 25 fd ff ff <0f> 0b e99 RSP: 0018:ffffb62c4120caa8 EFLAGS: 00010287 RAX: 0000000000000003 RBX: ffffb62c4120cb14 RCX: 0000000000000ec0 RDX: 0000000000001000 RSI: ffffa06e5d7dc000 RDI: 0000000000000003 RBP: ffffa06e5d7ddec0 R08: ffffa06e6120a800 R09: ffffa06e7a119900 R10: 0000000000002310 R11: ffffa06e5d7dcec0 R12: ffffe4360575f740 R13: ffffe43600000000 R14: 0000000000000002 R15: 0000000000000002 FS: 0000000000000000(0000) GS:ffffa0755f700000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f147b76b0f8 CR3: 00000001615d4000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: ? __warn+0x84/0x130 ? skb_try_coalesce+0x504/0x590 ? report_bug+0x18a/0x1a0 ? handle_bug+0x53/0x90 ? exc_invalid_op+0x14/0x70 ? asm_exc_invalid_op+0x16/0x20 ? skb_try_coalesce+0x504/0x590 inet_frag_reasm_finish+0x11f/0x2e0 ip_defrag+0x37a/0x900 ip_local_deliver+0x51/0x120 ip_sublist_rcv_finish+0x64/0x70 ip_sublist_rcv+0x179/0x210 ip_list_rcv+0xf9/0x130 How to reproduce: ip link set $interface1 xdp obj xdp_pass.o ip link set $interface1 mtu 9000 up ip a a 10.0.0.1/24 dev $interface1 ip link set $interfac2 mtu 9000 up ip a a 10.0.0.2/24 dev $interface2 ping 10.0.0.1 -s 65000 Following ping.py patch adds xdp-mb-pass case. so ping.py is going to be able to reproduce this issue. Fixes: 1dc4c557bfed ("bnxt: adding bnxt_xdp_build_skb to build skb from multibuffer xdp_buff") Signed-off-by: Taehee Yoo Link: https://patch.msgid.link/20250309134219.91670-2-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7b8b5b39c7bb..6b5fe4ee7a99 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2038,6 +2038,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, struct rx_cmp_ext *rxcmp1; u32 tmp_raw_cons = *raw_cons; u16 cons, prod, cp_cons = RING_CMP(tmp_raw_cons); + struct skb_shared_info *sinfo; struct bnxt_sw_rx_bd *rx_buf; unsigned int len; u8 *data_ptr, agg_bufs, cmp_type; @@ -2164,6 +2165,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, false); if (!frag_len) goto oom_next_rx; + } xdp_active = true; } @@ -2173,6 +2175,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, rc = 1; goto next_rx; } + if (xdp_buff_has_frags(&xdp)) { + sinfo = xdp_get_shared_info_from_buff(&xdp); + agg_bufs = sinfo->nr_frags; + } else { + agg_bufs = 0; + } } if (len <= bp->rx_copybreak) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index e6c64e4bd66c..e9b49cb5b735 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -476,7 +476,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags, } xdp_update_skb_shared_info(skb, num_frags, sinfo->xdp_frags_size, - BNXT_RX_PAGE_SIZE * sinfo->nr_frags, + BNXT_RX_PAGE_SIZE * num_frags, xdp_buff_is_frag_pfmemalloc(xdp)); return skb; } From ca2456e073957781e1184de68551c65161b2bd30 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:13 +0000 Subject: [PATCH 0832/1090] eth: bnxt: return fail if interface is down in bnxt_queue_mem_alloc() The bnxt_queue_mem_alloc() is called to allocate new queue memory when a queue is restarted. It internally accesses rx buffer descriptor corresponding to the index. The rx buffer descriptor is allocated and set when the interface is up and it's freed when the interface is down. So, if queue is restarted if interface is down, kernel panic occurs. Splat looks like: BUG: unable to handle page fault for address: 000000000000b240 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 3 UID: 0 PID: 1563 Comm: ncdevmem2 Not tainted 6.14.0-rc2+ #9 844ddba6e7c459cafd0bf4db9a3198e Hardware name: ASUS System Product Name/PRIME Z690-P D4, BIOS 0603 11/01/2021 RIP: 0010:bnxt_queue_mem_alloc+0x3f/0x4e0 [bnxt_en] Code: 41 54 4d 89 c4 4d 69 c0 c0 05 00 00 55 48 89 f5 53 48 89 fb 4c 8d b5 40 05 00 00 48 83 ec 15 RSP: 0018:ffff9dcc83fef9e8 EFLAGS: 00010202 RAX: ffffffffc0457720 RBX: ffff934ed8d40000 RCX: 0000000000000000 RDX: 000000000000001f RSI: ffff934ea508f800 RDI: ffff934ea508f808 RBP: ffff934ea508f800 R08: 000000000000b240 R09: ffff934e84f4b000 R10: ffff9dcc83fefa30 R11: ffff934e84f4b000 R12: 000000000000001f R13: ffff934ed8d40ac0 R14: ffff934ea508fd40 R15: ffff934e84f4b000 FS: 00007fa73888c740(0000) GS:ffff93559f780000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000000000b240 CR3: 0000000145a2e000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: ? __die+0x20/0x70 ? page_fault_oops+0x15a/0x460 ? exc_page_fault+0x6e/0x180 ? asm_exc_page_fault+0x22/0x30 ? __pfx_bnxt_queue_mem_alloc+0x10/0x10 [bnxt_en 7f85e76f4d724ba07471d7e39d9e773aea6597b7] ? bnxt_queue_mem_alloc+0x3f/0x4e0 [bnxt_en 7f85e76f4d724ba07471d7e39d9e773aea6597b7] netdev_rx_queue_restart+0xc5/0x240 net_devmem_bind_dmabuf_to_queue+0xf8/0x200 netdev_nl_bind_rx_doit+0x3a7/0x450 genl_family_rcv_msg_doit+0xd9/0x130 genl_rcv_msg+0x184/0x2b0 ? __pfx_netdev_nl_bind_rx_doit+0x10/0x10 ? __pfx_genl_rcv_msg+0x10/0x10 netlink_rcv_skb+0x54/0x100 genl_rcv+0x24/0x40 ... Reviewed-by: Somnath Kotur Reviewed-by: Jakub Kicinski Fixes: 2d694c27d32e ("bnxt_en: implement netdev_queue_mgmt_ops") Signed-off-by: Taehee Yoo Reviewed-by: Mina Almasry Link: https://patch.msgid.link/20250309134219.91670-3-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6b5fe4ee7a99..acb9500ef930 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -15447,6 +15447,9 @@ static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx) struct bnxt_ring_struct *ring; int rc; + if (!bp->rx_ring) + return -ENETDOWN; + rxr = &bp->rx_ring[idx]; clone = qmem; memcpy(clone, rxr, sizeof(*rxr)); From 661958552eda5bf64bfafb4821cbdded935f1f68 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:14 +0000 Subject: [PATCH 0833/1090] eth: bnxt: do not use BNXT_VNIC_NTUPLE unconditionally in queue restart logic When a queue is restarted, it sets MRU to 0 for stopping packet flow. MRU variable is a member of vnic_info[], the first vnic_info is default and the second is ntuple. Only when ntuple is enabled(ethtool -K eth0 ntuple on), vnic_info for ntuple is allocated in init logic. The bp->nr_vnics indicates how many vnic_info are allocated. However bnxt_queue_{start | stop}() accesses vnic_info[BNXT_VNIC_NTUPLE] regardless of ntuple state. Reviewed-by: Somnath Kotur Fixes: b9d2956e869c ("bnxt_en: stop packet flow during bnxt_queue_stop/start") Signed-off-by: Taehee Yoo Link: https://patch.msgid.link/20250309134219.91670-4-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index acb9500ef930..218109ee1c23 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -15643,7 +15643,7 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx) cpr = &rxr->bnapi->cp_ring; cpr->sw_stats->rx.rx_resets++; - for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) { + for (i = 0; i <= bp->nr_vnics; i++) { vnic = &bp->vnic_info[i]; rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true); @@ -15671,7 +15671,7 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx) struct bnxt_vnic_info *vnic; int i; - for (i = 0; i <= BNXT_VNIC_NTUPLE; i++) { + for (i = 0; i <= bp->nr_vnics; i++) { vnic = &bp->vnic_info[i]; vnic->mru = 0; bnxt_hwrm_vnic_update(bp, vnic, From c03e7d05aa0e2f7e9a9ce5ad8a12471a53f941dc Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:15 +0000 Subject: [PATCH 0834/1090] eth: bnxt: do not update checksum in bnxt_xdp_build_skb() The bnxt_rx_pkt() updates ip_summed value at the end if checksum offload is enabled. When the XDP-MB program is attached and it returns XDP_PASS, the bnxt_xdp_build_skb() is called to update skb_shared_info. The main purpose of bnxt_xdp_build_skb() is to update skb_shared_info, but it updates ip_summed value too if checksum offload is enabled. This is actually duplicate work. When the bnxt_rx_pkt() updates ip_summed value, it checks if ip_summed is CHECKSUM_NONE or not. It means that ip_summed should be CHECKSUM_NONE at this moment. But ip_summed may already be updated to CHECKSUM_UNNECESSARY in the XDP-MB-PASS path. So the by skb_checksum_none_assert() WARNS about it. This is duplicate work and updating ip_summed in the bnxt_xdp_build_skb() is not needed. Splat looks like: WARNING: CPU: 3 PID: 5782 at ./include/linux/skbuff.h:5155 bnxt_rx_pkt+0x479b/0x7610 [bnxt_en] Modules linked in: bnxt_re bnxt_en rdma_ucm rdma_cm iw_cm ib_cm ib_uverbs veth xt_nat xt_tcpudp xt_conntrack nft_chain_nat xt_MASQUERADE nf_] CPU: 3 UID: 0 PID: 5782 Comm: socat Tainted: G W 6.14.0-rc4+ #27 Tainted: [W]=WARN Hardware name: ASUS System Product Name/PRIME Z690-P D4, BIOS 0603 11/01/2021 RIP: 0010:bnxt_rx_pkt+0x479b/0x7610 [bnxt_en] Code: 54 24 0c 4c 89 f1 4c 89 ff c1 ea 1f ff d3 0f 1f 00 49 89 c6 48 85 c0 0f 84 4c e5 ff ff 48 89 c7 e8 ca 3d a0 c8 e9 8f f4 ff ff <0f> 0b f RSP: 0018:ffff88881ba09928 EFLAGS: 00010202 RAX: 0000000000000000 RBX: 00000000c7590303 RCX: 0000000000000000 RDX: 1ffff1104e7d1610 RSI: 0000000000000001 RDI: ffff8881c91300b8 RBP: ffff88881ba09b28 R08: ffff888273e8b0d0 R09: ffff888273e8b070 R10: ffff888273e8b010 R11: ffff888278b0f000 R12: ffff888273e8b080 R13: ffff8881c9130e00 R14: ffff8881505d3800 R15: ffff888273e8b000 FS: 00007f5a2e7be080(0000) GS:ffff88881ba00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fff2e708ff8 CR3: 000000013e3b0000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: ? __warn+0xcd/0x2f0 ? bnxt_rx_pkt+0x479b/0x7610 ? report_bug+0x326/0x3c0 ? handle_bug+0x53/0xa0 ? exc_invalid_op+0x14/0x50 ? asm_exc_invalid_op+0x16/0x20 ? bnxt_rx_pkt+0x479b/0x7610 ? bnxt_rx_pkt+0x3e41/0x7610 ? __pfx_bnxt_rx_pkt+0x10/0x10 ? napi_complete_done+0x2cf/0x7d0 __bnxt_poll_work+0x4e8/0x1220 ? __pfx___bnxt_poll_work+0x10/0x10 ? __pfx_mark_lock.part.0+0x10/0x10 bnxt_poll_p5+0x36a/0xfa0 ? __pfx_bnxt_poll_p5+0x10/0x10 __napi_poll.constprop.0+0xa0/0x440 net_rx_action+0x899/0xd00 ... Following ping.py patch adds xdp-mb-pass case. so ping.py is going to be able to reproduce this issue. Fixes: 1dc4c557bfed ("bnxt: adding bnxt_xdp_build_skb to build skb from multibuffer xdp_buff") Signed-off-by: Taehee Yoo Reviewed-by: Somnath Kotur Link: https://patch.msgid.link/20250309134219.91670-5-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 3 ++- drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 11 ++--------- drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h | 3 +-- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 218109ee1c23..9afb2c5072b1 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2218,7 +2218,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, if (!skb) goto oom_next_rx; } else { - skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1); + skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, + rxr->page_pool, &xdp); if (!skb) { /* we should be able to free the old skb here */ bnxt_xdp_buff_frags_free(rxr, &xdp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index e9b49cb5b735..299822cacca4 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -460,20 +460,13 @@ int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp) struct sk_buff * bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags, - struct page_pool *pool, struct xdp_buff *xdp, - struct rx_cmp_ext *rxcmp1) + struct page_pool *pool, struct xdp_buff *xdp) { struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); if (!skb) return NULL; - skb_checksum_none_assert(skb); - if (RX_CMP_L4_CS_OK(rxcmp1)) { - if (bp->dev->features & NETIF_F_RXCSUM) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->csum_level = RX_CMP_ENCAP(rxcmp1); - } - } + xdp_update_skb_shared_info(skb, num_frags, sinfo->xdp_frags_size, BNXT_RX_PAGE_SIZE * num_frags, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h index 0122782400b8..220285e190fc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h @@ -33,6 +33,5 @@ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, struct xdp_buff *xdp); struct sk_buff *bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags, struct page_pool *pool, - struct xdp_buff *xdp, - struct rx_cmp_ext *rxcmp1); + struct xdp_buff *xdp); #endif From f09af5fdfbd9b0fcee73aab1116904c53b199e97 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:16 +0000 Subject: [PATCH 0835/1090] eth: bnxt: fix kernel panic in the bnxt_get_queue_stats{rx | tx} When qstats-get operation is executed, callbacks of netdev_stats_ops are called. The bnxt_get_queue_stats{rx | tx} collect per-queue stats from sw_stats in the rings. But {rx | tx | cp}_ring are allocated when the interface is up. So, these rings are not allocated when the interface is down. The qstats-get is allowed even if the interface is down. However, the bnxt_get_queue_stats{rx | tx}() accesses cp_ring and tx_ring without null check. So, it needs to avoid accessing rings if the interface is down. Reproducer: ip link set $interface down ./cli.py --spec netdev.yaml --dump qstats-get OR ip link set $interface down python ./stats.py Splat looks like: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 1680fa067 P4D 1680fa067 PUD 16be3b067 PMD 0 Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 0 UID: 0 PID: 1495 Comm: python3 Not tainted 6.14.0-rc4+ #32 5cd0f999d5a15c574ac72b3e4b907341 Hardware name: ASUS System Product Name/PRIME Z690-P D4, BIOS 0603 11/01/2021 RIP: 0010:bnxt_get_queue_stats_rx+0xf/0x70 [bnxt_en] Code: c6 87 b5 18 00 00 02 eb a2 66 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 01 RSP: 0018:ffffabef43cdb7e0 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffffffffc04c8710 RCX: 0000000000000000 RDX: ffffabef43cdb858 RSI: 0000000000000000 RDI: ffff8d504e850000 RBP: ffff8d506c9f9c00 R08: 0000000000000004 R09: ffff8d506bcd901c R10: 0000000000000015 R11: ffff8d506bcd9000 R12: 0000000000000000 R13: ffffabef43cdb8c0 R14: ffff8d504e850000 R15: 0000000000000000 FS: 00007f2c5462b080(0000) GS:ffff8d575f600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000000167fd0000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: ? __die+0x20/0x70 ? page_fault_oops+0x15a/0x460 ? sched_balance_find_src_group+0x58d/0xd10 ? exc_page_fault+0x6e/0x180 ? asm_exc_page_fault+0x22/0x30 ? bnxt_get_queue_stats_rx+0xf/0x70 [bnxt_en cdd546fd48563c280cfd30e9647efa420db07bf1] netdev_nl_stats_by_netdev+0x2b1/0x4e0 ? xas_load+0x9/0xb0 ? xas_find+0x183/0x1d0 ? xa_find+0x8b/0xe0 netdev_nl_qstats_get_dumpit+0xbf/0x1e0 genl_dumpit+0x31/0x90 netlink_dump+0x1a8/0x360 Fixes: af7b3b4adda5 ("eth: bnxt: support per-queue statistics") Signed-off-by: Taehee Yoo Reviewed-by: Somnath Kotur Link: https://patch.msgid.link/20250309134219.91670-6-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 9afb2c5072b1..bee12d9b57ab 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -15384,6 +15384,9 @@ static void bnxt_get_queue_stats_rx(struct net_device *dev, int i, struct bnxt_cp_ring_info *cpr; u64 *sw; + if (!bp->bnapi) + return; + cpr = &bp->bnapi[i]->cp_ring; sw = cpr->stats.sw_stats; @@ -15407,6 +15410,9 @@ static void bnxt_get_queue_stats_tx(struct net_device *dev, int i, struct bnxt_napi *bnapi; u64 *sw; + if (!bp->tx_ring) + return; + bnapi = bp->tx_ring[bp->tx_ring_map[i]].bnapi; sw = bnapi->cp_ring.stats.sw_stats; From 87dd2850835dd7886726b428a8ef7d73a60520c7 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:17 +0000 Subject: [PATCH 0836/1090] eth: bnxt: fix memory leak in queue reset When the queue is reset, the bnxt_alloc_one_tpa_info() is called to allocate tpa_info for the new queue. And then the old queue's tpa_info should be removed by the bnxt_free_one_tpa_info(), but it is not called. So memory leak occurs. It adds the bnxt_free_one_tpa_info() in the bnxt_queue_mem_free(). unreferenced object 0xffff888293cc0000 (size 16384): comm "ncdevmem", pid 2076, jiffies 4296604081 hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 40 75 78 93 82 88 ff ff ........@ux..... 40 75 78 93 02 00 00 00 00 00 00 00 00 00 00 00 @ux............. backtrace (crc 5d7d4798): ___kmalloc_large_node+0x10d/0x1b0 __kmalloc_large_node_noprof+0x17/0x60 __kmalloc_noprof+0x3f6/0x520 bnxt_alloc_one_tpa_info+0x5f/0x300 [bnxt_en] bnxt_queue_mem_alloc+0x8e8/0x14f0 [bnxt_en] netdev_rx_queue_restart+0x233/0x620 net_devmem_bind_dmabuf_to_queue+0x2a3/0x600 netdev_nl_bind_rx_doit+0xc00/0x10a0 genl_family_rcv_msg_doit+0x1d4/0x2b0 genl_rcv_msg+0x3fb/0x6c0 netlink_rcv_skb+0x12c/0x360 genl_rcv+0x24/0x40 netlink_unicast+0x447/0x710 netlink_sendmsg+0x712/0xbc0 __sys_sendto+0x3fd/0x4d0 __x64_sys_sendto+0xdc/0x1b0 Fixes: 2d694c27d32e ("bnxt_en: implement netdev_queue_mgmt_ops") Signed-off-by: Taehee Yoo Link: https://patch.msgid.link/20250309134219.91670-7-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index bee12d9b57ab..55f553debd3b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -15539,6 +15539,7 @@ static void bnxt_queue_mem_free(struct net_device *dev, void *qmem) struct bnxt_ring_struct *ring; bnxt_free_one_rx_ring_skbs(bp, rxr); + bnxt_free_one_tpa_info(bp, rxr); xdp_rxq_info_unreg(&rxr->xdp_rxq); From a70f891e0fa0435379ad4950e156a15a4ef88b4d Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:18 +0000 Subject: [PATCH 0837/1090] net: devmem: do not WARN conditionally after netdev_rx_queue_restart() When devmem socket is closed, netdev_rx_queue_restart() is called to reset queue by the net_devmem_unbind_dmabuf(). But callback may return -ENETDOWN if the interface is down because queues are already freed when the interface is down so queue reset is not needed. So, it should not warn if the return value is -ENETDOWN. Signed-off-by: Taehee Yoo Reviewed-by: Mina Almasry Link: https://patch.msgid.link/20250309134219.91670-8-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- net/core/devmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/core/devmem.c b/net/core/devmem.c index 3bba3f018df0..0e5a2c672efd 100644 --- a/net/core/devmem.c +++ b/net/core/devmem.c @@ -109,6 +109,7 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding) struct netdev_rx_queue *rxq; unsigned long xa_idx; unsigned int rxq_idx; + int err; if (binding->list.next) list_del(&binding->list); @@ -120,7 +121,8 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding) rxq_idx = get_netdev_rx_queue_index(rxq); - WARN_ON(netdev_rx_queue_restart(binding->dev, rxq_idx)); + err = netdev_rx_queue_restart(binding->dev, rxq_idx); + WARN_ON(err && err != -ENETDOWN); } xa_erase(&net_devmem_dmabuf_bindings, binding->id); From 75cc19c8ff8932d7da23480a49d1f9a050289c37 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Sun, 9 Mar 2025 13:42:19 +0000 Subject: [PATCH 0838/1090] selftests: drv-net: add xdp cases for ping.py ping.py has 3 cases, test_v4, test_v6 and test_tcp. But these cases are not executed on the XDP environment. So, it adds XDP environment, existing tests(test_v4, test_v6, and test_tcp) are executed too on the below XDP environment. So, it adds XDP cases. 1. xdp-generic + single-buffer 2. xdp-generic + multi-buffer 3. xdp-native + single-buffer 4. xdp-native + multi-buffer 5. xdp-offload It also makes test_{v4 | v6 | tcp} sending large size packets. this may help to check whether multi-buffer is working or not. Note that the physical interface may be down and then up when xdp is attached or detached. This takes some period to activate traffic. So sleep(10) is added if the test interface is the physical interface. netdevsim and veth type interfaces skip sleep. Signed-off-by: Taehee Yoo Link: https://patch.msgid.link/20250309134219.91670-9-ap420073@gmail.com Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/ping.py | 198 ++++++++++++++++-- .../testing/selftests/net/lib/xdp_dummy.bpf.c | 6 + 2 files changed, 190 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py index eb83e7b48797..93f4b411b378 100755 --- a/tools/testing/selftests/drivers/net/ping.py +++ b/tools/testing/selftests/drivers/net/ping.py @@ -1,49 +1,219 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 +import os +import random, string, time from lib.py import ksft_run, ksft_exit -from lib.py import ksft_eq -from lib.py import NetDrvEpEnv +from lib.py import ksft_eq, KsftSkipEx, KsftFailEx +from lib.py import EthtoolFamily, NetDrvEpEnv from lib.py import bkg, cmd, wait_port_listen, rand_port +from lib.py import ethtool, ip +remote_ifname="" +no_sleep=False -def test_v4(cfg) -> None: +def _test_v4(cfg) -> None: cfg.require_v4() cmd(f"ping -c 1 -W0.5 {cfg.remote_v4}") cmd(f"ping -c 1 -W0.5 {cfg.v4}", host=cfg.remote) + cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v4}") + cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v4}", host=cfg.remote) - -def test_v6(cfg) -> None: +def _test_v6(cfg) -> None: cfg.require_v6() - cmd(f"ping -c 1 -W0.5 {cfg.remote_v6}") - cmd(f"ping -c 1 -W0.5 {cfg.v6}", host=cfg.remote) + cmd(f"ping -c 1 -W5 {cfg.remote_v6}") + cmd(f"ping -c 1 -W5 {cfg.v6}", host=cfg.remote) + cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.remote_v6}") + cmd(f"ping -s 65000 -c 1 -W0.5 {cfg.v6}", host=cfg.remote) - -def test_tcp(cfg) -> None: +def _test_tcp(cfg) -> None: cfg.require_cmd("socat", remote=True) port = rand_port() listen_cmd = f"socat -{cfg.addr_ipver} -t 2 -u TCP-LISTEN:{port},reuseport STDOUT" + test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536)) with bkg(listen_cmd, exit_wait=True) as nc: wait_port_listen(port) - cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}", + cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.baddr}:{port}", shell=True, host=cfg.remote) - ksft_eq(nc.stdout.strip(), "ping") + ksft_eq(nc.stdout.strip(), test_string) + test_string = ''.join(random.choice(string.ascii_lowercase) for _ in range(65536)) with bkg(listen_cmd, host=cfg.remote, exit_wait=True) as nc: wait_port_listen(port, host=cfg.remote) - cmd(f"echo ping | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True) - ksft_eq(nc.stdout.strip(), "ping") + cmd(f"echo {test_string} | socat -t 2 -u STDIN TCP:{cfg.remote_baddr}:{port}", shell=True) + ksft_eq(nc.stdout.strip(), test_string) +def _set_offload_checksum(cfg, netnl, on) -> None: + try: + ethtool(f" -K {cfg.ifname} rx {on} tx {on} ") + except: + return + +def _set_xdp_generic_sb_on(cfg) -> None: + test_dir = os.path.dirname(os.path.realpath(__file__)) + prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) + cmd(f"ip link set dev {cfg.ifname} mtu 1500 xdpgeneric obj {prog} sec xdp", shell=True) + + if no_sleep != True: + time.sleep(10) + +def _set_xdp_generic_mb_on(cfg) -> None: + test_dir = os.path.dirname(os.path.realpath(__file__)) + prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote) + ip("link set dev %s mtu 9000 xdpgeneric obj %s sec xdp.frags" % (cfg.ifname, prog)) + + if no_sleep != True: + time.sleep(10) + +def _set_xdp_native_sb_on(cfg) -> None: + test_dir = os.path.dirname(os.path.realpath(__file__)) + prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) + cmd(f"ip -j link set dev {cfg.ifname} mtu 1500 xdp obj {prog} sec xdp", shell=True) + xdp_info = ip("-d link show %s" % (cfg.ifname), json=True)[0] + if xdp_info['xdp']['mode'] != 1: + """ + If the interface doesn't support native-mode, it falls back to generic mode. + The mode value 1 is native and 2 is generic. + So it raises an exception if mode is not 1(native mode). + """ + raise KsftSkipEx('device does not support native-XDP') + + if no_sleep != True: + time.sleep(10) + +def _set_xdp_native_mb_on(cfg) -> None: + test_dir = os.path.dirname(os.path.realpath(__file__)) + prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + cmd(f"ip link set dev {remote_ifname} mtu 9000", shell=True, host=cfg.remote) + try: + cmd(f"ip link set dev {cfg.ifname} mtu 9000 xdp obj {prog} sec xdp.frags", shell=True) + except Exception as e: + cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) + raise KsftSkipEx('device does not support native-multi-buffer XDP') + + if no_sleep != True: + time.sleep(10) + +def _set_xdp_offload_on(cfg) -> None: + test_dir = os.path.dirname(os.path.realpath(__file__)) + prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o" + cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True) + try: + cmd(f"ip link set dev {cfg.ifname} xdpoffload obj {prog} sec xdp", shell=True) + except Exception as e: + raise KsftSkipEx('device does not support offloaded XDP') + cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) + + if no_sleep != True: + time.sleep(10) + +def get_interface_info(cfg) -> None: + global remote_ifname + global no_sleep + + remote_info = cmd(f"ip -4 -o addr show to {cfg.remote_v4} | awk '{{print $2}}'", shell=True, host=cfg.remote).stdout + remote_ifname = remote_info.rstrip('\n') + if remote_ifname == "": + raise KsftFailEx('Can not get remote interface') + local_info = ip("-d link show %s" % (cfg.ifname), json=True)[0] + if 'parentbus' in local_info and local_info['parentbus'] == "netdevsim": + no_sleep=True + if 'linkinfo' in local_info and local_info['linkinfo']['info_kind'] == "veth": + no_sleep=True + +def set_interface_init(cfg) -> None: + cmd(f"ip link set dev {cfg.ifname} mtu 1500", shell=True) + cmd(f"ip link set dev {cfg.ifname} xdp off ", shell=True) + cmd(f"ip link set dev {cfg.ifname} xdpgeneric off ", shell=True) + cmd(f"ip link set dev {cfg.ifname} xdpoffload off", shell=True) + cmd(f"ip link set dev {remote_ifname} mtu 1500", shell=True, host=cfg.remote) + +def test_default(cfg, netnl) -> None: + _set_offload_checksum(cfg, netnl, "off") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + _set_offload_checksum(cfg, netnl, "on") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + +def test_xdp_generic_sb(cfg, netnl) -> None: + _set_xdp_generic_sb_on(cfg) + _set_offload_checksum(cfg, netnl, "off") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + _set_offload_checksum(cfg, netnl, "on") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + ip("link set dev %s xdpgeneric off" % cfg.ifname) + +def test_xdp_generic_mb(cfg, netnl) -> None: + _set_xdp_generic_mb_on(cfg) + _set_offload_checksum(cfg, netnl, "off") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + _set_offload_checksum(cfg, netnl, "on") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + ip("link set dev %s xdpgeneric off" % cfg.ifname) + +def test_xdp_native_sb(cfg, netnl) -> None: + _set_xdp_native_sb_on(cfg) + _set_offload_checksum(cfg, netnl, "off") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + _set_offload_checksum(cfg, netnl, "on") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + ip("link set dev %s xdp off" % cfg.ifname) + +def test_xdp_native_mb(cfg, netnl) -> None: + _set_xdp_native_mb_on(cfg) + _set_offload_checksum(cfg, netnl, "off") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + _set_offload_checksum(cfg, netnl, "on") + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + ip("link set dev %s xdp off" % cfg.ifname) + +def test_xdp_offload(cfg, netnl) -> None: + _set_xdp_offload_on(cfg) + _test_v4(cfg) + _test_v6(cfg) + _test_tcp(cfg) + ip("link set dev %s xdpoffload off" % cfg.ifname) def main() -> None: with NetDrvEpEnv(__file__) as cfg: - ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, )) + get_interface_info(cfg) + set_interface_init(cfg) + ksft_run([test_default, + test_xdp_generic_sb, + test_xdp_generic_mb, + test_xdp_native_sb, + test_xdp_native_mb, + test_xdp_offload], + args=(cfg, EthtoolFamily())) + set_interface_init(cfg) ksft_exit() diff --git a/tools/testing/selftests/net/lib/xdp_dummy.bpf.c b/tools/testing/selftests/net/lib/xdp_dummy.bpf.c index d988b2e0cee8..e73fab3edd9f 100644 --- a/tools/testing/selftests/net/lib/xdp_dummy.bpf.c +++ b/tools/testing/selftests/net/lib/xdp_dummy.bpf.c @@ -10,4 +10,10 @@ int xdp_dummy_prog(struct xdp_md *ctx) return XDP_PASS; } +SEC("xdp.frags") +int xdp_dummy_prog_frags(struct xdp_md *ctx) +{ + return XDP_PASS; +} + char _license[] SEC("license") = "GPL"; From 77b2ab31fc65c595ca0a339f6c5b8ef3adfae5c6 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Fri, 7 Mar 2025 15:47:31 +0000 Subject: [PATCH 0839/1090] MAINTAINERS: sfc: remove Martin Habets Martin has left AMD and no longer works on the sfc driver. Signed-off-by: Edward Cree Link: https://patch.msgid.link/20250307154731.211368-1-edward.cree@amd.com Signed-off-by: Jakub Kicinski --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ca11a553d412..07b2d3c7ae5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21502,7 +21502,6 @@ F: include/linux/slimbus.h SFC NETWORK DRIVER M: Edward Cree -M: Martin Habets L: netdev@vger.kernel.org L: linux-net-drivers@amd.com S: Maintained From 12d8f318347b1d4feac48e8ac351d3786af39599 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 7 Mar 2025 20:31:52 +0200 Subject: [PATCH 0840/1090] drm/dp_mst: Fix locking when skipping CSN before topology probing The handling of the MST Connection Status Notify message is skipped if the probing of the topology is still pending. Acquiring the drm_dp_mst_topology_mgr::probe_lock for this in drm_dp_mst_handle_up_req() is problematic: the task/work this function is called from is also responsible for handling MST down-request replies (in drm_dp_mst_handle_down_rep()). Thus drm_dp_mst_link_probe_work() - holding already probe_lock - could be blocked waiting for an MST down-request reply while drm_dp_mst_handle_up_req() is waiting for probe_lock while processing a CSN message. This leads to the probe work's down-request message timing out. A scenario similar to the above leading to a down-request timeout is handling a CSN message in drm_dp_mst_handle_conn_stat(), holding the probe_lock and sending down-request messages while a second CSN message sent by the sink subsequently is handled by drm_dp_mst_handle_up_req(). Fix the above by moving the logic to skip the CSN handling to drm_dp_mst_process_up_req(). This function is called from a work (separate from the task/work handling new up/down messages), already holding probe_lock. This solves the above timeout issue, since handling of down-request replies won't be blocked by probe_lock. Fixes: ddf983488c3e ("drm/dp_mst: Skip CSN if topology probing is not done yet") Cc: Wayne Lin Cc: Lyude Paul Cc: stable@vger.kernel.org # v6.6+ Reviewed-by: Wayne Lin Reviewed-by: Lyude Paul Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20250307183152.3822170-1-imre.deak@intel.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 06c91c5b7f7c..6d09bef671da 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4025,6 +4025,22 @@ out: return 0; } +static bool primary_mstb_probing_is_done(struct drm_dp_mst_topology_mgr *mgr) +{ + bool probing_done = false; + + mutex_lock(&mgr->lock); + + if (mgr->mst_primary && drm_dp_mst_topology_try_get_mstb(mgr->mst_primary)) { + probing_done = mgr->mst_primary->link_address_sent; + drm_dp_mst_topology_put_mstb(mgr->mst_primary); + } + + mutex_unlock(&mgr->lock); + + return probing_done; +} + static inline bool drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_pending_up_req *up_req) @@ -4055,8 +4071,12 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr, /* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */ if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) { - dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat); - hotplug = true; + if (!primary_mstb_probing_is_done(mgr)) { + drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.\n"); + } else { + dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat); + hotplug = true; + } } drm_dp_mst_topology_put_mstb(mstb); @@ -4138,10 +4158,11 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type, false); + drm_dp_mst_topology_put_mstb(mst_primary); + if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { const struct drm_dp_connection_status_notify *conn_stat = &up_req->msg.u.conn_stat; - bool handle_csn; drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", conn_stat->port_number, @@ -4150,16 +4171,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) conn_stat->message_capability_status, conn_stat->input_port, conn_stat->peer_device_type); - - mutex_lock(&mgr->probe_lock); - handle_csn = mst_primary->link_address_sent; - mutex_unlock(&mgr->probe_lock); - - if (!handle_csn) { - drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it."); - kfree(up_req); - goto out_put_primary; - } } else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { const struct drm_dp_resource_status_notify *res_stat = &up_req->msg.u.resource_stat; @@ -4174,9 +4185,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) list_add_tail(&up_req->next, &mgr->up_req_list); mutex_unlock(&mgr->up_req_lock); queue_work(system_long_wq, &mgr->up_req_work); - -out_put_primary: - drm_dp_mst_topology_put_mstb(mst_primary); out_clear_reply: reset_msg_rx_state(&mgr->up_req_recv); return ret; From 62531a1effa87bdab12d5104015af72e60d926ff Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Wed, 5 Mar 2025 14:15:09 +0200 Subject: [PATCH 0841/1090] net: switchdev: Convert blocking notification chain to a raw one A blocking notification chain uses a read-write semaphore to protect the integrity of the chain. The semaphore is acquired for writing when adding / removing notifiers to / from the chain and acquired for reading when traversing the chain and informing notifiers about an event. In case of the blocking switchdev notification chain, recursive notifications are possible which leads to the semaphore being acquired twice for reading and to lockdep warnings being generated [1]. Specifically, this can happen when the bridge driver processes a SWITCHDEV_BRPORT_UNOFFLOADED event which causes it to emit notifications about deferred events when calling switchdev_deferred_process(). Fix this by converting the notification chain to a raw notification chain in a similar fashion to the netdev notification chain. Protect the chain using the RTNL mutex by acquiring it when modifying the chain. Events are always informed under the RTNL mutex, but add an assertion in call_switchdev_blocking_notifiers() to make sure this is not violated in the future. Maintain the "blocking" prefix as events are always emitted from process context and listeners are allowed to block. [1]: WARNING: possible recursive locking detected 6.14.0-rc4-custom-g079270089484 #1 Not tainted -------------------------------------------- ip/52731 is trying to acquire lock: ffffffff850918d8 ((switchdev_blocking_notif_chain).rwsem){++++}-{4:4}, at: blocking_notifier_call_chain+0x58/0xa0 but task is already holding lock: ffffffff850918d8 ((switchdev_blocking_notif_chain).rwsem){++++}-{4:4}, at: blocking_notifier_call_chain+0x58/0xa0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock((switchdev_blocking_notif_chain).rwsem); lock((switchdev_blocking_notif_chain).rwsem); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by ip/52731: #0: ffffffff84f795b0 (rtnl_mutex){+.+.}-{4:4}, at: rtnl_newlink+0x727/0x1dc0 #1: ffffffff8731f628 (&net->rtnl_mutex){+.+.}-{4:4}, at: rtnl_newlink+0x790/0x1dc0 #2: ffffffff850918d8 ((switchdev_blocking_notif_chain).rwsem){++++}-{4:4}, at: blocking_notifier_call_chain+0x58/0xa0 stack backtrace: ... ? __pfx_down_read+0x10/0x10 ? __pfx_mark_lock+0x10/0x10 ? __pfx_switchdev_port_attr_set_deferred+0x10/0x10 blocking_notifier_call_chain+0x58/0xa0 switchdev_port_attr_notify.constprop.0+0xb3/0x1b0 ? __pfx_switchdev_port_attr_notify.constprop.0+0x10/0x10 ? mark_held_locks+0x94/0xe0 ? switchdev_deferred_process+0x11a/0x340 switchdev_port_attr_set_deferred+0x27/0xd0 switchdev_deferred_process+0x164/0x340 br_switchdev_port_unoffload+0xc8/0x100 [bridge] br_switchdev_blocking_event+0x29f/0x580 [bridge] notifier_call_chain+0xa2/0x440 blocking_notifier_call_chain+0x6e/0xa0 switchdev_bridge_port_unoffload+0xde/0x1a0 ... Fixes: f7a70d650b0b6 ("net: bridge: switchdev: Ensure deferred event delivery on unoffload") Signed-off-by: Amit Cohen Reviewed-by: Ido Schimmel Reviewed-by: Simon Horman Reviewed-by: Vladimir Oltean Tested-by: Vladimir Oltean Link: https://patch.msgid.link/20250305121509.631207-1-amcohen@nvidia.com Signed-off-by: Paolo Abeni --- net/switchdev/switchdev.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 6488ead9e464..4d5fbacef496 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -472,7 +472,7 @@ bool switchdev_port_obj_act_is_deferred(struct net_device *dev, EXPORT_SYMBOL_GPL(switchdev_port_obj_act_is_deferred); static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain); -static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain); +static RAW_NOTIFIER_HEAD(switchdev_blocking_notif_chain); /** * register_switchdev_notifier - Register notifier @@ -518,17 +518,27 @@ EXPORT_SYMBOL_GPL(call_switchdev_notifiers); int register_switchdev_blocking_notifier(struct notifier_block *nb) { - struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain; + struct raw_notifier_head *chain = &switchdev_blocking_notif_chain; + int err; - return blocking_notifier_chain_register(chain, nb); + rtnl_lock(); + err = raw_notifier_chain_register(chain, nb); + rtnl_unlock(); + + return err; } EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier); int unregister_switchdev_blocking_notifier(struct notifier_block *nb) { - struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain; + struct raw_notifier_head *chain = &switchdev_blocking_notif_chain; + int err; - return blocking_notifier_chain_unregister(chain, nb); + rtnl_lock(); + err = raw_notifier_chain_unregister(chain, nb); + rtnl_unlock(); + + return err; } EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier); @@ -536,10 +546,11 @@ int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev, struct switchdev_notifier_info *info, struct netlink_ext_ack *extack) { + ASSERT_RTNL(); info->dev = dev; info->extack = extack; - return blocking_notifier_call_chain(&switchdev_blocking_notif_chain, - val, info); + return raw_notifier_call_chain(&switchdev_blocking_notif_chain, + val, info); } EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); From d4234d131b0a3f9e65973f1cdc71bb3560f5d14b Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Tue, 4 Mar 2025 15:27:00 +0800 Subject: [PATCH 0842/1090] arm64: mm: Populate vmemmap at the page level if not section aligned On the arm64 platform with 4K base page config, SECTION_SIZE_BITS is set to 27, making one section 128M. The related page struct which vmemmap points to is 2M then. Commit c1cc1552616d ("arm64: MMU initialisation") optimizes the vmemmap to populate at the PMD section level which was suitable initially since hot plug granule is always one section(128M). However, commit ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug") introduced a 2M(SUBSECTION_SIZE) hot plug granule, which disrupted the existing arm64 assumptions. The first problem is that if start or end is not aligned to a section boundary, such as when a subsection is hot added, populating the entire section is wasteful. The next problem is if we hotplug something that spans part of 128 MiB section (subsections, let's call it memblock1), and then hotplug something that spans another part of a 128 MiB section(subsections, let's call it memblock2), and subsequently unplug memblock1, vmemmap_free() will clear the entire PMD entry which also supports memblock2 even though memblock2 is still active. Assuming hotplug/unplug sizes are guaranteed to be symmetric. Do the fix similar to x86-64: populate to pages levels if start/end is not aligned with section boundary. Cc: stable@vger.kernel.org # v5.4+ Fixes: ba72b4c8cf60 ("mm/sparsemem: support sub-section hotplug") Acked-by: David Hildenbrand Signed-off-by: Zhenhua Huang Reviewed-by: Oscar Salvador Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20250304072700.3405036-1-quic_zhenhuah@quicinc.com Signed-off-by: Will Deacon --- arch/arm64/mm/mmu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b4df5bc5b1b8..1dfe1a8efdbe 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1177,8 +1177,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap) { WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END)); + /* [start, end] should be within one section */ + WARN_ON_ONCE(end - start > PAGES_PER_SECTION * sizeof(struct page)); - if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES)) + if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES) || + (end - start < PAGES_PER_SECTION * sizeof(struct page))) return vmemmap_populate_basepages(start, end, node, altmap); else return vmemmap_populate_hugepages(start, end, node, altmap); From f7edb07ad7c66eab3dce57384f33b9799d579133 Mon Sep 17 00:00:00 2001 From: Piotr Jaroszynski Date: Tue, 4 Mar 2025 00:51:27 -0800 Subject: [PATCH 0843/1090] Fix mmu notifiers for range-based invalidates Update the __flush_tlb_range_op macro not to modify its parameters as these are unexepcted semantics. In practice, this fixes the call to mmu_notifier_arch_invalidate_secondary_tlbs() in __flush_tlb_range_nosync() to use the correct range instead of an empty range with start=end. The empty range was (un)lucky as it results in taking the invalidate-all path that doesn't cause correctness issues, but can certainly result in suboptimal perf. This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs") when the call to the notifiers was added to __flush_tlb_range(). It predates the addition of the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range") that made the bug hard to spot. Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs") Signed-off-by: Piotr Jaroszynski Cc: Catalin Marinas Cc: Will Deacon Cc: Robin Murphy Cc: Alistair Popple Cc: Raghavendra Rao Ananta Cc: SeongJae Park Cc: Jason Gunthorpe Cc: John Hubbard Cc: Nicolin Chen Cc: linux-arm-kernel@lists.infradead.org Cc: iommu@lists.linux.dev Cc: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Reviewed-by: Catalin Marinas Reviewed-by: Alistair Popple Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski@nvidia.com Signed-off-by: Will Deacon --- arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index bc94e036a26b..8104aee4f9a0 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -396,33 +396,35 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) #define __flush_tlb_range_op(op, start, pages, stride, \ asid, tlb_level, tlbi_user, lpa2) \ do { \ + typeof(start) __flush_start = start; \ + typeof(pages) __flush_pages = pages; \ int num = 0; \ int scale = 3; \ int shift = lpa2 ? 16 : PAGE_SHIFT; \ unsigned long addr; \ \ - while (pages > 0) { \ + while (__flush_pages > 0) { \ if (!system_supports_tlb_range() || \ - pages == 1 || \ - (lpa2 && start != ALIGN(start, SZ_64K))) { \ - addr = __TLBI_VADDR(start, asid); \ + __flush_pages == 1 || \ + (lpa2 && __flush_start != ALIGN(__flush_start, SZ_64K))) { \ + addr = __TLBI_VADDR(__flush_start, asid); \ __tlbi_level(op, addr, tlb_level); \ if (tlbi_user) \ __tlbi_user_level(op, addr, tlb_level); \ - start += stride; \ - pages -= stride >> PAGE_SHIFT; \ + __flush_start += stride; \ + __flush_pages -= stride >> PAGE_SHIFT; \ continue; \ } \ \ - num = __TLBI_RANGE_NUM(pages, scale); \ + num = __TLBI_RANGE_NUM(__flush_pages, scale); \ if (num >= 0) { \ - addr = __TLBI_VADDR_RANGE(start >> shift, asid, \ + addr = __TLBI_VADDR_RANGE(__flush_start >> shift, asid, \ scale, num, tlb_level); \ __tlbi(r##op, addr); \ if (tlbi_user) \ __tlbi_user(r##op, addr); \ - start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ - pages -= __TLBI_RANGE_PAGES(num, scale); \ + __flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ + __flush_pages -= __TLBI_RANGE_PAGES(num, scale);\ } \ scale--; \ } \ From 986a6f5eacb900ea0f6036ef724b26e76be40f65 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 10 Mar 2025 15:25:31 -0700 Subject: [PATCH 0844/1090] vboxsf: Add __nonstring annotations for unterminated strings When a character array without a terminating NUL character has a static initializer, GCC 15's -Wunterminated-string-initialization will only warn if the array lacks the "nonstring" attribute[1]. Mark the arrays with __nonstring to and correctly identify the char array as "not a C string" and thereby eliminate the warning. This effectively reverts the change in 4e7487245abc ("vboxsf: fix building with GCC 15"), to add the annotation that has other uses (i.e. warning if the string is ever used with C string APIs). Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] Cc: Hans de Goede Cc: Brahmajit Das Cc: Christian Brauner Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20250310222530.work.374-kees@kernel.org Reviewed-by: Hans de Goede Signed-off-by: Christian Brauner --- fs/vboxsf/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c index 1d94bb784108..0bc96ab6580b 100644 --- a/fs/vboxsf/super.c +++ b/fs/vboxsf/super.c @@ -21,8 +21,7 @@ #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ -static const unsigned char VBSF_MOUNT_SIGNATURE[4] = { '\000', '\377', '\376', - '\375' }; +static const unsigned char VBSF_MOUNT_SIGNATURE[4] __nonstring = "\000\377\376\375"; static int follow_symlinks; module_param(follow_symlinks, int, 0444); From f5d83cf0eeb90fade4d5c4d17d24b8bee9ceeecc Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 6 Mar 2025 10:32:45 +0800 Subject: [PATCH 0845/1090] net: mctp: unshare packets when reassembling Ensure that the frag_list used for reassembly isn't shared with other packets. This avoids incorrect reassembly when packets are cloned, and prevents a memory leak due to circular references between fragments and their skb_shared_info. The upcoming MCTP-over-USB driver uses skb_clone which can trigger the problem - other MCTP drivers don't share SKBs. A kunit test is added to reproduce the issue. Signed-off-by: Matt Johnston Fixes: 4a992bbd3650 ("mctp: Implement message fragmentation & reassembly") Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306-matt-mctp-usb-v1-1-085502b3dd28@codeconstruct.com.au Signed-off-by: Paolo Abeni --- net/mctp/route.c | 10 +++- net/mctp/test/route-test.c | 109 +++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/net/mctp/route.c b/net/mctp/route.c index 3f2bd65ff5e3..4c460160914f 100644 --- a/net/mctp/route.c +++ b/net/mctp/route.c @@ -332,8 +332,14 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb) & MCTP_HDR_SEQ_MASK; if (!key->reasm_head) { - key->reasm_head = skb; - key->reasm_tailp = &(skb_shinfo(skb)->frag_list); + /* Since we're manipulating the shared frag_list, ensure it isn't + * shared with any other SKBs. + */ + key->reasm_head = skb_unshare(skb, GFP_ATOMIC); + if (!key->reasm_head) + return -ENOMEM; + + key->reasm_tailp = &(skb_shinfo(key->reasm_head)->frag_list); key->last_seq = this_seq; return 0; } diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c index 17165b86ce22..06c1897b685a 100644 --- a/net/mctp/test/route-test.c +++ b/net/mctp/test/route-test.c @@ -921,6 +921,114 @@ static void mctp_test_route_input_sk_fail_frag(struct kunit *test) __mctp_route_test_fini(test, dev, rt, sock); } +/* Input route to socket, using a fragmented message created from clones. + */ +static void mctp_test_route_input_cloned_frag(struct kunit *test) +{ + /* 5 packet fragments, forming 2 complete messages */ + const struct mctp_hdr hdrs[5] = { + RX_FRAG(FL_S, 0), + RX_FRAG(0, 1), + RX_FRAG(FL_E, 2), + RX_FRAG(FL_S, 0), + RX_FRAG(FL_E, 1), + }; + struct mctp_test_route *rt; + struct mctp_test_dev *dev; + struct sk_buff *skb[5]; + struct sk_buff *rx_skb; + struct socket *sock; + size_t data_len; + u8 compare[100]; + u8 flat[100]; + size_t total; + void *p; + int rc; + + /* Arbitrary length */ + data_len = 3; + total = data_len + sizeof(struct mctp_hdr); + + __mctp_route_test_init(test, &dev, &rt, &sock, MCTP_NET_ANY); + + /* Create a single skb initially with concatenated packets */ + skb[0] = mctp_test_create_skb(&hdrs[0], 5 * total); + mctp_test_skb_set_dev(skb[0], dev); + memset(skb[0]->data, 0 * 0x11, skb[0]->len); + memcpy(skb[0]->data, &hdrs[0], sizeof(struct mctp_hdr)); + + /* Extract and populate packets */ + for (int i = 1; i < 5; i++) { + skb[i] = skb_clone(skb[i - 1], GFP_ATOMIC); + KUNIT_ASSERT_TRUE(test, skb[i]); + p = skb_pull(skb[i], total); + KUNIT_ASSERT_TRUE(test, p); + skb_reset_network_header(skb[i]); + memcpy(skb[i]->data, &hdrs[i], sizeof(struct mctp_hdr)); + memset(&skb[i]->data[sizeof(struct mctp_hdr)], i * 0x11, data_len); + } + for (int i = 0; i < 5; i++) + skb_trim(skb[i], total); + + /* SOM packets have a type byte to match the socket */ + skb[0]->data[4] = 0; + skb[3]->data[4] = 0; + + skb_dump("pkt1 ", skb[0], false); + skb_dump("pkt2 ", skb[1], false); + skb_dump("pkt3 ", skb[2], false); + skb_dump("pkt4 ", skb[3], false); + skb_dump("pkt5 ", skb[4], false); + + for (int i = 0; i < 5; i++) { + KUNIT_EXPECT_EQ(test, refcount_read(&skb[i]->users), 1); + /* Take a reference so we can check refcounts at the end */ + skb_get(skb[i]); + } + + /* Feed the fragments into MCTP core */ + for (int i = 0; i < 5; i++) { + rc = mctp_route_input(&rt->rt, skb[i]); + KUNIT_EXPECT_EQ(test, rc, 0); + } + + /* Receive first reassembled message */ + rx_skb = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, rx_skb->len, 3 * data_len); + rc = skb_copy_bits(rx_skb, 0, flat, rx_skb->len); + for (int i = 0; i < rx_skb->len; i++) + compare[i] = (i / data_len) * 0x11; + /* Set type byte */ + compare[0] = 0; + + KUNIT_EXPECT_MEMEQ(test, flat, compare, rx_skb->len); + KUNIT_EXPECT_EQ(test, refcount_read(&rx_skb->users), 1); + kfree_skb(rx_skb); + + /* Receive second reassembled message */ + rx_skb = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc); + KUNIT_EXPECT_EQ(test, rc, 0); + KUNIT_EXPECT_EQ(test, rx_skb->len, 2 * data_len); + rc = skb_copy_bits(rx_skb, 0, flat, rx_skb->len); + for (int i = 0; i < rx_skb->len; i++) + compare[i] = (i / data_len + 3) * 0x11; + /* Set type byte */ + compare[0] = 0; + + KUNIT_EXPECT_MEMEQ(test, flat, compare, rx_skb->len); + KUNIT_EXPECT_EQ(test, refcount_read(&rx_skb->users), 1); + kfree_skb(rx_skb); + + /* Check input skb refcounts */ + for (int i = 0; i < 5; i++) { + KUNIT_EXPECT_EQ(test, refcount_read(&skb[i]->users), 1); + kfree_skb(skb[i]); + } + + __mctp_route_test_fini(test, dev, rt, sock); +} + #if IS_ENABLED(CONFIG_MCTP_FLOWS) static void mctp_test_flow_init(struct kunit *test, @@ -1144,6 +1252,7 @@ static struct kunit_case mctp_test_cases[] = { KUNIT_CASE(mctp_test_packet_flow), KUNIT_CASE(mctp_test_fragment_flow), KUNIT_CASE(mctp_test_route_output_key_create), + KUNIT_CASE(mctp_test_route_input_cloned_frag), {} }; From 0c5e145a350de3b38cd5ae77a401b12c46fb7c1d Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 6 Mar 2025 02:39:22 +0000 Subject: [PATCH 0846/1090] bonding: fix incorrect MAC address setting to receive NS messages When validation on the backup slave is enabled, we need to validate the Neighbor Solicitation (NS) messages received on the backup slave. To receive these messages, the correct destination MAC address must be added to the slave. However, the target in bonding is a unicast address, which we cannot use directly. Instead, we should first convert it to a Solicited-Node Multicast Address and then derive the corresponding MAC address. Fix the incorrect MAC address setting on both slave_set_ns_maddr() and slave_set_ns_maddrs(). Since the two function names are similar. Add some description for the functions. Also only use one mac_addr variable in slave_set_ns_maddr() to save some code and logic. Fixes: 8eb36164d1a6 ("bonding: add ns target multicast address to slave device") Acked-by: Jay Vosburgh Reviewed-by: Nikolay Aleksandrov Signed-off-by: Hangbin Liu Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306023923.38777-2-liuhangbin@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/bonding/bond_options.c | 55 +++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 327b6ecdc77e..d1b095af253b 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1242,10 +1242,28 @@ static bool slave_can_set_ns_maddr(const struct bonding *bond, struct slave *sla slave->dev->flags & IFF_MULTICAST; } +/** + * slave_set_ns_maddrs - add/del all NS mac addresses for slave + * @bond: bond device + * @slave: slave device + * @add: add or remove all the NS mac addresses + * + * This function tries to add or delete all the NS mac addresses on the slave + * + * Note, the IPv6 NS target address is the unicast address in Neighbor + * Solicitation (NS) message. The dest address of NS message should be + * solicited-node multicast address of the target. The dest mac of NS message + * is converted from the solicited-node multicast address. + * + * This function is called when + * * arp_validate changes + * * enslaving, releasing new slaves + */ static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool add) { struct in6_addr *targets = bond->params.ns_targets; char slot_maddr[MAX_ADDR_LEN]; + struct in6_addr mcaddr; int i; if (!slave_can_set_ns_maddr(bond, slave)) @@ -1255,7 +1273,8 @@ static void slave_set_ns_maddrs(struct bonding *bond, struct slave *slave, bool if (ipv6_addr_any(&targets[i])) break; - if (!ndisc_mc_map(&targets[i], slot_maddr, slave->dev, 0)) { + addrconf_addr_solict_mult(&targets[i], &mcaddr); + if (!ndisc_mc_map(&mcaddr, slot_maddr, slave->dev, 0)) { if (add) dev_mc_add(slave->dev, slot_maddr); else @@ -1278,23 +1297,43 @@ void bond_slave_ns_maddrs_del(struct bonding *bond, struct slave *slave) slave_set_ns_maddrs(bond, slave, false); } +/** + * slave_set_ns_maddr - set new NS mac address for slave + * @bond: bond device + * @slave: slave device + * @target: the new IPv6 target + * @slot: the old IPv6 target in the slot + * + * This function tries to replace the old mac address to new one on the slave. + * + * Note, the target/slot IPv6 address is the unicast address in Neighbor + * Solicitation (NS) message. The dest address of NS message should be + * solicited-node multicast address of the target. The dest mac of NS message + * is converted from the solicited-node multicast address. + * + * This function is called when + * * An IPv6 NS target is added or removed. + */ static void slave_set_ns_maddr(struct bonding *bond, struct slave *slave, struct in6_addr *target, struct in6_addr *slot) { - char target_maddr[MAX_ADDR_LEN], slot_maddr[MAX_ADDR_LEN]; + char mac_addr[MAX_ADDR_LEN]; + struct in6_addr mcast_addr; if (!bond->params.arp_validate || !slave_can_set_ns_maddr(bond, slave)) return; - /* remove the previous maddr from slave */ + /* remove the previous mac addr from slave */ + addrconf_addr_solict_mult(slot, &mcast_addr); if (!ipv6_addr_any(slot) && - !ndisc_mc_map(slot, slot_maddr, slave->dev, 0)) - dev_mc_del(slave->dev, slot_maddr); + !ndisc_mc_map(&mcast_addr, mac_addr, slave->dev, 0)) + dev_mc_del(slave->dev, mac_addr); - /* add new maddr on slave if target is set */ + /* add new mac addr on slave if target is set */ + addrconf_addr_solict_mult(target, &mcast_addr); if (!ipv6_addr_any(target) && - !ndisc_mc_map(target, target_maddr, slave->dev, 0)) - dev_mc_add(slave->dev, target_maddr); + !ndisc_mc_map(&mcast_addr, mac_addr, slave->dev, 0)) + dev_mc_add(slave->dev, mac_addr); } static void _bond_options_ns_ip6_target_set(struct bonding *bond, int slot, From 9318dc2357b6b8b2ea1200ab7f2d5877851b7382 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 6 Mar 2025 02:39:23 +0000 Subject: [PATCH 0847/1090] selftests: bonding: fix incorrect mac address The correct mac address for NS target 2001:db8::254 is 33:33:ff:00:02:54, not 33:33:00:00:02:54. The same with client maddress. Fixes: 86fb6173d11e ("selftests: bonding: add ns multicast group testing") Acked-by: Jay Vosburgh Reviewed-by: Nikolay Aleksandrov Signed-off-by: Hangbin Liu Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306023923.38777-3-liuhangbin@gmail.com Signed-off-by: Paolo Abeni --- tools/testing/selftests/drivers/net/bonding/bond_options.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/bonding/bond_options.sh b/tools/testing/selftests/drivers/net/bonding/bond_options.sh index edc56e2cc606..7bc148889ca7 100755 --- a/tools/testing/selftests/drivers/net/bonding/bond_options.sh +++ b/tools/testing/selftests/drivers/net/bonding/bond_options.sh @@ -11,8 +11,8 @@ ALL_TESTS=" lib_dir=$(dirname "$0") source ${lib_dir}/bond_topo_3d1c.sh -c_maddr="33:33:00:00:00:10" -g_maddr="33:33:00:00:02:54" +c_maddr="33:33:ff:00:00:10" +g_maddr="33:33:ff:00:02:54" skip_prio() { From 415f135ace7fd824cde083184a922e39156055b5 Mon Sep 17 00:00:00 2001 From: Justin Lai Date: Thu, 6 Mar 2025 15:05:10 +0800 Subject: [PATCH 0848/1090] rtase: Fix improper release of ring list entries in rtase_sw_reset Since rtase_init_ring, which is called within rtase_sw_reset, adds ring entries already present in the ring list back into the list, it causes the ring list to form a cycle. This results in list_for_each_entry_safe failing to find an endpoint during traversal, leading to an error. Therefore, it is necessary to remove the previously added ring_list nodes before calling rtase_init_ring. Fixes: 079600489960 ("rtase: Implement net_device_ops") Signed-off-by: Justin Lai Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306070510.18129-1-justinlai0215@realtek.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/realtek/rtase/rtase_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c index 3bd11cb56294..2aacc1996796 100644 --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c @@ -1501,7 +1501,10 @@ static void rtase_wait_for_quiescence(const struct net_device *dev) static void rtase_sw_reset(struct net_device *dev) { struct rtase_private *tp = netdev_priv(dev); + struct rtase_ring *ring, *tmp; + struct rtase_int_vector *ivec; int ret; + u32 i; netif_stop_queue(dev); netif_carrier_off(dev); @@ -1512,6 +1515,13 @@ static void rtase_sw_reset(struct net_device *dev) rtase_tx_clear(tp); rtase_rx_clear(tp); + for (i = 0; i < tp->int_nums; i++) { + ivec = &tp->int_vector[i]; + list_for_each_entry_safe(ring, tmp, &ivec->ring_list, + ring_entry) + list_del(&ring->ring_entry); + } + ret = rtase_init_ring(dev); if (ret) { netdev_err(dev, "unable to init ring\n"); From ac5b4a24f16f2f56b5cc5092969930b867274edc Mon Sep 17 00:00:00 2001 From: Naveen Manohar Date: Tue, 11 Mar 2025 08:31:01 +0800 Subject: [PATCH 0849/1090] ASoC: Intel: soc-acpi-intel-ptl-match: Add cs42l43 support Patch adds driver data & match table for cs42l43 multi-function codec on PTL-RVP at sdw link3. Signed-off-by: Naveen Manohar Reviewed-by: Liam Girdwood Signed-off-by: Bard Liao Link: https://patch.msgid.link/20250311003101.80967-1-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-ptl-match.c | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c index a07526eb802b..6603d8de501c 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -185,6 +185,33 @@ static const struct snd_soc_acpi_endpoint cs42l43_amp_spkagg_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = { { .adr = 0x00023001fa424301ull, @@ -236,6 +263,15 @@ static const struct snd_soc_acpi_adr_device cs35l56_3_3amp_adr[] = { } }; +static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = { + { + .adr = 0x00033001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { { .adr = 0x000030025D071101ull, @@ -390,6 +426,14 @@ static const struct snd_soc_acpi_link_adr ptl_cs42l43_l2_cs35l56x6_l13[] = { {} }; +static const struct snd_soc_acpi_link_adr ptl_cs42l43_l3[] = { + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(cs42l43_3_adr), + .adr_d = cs42l43_3_adr, + } +}; + static const struct snd_soc_acpi_link_adr ptl_rt722_only[] = { { .mask = BIT(0), @@ -531,6 +575,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-ptl-rt711.tplg", }, + { + .link_mask = BIT(3), + .links = ptl_cs42l43_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-cs42l43-l3.tplg", + }, { .link_mask = BIT(3), .links = ptl_rt721_l3, From 3a04334d6282d08fbdd6201e374db17d31927ba3 Mon Sep 17 00:00:00 2001 From: Alan Huang Date: Sat, 8 Mar 2025 00:58:27 +0800 Subject: [PATCH 0850/1090] bcachefs: Fix b->written overflow When bset past end of btree node, we should not add sectors to b->written, which will overflow b->written. Reported-by: syzbot+3cb3d9e8c3f197754825@syzkaller.appspotmail.com Tested-by: syzbot+3cb3d9e8c3f197754825@syzkaller.appspotmail.com Signed-off-by: Alan Huang Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index dece27d9db04..756736f9243d 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1186,7 +1186,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, le64_to_cpu(i->journal_seq), b->written, b->written + sectors, ptr_written); - b->written += sectors; + b->written = min(b->written + sectors, btree_sectors(c)); if (blacklisted && !first) continue; From e5c2bcc0cd47321d78bb4e865d7857304139f95d Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Tue, 11 Mar 2025 19:43:58 +0900 Subject: [PATCH 0851/1090] nvme: move error logging from nvme_end_req() to __nvme_end_req() Before the Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions"), blk_mq_add_to_batch() did not add failed passthrough requests to batch, and returned false. After the commit, blk_mq_add_to_batch() always adds passthrough requests to batch regardless of whether the request failed or not, and returns true. This affected error logging feature in the NVME driver. Before the commit, the call chain of failed passthrough request was as follows: nvme_handle_cqe() blk_mq_add_to_batch() .. false is returned, then call nvme_pci_complete_rq() nvme_pci_complete_rq() nvme_complete_rq() nvme_end_req() nvme_log_err_passthru() .. error logging __nvme_end_req() .. end of the rqeuest After the commit, the call chain is as follows: nvme_handle_cqe() blk_mq_add_to_batch() .. true is returned, then set nvme_pci_complete_batch() .. nvme_pci_complete_batch() nvme_complete_batch() nvme_complete_batch_req() __nvme_end_req() .. end of the request, without error logging To make the error logging feature work again for passthrough requests, move the nvme_log_err_passthru() call from nvme_end_req() to __nvme_end_req(). While at it, move nvme_log_error() call for non-passthrough requests together with nvme_log_err_passthru(). Even though the trigger commit does not affect non-passthrough requests, move it together for code simplicity. Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions") Signed-off-by: Shin'ichiro Kawasaki Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20250311104359.1767728-2-shinichiro.kawasaki@wdc.com Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index f028913e2e62..8359d0aa0e44 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -431,6 +431,12 @@ static inline void nvme_end_req_zoned(struct request *req) static inline void __nvme_end_req(struct request *req) { + if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) { + if (blk_rq_is_passthrough(req)) + nvme_log_err_passthru(req); + else + nvme_log_error(req); + } nvme_end_req_zoned(req); nvme_trace_bio_complete(req); if (req->cmd_flags & REQ_NVME_MPATH) @@ -441,12 +447,6 @@ void nvme_end_req(struct request *req) { blk_status_t status = nvme_error_status(nvme_req(req)->status); - if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) { - if (blk_rq_is_passthrough(req)) - nvme_log_err_passthru(req); - else - nvme_log_error(req); - } __nvme_end_req(req); blk_mq_end_request(req, status); } From d2b9d97e89c79c95f8b517e4fa43fd100f936acc Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Fri, 7 Mar 2025 17:49:52 +0800 Subject: [PATCH 0852/1090] qlcnic: fix memory leak issues in qlcnic_sriov_common.c Add qlcnic_sriov_free_vlans() in qlcnic_sriov_alloc_vlans() if any sriov_vlans fails to be allocated. Add qlcnic_sriov_free_vlans() to free the memory allocated by qlcnic_sriov_alloc_vlans() if "sriov->allowed_vlans" fails to be allocated. Fixes: 91b7282b613d ("qlcnic: Support VLAN id config.") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Link: https://patch.msgid.link/20250307094952.14874-1-haoxiang_li2024@163.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index f9dd50152b1e..28d24d59efb8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -454,8 +454,10 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, num_vlans = sriov->num_allowed_vlans; sriov->allowed_vlans = kcalloc(num_vlans, sizeof(u16), GFP_KERNEL); - if (!sriov->allowed_vlans) + if (!sriov->allowed_vlans) { + qlcnic_sriov_free_vlans(adapter); return -ENOMEM; + } vlans = (u16 *)&cmd->rsp.arg[3]; for (i = 0; i < num_vlans; i++) @@ -2167,8 +2169,10 @@ int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter) vf = &sriov->vf_info[i]; vf->sriov_vlans = kcalloc(sriov->num_allowed_vlans, sizeof(*vf->sriov_vlans), GFP_KERNEL); - if (!vf->sriov_vlans) + if (!vf->sriov_vlans) { + qlcnic_sriov_free_vlans(adapter); return -ENOMEM; + } } return 0; From 58517f4df8424ec28dfe7290ccc61908eda57aae Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Tue, 11 Mar 2025 15:06:10 +0000 Subject: [PATCH 0853/1090] bcachefs: Initialize from_inode members for bch_io_opts When there is no inode source, all "from_inode" members in the structure bhc_io_opts should be set false. Fixes: 7a7c43a0c1ecf ("bcachefs: Add bch_io_opts fields for indicating whether the opts came from the inode") Reported-by: syzbot+c17ad4b4367b72a853cb@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c17ad4b4367b72a853cb Signed-off-by: Roxana Nicolescu Signed-off-by: Kent Overstreet --- fs/bcachefs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 04ec05206f8c..339b80770f1d 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -1198,6 +1198,7 @@ void bch2_inode_opts_get(struct bch_io_opts *opts, struct bch_fs *c, opts->_name##_from_inode = true; \ } else { \ opts->_name = c->opts._name; \ + opts->_name##_from_inode = false; \ } BCH_INODE_OPTS() #undef x From dbac8feb23382af1efa2e1a86049e079b6e42e12 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 11 Mar 2025 10:39:36 -0400 Subject: [PATCH 0854/1090] bcachefs: Make sure trans is unlocked when submitting read IO We were still using the trans after the unlock, leading to this bug in the retry path: 00255 ------------[ cut here ]------------ 00255 kernel BUG at fs/bcachefs/btree_iter.c:3348! 00255 Internal error: Oops - BUG: 00000000f2000800 [#1] SMP 00255 bcachefs (0ca38fe8-0a26-41f9-9b5d-6a27796c7803): /fiotest offset 86048768: no device to read from: 00255 u64s 8 type extent 4098:168192:U32_MAX len 128 ver 0: durability: 0 crc: c_size 128 size 128 offset 0 nonce 0 csum crc32c 0:8040a368 compress none ec: idx 83 block 1 ptr: 0:302:128 gen 0 00255 bcachefs (0ca38fe8-0a26-41f9-9b5d-6a27796c7803): /fiotest offset 85983232: no device to read from: 00255 u64s 8 type extent 4098:168064:U32_MAX len 128 ver 0: durability: 0 crc: c_size 128 size 128 offset 0 nonce 0 csum crc32c 0:43311336 compress none ec: idx 83 block 1 ptr: 0:302:0 gen 0 00255 Modules linked in: 00255 CPU: 5 UID: 0 PID: 304 Comm: kworker/u70:2 Not tainted 6.14.0-rc6-ktest-g526aae23d67d #16040 00255 Hardware name: linux,dummy-virt (DT) 00255 Workqueue: events_unbound bch2_rbio_retry 00255 pstate: 60001005 (nZCv daif -PAN -UAO -TCO -DIT +SSBS BTYPE=--) 00255 pc : __bch2_trans_get+0x100/0x378 00255 lr : __bch2_trans_get+0xa0/0x378 00255 sp : ffffff80c865b760 00255 x29: ffffff80c865b760 x28: 0000000000000000 x27: ffffff80d76ed880 00255 x26: 0000000000000018 x25: 0000000000000000 x24: ffffff80f4ec3760 00255 x23: ffffff80f4010140 x22: 0000000000000056 x21: ffffff80f4ec0000 00255 x20: ffffff80f4ec3788 x19: ffffff80d75f8000 x18: 00000000ffffffff 00255 x17: 2065707974203820 x16: 7334367520200a3a x15: 0000000000000008 00255 x14: 0000000000000001 x13: 0000000000000100 x12: 0000000000000006 00255 x11: ffffffc080b47a40 x10: 0000000000000000 x9 : ffffffc08038dea8 00255 x8 : ffffff80d75fc018 x7 : 0000000000000000 x6 : 0000000000003788 00255 x5 : 0000000000003760 x4 : ffffff80c922de80 x3 : ffffff80f18f0000 00255 x2 : ffffff80c922de80 x1 : 0000000000000130 x0 : 0000000000000006 00255 Call trace: 00255 __bch2_trans_get+0x100/0x378 (P) 00255 bch2_read_io_err+0x98/0x260 00255 bch2_read_endio+0xb8/0x2d0 00255 __bch2_read_extent+0xce8/0xfe0 00255 __bch2_read+0x2a8/0x978 00255 bch2_rbio_retry+0x188/0x318 00255 process_one_work+0x154/0x390 00255 worker_thread+0x20c/0x3b8 00255 kthread+0xf0/0x1b0 00255 ret_from_fork+0x10/0x20 00255 Code: 6b01001f 54ffff01 79408460 3617fec0 (d4210000) 00255 ---[ end trace 0000000000000000 ]--- 00255 Kernel panic - not syncing: Oops - BUG: Fatal exception 00255 SMP: stopping secondary CPUs 00255 Kernel Offset: disabled 00255 CPU features: 0x000,00000070,00000010,8240500b 00255 Memory Limit: none 00255 ---[ end Kernel panic - not syncing: Oops - BUG: Fatal exception ]--- Signed-off-by: Kent Overstreet --- fs/bcachefs/io_read.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index 8c7b2d3d779d..726da68073e2 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -951,12 +951,6 @@ retry_pick: goto retry_pick; } - /* - * Unlock the iterator while the btree node's lock is still in - * cache, before doing the IO: - */ - bch2_trans_unlock(trans); - if (flags & BCH_READ_NODECODE) { /* * can happen if we retry, and the extent we were going to read @@ -1113,6 +1107,15 @@ get_bio: trace_and_count(c, read_split, &orig->bio); } + /* + * Unlock the iterator while the btree node's lock is still in + * cache, before doing the IO: + */ + if (!(flags & BCH_READ_IN_RETRY)) + bch2_trans_unlock(trans); + else + bch2_trans_unlock_long(trans); + if (!rbio->pick.idx) { if (unlikely(!rbio->have_ioref)) { struct printbuf buf = PRINTBUF; @@ -1160,6 +1163,8 @@ out: if (likely(!(flags & BCH_READ_IN_RETRY))) { return 0; } else { + bch2_trans_unlock(trans); + int ret; rbio->context = RBIO_CONTEXT_UNBOUND; From 5b1122fc4995f308b21d7cfc64ef9880ac834d20 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 10 Mar 2025 22:48:29 +0300 Subject: [PATCH 0855/1090] platform/x86/amd/pmf: fix cleanup in amd_pmf_init_smart_pc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a few problems in this code: First, if amd_pmf_tee_init() fails then the function returns directly instead of cleaning up. We cannot simply do a "goto error;" because the amd_pmf_tee_init() cleanup calls tee_shm_free(dev->fw_shm_pool); and amd_pmf_tee_deinit() calls it as well leading to a double free. I have re-written this code to use an unwind ladder to free the allocations. Second, if amd_pmf_start_policy_engine() fails on every iteration though the loop then the code calls amd_pmf_tee_deinit() twice which is also a double free. Call amd_pmf_tee_deinit() inside the loop for each failed iteration. Also on that path the error codes are not necessarily negative kernel error codes. Set the error code to -EINVAL. There is a very subtle third bug which is that if the call to input_register_device() in amd_pmf_register_input_device() fails then we call input_unregister_device() on an input device that wasn't registered. This will lead to a reference counting underflow because of the device_del(&dev->dev) in __input_unregister_device(). It's unlikely that anyone would ever hit this bug in real life. Fixes: 376a8c2a1443 ("platform/x86/amd/pmf: Update PMF Driver for Compatibility with new PMF-TA") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/232231fc-6a71-495e-971b-be2a76f6db4c@stanley.mountain Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/tee-if.c | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c index ceaff1ebb7b9..a1e43873a07b 100644 --- a/drivers/platform/x86/amd/pmf/tee-if.c +++ b/drivers/platform/x86/amd/pmf/tee-if.c @@ -510,18 +510,18 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) ret = amd_pmf_set_dram_addr(dev, true); if (ret) - goto error; + goto err_cancel_work; dev->policy_base = devm_ioremap_resource(dev->dev, dev->res); if (IS_ERR(dev->policy_base)) { ret = PTR_ERR(dev->policy_base); - goto error; + goto err_free_dram_buf; } dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL); if (!dev->policy_buf) { ret = -ENOMEM; - goto error; + goto err_free_dram_buf; } memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz); @@ -531,13 +531,13 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL); if (!dev->prev_data) { ret = -ENOMEM; - goto error; + goto err_free_policy; } for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) { ret = amd_pmf_tee_init(dev, &amd_pmf_ta_uuid[i]); if (ret) - return ret; + goto err_free_prev_data; ret = amd_pmf_start_policy_engine(dev); switch (ret) { @@ -550,27 +550,41 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) status = false; break; default: - goto error; + ret = -EINVAL; + amd_pmf_tee_deinit(dev); + goto err_free_prev_data; } if (status) break; } - if (!status && !pb_side_load) - goto error; + if (!status && !pb_side_load) { + ret = -EINVAL; + goto err_free_prev_data; + } if (pb_side_load) amd_pmf_open_pb(dev, dev->dbgfs_dir); ret = amd_pmf_register_input_device(dev); if (ret) - goto error; + goto err_pmf_remove_pb; return 0; -error: - amd_pmf_deinit_smart_pc(dev); +err_pmf_remove_pb: + if (pb_side_load && dev->esbin) + amd_pmf_remove_pb(dev); + amd_pmf_tee_deinit(dev); +err_free_prev_data: + kfree(dev->prev_data); +err_free_policy: + kfree(dev->policy_buf); +err_free_dram_buf: + kfree(dev->buf); +err_cancel_work: + cancel_delayed_work_sync(&dev->pb_work); return ret; } From a05507cef0ee6a0af402c0d7e994115033ff746b Mon Sep 17 00:00:00 2001 From: Lukas Hetzenecker Date: Tue, 11 Mar 2025 00:28:03 +0100 Subject: [PATCH 0856/1090] platform/surface: aggregator_registry: Add Support for Surface Pro 11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add SAM client device nodes for the Surface Pro 11 (Intel). Like with the Surface Pro 10 already, the node group is compatible, so it can be reused. Signed-off-by: Lukas Hetzenecker Link: https://lore.kernel.org/r/20250310232803.23691-1-lukas@hetzenecker.me Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/surface/surface_aggregator_registry.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c index d4f32ad66530..a594d5fcfcfd 100644 --- a/drivers/platform/surface/surface_aggregator_registry.c +++ b/drivers/platform/surface/surface_aggregator_registry.c @@ -371,7 +371,7 @@ static const struct software_node *ssam_node_group_sp8[] = { NULL, }; -/* Devices for Surface Pro 9 (Intel/x86) and 10 */ +/* Devices for Surface Pro 9, 10 and 11 (Intel/x86) */ static const struct software_node *ssam_node_group_sp9[] = { &ssam_node_root, &ssam_node_hub_kip, @@ -430,6 +430,9 @@ static const struct acpi_device_id ssam_platform_hub_acpi_match[] = { /* Surface Pro 10 */ { "MSHW0510", (unsigned long)ssam_node_group_sp9 }, + /* Surface Pro 11 */ + { "MSHW0583", (unsigned long)ssam_node_group_sp9 }, + /* Surface Book 2 */ { "MSHW0107", (unsigned long)ssam_node_group_gen5 }, From c3d5d331c96f35c6425f7dcfa5c60cf9a5055d0e Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:48 +0530 Subject: [PATCH 0857/1090] ASoC: amd: acp: Remove redundant acp70 chip->name As acp71 platform driver uses acp70 platform driver, remove the redundant chip->name. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-2-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index e0fc42d939d3..dcd92d716e78 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -89,8 +89,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->name = "acp_asoc_acp63"; break; case 0x70: - chip->name = "acp_asoc_acp70"; - break; case 0x71: chip->name = "acp_asoc_acp70"; break; From 8ae746fe51041484e52eba99bed15a444c7d4372 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:49 +0530 Subject: [PATCH 0858/1090] ASoC: amd: acp: Implement acp_common_hw_ops support for acp platforms Implement acp common hardware ops for acp_init and acp_deinit funcions to support commons ops for all platforms. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-3-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 50 +++++++++++++++++++++++++++ sound/soc/amd/acp/acp-pci.c | 13 ++++--- sound/soc/amd/acp/amd.h | 36 +++++++++++++++++++ 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 89f5cda18a23..f87a2da8c641 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -21,6 +21,12 @@ #define ACP63_PDM_ADDR 0x02 #define ACP70_PDM_ADDR 0x02 +const struct snd_acp_hw_ops acp_common_hw_ops = { + /* ACP hardware initilizations */ + .acp_init = acp_init, + .acp_deinit = acp_deinit, +}; +EXPORT_SYMBOL_NS_GPL(acp_common_hw_ops, "SND_SOC_ACP_COMMON"); void acp_enable_interrupts(struct acp_dev_data *adata) { struct acp_resource *rsrc = adata->rsrc; @@ -463,5 +469,49 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) } EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON"); +struct snd_acp_hw_ops acp31_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp31_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp31_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp31_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp31_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp31_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp6x_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp6x_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp6x_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp6x_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp6x_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp6x_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp63_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp63_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp63_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp63_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp63_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp63_hw_ops_init, "SND_SOC_ACP_COMMON"); + +struct snd_acp_hw_ops acp70_common_hw_ops; +EXPORT_SYMBOL_NS_GPL(acp70_common_hw_ops, "SND_SOC_ACP_COMMON"); +int acp70_hw_ops_init(struct acp_chip_info *chip) +{ + memcpy(&acp70_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); + chip->acp_hw_ops = &acp70_common_hw_ops; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp70_hw_ops_init, "SND_SOC_ACP_COMMON"); + MODULE_DESCRIPTION("AMD ACP legacy common features"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index dcd92d716e78..b5eabd0280bc 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -81,16 +81,20 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id switch (pci->revision) { case 0x01: chip->name = "acp_asoc_renoir"; + chip->acp_hw_ops_init = acp31_hw_ops_init; break; case 0x6f: chip->name = "acp_asoc_rembrandt"; + chip->acp_hw_ops_init = acp6x_hw_ops_init; break; case 0x63: chip->name = "acp_asoc_acp63"; + chip->acp_hw_ops_init = acp63_hw_ops_init; break; case 0x70: case 0x71: chip->name = "acp_asoc_acp70"; + chip->acp_hw_ops_init = acp70_hw_ops_init; break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); @@ -112,7 +116,8 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id goto unregister_dmic_dev; } - ret = acp_init(chip); + chip->acp_hw_ops_init(chip); + ret = acp_hw_init(chip); if (ret) goto unregister_dmic_dev; @@ -179,7 +184,7 @@ static int __maybe_unused snd_acp_suspend(struct device *dev) int ret; chip = dev_get_drvdata(dev); - ret = acp_deinit(chip); + ret = acp_hw_deinit(chip); if (ret) dev_err(dev, "ACP de-init failed\n"); return ret; @@ -193,7 +198,7 @@ static int __maybe_unused snd_acp_resume(struct device *dev) int ret; chip = dev_get_drvdata(dev); - ret = acp_init(chip); + ret = acp_hw_init(chip); if (ret) dev_err(dev, "ACP init failed\n"); if (chip->chip_pdev) { @@ -222,7 +227,7 @@ static void acp_pci_remove(struct pci_dev *pci) platform_device_unregister(dmic_dev); if (pdev) platform_device_unregister(pdev); - ret = acp_deinit(chip); + ret = acp_hw_deinit(chip); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); } diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index c921bcabbcec..3c06567e112c 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -142,6 +142,8 @@ struct acp_chip_info { char *name; /* Platform name */ unsigned int acp_rev; /* ACP Revision id */ void __iomem *base; /* ACP memory PCI base */ + struct snd_acp_hw_ops *acp_hw_ops; + int (*acp_hw_ops_init)(struct acp_chip_info *chip); struct platform_device *chip_pdev; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ @@ -203,6 +205,17 @@ struct acp_dev_data { unsigned int flag; }; +/** + * struct snd_acp_hw_ops - ACP PCI driver platform specific ops + * @acp_init: ACP initialization + * @acp_deinit: ACP de-initialization + */ +struct snd_acp_hw_ops { + /* ACP hardware initilizations */ + int (*acp_init)(struct acp_chip_info *chip); + int (*acp_deinit)(struct acp_chip_info *chip); +}; + enum acp_config { ACP_CONFIG_0 = 0, ACP_CONFIG_1, @@ -239,6 +252,15 @@ int acp_init(struct acp_chip_info *chip); int acp_deinit(struct acp_chip_info *chip); void acp_enable_interrupts(struct acp_dev_data *adata); void acp_disable_interrupts(struct acp_dev_data *adata); + +extern struct snd_acp_hw_ops acp31_common_hw_ops; +extern struct snd_acp_hw_ops acp6x_common_hw_ops; +extern struct snd_acp_hw_ops acp63_common_hw_ops; +extern struct snd_acp_hw_ops acp70_common_hw_ops; +extern int acp31_hw_ops_init(struct acp_chip_info *chip); +extern int acp6x_hw_ops_init(struct acp_chip_info *chip); +extern int acp63_hw_ops_init(struct acp_chip_info *chip); +extern int acp70_hw_ops_init(struct acp_chip_info *chip); /* Machine configuration */ int snd_amd_acp_find_config(struct pci_dev *pci); @@ -252,6 +274,20 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream, void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip); +static inline int acp_hw_init(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_init) + return chip->acp_hw_ops->acp_init(chip); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_deinit) + return chip->acp_hw_ops->acp_deinit(chip); + return -EOPNOTSUPP; +} + static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction) { u64 byte_count = 0, low = 0, high = 0; From e2cda461765692757cd5c3b1fc80bd260ffe1394 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:50 +0530 Subject: [PATCH 0859/1090] ASoC: amd: acp: Refactor dmic-codec platform device creation Refactor dmic-codec platform driver creation using helper function. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-4-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 49 +++++++++++++++++++++++++------------ sound/soc/amd/acp/amd.h | 1 + 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index b5eabd0280bc..549e95415ab2 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -26,7 +26,6 @@ #define ACP3x_REG_START 0x1240000 #define ACP3x_REG_END 0x125C000 -static struct platform_device *dmic_dev; static struct platform_device *pdev; static const struct resource acp_res[] = { @@ -44,6 +43,26 @@ static const struct resource acp_res[] = { }, }; +static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *chip) +{ + int ret; + + if (chip->is_pdm_dev && chip->is_pdm_config) { + chip->dmic_codec_dev = platform_device_register_data(&pci->dev, + "dmic-codec", + PLATFORM_DEVID_NONE, + NULL, 0); + if (IS_ERR(chip->dmic_codec_dev)) { + dev_err(&pci->dev, "failed to create DMIC device\n"); + ret = PTR_ERR(chip->dmic_codec_dev); + goto err; + } + } + return 0; +err: + return ret; +} + static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct platform_device_info pdevinfo; @@ -102,33 +121,33 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id goto release_regions; } chip->flag = flag; - dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); - if (IS_ERR(dmic_dev)) { - dev_err(dev, "failed to create DMIC device\n"); - ret = PTR_ERR(dmic_dev); - goto release_regions; - } addr = pci_resource_start(pci, 0); chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0)); if (!chip->base) { ret = -ENOMEM; - goto unregister_dmic_dev; + goto release_regions; } chip->acp_hw_ops_init(chip); ret = acp_hw_init(chip); if (ret) - goto unregister_dmic_dev; + goto release_regions; check_acp_config(pci, chip); if (!chip->is_pdm_dev && !chip->is_i2s_config) goto skip_pdev_creation; + ret = create_acp_platform_devs(pci, chip); + if (ret < 0) { + dev_err(&pci->dev, "ACP platform devices creation failed\n"); + goto de_init; + } + res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL); if (!res) { ret = -ENOMEM; - goto unregister_dmic_dev; + goto de_init; } for (i = 0; i < num_res; i++, res_acp++) { @@ -156,7 +175,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id if (IS_ERR(pdev)) { dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); ret = PTR_ERR(pdev); - goto unregister_dmic_dev; + goto de_init; } skip_pdev_creation: @@ -168,8 +187,8 @@ skip_pdev_creation: pm_runtime_allow(&pci->dev); return ret; -unregister_dmic_dev: - platform_device_unregister(dmic_dev); +de_init: + acp_hw_deinit(chip); release_regions: pci_release_regions(pci); disable_pci: @@ -223,8 +242,8 @@ static void acp_pci_remove(struct pci_dev *pci) chip = pci_get_drvdata(pci); pm_runtime_forbid(&pci->dev); pm_runtime_get_noresume(&pci->dev); - if (dmic_dev) - platform_device_unregister(dmic_dev); + if (chip->dmic_codec_dev) + platform_device_unregister(chip->dmic_codec_dev); if (pdev) platform_device_unregister(pdev); ret = acp_hw_deinit(chip); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 3c06567e112c..9511995da591 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -145,6 +145,7 @@ struct acp_chip_info { struct snd_acp_hw_ops *acp_hw_ops; int (*acp_hw_ops_init)(struct acp_chip_info *chip); struct platform_device *chip_pdev; + struct platform_device *dmic_codec_dev; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */ From a8b9d2d7376d2caf74c0ffbf9bc71b98ed9d1a01 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:51 +0530 Subject: [PATCH 0860/1090] ASoC: amd: acp: Refactor acp platform device creation Refactor acp platform device creation logic and remove unused acp resource (acp_res) structure. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-5-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 121 ++++++++++++++++++------------------ sound/soc/amd/acp/amd.h | 4 ++ 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 549e95415ab2..0ffef70ab979 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -26,27 +26,56 @@ #define ACP3x_REG_START 0x1240000 #define ACP3x_REG_END 0x125C000 -static struct platform_device *pdev; - -static const struct resource acp_res[] = { - { - .start = 0, - .end = ACP3x_REG_END - ACP3x_REG_START, - .name = "acp_mem", - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .name = "acp_dai_irq", - .flags = IORESOURCE_IRQ, - }, -}; - -static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *chip) +static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo, + struct device *parent, + struct fwnode_handle *fw_node, + char *name, unsigned int id, + const struct resource *res, + unsigned int num_res, + const void *data, + size_t size_data) { + pdevinfo->name = name; + pdevinfo->id = id; + pdevinfo->parent = parent; + pdevinfo->num_res = num_res; + pdevinfo->res = res; + pdevinfo->data = data; + pdevinfo->size_data = size_data; + pdevinfo->fwnode = fw_node; +} + +static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *chip, u32 addr) +{ + struct platform_device_info pdevinfo; + struct device *parent; int ret; + parent = &pci->dev; + + if (chip->is_i2s_config || chip->is_pdm_dev) { + chip->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL); + if (!chip->res) { + ret = -ENOMEM; + goto err; + } + chip->res->flags = IORESOURCE_MEM; + chip->res->start = addr; + chip->res->end = addr + (ACP3x_REG_END - ACP3x_REG_START); + memset(&pdevinfo, 0, sizeof(pdevinfo)); + } + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + acp_fill_platform_dev_info(&pdevinfo, parent, NULL, chip->name, + 0, chip->res, 1, chip, sizeof(*chip)); + + chip->acp_plat_dev = platform_device_register_full(&pdevinfo); + if (IS_ERR(chip->acp_plat_dev)) { + dev_err(&pci->dev, + "cannot register %s device\n", pdevinfo.name); + ret = PTR_ERR(chip->acp_plat_dev); + goto err; + } if (chip->is_pdm_dev && chip->is_pdm_config) { chip->dmic_codec_dev = platform_device_register_data(&pci->dev, "dmic-codec", @@ -55,22 +84,21 @@ static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *c if (IS_ERR(chip->dmic_codec_dev)) { dev_err(&pci->dev, "failed to create DMIC device\n"); ret = PTR_ERR(chip->dmic_codec_dev); - goto err; + goto unregister_acp_plat_dev; } } return 0; +unregister_acp_plat_dev: + platform_device_unregister(chip->acp_plat_dev); err: return ret; } static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - struct platform_device_info pdevinfo; struct device *dev = &pci->dev; - const struct resource *res_acp; struct acp_chip_info *chip; - struct resource *res; - unsigned int flag, addr, num_res, i; + unsigned int flag, addr; int ret; flag = snd_amd_acp_find_config(pci); @@ -94,8 +122,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id pci_set_master(pci); - res_acp = acp_res; - num_res = ARRAY_SIZE(acp_res); chip->acp_rev = pci->revision; switch (pci->revision) { case 0x01: @@ -129,6 +155,8 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id goto release_regions; } + chip->addr = addr; + chip->acp_hw_ops_init(chip); ret = acp_hw_init(chip); if (ret) @@ -138,48 +166,16 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id if (!chip->is_pdm_dev && !chip->is_i2s_config) goto skip_pdev_creation; - ret = create_acp_platform_devs(pci, chip); + ret = create_acp_platform_devs(pci, chip, addr); if (ret < 0) { dev_err(&pci->dev, "ACP platform devices creation failed\n"); goto de_init; } - res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL); - if (!res) { - ret = -ENOMEM; - goto de_init; - } - - for (i = 0; i < num_res; i++, res_acp++) { - res[i].name = res_acp->name; - res[i].flags = res_acp->flags; - res[i].start = addr + res_acp->start; - res[i].end = addr + res_acp->end; - if (res_acp->flags == IORESOURCE_IRQ) { - res[i].start = pci->irq; - res[i].end = res[i].start; - } - } - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - - pdevinfo.name = chip->name; - pdevinfo.id = 0; - pdevinfo.parent = &pci->dev; - pdevinfo.num_res = num_res; - pdevinfo.res = &res[0]; - pdevinfo.data = chip; - pdevinfo.size_data = sizeof(*chip); - - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { - dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name); - ret = PTR_ERR(pdev); - goto de_init; - } + chip->chip_pdev = chip->acp_plat_dev; + chip->dev = &chip->acp_plat_dev->dev; skip_pdev_creation: - chip->chip_pdev = pdev; dev_set_drvdata(&pci->dev, chip); pm_runtime_set_autosuspend_delay(&pci->dev, 2000); pm_runtime_use_autosuspend(&pci->dev); @@ -244,8 +240,9 @@ static void acp_pci_remove(struct pci_dev *pci) pm_runtime_get_noresume(&pci->dev); if (chip->dmic_codec_dev) platform_device_unregister(chip->dmic_codec_dev); - if (pdev) - platform_device_unregister(pdev); + if (chip->acp_plat_dev) + platform_device_unregister(chip->acp_plat_dev); + ret = acp_hw_deinit(chip); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 9511995da591..be1aa405a14a 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -140,12 +140,16 @@ struct acp_chip_info { char *name; /* Platform name */ + struct resource *res; + struct device *dev; unsigned int acp_rev; /* ACP Revision id */ void __iomem *base; /* ACP memory PCI base */ struct snd_acp_hw_ops *acp_hw_ops; int (*acp_hw_ops_init)(struct acp_chip_info *chip); struct platform_device *chip_pdev; struct platform_device *dmic_codec_dev; + struct platform_device *acp_plat_dev; + u32 addr; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */ From 6e60db74b69c29b528c8d10d86108f78f2995dcb Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:52 +0530 Subject: [PATCH 0861/1090] ASoC: amd: acp: Refactor acp machine select Refactor and move acp machine select function from acp platform driver to acp pci driver and assign platform specific acpi machines to chip->machines. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-6-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 28 +++++++++ sound/soc/amd/acp/acp-pci.c | 7 +++ sound/soc/amd/acp/acp-platform.c | 28 --------- sound/soc/amd/acp/acp-rembrandt.c | 32 ----------- sound/soc/amd/acp/acp-renoir.c | 42 -------------- sound/soc/amd/acp/acp63.c | 10 ---- sound/soc/amd/acp/acp70.c | 10 ---- sound/soc/amd/acp/amd.h | 81 ++++++++++++++++++++++++++- 8 files changed, 114 insertions(+), 124 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index f87a2da8c641..886615798b93 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -16,6 +16,8 @@ #include #include +#include "../mach-config.h" + #define ACP_RENOIR_PDM_ADDR 0x02 #define ACP_REMBRANDT_PDM_ADDR 0x03 #define ACP63_PDM_ADDR 0x02 @@ -350,6 +352,32 @@ int acp_deinit(struct acp_chip_info *chip) return 0; } EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON"); +int acp_machine_select(struct acp_chip_info *chip) +{ + struct snd_soc_acpi_mach *mach; + int size, platform; + + if (chip->flag == FLAG_AMD_LEGACY_ONLY_DMIC) { + platform = chip->acp_rev; + chip->mach_dev = platform_device_register_data(chip->dev, "acp-pdm-mach", + PLATFORM_DEVID_NONE, &platform, + sizeof(platform)); + } else { + size = sizeof(*chip->machines); + mach = snd_soc_acpi_find_machine(chip->machines); + if (!mach) { + dev_err(chip->dev, "warning: No matching ASoC machine driver found\n"); + return -EINVAL; + } + mach->mach_params.subsystem_rev = chip->acp_rev; + chip->mach_dev = platform_device_register_data(chip->dev, mach->drv_name, + PLATFORM_DEVID_NONE, mach, size); + } + if (IS_ERR(chip->mach_dev)) + dev_warn(chip->dev, "Unable to register Machine device\n"); + return 0; +} +EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON"); static void check_acp3x_config(struct acp_chip_info *chip) { diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 0ffef70ab979..99297a388ed7 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -127,19 +127,23 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id case 0x01: chip->name = "acp_asoc_renoir"; chip->acp_hw_ops_init = acp31_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp_machines; break; case 0x6f: chip->name = "acp_asoc_rembrandt"; chip->acp_hw_ops_init = acp6x_hw_ops_init; + chip->machines = snd_soc_acpi_amd_rmb_acp_machines; break; case 0x63: chip->name = "acp_asoc_acp63"; chip->acp_hw_ops_init = acp63_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp63_acp_machines; break; case 0x70: case 0x71: chip->name = "acp_asoc_acp70"; chip->acp_hw_ops_init = acp70_hw_ops_init; + chip->machines = snd_soc_acpi_amd_acp70_acp_machines; break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); @@ -175,6 +179,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->chip_pdev = chip->acp_plat_dev; chip->dev = &chip->acp_plat_dev->dev; + acp_machine_select(chip); skip_pdev_creation: dev_set_drvdata(&pci->dev, chip); pm_runtime_set_autosuspend_delay(&pci->dev, 2000); @@ -242,6 +247,8 @@ static void acp_pci_remove(struct pci_dev *pci) platform_device_unregister(chip->dmic_codec_dev); if (chip->acp_plat_dev) platform_device_unregister(chip->acp_plat_dev); + if (chip->mach_dev) + platform_device_unregister(chip->mach_dev); ret = acp_hw_deinit(chip); if (ret) diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index aa330aeeb301..7d6abff28b23 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -21,7 +21,6 @@ #include #include "amd.h" -#include "../mach-config.h" #include "acp-mach.h" #define DRV_NAME "acp_i2s_dma" @@ -108,33 +107,6 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, }; -int acp_machine_select(struct acp_dev_data *adata) -{ - struct snd_soc_acpi_mach *mach; - int size, platform; - - if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) { - platform = adata->acp_rev; - adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach", - PLATFORM_DEVID_NONE, &platform, - sizeof(platform)); - } else { - size = sizeof(*adata->machines); - mach = snd_soc_acpi_find_machine(adata->machines); - if (!mach) { - dev_err(adata->dev, "warning: No matching ASoC machine driver found\n"); - return -EINVAL; - } - mach->mach_params.subsystem_rev = adata->acp_rev; - adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name, - PLATFORM_DEVID_NONE, mach, size); - } - if (IS_ERR(adata->mach_dev)) - dev_warn(adata->dev, "Unable to register Machine device\n"); - return 0; -} -EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON"); - static irqreturn_t i2s_irq_handler(int irq, void *data) { struct acp_dev_data *adata = data; diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index e727754a8231..eb09878c0d5c 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -44,36 +44,6 @@ static struct acp_resource rsrc = { .sram_pte_offset = 0x03802800, }; -static struct snd_soc_acpi_codecs amp_rt1019 = { - .num_codecs = 1, - .codecs = {"10EC1019"} -}; - -static struct snd_soc_acpi_codecs amp_max = { - .num_codecs = 1, - .codecs = {"MX98360A"} -}; - -static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { - { - .id = "10508825", - .drv_name = "rmb-nau8825-max", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_max, - }, - { - .id = "AMDI0007", - .drv_name = "rembrandt-acp", - }, - { - .id = "RTL5682", - .drv_name = "rmb-rt5682s-rt1019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - {}, -}; - static struct snd_soc_dai_driver acp_rmb_dai[] = { { .name = "acp-i2s-sp", @@ -230,8 +200,6 @@ static int rembrandt_audio_probe(struct platform_device *pdev) adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; - adata->machines = snd_soc_acpi_amd_rmb_acp_machines; - acp_machine_select(adata); dev_set_drvdata(dev, adata); diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index ca2b74283d8f..2b47c6bfc9e7 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -36,45 +36,6 @@ static struct acp_resource rsrc = { .sram_pte_offset = 0x02052800, }; -static struct snd_soc_acpi_codecs amp_rt1019 = { - .num_codecs = 1, - .codecs = {"10EC1019"} -}; - -static struct snd_soc_acpi_codecs amp_max = { - .num_codecs = 1, - .codecs = {"MX98360A"} -}; - -static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { - { - .id = "10EC5682", - .drv_name = "acp3xalc56821019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - { - .id = "RTL5682", - .drv_name = "acp3xalc5682sm98360", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_max, - }, - { - .id = "RTL5682", - .drv_name = "acp3xalc5682s1019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - { - .id = "AMDI1019", - .drv_name = "renoir-acp", - }, - { - .id = "ESSX8336", - .drv_name = "acp3x-es83xx", - }, - {}, -}; static struct snd_soc_dai_driver acp_renoir_dai[] = { { @@ -188,9 +149,6 @@ static int renoir_audio_probe(struct platform_device *pdev) adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; - adata->machines = snd_soc_acpi_amd_acp_machines; - acp_machine_select(adata); - dev_set_drvdata(dev, adata); acp_enable_interrupts(adata); acp_platform_register(dev); diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 4187a8968de7..76a26b82e3ad 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -62,14 +62,6 @@ static struct acp_resource rsrc = { .sram_pte_offset = 0x03802800, }; -static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { - { - .id = "AMDI0052", - .drv_name = "acp63-acp", - }, - {}, -}; - static struct snd_soc_dai_driver acp63_dai[] = { { .name = "acp-i2s-sp", @@ -259,8 +251,6 @@ static int acp63_audio_probe(struct platform_device *pdev) adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; adata->is_i2s_config = chip->is_i2s_config; - adata->machines = snd_soc_acpi_amd_acp63_acp_machines; - acp_machine_select(adata); dev_set_drvdata(dev, adata); if (chip->is_i2s_config && rsrc.soc_mclk) { diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 7f4ec3bfaeab..3e603c5f736a 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -40,14 +40,6 @@ static struct acp_resource rsrc = { .sram_pte_offset = 0x03800000, }; -static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { - { - .id = "AMDI0029", - .drv_name = "acp70-acp", - }, - {}, -}; - static struct snd_soc_dai_driver acp70_dai[] = { { .name = "acp-i2s-sp", @@ -187,10 +179,8 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->dai_driver = acp70_dai; adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; - adata->machines = snd_soc_acpi_amd_acp70_acp_machines; adata->acp_rev = chip->acp_rev; adata->flag = chip->flag; - acp_machine_select(adata); dev_set_drvdata(dev, adata); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index be1aa405a14a..b7a1b4aa8fef 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -149,6 +149,8 @@ struct acp_chip_info { struct platform_device *chip_pdev; struct platform_device *dmic_codec_dev; struct platform_device *acp_plat_dev; + struct platform_device *mach_dev; + struct snd_soc_acpi_mach *machines; u32 addr; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ @@ -195,7 +197,6 @@ struct acp_dev_data { struct list_head stream_list; spinlock_t acp_lock; - struct snd_soc_acpi_mach *machines; struct platform_device *mach_dev; u32 bclk_div; @@ -245,13 +246,89 @@ enum acp_config { ACP_CONFIG_20, }; +struct snd_soc_acpi_codecs amp_rt1019 = { + .num_codecs = 1, + .codecs = {"10EC1019"} +}; + +struct snd_soc_acpi_codecs amp_max = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { + { + .id = "10EC5682", + .drv_name = "acp3xalc56821019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682sm98360", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682s1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "AMDI1019", + .drv_name = "renoir-acp", + }, + { + .id = "ESSX8336", + .drv_name = "acp3x-es83xx", + }, + {}, +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { + { + .id = "10508825", + .drv_name = "rmb-nau8825-max", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "AMDI0007", + .drv_name = "rembrandt-acp", + }, + { + .id = "RTL5682", + .drv_name = "rmb-rt5682s-rt1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + {}, +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { + { + .id = "AMDI0052", + .drv_name = "acp63-acp", + }, + {}, +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { + { + .id = "AMDI0029", + .drv_name = "acp70-acp", + }, + {}, +}; + extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; extern const struct snd_soc_dai_ops acp_dmic_dai_ops; int acp_platform_register(struct device *dev); int acp_platform_unregister(struct device *dev); -int acp_machine_select(struct acp_dev_data *adata); +int acp_machine_select(struct acp_chip_info *chip); int acp_init(struct acp_chip_info *chip); int acp_deinit(struct acp_chip_info *chip); From aaf7a668bb3814f084f9f6f673567f6aa316632f Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:53 +0530 Subject: [PATCH 0862/1090] ASoC: amd: acp: Add new interrupt handle callbacks in acp_common_hw_ops Add new interrupt handle callbacks in acp_common_hw_ops. Refactor and move interrupt handler registration form platform driver to pci driver. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-7-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-i2s.c | 4 +- sound/soc/amd/acp/acp-legacy-common.c | 79 +++++++++++++++++++++++---- sound/soc/amd/acp/acp-pci.c | 29 +++++++--- sound/soc/amd/acp/acp-pdm.c | 12 ++-- sound/soc/amd/acp/acp-platform.c | 50 +++-------------- sound/soc/amd/acp/acp-rembrandt.c | 15 ++++- sound/soc/amd/acp/acp-renoir.c | 15 ++++- sound/soc/amd/acp/acp63.c | 15 ++++- sound/soc/amd/acp/acp70.c | 15 ++++- sound/soc/amd/acp/amd.h | 29 +++++++++- sound/soc/amd/acp/chip_offset_byte.h | 12 ++-- 11 files changed, 184 insertions(+), 91 deletions(-) diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 89e99ed4275a..2f458c76f9fc 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -617,7 +617,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); - ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | BIT(BT_RX_THRESHOLD(rsrc->offset)) | BIT(I2S_TX_THRESHOLD(rsrc->offset)) | @@ -625,7 +625,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d BIT(HS_RX_THRESHOLD(rsrc->offset)) | BIT(HS_TX_THRESHOLD(rsrc->offset)); - writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); return 0; } diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 886615798b93..13fddce8df56 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -27,26 +27,76 @@ const struct snd_acp_hw_ops acp_common_hw_ops = { /* ACP hardware initilizations */ .acp_init = acp_init, .acp_deinit = acp_deinit, + + /* ACP Interrupts*/ + .irq = acp_irq_handler, + .en_interrupts = acp_enable_interrupts, + .dis_interrupts = acp_disable_interrupts, }; EXPORT_SYMBOL_NS_GPL(acp_common_hw_ops, "SND_SOC_ACP_COMMON"); -void acp_enable_interrupts(struct acp_dev_data *adata) + +irqreturn_t acp_irq_handler(int irq, void *data) { + struct acp_chip_info *chip = data; + struct acp_dev_data *adata = chip->adata; struct acp_resource *rsrc = adata->rsrc; + struct acp_stream *stream; + u16 i2s_flag = 0; + u32 ext_intr_stat, ext_intr_stat1; + + if (adata->rsrc->no_of_ctrls == 2) + ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1))); + + ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + + spin_lock(&adata->acp_lock); + list_for_each_entry(stream, &adata->stream_list, list) { + if (ext_intr_stat & stream->irq_bit) { + writel(stream->irq_bit, + ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + snd_pcm_period_elapsed(stream->substream); + i2s_flag = 1; + } + if (adata->rsrc->no_of_ctrls == 2) { + if (ext_intr_stat1 & stream->irq_bit) { + writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip, + (rsrc->irqp_used - 1))); + snd_pcm_period_elapsed(stream->substream); + i2s_flag = 1; + } + } + } + spin_unlock(&adata->acp_lock); + if (i2s_flag) + return IRQ_HANDLED; + + return IRQ_NONE; +} + +int acp_enable_interrupts(struct acp_chip_info *chip) +{ + struct acp_resource *rsrc; u32 ext_intr_ctrl; - writel(0x01, ACP_EXTERNAL_INTR_ENB(adata)); - ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + rsrc = chip->rsrc; + writel(0x01, ACP_EXTERNAL_INTR_ENB(chip)); + ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); ext_intr_ctrl |= ACP_ERROR_MASK; - writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); + + return 0; } EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON"); -void acp_disable_interrupts(struct acp_dev_data *adata) +int acp_disable_interrupts(struct acp_chip_info *chip) { - struct acp_resource *rsrc = adata->rsrc; + struct acp_resource *rsrc; - writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); - writel(0x00, ACP_EXTERNAL_INTR_ENB(adata)); + rsrc = chip->rsrc; + writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); + writel(0x00, ACP_EXTERNAL_INTR_ENB(chip)); + + return 0; } EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON"); @@ -90,19 +140,23 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream, struct acp_dev_data *adata) { struct snd_soc_dai *dai; + struct device *dev; + struct acp_chip_info *chip; struct snd_soc_pcm_runtime *soc_runtime; u32 ext_int_ctrl; soc_runtime = snd_soc_substream_to_rtd(substream); dai = snd_soc_rtd_to_cpu(soc_runtime, 0); + dev = dai->component->dev; + chip = dev_get_platdata(dev); /* Programming channel mask and sampling rate */ writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR); /* Enabling ACP Pdm interuppts */ - ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0)); + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); ext_int_ctrl |= PDM_DMA_INTR_MASK; - writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0)); + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); set_acp_pdm_clk(substream, dai); } EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON"); @@ -113,6 +167,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, struct device *dev = dai->component->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); struct acp_resource *rsrc = adata->rsrc; + struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream = substream->runtime->private_data; u32 reg_dma_size, reg_fifo_size, reg_fifo_addr; u32 phy_addr, acp_fifo_addr, ext_int_ctrl; @@ -185,7 +240,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); - ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | BIT(BT_RX_THRESHOLD(rsrc->offset)) | BIT(I2S_TX_THRESHOLD(rsrc->offset)) | @@ -193,7 +248,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, BIT(HS_RX_THRESHOLD(rsrc->offset)) | BIT(HS_TX_THRESHOLD(rsrc->offset)); - writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); return 0; } diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 99297a388ed7..1ef9faba1d8a 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -26,6 +26,15 @@ #define ACP3x_REG_START 0x1240000 #define ACP3x_REG_END 0x125C000 +static irqreturn_t irq_handler(int irq, void *data) +{ + struct acp_chip_info *chip = data; + + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->irq) + return chip->acp_hw_ops->irq(irq, chip); + + return IRQ_NONE; +} static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo, struct device *parent, struct fwnode_handle *fw_node, @@ -166,6 +175,13 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id if (ret) goto release_regions; + ret = devm_request_irq(dev, pci->irq, irq_handler, + IRQF_SHARED, "ACP_I2S_IRQ", chip); + if (ret) { + dev_err(&pci->dev, "ACP I2S IRQ request failed %d\n", ret); + return ret; + } + check_acp_config(pci, chip); if (!chip->is_pdm_dev && !chip->is_i2s_config) goto skip_pdev_creation; @@ -213,20 +229,17 @@ static int __maybe_unused snd_acp_suspend(struct device *dev) static int __maybe_unused snd_acp_resume(struct device *dev) { struct acp_chip_info *chip; - struct acp_dev_data *adata; - struct device child; int ret; chip = dev_get_drvdata(dev); ret = acp_hw_init(chip); if (ret) dev_err(dev, "ACP init failed\n"); - if (chip->chip_pdev) { - child = chip->chip_pdev->dev; - adata = dev_get_drvdata(&child); - if (adata) - acp_enable_interrupts(adata); - } + + ret = acp_hw_en_interrupts(chip); + if (ret) + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; } diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index d4855da05b6a..9a820ef3bf46 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -145,7 +145,7 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream, { struct acp_stream *stream = substream->runtime->private_data; struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); u32 ext_int_ctrl; stream->dai_id = DMIC_INSTANCE; @@ -154,9 +154,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream, stream->reg_offset = ACP_REGION2_OFFSET; /* Enable DMIC Interrupts */ - ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0)); + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); ext_int_ctrl |= PDM_DMA_INTR_MASK; - writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0)); + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); return 0; } @@ -165,13 +165,13 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); u32 ext_int_ctrl; /* Disable DMIC interrupts */ - ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0)); + ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); ext_int_ctrl &= ~PDM_DMA_INTR_MASK; - writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0)); + writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); } const struct snd_soc_dai_ops acp_dmic_dai_ops = { diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 7d6abff28b23..9b181fb5861c 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -107,43 +107,6 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, }; -static irqreturn_t i2s_irq_handler(int irq, void *data) -{ - struct acp_dev_data *adata = data; - struct acp_resource *rsrc = adata->rsrc; - struct acp_stream *stream; - u16 i2s_flag = 0; - u32 ext_intr_stat, ext_intr_stat1; - - if (adata->rsrc->no_of_ctrls == 2) - ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1))); - - ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); - - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { - if (ext_intr_stat & stream->irq_bit) { - writel(stream->irq_bit, - ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); - snd_pcm_period_elapsed(stream->substream); - i2s_flag = 1; - } - if (adata->rsrc->no_of_ctrls == 2) { - if (ext_intr_stat1 & stream->irq_bit) { - writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata, - (rsrc->irqp_used - 1))); - snd_pcm_period_elapsed(stream->substream); - i2s_flag = 1; - } - } - } - spin_unlock(&adata->acp_lock); - if (i2s_flag) - return IRQ_HANDLED; - - return IRQ_NONE; -} - void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream) { struct acp_resource *rsrc = adata->rsrc; @@ -278,7 +241,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs } runtime->private_data = stream; - writel(1, ACP_EXTERNAL_INTR_ENB(adata)); + writel(1, ACP_EXTERNAL_INTR_ENB(chip)); spin_lock_irq(&adata->acp_lock); list_add_tail(&stream->list, &adata->stream_list); @@ -363,16 +326,17 @@ static const struct snd_soc_component_driver acp_pcm_component = { int acp_platform_register(struct device *dev) { struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip; struct snd_soc_dai_driver; unsigned int status; - status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler, - IRQF_SHARED, "ACP_I2S_IRQ", adata); - if (status) { - dev_err(dev, "ACP I2S IRQ request failed\n"); - return status; + chip = dev_get_platdata(dev); + if (!chip || !chip->base) { + dev_err(dev, "ACP chip data is NULL\n"); + return -ENODEV; } + chip->adata = adata; status = devm_snd_soc_register_component(dev, &acp_pcm_component, adata->dai_driver, adata->num_dai); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index eb09878c0d5c..13633b3f3730 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -192,6 +192,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev) return -ENODEV; } + chip->rsrc = &rsrc; adata->i2s_irq = res->start; adata->dev = dev; adata->dai_driver = acp_rmb_dai; @@ -208,7 +209,11 @@ static int rembrandt_audio_probe(struct platform_device *pdev) if (ret) return ret; } - acp_enable_interrupts(adata); + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); @@ -221,9 +226,13 @@ static int rembrandt_audio_probe(struct platform_device *pdev) static void rembrandt_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); - acp_disable_interrupts(adata); acp_platform_unregister(dev); pm_runtime_disable(&pdev->dev); } diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 2b47c6bfc9e7..94ecb17684b7 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -142,6 +142,7 @@ static int renoir_audio_probe(struct platform_device *pdev) return ret; adata->i2s_irq = ret; + chip->rsrc = &rsrc; adata->dev = dev; adata->dai_driver = acp_renoir_dai; adata->num_dai = ARRAY_SIZE(acp_renoir_dai); @@ -150,7 +151,11 @@ static int renoir_audio_probe(struct platform_device *pdev) adata->flag = chip->flag; dev_set_drvdata(dev, adata); - acp_enable_interrupts(adata); + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); @@ -164,9 +169,13 @@ static int renoir_audio_probe(struct platform_device *pdev) static void renoir_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); - acp_disable_interrupts(adata); acp_platform_unregister(dev); } diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 76a26b82e3ad..e38ad9f7fb48 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -243,6 +243,7 @@ static int acp63_audio_probe(struct platform_device *pdev) return -ENODEV; } + chip->rsrc = &rsrc; adata->i2s_irq = res->start; adata->dev = dev; adata->dai_driver = acp63_dai; @@ -258,7 +259,11 @@ static int acp63_audio_probe(struct platform_device *pdev) if (ret) return ret; } - acp_enable_interrupts(adata); + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); @@ -271,9 +276,13 @@ static int acp63_audio_probe(struct platform_device *pdev) static void acp63_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); - acp_disable_interrupts(adata); acp_platform_unregister(dev); pm_runtime_disable(&pdev->dev); } diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 3e603c5f736a..be4302a5a584 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -174,6 +174,7 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) return -ENODEV; } + chip->rsrc = &rsrc; adata->i2s_irq = res->start; adata->dev = dev; adata->dai_driver = acp70_dai; @@ -190,7 +191,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); return ret; } - acp_enable_interrupts(adata); + ret = acp_hw_en_interrupts(chip); + if (ret) { + dev_err(dev, "ACP en-interrupts failed\n"); + return ret; + } acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); @@ -203,9 +208,13 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) static void acp_acp70_audio_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); + int ret; + + ret = acp_hw_dis_interrupts(chip); + if (ret) + dev_err(dev, "ACP dis-interrupts failed\n"); - acp_disable_interrupts(adata); acp_platform_unregister(dev); pm_runtime_disable(&pdev->dev); } diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index b7a1b4aa8fef..4beaa9cae352 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -147,10 +147,12 @@ struct acp_chip_info { struct snd_acp_hw_ops *acp_hw_ops; int (*acp_hw_ops_init)(struct acp_chip_info *chip); struct platform_device *chip_pdev; + struct acp_resource *rsrc; /* Platform specific resources*/ struct platform_device *dmic_codec_dev; struct platform_device *acp_plat_dev; struct platform_device *mach_dev; struct snd_soc_acpi_mach *machines; + struct acp_dev_data *adata; u32 addr; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ @@ -215,11 +217,19 @@ struct acp_dev_data { * struct snd_acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization * @acp_deinit: ACP de-initialization + * @irq: ACP irq handler + * @en_interrupts: ACP enable interrupts + * @dis_interrupts: ACP disable interrupts */ struct snd_acp_hw_ops { /* ACP hardware initilizations */ int (*acp_init)(struct acp_chip_info *chip); int (*acp_deinit)(struct acp_chip_info *chip); + + /* ACP Interrupts*/ + irqreturn_t (*irq)(int irq, void *data); + int (*en_interrupts)(struct acp_chip_info *chip); + int (*dis_interrupts)(struct acp_chip_info *chip); }; enum acp_config { @@ -332,8 +342,9 @@ int acp_machine_select(struct acp_chip_info *chip); int acp_init(struct acp_chip_info *chip); int acp_deinit(struct acp_chip_info *chip); -void acp_enable_interrupts(struct acp_dev_data *adata); -void acp_disable_interrupts(struct acp_dev_data *adata); +int acp_enable_interrupts(struct acp_chip_info *chip); +int acp_disable_interrupts(struct acp_chip_info *chip); +irqreturn_t acp_irq_handler(int irq, void *data); extern struct snd_acp_hw_ops acp31_common_hw_ops; extern struct snd_acp_hw_ops acp6x_common_hw_ops; @@ -370,6 +381,20 @@ static inline int acp_hw_deinit(struct acp_chip_info *chip) return -EOPNOTSUPP; } +static inline int acp_hw_en_interrupts(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->en_interrupts) + return chip->acp_hw_ops->en_interrupts(chip); + return -EOPNOTSUPP; +} + +static inline int acp_hw_dis_interrupts(struct acp_chip_info *chip) +{ + if (chip && chip->acp_hw_ops && chip->acp_hw_ops->dis_interrupts) + chip->acp_hw_ops->dis_interrupts(chip); + return -EOPNOTSUPP; +} + static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction) { u64 byte_count = 0, low = 0, high = 0; diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h index 117ea63e85c6..82275c9de53a 100644 --- a/sound/soc/amd/acp/chip_offset_byte.h +++ b/sound/soc/amd/acp/chip_offset_byte.h @@ -29,13 +29,13 @@ #define ACP_PIN_CONFIG 0x1440 #define ACP3X_PIN_CONFIG 0x1400 -#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \ - (adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04)) +#define ACP_EXTERNAL_INTR_REG_ADDR(chip, offset, ctrl) \ + (chip->base + chip->rsrc->irq_reg_offset + offset + (ctrl * 0x04)) -#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0) -#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl) -#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \ - (0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl) +#define ACP_EXTERNAL_INTR_ENB(chip) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x0, 0x0) +#define ACP_EXTERNAL_INTR_CNTL(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x4, ctrl) +#define ACP_EXTERNAL_INTR_STAT(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, \ + (0x4 + (chip->rsrc->no_of_ctrls * 0x04)), ctrl) /* Registers from ACP_AUDIO_BUFFERS block */ From e3933683b25e2cc94485da4909e3338e1a177b39 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:54 +0530 Subject: [PATCH 0863/1090] ASoC: amd: acp: Remove redundant acp_dev_data structure Move acp_dev_data structure members to acp_chip_info structure to avoid using common members in each structure and remove redundant acp_dev_data structure. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-8-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-i2s.c | 179 +++++++++++++------------- sound/soc/amd/acp/acp-legacy-common.c | 107 ++++++++------- sound/soc/amd/acp/acp-pdm.c | 41 +++--- sound/soc/amd/acp/acp-platform.c | 70 +++++----- sound/soc/amd/acp/acp-rembrandt.c | 53 ++------ sound/soc/amd/acp/acp-renoir.c | 48 ++----- sound/soc/amd/acp/acp63.c | 58 +++------ sound/soc/amd/acp/acp70.c | 50 ++----- sound/soc/amd/acp/amd.h | 86 +++++-------- 9 files changed, 274 insertions(+), 418 deletions(-) diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 2f458c76f9fc..a38409dd1d34 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -31,14 +31,10 @@ #define ACP63_LRCLK_DIV_FIELD GENMASK(12, 2) #define ACP63_BCLK_DIV_FIELD GENMASK(23, 13) -static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id) +static inline void acp_set_i2s_clk(struct acp_chip_info *chip, int dai_id) { u32 i2s_clk_reg, val; - struct acp_chip_info *chip; - struct device *dev; - dev = adata->dev; - chip = dev_get_platdata(dev); switch (dai_id) { case I2S_SP_INSTANCE: i2s_clk_reg = ACP_I2STDM0_MSTRCLKGEN; @@ -55,36 +51,37 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id) } val = I2S_MASTER_MODE_ENABLE; - if (adata->tdm_mode) + if (chip->tdm_mode) val |= BIT(1); switch (chip->acp_rev) { case ACP63_PCI_ID: case ACP70_PCI_ID: case ACP71_PCI_ID: - val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div); - val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div); + val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, chip->lrclk_div); + val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, chip->bclk_div); break; default: - val |= FIELD_PREP(LRCLK_DIV_FIELD, adata->lrclk_div); - val |= FIELD_PREP(BCLK_DIV_FIELD, adata->bclk_div); + val |= FIELD_PREP(LRCLK_DIV_FIELD, chip->lrclk_div); + val |= FIELD_PREP(BCLK_DIV_FIELD, chip->bclk_div); } - writel(val, adata->acp_base + i2s_clk_reg); + writel(val, chip->base + i2s_clk_reg); } static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai); + struct device *dev = cpu_dai->component->dev; + struct acp_chip_info *chip = dev_get_platdata(dev); int mode; mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; switch (mode) { case SND_SOC_DAIFMT_I2S: - adata->tdm_mode = TDM_DISABLE; + chip->tdm_mode = TDM_DISABLE; break; case SND_SOC_DAIFMT_DSP_A: - adata->tdm_mode = TDM_ENABLE; + chip->tdm_mode = TDM_ENABLE; break; default: return -EINVAL; @@ -96,7 +93,6 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas int slots, int slot_width) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai); struct acp_chip_info *chip; struct acp_stream *stream; int slot_len, no_of_slots; @@ -157,35 +153,35 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas slots = no_of_slots; - spin_lock_irq(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock_irq(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { switch (chip->acp_rev) { case ACP_RN_PCI_ID: case ACP_RMB_PCI_ID: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) - adata->tdm_tx_fmt[stream->dai_id - 1] = + chip->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) - adata->tdm_rx_fmt[stream->dai_id - 1] = + chip->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); break; case ACP63_PCI_ID: case ACP70_PCI_ID: case ACP71_PCI_ID: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) - adata->tdm_tx_fmt[stream->dai_id - 1] = + chip->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 13) | (slot_len << 18); else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) - adata->tdm_rx_fmt[stream->dai_id - 1] = + chip->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 13) | (slot_len << 18); break; default: dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); - spin_unlock_irq(&adata->acp_lock); + spin_unlock_irq(&chip->acp_lock); return -EINVAL; } } - spin_unlock_irq(&adata->acp_lock); + spin_unlock_irq(&chip->acp_lock); return 0; } @@ -193,15 +189,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata; + struct acp_chip_info *chip; struct acp_resource *rsrc; u32 val; u32 xfer_resolution; u32 reg_val, fmt_reg, tdm_fmt; u32 lrclk_div_val, bclk_div_val; - adata = snd_soc_dai_get_drvdata(dai); - rsrc = adata->rsrc; + chip = dev_get_platdata(dev); + rsrc = chip->rsrc; /* These values are as per Hardware Spec */ switch (params_format(params)) { @@ -240,7 +236,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ dev_err(dev, "Invalid dai id %x\n", dai->driver->id); return -EINVAL; } - adata->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution; + chip->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution; } else { switch (dai->driver->id) { case I2S_BT_INSTANCE: @@ -259,22 +255,22 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ dev_err(dev, "Invalid dai id %x\n", dai->driver->id); return -EINVAL; } - adata->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution; + chip->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution; } - val = readl(adata->acp_base + reg_val); + val = readl(chip->base + reg_val); val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK; val = val | (xfer_resolution << 3); - writel(val, adata->acp_base + reg_val); + writel(val, chip->base + reg_val); - if (adata->tdm_mode) { - val = readl(adata->acp_base + reg_val); - writel(val | BIT(1), adata->acp_base + reg_val); + if (chip->tdm_mode) { + val = readl(chip->base + reg_val); + writel(val | BIT(1), chip->base + reg_val); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1]; + tdm_fmt = chip->tdm_tx_fmt[dai->driver->id - 1]; else - tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1]; - writel(tdm_fmt, adata->acp_base + fmt_reg); + tdm_fmt = chip->tdm_rx_fmt[dai->driver->id - 1]; + writel(tdm_fmt, chip->base + fmt_reg); } if (rsrc->soc_mclk) { @@ -377,8 +373,8 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ default: break; } - adata->lrclk_div = lrclk_div_val; - adata->bclk_div = bclk_div_val; + chip->lrclk_div = lrclk_div_val; + chip->bclk_div = bclk_div_val; } return 0; } @@ -387,8 +383,8 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct { struct acp_stream *stream = substream->runtime->private_data; struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_resource *rsrc = adata->rsrc; + struct acp_chip_info *chip = dev_get_platdata(dev); + struct acp_resource *rsrc = chip->rsrc; u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg; period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); @@ -398,20 +394,20 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream); + stream->bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai->driver->id) { case I2S_BT_INSTANCE: - water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(adata); + water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(chip); reg_val = ACP_BTTDM_ITER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_TX_RINGBUFSIZE(adata); + buf_reg = ACP_BT_TX_RINGBUFSIZE(chip); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(adata); + water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(chip); reg_val = ACP_I2STDM_ITER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_TX_RINGBUFSIZE(adata); + buf_reg = ACP_I2S_TX_RINGBUFSIZE(chip); break; case I2S_HS_INSTANCE: water_val = ACP_HS_TX_INTR_WATERMARK_SIZE; @@ -426,16 +422,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct } else { switch (dai->driver->id) { case I2S_BT_INSTANCE: - water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(adata); + water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(chip); reg_val = ACP_BTTDM_IRER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_RX_RINGBUFSIZE(adata); + buf_reg = ACP_BT_RX_RINGBUFSIZE(chip); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(adata); + water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(chip); reg_val = ACP_I2STDM_IRER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_RX_RINGBUFSIZE(adata); + buf_reg = ACP_I2S_RX_RINGBUFSIZE(chip); break; case I2S_HS_INSTANCE: water_val = ACP_HS_RX_INTR_WATERMARK_SIZE; @@ -449,14 +445,14 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct } } - writel(period_bytes, adata->acp_base + water_val); - writel(buf_size, adata->acp_base + buf_reg); + writel(period_bytes, chip->base + water_val); + writel(buf_size, chip->base + buf_reg); if (rsrc->soc_mclk) - acp_set_i2s_clk(adata, dai->driver->id); - val = readl(adata->acp_base + reg_val); + acp_set_i2s_clk(chip, dai->driver->id); + val = readl(chip->base + reg_val); val = val | BIT(0); - writel(val, adata->acp_base + reg_val); - writel(1, adata->acp_base + ier_val); + writel(val, chip->base + reg_val); + writel(1, chip->base + ier_val); return 0; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -493,19 +489,19 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct return -EINVAL; } } - val = readl(adata->acp_base + reg_val); + val = readl(chip->base + reg_val); val = val & ~BIT(0); - writel(val, adata->acp_base + reg_val); + writel(val, chip->base + reg_val); - if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) && - !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0))) - writel(0, adata->acp_base + ACP_BTTDM_IER); - if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) && - !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0))) - writel(0, adata->acp_base + ACP_I2STDM_IER); - if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) && - !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0))) - writel(0, adata->acp_base + ACP_HSTDM_IER); + if (!(readl(chip->base + ACP_BTTDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_BTTDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_BTTDM_IER); + if (!(readl(chip->base + ACP_I2STDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_I2STDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_I2STDM_IER); + if (!(readl(chip->base + ACP_HSTDM_ITER) & BIT(0)) && + !(readl(chip->base + ACP_HSTDM_IRER) & BIT(0))) + writel(0, chip->base + ACP_HSTDM_IER); return 0; default: return -EINVAL; @@ -517,9 +513,8 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_chip_info *chip; - struct acp_resource *rsrc = adata->rsrc; + struct acp_chip_info *chip = dev_get_platdata(dev); + struct acp_resource *rsrc = chip->rsrc; struct acp_stream *stream = substream->runtime->private_data; u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0; u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl; @@ -529,56 +524,56 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d switch (dai->driver->id) { case I2S_SP_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); + reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + SP_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); - reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip); if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START; else phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_I2S_TX_RINGBUFADDR(chip)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); + reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + SP_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); - reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip); if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START; else phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_I2S_RX_RINGBUFADDR(chip)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); + reg_dma_size = ACP_BT_TX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + BT_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); - reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); + reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip); if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START; else phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_BT_TX_RINGBUFADDR(chip)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); + reg_dma_size = ACP_BT_RX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + BT_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); - reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); + reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip); if (chip->acp_rev >= ACP70_PCI_ID) phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START; else phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip)); } break; case I2S_HS_INSTANCE: @@ -593,7 +588,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START; else phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR); + writel(phy_addr, chip->base + ACP_HS_TX_RINGBUFADDR); } else { reg_dma_size = ACP_HS_RX_DMA_SIZE; acp_fifo_addr = rsrc->sram_pte_offset + @@ -605,7 +600,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START; else phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR); + writel(phy_addr, chip->base + ACP_HS_RX_RINGBUFADDR); } break; default: @@ -613,9 +608,9 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d return -EINVAL; } - writel(DMA_SIZE, adata->acp_base + reg_dma_size); - writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); - writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); + writel(DMA_SIZE, chip->base + reg_dma_size); + writel(acp_fifo_addr, chip->base + reg_fifo_addr); + writel(FIFO_SIZE, chip->base + reg_fifo_size); ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | @@ -634,8 +629,8 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d { struct acp_stream *stream = substream->runtime->private_data; struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_resource *rsrc = adata->rsrc; + struct acp_chip_info *chip = dev_get_platdata(dev); + struct acp_resource *rsrc = chip->rsrc; unsigned int dir = substream->stream; unsigned int irq_bit = 0; diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 13fddce8df56..988b7a17b2f4 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -38,26 +38,25 @@ EXPORT_SYMBOL_NS_GPL(acp_common_hw_ops, "SND_SOC_ACP_COMMON"); irqreturn_t acp_irq_handler(int irq, void *data) { struct acp_chip_info *chip = data; - struct acp_dev_data *adata = chip->adata; - struct acp_resource *rsrc = adata->rsrc; + struct acp_resource *rsrc = chip->rsrc; struct acp_stream *stream; u16 i2s_flag = 0; u32 ext_intr_stat, ext_intr_stat1; - if (adata->rsrc->no_of_ctrls == 2) + if (rsrc->no_of_ctrls == 2) ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1))); ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { if (ext_intr_stat & stream->irq_bit) { writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); snd_pcm_period_elapsed(stream->substream); i2s_flag = 1; } - if (adata->rsrc->no_of_ctrls == 2) { + if (chip->rsrc->no_of_ctrls == 2) { if (ext_intr_stat1 & stream->irq_bit) { writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1))); @@ -66,7 +65,7 @@ irqreturn_t acp_irq_handler(int irq, void *data) } } } - spin_unlock(&adata->acp_lock); + spin_unlock(&chip->acp_lock); if (i2s_flag) return IRQ_HANDLED; @@ -106,7 +105,7 @@ static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct acp_stream *stream = runtime->private_data; struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); u32 physical_addr, pdm_size, period_bytes; @@ -115,43 +114,40 @@ static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream, physical_addr = stream->reg_offset + MEM_WINDOW_START; /* Init ACP PDM Ring buffer */ - writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR); - writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE); - writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); - writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); + writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR); + writel(pdm_size, chip->base + ACP_WOV_RX_RINGBUFSIZE); + writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); } static void set_acp_pdm_clk(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); unsigned int pdm_ctrl; /* Enable default ACP PDM clk */ - writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL); - pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL); + writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL); + pdm_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL); pdm_ctrl |= PDM_MISC_CTRL_MASK; - writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL); + writel(pdm_ctrl, chip->base + ACP_WOV_MISC_CTRL); set_acp_pdm_ring_buffer(substream, dai); } void restore_acp_pdm_params(struct snd_pcm_substream *substream, - struct acp_dev_data *adata) + struct acp_chip_info *chip) { struct snd_soc_dai *dai; - struct device *dev; - struct acp_chip_info *chip; struct snd_soc_pcm_runtime *soc_runtime; u32 ext_int_ctrl; soc_runtime = snd_soc_substream_to_rtd(substream); dai = snd_soc_rtd_to_cpu(soc_runtime, 0); - dev = dai->component->dev; - chip = dev_get_platdata(dev); + /* Programming channel mask and sampling rate */ - writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); - writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR); + writel(chip->ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS); + writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR); /* Enabling ACP Pdm interuppts */ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); @@ -165,9 +161,8 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_resource *rsrc = adata->rsrc; struct acp_chip_info *chip = dev_get_platdata(dev); + struct acp_resource *rsrc = chip->rsrc; struct acp_stream *stream = substream->runtime->private_data; u32 reg_dma_size, reg_fifo_size, reg_fifo_addr; u32 phy_addr, acp_fifo_addr, ext_int_ctrl; @@ -176,40 +171,40 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, switch (dai->driver->id) { case I2S_SP_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); + reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + SP_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); - reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip); phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_I2S_TX_RINGBUFADDR(chip)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); + reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + SP_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); - reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip); phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_I2S_RX_RINGBUFADDR(chip)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); + reg_dma_size = ACP_BT_TX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + BT_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); - reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); + reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_BT_TX_RINGBUFADDR(chip)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); + reg_dma_size = ACP_BT_RX_DMA_SIZE(chip); acp_fifo_addr = rsrc->sram_pte_offset + BT_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); - reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); + reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); + writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip)); } break; case I2S_HS_INSTANCE: @@ -220,7 +215,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, reg_fifo_addr = ACP_HS_TX_FIFOADDR; reg_fifo_size = ACP_HS_TX_FIFOSIZE; phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR); + writel(phy_addr, chip->base + ACP_HS_TX_RINGBUFADDR); } else { reg_dma_size = ACP_HS_RX_DMA_SIZE; acp_fifo_addr = rsrc->sram_pte_offset + @@ -228,7 +223,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, reg_fifo_addr = ACP_HS_RX_FIFOADDR; reg_fifo_size = ACP_HS_RX_FIFOSIZE; phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR); + writel(phy_addr, chip->base + ACP_HS_RX_RINGBUFADDR); } break; default: @@ -236,9 +231,9 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, return -EINVAL; } - writel(DMA_SIZE, adata->acp_base + reg_dma_size); - writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr); - writel(FIFO_SIZE, adata->acp_base + reg_fifo_size); + writel(DMA_SIZE, chip->base + reg_dma_size); + writel(acp_fifo_addr, chip->base + reg_fifo_addr); + writel(FIFO_SIZE, chip->base + reg_fifo_size); ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | @@ -253,7 +248,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, } int restore_acp_i2s_params(struct snd_pcm_substream *substream, - struct acp_dev_data *adata, + struct acp_chip_info *chip, struct acp_stream *stream) { struct snd_soc_dai *dai; @@ -263,7 +258,7 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream, soc_runtime = snd_soc_substream_to_rtd(substream); dai = snd_soc_rtd_to_cpu(soc_runtime, 0); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1]; + tdm_fmt = chip->tdm_tx_fmt[stream->dai_id - 1]; switch (stream->dai_id) { case I2S_BT_INSTANCE: reg_val = ACP_BTTDM_ITER; @@ -281,9 +276,9 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream, pr_err("Invalid dai id %x\n", stream->dai_id); return -EINVAL; } - val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3; + val = chip->xfer_tx_resolution[stream->dai_id - 1] << 3; } else { - tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1]; + tdm_fmt = chip->tdm_rx_fmt[stream->dai_id - 1]; switch (stream->dai_id) { case I2S_BT_INSTANCE: reg_val = ACP_BTTDM_IRER; @@ -301,13 +296,13 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream, pr_err("Invalid dai id %x\n", stream->dai_id); return -EINVAL; } - val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3; + val = chip->xfer_rx_resolution[stream->dai_id - 1] << 3; } - writel(val, adata->acp_base + reg_val); - if (adata->tdm_mode == TDM_ENABLE) { - writel(tdm_fmt, adata->acp_base + fmt_reg); - val = readl(adata->acp_base + reg_val); - writel(val | 0x2, adata->acp_base + reg_val); + writel(val, chip->base + reg_val); + if (chip->tdm_mode == TDM_ENABLE) { + writel(tdm_fmt, chip->base + fmt_reg); + val = readl(chip->base + reg_val); + writel(val | 0x2, chip->base + reg_val); } return set_acp_i2s_dma_fifo(substream, dai); } diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index 9a820ef3bf46..1bfc34c2aa53 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -30,17 +30,16 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, { struct acp_stream *stream = substream->runtime->private_data; struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); struct acp_chip_info *chip; u32 physical_addr, size_dmic, period_bytes; unsigned int dmic_ctrl; chip = dev_get_platdata(dev); /* Enable default DMIC clk */ - writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL); - dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL); + writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL); + dmic_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL); dmic_ctrl |= PDM_MISC_CTRL_MASK; - writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL); + writel(dmic_ctrl, chip->base + ACP_WOV_MISC_CTRL); period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); @@ -53,10 +52,10 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, physical_addr = stream->reg_offset + MEM_WINDOW_START; /* Init DMIC Ring buffer */ - writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR); - writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE); - writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); - writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); + writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR); + writel(size_dmic, chip->base + ACP_WOV_RX_RINGBUFSIZE); + writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE); + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); return 0; } @@ -65,7 +64,7 @@ static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); unsigned int dma_enable; int ret = 0; @@ -73,27 +72,27 @@ static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE); + dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE); if (!(dma_enable & DMA_EN_MASK)) { - writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE); - writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE); + writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_ENABLE); + writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE); } - ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE, + ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE, dma_enable, (dma_enable & DMA_EN_MASK), DELAY_US, PDM_TIMEOUT); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE); + dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE); if ((dma_enable & DMA_EN_MASK)) { - writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE); - writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE); + writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_ENABLE); + writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE); } - ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE, + ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE, dma_enable, !(dma_enable & DMA_EN_MASK), DELAY_US, PDM_TIMEOUT); break; @@ -109,7 +108,7 @@ static int acp_dmic_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai) { struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); unsigned int channels, ch_mask; channels = params_channels(hwparams); @@ -128,14 +127,14 @@ static int acp_dmic_hwparams(struct snd_pcm_substream *substream, return -EINVAL; } - adata->ch_mask = ch_mask; + chip->ch_mask = ch_mask; if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) { dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams)); return -EINVAL; } - writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS); - writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR); + writel(ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS); + writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR); return 0; } diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 9b181fb5861c..8d61e1991e4f 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -107,37 +107,37 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, }; -void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream) +void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream) { - struct acp_resource *rsrc = adata->rsrc; + struct acp_resource *rsrc = chip->rsrc; u32 reg_val; reg_val = rsrc->sram_pte_offset; stream->reg_offset = 0x02000000; - writel((reg_val + GRP1_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); - writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + writel((reg_val + GRP1_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); - writel((reg_val + GRP2_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); - writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); + writel((reg_val + GRP2_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); - writel(reg_val | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5); - writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5); + writel(reg_val | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5); + writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5); - writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); + writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); } EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON"); -void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size) +void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size) { struct snd_pcm_substream *substream = stream->substream; - struct acp_resource *rsrc = adata->rsrc; + struct acp_resource *rsrc = chip->rsrc; dma_addr_t addr = substream->dma_buffer.addr; int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); u32 low, high, val; u16 page_idx; - switch (adata->acp_rev) { + switch (chip->acp_rev) { case ACP70_PCI_ID: case ACP71_PCI_ID: switch (stream->dai_id) { @@ -163,7 +163,7 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s val = 0x6000; break; default: - dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id); + dev_err(chip->dev, "Invalid dai id %x\n", stream->dai_id); return; } break; @@ -176,9 +176,9 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s /* Load the low address of page int ACP SRAM through SRBM */ low = lower_32_bits(addr); high = upper_32_bits(addr); - writel(low, adata->acp_base + rsrc->scratch_reg_offset + val); + writel(low, chip->base + rsrc->scratch_reg_offset + val); high |= BIT(31); - writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4); + writel(high, chip->base + rsrc->scratch_reg_offset + val + 4); /* Move to next physically contiguous page */ val += 8; @@ -191,7 +191,6 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs { struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); struct acp_chip_info *chip; struct acp_stream *stream; int ret; @@ -201,7 +200,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs return -ENOMEM; stream->substream = substream; - chip = dev_get_platdata(dev); + chip = dev_get_drvdata(dev->parent); switch (chip->acp_rev) { case ACP63_PCI_ID: case ACP70_PCI_ID: @@ -243,9 +242,9 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs writel(1, ACP_EXTERNAL_INTR_ENB(chip)); - spin_lock_irq(&adata->acp_lock); - list_add_tail(&stream->list, &adata->stream_list); - spin_unlock_irq(&adata->acp_lock); + spin_lock_irq(&chip->acp_lock); + list_add_tail(&stream->list, &chip->stream_list); + spin_unlock_irq(&chip->acp_lock); return ret; } @@ -254,13 +253,14 @@ static int acp_dma_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct acp_dev_data *adata = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); struct acp_stream *stream = substream->runtime->private_data; u64 size = params_buffer_bytes(params); /* Configure ACP DMA block with params */ - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, size); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, size); return 0; } @@ -269,7 +269,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct device *dev = component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); struct acp_stream *stream = substream->runtime->private_data; u32 pos, buffersize; u64 bytescount; @@ -277,7 +277,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, buffersize = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); - bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream); + bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); if (bytescount > stream->bytescount) bytescount -= stream->bytescount; @@ -301,13 +301,13 @@ static int acp_dma_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct device *dev = component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_drvdata(dev->parent); struct acp_stream *stream = substream->runtime->private_data; /* Remove entry from list */ - spin_lock_irq(&adata->acp_lock); + spin_lock_irq(&chip->acp_lock); list_del(&stream->list); - spin_unlock_irq(&adata->acp_lock); + spin_unlock_irq(&chip->acp_lock); kfree(stream); return 0; @@ -325,7 +325,6 @@ static const struct snd_soc_component_driver acp_pcm_component = { int acp_platform_register(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); struct acp_chip_info *chip; struct snd_soc_dai_driver; unsigned int status; @@ -336,17 +335,16 @@ int acp_platform_register(struct device *dev) return -ENODEV; } - chip->adata = adata; status = devm_snd_soc_register_component(dev, &acp_pcm_component, - adata->dai_driver, - adata->num_dai); + chip->dai_driver, + chip->num_dai); if (status) { dev_err(dev, "Fail to register acp i2s component\n"); return status; } - INIT_LIST_HEAD(&adata->stream_list); - spin_lock_init(&adata->acp_lock); + INIT_LIST_HEAD(&chip->stream_list); + spin_lock_init(&chip->acp_lock); return 0; } @@ -354,10 +352,6 @@ EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON"); int acp_platform_unregister(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); - - if (adata->mach_dev) - platform_device_unregister(adata->mach_dev); return 0; } EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON"); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 13633b3f3730..dfb18d5cdc7a 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -157,8 +157,6 @@ static int rembrandt_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; - struct acp_dev_data *adata; - struct resource *res; u32 ret; chip = dev_get_platdata(&pdev->dev); @@ -172,37 +170,10 @@ static int rembrandt_audio_probe(struct platform_device *pdev) return -ENODEV; } - adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); - if (!adata) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); - return -ENODEV; - } - - adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!adata->acp_base) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); - return -ENODEV; - } - + chip->dev = dev; chip->rsrc = &rsrc; - adata->i2s_irq = res->start; - adata->dev = dev; - adata->dai_driver = acp_rmb_dai; - adata->num_dai = ARRAY_SIZE(acp_rmb_dai); - adata->rsrc = &rsrc; - adata->acp_rev = chip->acp_rev; - adata->flag = chip->flag; - adata->is_i2s_config = chip->is_i2s_config; - - dev_set_drvdata(dev, adata); + chip->dai_driver = acp_rmb_dai; + chip->num_dai = ARRAY_SIZE(acp_rmb_dai); if (chip->is_i2s_config && rsrc.soc_mclk) { ret = acp6x_master_clock_generate(dev); @@ -239,30 +210,30 @@ static void rembrandt_audio_remove(struct platform_device *pdev) static int __maybe_unused rmb_pcm_resume(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; struct snd_pcm_substream *substream; snd_pcm_uframes_t buf_in_frames; u64 buf_size; - if (adata->is_i2s_config && adata->rsrc->soc_mclk) + if (chip->is_i2s_config && chip->rsrc->soc_mclk) acp6x_master_clock_generate(dev); - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { substream = stream->substream; if (substream && substream->runtime) { buf_in_frames = (substream->runtime->buffer_size); buf_size = frames_to_bytes(substream->runtime, buf_in_frames); - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, buf_size); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); if (stream->dai_id) - restore_acp_i2s_params(substream, adata, stream); + restore_acp_i2s_params(substream, chip, stream); else - restore_acp_pdm_params(substream, adata); + restore_acp_pdm_params(substream, chip); } } - spin_unlock(&adata->acp_lock); + spin_unlock(&chip->acp_lock); return 0; } diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 94ecb17684b7..2037af67509a 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -108,8 +108,6 @@ static int renoir_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; - struct acp_dev_data *adata; - struct resource *res; int ret; chip = dev_get_platdata(&pdev->dev); @@ -123,39 +121,17 @@ static int renoir_audio_probe(struct platform_device *pdev) return -ENODEV; } - adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); - if (!adata) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); - return -ENODEV; - } - - adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!adata->acp_base) - return -ENOMEM; - - ret = platform_get_irq_byname(pdev, "acp_dai_irq"); - if (ret < 0) - return ret; - adata->i2s_irq = ret; - + chip->dev = dev; chip->rsrc = &rsrc; - adata->dev = dev; - adata->dai_driver = acp_renoir_dai; - adata->num_dai = ARRAY_SIZE(acp_renoir_dai); - adata->rsrc = &rsrc; - adata->acp_rev = chip->acp_rev; - adata->flag = chip->flag; + chip->dai_driver = acp_renoir_dai; + chip->num_dai = ARRAY_SIZE(acp_renoir_dai); - dev_set_drvdata(dev, adata); ret = acp_hw_en_interrupts(chip); if (ret) { dev_err(dev, "ACP en-interrupts failed\n"); return ret; } + acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); @@ -181,27 +157,27 @@ static void renoir_audio_remove(struct platform_device *pdev) static int __maybe_unused rn_pcm_resume(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; struct snd_pcm_substream *substream; snd_pcm_uframes_t buf_in_frames; u64 buf_size; - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { substream = stream->substream; if (substream && substream->runtime) { buf_in_frames = (substream->runtime->buffer_size); buf_size = frames_to_bytes(substream->runtime, buf_in_frames); - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, buf_size); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); if (stream->dai_id) - restore_acp_i2s_params(substream, adata, stream); + restore_acp_i2s_params(substream, chip, stream); else - restore_acp_pdm_params(substream, adata); + restore_acp_pdm_params(substream, chip); } } - spin_unlock(&adata->acp_lock); + spin_unlock(&chip->acp_lock); return 0; } diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index e38ad9f7fb48..49786e1a214f 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -153,7 +153,7 @@ static struct snd_soc_dai_driver acp63_dai[] = { }, }; -static int acp63_i2s_master_clock_generate(struct acp_dev_data *adata) +static int acp63_i2s_master_clock_generate(struct acp_chip_info *chip) { int rc; u32 data; @@ -208,8 +208,6 @@ static int acp63_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; - struct acp_dev_data *adata; - struct resource *res; int ret; chip = dev_get_platdata(&pdev->dev); @@ -223,39 +221,13 @@ static int acp63_audio_probe(struct platform_device *pdev) return -ENODEV; } - adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); - if (!adata) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); - return -ENODEV; - } - - adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!adata->acp_base) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); - return -ENODEV; - } - + chip->dev = dev; chip->rsrc = &rsrc; - adata->i2s_irq = res->start; - adata->dev = dev; - adata->dai_driver = acp63_dai; - adata->num_dai = ARRAY_SIZE(acp63_dai); - adata->rsrc = &rsrc; - adata->acp_rev = chip->acp_rev; - adata->flag = chip->flag; - adata->is_i2s_config = chip->is_i2s_config; - dev_set_drvdata(dev, adata); + chip->dai_driver = acp63_dai; + chip->num_dai = ARRAY_SIZE(acp63_dai); if (chip->is_i2s_config && rsrc.soc_mclk) { - ret = acp63_i2s_master_clock_generate(adata); + ret = acp63_i2s_master_clock_generate(chip); if (ret) return ret; } @@ -289,30 +261,30 @@ static void acp63_audio_remove(struct platform_device *pdev) static int __maybe_unused acp63_pcm_resume(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; struct snd_pcm_substream *substream; snd_pcm_uframes_t buf_in_frames; u64 buf_size; - if (adata->is_i2s_config && adata->rsrc->soc_mclk) - acp63_i2s_master_clock_generate(adata); + if (chip->is_i2s_config && chip->rsrc->soc_mclk) + acp63_i2s_master_clock_generate(chip); - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { substream = stream->substream; if (substream && substream->runtime) { buf_in_frames = (substream->runtime->buffer_size); buf_size = frames_to_bytes(substream->runtime, buf_in_frames); - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, buf_size); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); if (stream->dai_id) - restore_acp_i2s_params(substream, adata, stream); + restore_acp_i2s_params(substream, chip, stream); else - restore_acp_pdm_params(substream, adata); + restore_acp_pdm_params(substream, chip); } } - spin_unlock(&adata->acp_lock); + spin_unlock(&chip->acp_lock); return 0; } diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index be4302a5a584..c1b546df5e67 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -135,8 +135,6 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; - struct acp_dev_data *adata; - struct resource *res; int ret; chip = dev_get_platdata(&pdev->dev); @@ -154,36 +152,10 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) return -ENODEV; } - adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); - if (!adata) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); - return -ENODEV; - } - - adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!adata->acp_base) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq"); - if (!res) { - dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); - return -ENODEV; - } - + chip->dev = dev; chip->rsrc = &rsrc; - adata->i2s_irq = res->start; - adata->dev = dev; - adata->dai_driver = acp70_dai; - adata->num_dai = ARRAY_SIZE(acp70_dai); - adata->rsrc = &rsrc; - adata->acp_rev = chip->acp_rev; - adata->flag = chip->flag; - - dev_set_drvdata(dev, adata); + chip->dai_driver = acp70_dai; + chip->num_dai = ARRAY_SIZE(acp70_dai); /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ ret = amd_smn_write(0, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); @@ -221,27 +193,27 @@ static void acp_acp70_audio_remove(struct platform_device *pdev) static int __maybe_unused acp70_pcm_resume(struct device *dev) { - struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; struct snd_pcm_substream *substream; snd_pcm_uframes_t buf_in_frames; u64 buf_size; - spin_lock(&adata->acp_lock); - list_for_each_entry(stream, &adata->stream_list, list) { + spin_lock(&chip->acp_lock); + list_for_each_entry(stream, &chip->stream_list, list) { substream = stream->substream; if (substream && substream->runtime) { buf_in_frames = (substream->runtime->buffer_size); buf_size = frames_to_bytes(substream->runtime, buf_in_frames); - config_pte_for_stream(adata, stream); - config_acp_dma(adata, stream, buf_size); + config_pte_for_stream(chip, stream); + config_acp_dma(chip, stream, buf_size); if (stream->dai_id) - restore_acp_i2s_params(substream, adata, stream); + restore_acp_i2s_params(substream, chip, stream); else - restore_acp_pdm_params(substream, adata); + restore_acp_pdm_params(substream, chip); } } - spin_unlock(&adata->acp_lock); + spin_unlock(&chip->acp_lock); return 0; } diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 4beaa9cae352..084d9db1b65c 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -142,22 +142,34 @@ struct acp_chip_info { char *name; /* Platform name */ struct resource *res; struct device *dev; + struct snd_soc_dai_driver *dai_driver; + unsigned int acp_rev; /* ACP Revision id */ void __iomem *base; /* ACP memory PCI base */ struct snd_acp_hw_ops *acp_hw_ops; int (*acp_hw_ops_init)(struct acp_chip_info *chip); struct platform_device *chip_pdev; struct acp_resource *rsrc; /* Platform specific resources*/ + struct list_head stream_list; + spinlock_t acp_lock; /* Used to protect stream_list */ struct platform_device *dmic_codec_dev; struct platform_device *acp_plat_dev; struct platform_device *mach_dev; struct snd_soc_acpi_mach *machines; - struct acp_dev_data *adata; + int num_dai; u32 addr; + u32 bclk_div; + u32 lrclk_div; + u32 ch_mask; + u32 tdm_tx_fmt[3]; + u32 tdm_rx_fmt[3]; + u32 xfer_tx_resolution[3]; + u32 xfer_rx_resolution[3]; unsigned int flag; /* Distinguish b/w Legacy or Only PDM */ bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */ bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */ bool is_i2s_config; /* flag set to true when I2S configuration is selected from BIOS */ + bool tdm_mode; }; struct acp_stream { @@ -183,36 +195,6 @@ struct acp_resource { u64 sram_pte_offset; }; -struct acp_dev_data { - char *name; - struct device *dev; - void __iomem *acp_base; - unsigned int i2s_irq; - unsigned int acp_rev; /* ACP Revision id */ - - bool tdm_mode; - bool is_i2s_config; - /* SOC specific dais */ - struct snd_soc_dai_driver *dai_driver; - int num_dai; - - struct list_head stream_list; - spinlock_t acp_lock; - - struct platform_device *mach_dev; - - u32 bclk_div; - u32 lrclk_div; - - struct acp_resource *rsrc; - u32 ch_mask; - u32 tdm_tx_fmt[3]; - u32 tdm_rx_fmt[3]; - u32 xfer_tx_resolution[3]; - u32 xfer_rx_resolution[3]; - unsigned int flag; -}; - /** * struct snd_acp_hw_ops - ACP PCI driver platform specific ops * @acp_init: ACP initialization @@ -357,13 +339,13 @@ extern int acp70_hw_ops_init(struct acp_chip_info *chip); /* Machine configuration */ int snd_amd_acp_find_config(struct pci_dev *pci); -void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream); -void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size); +void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream); +void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size); void restore_acp_pdm_params(struct snd_pcm_substream *substream, - struct acp_dev_data *adata); + struct acp_chip_info *chip); int restore_acp_i2s_params(struct snd_pcm_substream *substream, - struct acp_dev_data *adata, struct acp_stream *stream); + struct acp_chip_info *chip, struct acp_stream *stream); void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip); @@ -395,48 +377,48 @@ static inline int acp_hw_dis_interrupts(struct acp_chip_info *chip) return -EOPNOTSUPP; } -static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction) +static inline u64 acp_get_byte_count(struct acp_chip_info *chip, int dai_id, int direction) { u64 byte_count = 0, low = 0, high = 0; if (direction == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata)); - low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata)); + high = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(chip)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata)); - low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata)); + high = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(chip)); break; case I2S_HS_INSTANCE: - high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW); + high = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW); break; default: - dev_err(adata->dev, "Invalid dai id %x\n", dai_id); + dev_err(chip->dev, "Invalid dai id %x\n", dai_id); goto POINTER_RETURN_BYTES; } } else { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata)); - low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata)); + high = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(chip)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata)); - low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata)); + high = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(chip)); + low = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(chip)); break; case I2S_HS_INSTANCE: - high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW); + high = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW); break; case DMIC_INSTANCE: - high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); + high = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); + low = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); break; default: - dev_err(adata->dev, "Invalid dai id %x\n", dai_id); + dev_err(chip->dev, "Invalid dai id %x\n", dai_id); goto POINTER_RETURN_BYTES; } } From a95a1dbbd3d64adf392fed13c8eef4f72b4e5b90 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:55 +0530 Subject: [PATCH 0864/1090] ASoC: amd: acp: Move spin_lock and list initialization to acp-pci driver Move spin_lock and linked list initialization from platform driver to acp-pci driver. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-9-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 3 +++ sound/soc/amd/acp/acp-platform.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 1ef9faba1d8a..8bb93ca18053 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -196,6 +196,9 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->dev = &chip->acp_plat_dev->dev; acp_machine_select(chip); + + INIT_LIST_HEAD(&chip->stream_list); + spin_lock_init(&chip->acp_lock); skip_pdev_creation: dev_set_drvdata(&pci->dev, chip); pm_runtime_set_autosuspend_delay(&pci->dev, 2000); diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 8d61e1991e4f..b3eddf76aaa4 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -343,9 +343,6 @@ int acp_platform_register(struct device *dev) return status; } - INIT_LIST_HEAD(&chip->stream_list); - spin_lock_init(&chip->acp_lock); - return 0; } EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON"); From c8b5f251f0e53edab220ac4edf444120815fed3c Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:56 +0530 Subject: [PATCH 0865/1090] ASoC: amd: acp: Remove white line Remove white line in renoir platform driver. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-10-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-renoir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 2037af67509a..970ca613a439 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -36,7 +36,6 @@ static struct acp_resource rsrc = { .sram_pte_offset = 0x02052800, }; - static struct snd_soc_dai_driver acp_renoir_dai[] = { { .name = "acp-i2s-sp", From f8b4f3f525e82d78079a6ebbde68e4a0d79fd1c0 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:57 +0530 Subject: [PATCH 0866/1090] ASoC: amd: acp: Refactor acp70 platform resource structure Refactor acp70 platform resource private structure to amd.h header file. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-11-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 1 + sound/soc/amd/acp/acp70.c | 11 ----------- sound/soc/amd/acp/amd.h | 10 ++++++++++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 8bb93ca18053..6728eee29993 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -151,6 +151,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id case 0x70: case 0x71: chip->name = "acp_asoc_acp70"; + chip->rsrc = &acp70_rsrc; chip->acp_hw_ops_init = acp70_hw_ops_init; chip->machines = snd_soc_acpi_amd_acp70_acp_machines; break; diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index c1b546df5e67..1a89f8a3724f 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -30,16 +30,6 @@ #define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4 #define CLK0_DIVIDER 0X19 -static struct acp_resource rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x10000, - .sram_pte_offset = 0x03800000, -}; - static struct snd_soc_dai_driver acp70_dai[] = { { .name = "acp-i2s-sp", @@ -153,7 +143,6 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) } chip->dev = dev; - chip->rsrc = &rsrc; chip->dai_driver = acp70_dai; chip->num_dai = ARRAY_SIZE(acp70_dai); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 084d9db1b65c..979d8b8801a3 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -238,6 +238,16 @@ enum acp_config { ACP_CONFIG_20, }; +struct acp_resource acp70_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, +}; + struct snd_soc_acpi_codecs amp_rt1019 = { .num_codecs = 1, .codecs = {"10EC1019"} From d08220b6e32e88655f54b497fd45a3982b59093c Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:58 +0530 Subject: [PATCH 0867/1090] ASoC: amd: acp: Refactor acp63 platform resource structure Refactor acp63 platform resource private structure to amd.h header file. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-12-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 1 + sound/soc/amd/acp/acp63.c | 13 +------------ sound/soc/amd/acp/amd.h | 10 ++++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 6728eee29993..3df665ca1b0b 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -145,6 +145,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id break; case 0x63: chip->name = "acp_asoc_acp63"; + chip->rsrc = &acp63_rsrc; chip->acp_hw_ops_init = acp63_hw_ops_init; chip->machines = snd_soc_acpi_amd_acp63_acp_machines; break; diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 49786e1a214f..53c013a64854 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -52,16 +52,6 @@ union clk_pll_req_no { u32 clk_pll_req_no_reg; }; -static struct acp_resource rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, -}; - static struct snd_soc_dai_driver acp63_dai[] = { { .name = "acp-i2s-sp", @@ -222,11 +212,10 @@ static int acp63_audio_probe(struct platform_device *pdev) } chip->dev = dev; - chip->rsrc = &rsrc; chip->dai_driver = acp63_dai; chip->num_dai = ARRAY_SIZE(acp63_dai); - if (chip->is_i2s_config && rsrc.soc_mclk) { + if (chip->is_i2s_config && chip->rsrc->soc_mclk) { ret = acp63_i2s_master_clock_generate(chip); if (ret) return ret; diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 979d8b8801a3..075659fb3314 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -238,6 +238,16 @@ enum acp_config { ACP_CONFIG_20, }; +struct acp_resource acp63_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; + struct acp_resource acp70_rsrc = { .offset = 0, .no_of_ctrls = 2, From ee7ab0fd540877fceb3d51f87016e6531d86406f Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:01:59 +0530 Subject: [PATCH 0868/1090] ASoC: amd: acp: Refactor rembrant platform resource structure Refactor rembrandt platform resource private structure to amd.h header fle. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-13-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 1 + sound/soc/amd/acp/acp-rembrandt.c | 13 +------------ sound/soc/amd/acp/amd.h | 10 ++++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 3df665ca1b0b..6dd905e75f1d 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -140,6 +140,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id break; case 0x6f: chip->name = "acp_asoc_rembrandt"; + chip->rsrc = &rmb_rsrc; chip->acp_hw_ops_init = acp6x_hw_ops_init; chip->machines = snd_soc_acpi_amd_rmb_acp_machines; break; diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index dfb18d5cdc7a..21614e2e1b6c 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -34,16 +34,6 @@ #define MP1_C2PMSG_85 0x3B10A54 #define MP1_C2PMSG_93 0x3B10A74 -static struct acp_resource rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, -}; - static struct snd_soc_dai_driver acp_rmb_dai[] = { { .name = "acp-i2s-sp", @@ -171,11 +161,10 @@ static int rembrandt_audio_probe(struct platform_device *pdev) } chip->dev = dev; - chip->rsrc = &rsrc; chip->dai_driver = acp_rmb_dai; chip->num_dai = ARRAY_SIZE(acp_rmb_dai); - if (chip->is_i2s_config && rsrc.soc_mclk) { + if (chip->is_i2s_config && chip->rsrc->soc_mclk) { ret = acp6x_master_clock_generate(dev); if (ret) return ret; diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 075659fb3314..0cb6d2abf832 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -238,6 +238,16 @@ enum acp_config { ACP_CONFIG_20, }; +struct acp_resource rmb_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; + struct acp_resource acp63_rsrc = { .offset = 0, .no_of_ctrls = 2, From e167e5b268b2d06a7b59872c189fae0f587562ee Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:02:00 +0530 Subject: [PATCH 0869/1090] ASoC: amd: acp: Refactor renoir platform resource structure Refactor renoir platform resource private structure to amd.h header file. Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-14-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 1 + sound/soc/amd/acp/acp-renoir.c | 10 ---------- sound/soc/amd/acp/amd.h | 9 +++++++++ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 6dd905e75f1d..9322379cb36f 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -135,6 +135,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id switch (pci->revision) { case 0x01: chip->name = "acp_asoc_renoir"; + chip->rsrc = &rn_rsrc; chip->acp_hw_ops_init = acp31_hw_ops_init; chip->machines = snd_soc_acpi_amd_acp_machines; break; diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index 970ca613a439..b8ded929d52e 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -27,15 +27,6 @@ #define DRV_NAME "acp_asoc_renoir" -static struct acp_resource rsrc = { - .offset = 20, - .no_of_ctrls = 1, - .irqp_used = 0, - .irq_reg_offset = 0x1800, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x02052800, -}; - static struct snd_soc_dai_driver acp_renoir_dai[] = { { .name = "acp-i2s-sp", @@ -121,7 +112,6 @@ static int renoir_audio_probe(struct platform_device *pdev) } chip->dev = dev; - chip->rsrc = &rsrc; chip->dai_driver = acp_renoir_dai; chip->num_dai = ARRAY_SIZE(acp_renoir_dai); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 0cb6d2abf832..796f8efd395c 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -238,6 +238,15 @@ enum acp_config { ACP_CONFIG_20, }; +struct acp_resource rn_rsrc = { + .offset = 20, + .no_of_ctrls = 1, + .irqp_used = 0, + .irq_reg_offset = 0x1800, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x02052800, +}; + struct acp_resource rmb_rsrc = { .offset = 0, .no_of_ctrls = 2, From 02e1cf7a352a3ba5f768849f2b4fcaaaa19f89e3 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Tue, 11 Mar 2025 00:02:01 +0530 Subject: [PATCH 0870/1090] ASoC: amd: acp: Fix for enabling DMIC on acp platforms via _DSD entry Add condition check to register ACP PDM sound card by reading _WOV acpi entry. Fixes: 09068d624c49 ("ASoC: amd: acp: fix for acp platform device creation failure") Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250310183201.11979-15-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 988b7a17b2f4..255f90ca956a 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -13,6 +13,7 @@ */ #include "amd.h" +#include #include #include @@ -511,7 +512,9 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) { struct acpi_device *pdm_dev; const union acpi_object *obj; - u32 pdm_addr; + acpi_handle handle; + acpi_integer dmic_status; + u32 pdm_addr, ret; switch (chip->acp_rev) { case ACP_RN_PCI_ID: @@ -543,6 +546,11 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) obj->integer.value == pdm_addr) chip->is_pdm_dev = true; } + + handle = ACPI_HANDLE(&pci->dev); + ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); + if (!ACPI_FAILURE(ret)) + chip->is_pdm_dev = dmic_status; } } EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON"); From a8045e46c508b70fe4b30cc020fd0a2b0709b2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Thu, 6 Mar 2025 13:08:27 -0800 Subject: [PATCH 0871/1090] drm/i915: Increase I915_PARAM_MMAP_GTT_VERSION version to indicate support for partial mmaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 255fc1703e42 ("drm/i915/gem: Calculate object page offset for partial memory mapping") was the last patch of several patches fixing multiple partial mmaps. But without a bump in I915_PARAM_MMAP_GTT_VERSION there is no clean way for UMD to know if it can do multiple partial mmaps. Fixes: 255fc1703e42 ("drm/i915/gem: Calculate object page offset for partial memory mapping") Cc: Andi Shyti Cc: Nirmoy Das Cc: Lionel Landwerlin Signed-off-by: José Roberto de Souza Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20250306210827.171147-1-jose.souza@intel.com (cherry picked from commit bfef148f3680e6b9d28e7fca46d9520f80c5e50e) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 21274aa9bddd..c3dabb857960 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -164,6 +164,9 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj) * 4 - Support multiple fault handlers per object depending on object's * backing storage (a.k.a. MMAP_OFFSET). * + * 5 - Support multiple partial mmaps(mmap part of BO + unmap a offset, multiple + * times with different size and offset). + * * Restrictions: * * * snoopable objects cannot be accessed via the GTT. It can cause machine @@ -191,7 +194,7 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj) */ int i915_gem_mmap_gtt_version(void) { - return 4; + return 5; } static inline struct i915_gtt_view From 5daa0c35a1f0e7a6c3b8ba9cb721e7d1ace6e619 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Wed, 8 Jan 2025 23:35:08 +0000 Subject: [PATCH 0872/1090] rust: Disallow BTF generation with Rust + LTO The kernel cannot currently self-parse BTF containing Rust debug information. pahole uses the language of the CU to determine whether to filter out debug information when generating the BTF. When LTO is enabled, Rust code can cross CU boundaries, resulting in Rust debug information in CUs labeled as C. This results in a system which cannot parse its own BTF. Signed-off-by: Matthew Maurer Cc: stable@vger.kernel.org Fixes: c1177979af9c ("btf, scripts: Exclude Rust CUs with pahole") Link: https://lore.kernel.org/r/20250108-rust-btf-lto-incompat-v1-1-60243ff6d820@google.com Signed-off-by: Miguel Ojeda --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index d0d021b3fa3b..324c2886b2ea 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1973,7 +1973,7 @@ config RUST depends on !MODVERSIONS || GENDWARFKSYMS depends on !GCC_PLUGIN_RANDSTRUCT depends on !RANDSTRUCT - depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE + depends on !DEBUG_INFO_BTF || (PAHOLE_HAS_LANG_EXCLUDE && !LTO) depends on !CFI_CLANG || HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC select CFI_ICALL_NORMALIZE_INTEGERS if CFI_CLANG depends on !CALL_PADDING || RUSTC_VERSION >= 108100 From 2e0f91aba507a3cb59f7a12fc3ea2b7d4d6675b7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 10 Feb 2025 12:03:24 -0500 Subject: [PATCH 0873/1090] scripts: generate_rust_analyzer: add missing macros deps The macros crate has depended on std and proc_macro since its introduction in commit 1fbde52bde73 ("rust: add `macros` crate"). These dependencies were omitted from commit 8c4555ccc55c ("scripts: add `generate_rust_analyzer.py`") resulting in missing go-to-definition and autocomplete, and false-positive warnings emitted from rust-analyzer such as: [{ "resource": "/Users/tamird/src/linux/rust/macros/module.rs", "owner": "_generated_diagnostic_collection_name_#1", "code": { "value": "non_snake_case", "target": { "$mid": 1, "path": "/rustc/", "scheme": "https", "authority": "doc.rust-lang.org", "query": "search=non_snake_case" } }, "severity": 4, "message": "Variable `None` should have snake_case name, e.g. `none`", "source": "rust-analyzer", "startLineNumber": 123, "startColumn": 17, "endLineNumber": 123, "endColumn": 21 }] Add the missing dependencies to improve the developer experience. [ Fiona had a different approach (thanks!) at: https://lore.kernel.org/rust-for-linux/20241205115438.234221-1-me@kloenk.dev/ But Tamir and Fiona agreed to this one. - Miguel ] Fixes: 8c4555ccc55c ("scripts: add `generate_rust_analyzer.py`") Reviewed-by: Fiona Behrens Diagnosed-by: Chayim Refael Friedman Link: https://github.com/rust-lang/rust-analyzer/issues/17759#issuecomment-2646328275 Signed-off-by: Tamir Duberstein Tested-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250210-rust-analyzer-macros-core-dep-v3-1-45eb4836f218@gmail.com [ Removed `return`. Changed tag name. Added Link. Slightly reworded. - Miguel ] Signed-off-by: Miguel Ojeda --- scripts/generate_rust_analyzer.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index aa8ea1a4dbe5..b40679a90843 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -57,14 +57,26 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): crates_indexes[display_name] = len(crates) crates.append(crate) - # First, the ones in `rust/` since they are a bit special. - append_crate( - "core", - sysroot_src / "core" / "src" / "lib.rs", - [], - cfg=crates_cfgs.get("core", []), - is_workspace_member=False, - ) + def append_sysroot_crate( + display_name, + deps, + cfg=[], + ): + append_crate( + display_name, + sysroot_src / display_name / "src" / "lib.rs", + deps, + cfg, + is_workspace_member=False, + ) + + # NB: sysroot crates reexport items from one another so setting up our transitive dependencies + # here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth + # for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`. + append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", [])) + append_sysroot_crate("alloc", ["core"]) + append_sysroot_crate("std", ["alloc", "core"]) + append_sysroot_crate("proc_macro", ["core", "std"]) append_crate( "compiler_builtins", @@ -75,7 +87,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): append_crate( "macros", srctree / "rust" / "macros" / "lib.rs", - [], + ["std", "proc_macro"], is_proc_macro=True, ) From d1f928052439cad028438a8b8b34c1f01bc06068 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 10 Feb 2025 13:04:16 -0500 Subject: [PATCH 0874/1090] scripts: generate_rust_analyzer: add missing include_dirs Commit 8c4555ccc55c ("scripts: add `generate_rust_analyzer.py`") specified OBJTREE for the bindings crate, and `source.include_dirs` for the kernel crate, likely in an attempt to support out-of-source builds for those crates where the generated files reside in `objtree` rather than `srctree`. This was insufficient because both bits of configuration are required for each crate; the result is that rust-analyzer is unable to resolve generated files for either crate in an out-of-source build. [ Originally we were not using `OBJTREE` in the `kernel` crate, but we did pass the variable anyway, so conceptually it could have been there since then. Regarding `include_dirs`, it started in `kernel` before being in mainline because we included the bindings directly there (i.e. there was no `bindings` crate). However, when that crate got created, we moved the `OBJTREE` there but not the `include_dirs`. Nowadays, though, we happen to need the `include_dirs` also in the `kernel` crate for `generated_arch_static_branch_asm.rs` which was not there back then -- Tamir confirms it is indeed required for that reason. - Miguel ] Add the missing bits to improve the developer experience. Fixes: 8c4555ccc55c ("scripts: add `generate_rust_analyzer.py`") Signed-off-by: Tamir Duberstein Tested-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250210-rust-analyzer-bindings-include-v2-1-23dff845edc3@gmail.com [ Slightly reworded title. - Miguel ] Signed-off-by: Miguel Ojeda --- scripts/generate_rust_analyzer.py | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index b40679a90843..f2d6787e9c0c 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -97,27 +97,27 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): ["core", "compiler_builtins"], ) - append_crate( - "bindings", - srctree / "rust"/ "bindings" / "lib.rs", - ["core"], - cfg=cfg, - ) - crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True)) + def append_crate_with_generated( + display_name, + deps, + ): + append_crate( + display_name, + srctree / "rust"/ display_name / "lib.rs", + deps, + cfg=cfg, + ) + crates[-1]["env"]["OBJTREE"] = str(objtree.resolve(True)) + crates[-1]["source"] = { + "include_dirs": [ + str(srctree / "rust" / display_name), + str(objtree / "rust") + ], + "exclude_dirs": [], + } - append_crate( - "kernel", - srctree / "rust" / "kernel" / "lib.rs", - ["core", "macros", "build_error", "bindings"], - cfg=cfg, - ) - crates[-1]["source"] = { - "include_dirs": [ - str(srctree / "rust" / "kernel"), - str(objtree / "rust") - ], - "exclude_dirs": [], - } + append_crate_with_generated("bindings", ["core"]) + append_crate_with_generated("kernel", ["core", "macros", "build_error", "bindings"]) def is_root_crate(build_file, target): try: From a1eb95d6b5f4cf5cc7b081e85e374d1dd98a213b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 10 Feb 2025 13:04:17 -0500 Subject: [PATCH 0875/1090] scripts: generate_rust_analyzer: add uapi crate Commit 4e1746656839 ("rust: uapi: Add UAPI crate") did not update rust-analyzer to include the new crate. Add the missing definition to improve the developer experience. Fixes: 4e1746656839 ("rust: uapi: Add UAPI crate") Signed-off-by: Tamir Duberstein Tested-by: Andreas Hindborg Link: https://lore.kernel.org/r/20250210-rust-analyzer-bindings-include-v2-2-23dff845edc3@gmail.com [ Slightly reworded title. - Miguel ] Signed-off-by: Miguel Ojeda --- scripts/generate_rust_analyzer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index f2d6787e9c0c..adae71544cbd 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -117,7 +117,8 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): } append_crate_with_generated("bindings", ["core"]) - append_crate_with_generated("kernel", ["core", "macros", "build_error", "bindings"]) + append_crate_with_generated("uapi", ["core"]) + append_crate_with_generated("kernel", ["core", "macros", "build_error", "bindings", "uapi"]) def is_root_crate(build_file, target): try: From 8ae227f8a7749eec92fc381dfbe213429c852278 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 11 Mar 2025 12:17:04 +0100 Subject: [PATCH 0876/1090] wifi: mac80211: fix MPDU length parsing for EHT 5/6 GHz The MPDU length is only configured using the EHT capabilities element on 2.4 GHz. On 5/6 GHz it is configured using the VHT or HE capabilities respectively. Fixes: cf0079279727 ("wifi: mac80211: parse A-MSDU len from EHT capabilities") Reviewed-by: Miriam Rachel Korenblit Signed-off-by: Benjamin Berg Link: https://patch.msgid.link/20250311121704.0634d31f0883.I28063e4d3ef7d296b7e8a1c303460346a30bf09c@changeid Signed-off-by: Johannes Berg --- net/mac80211/eht.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c index 7a3116c36df9..fd41046e3b68 100644 --- a/net/mac80211/eht.c +++ b/net/mac80211/eht.c @@ -2,7 +2,7 @@ /* * EHT handling * - * Copyright(c) 2021-2024 Intel Corporation + * Copyright(c) 2021-2025 Intel Corporation */ #include "ieee80211_i.h" @@ -76,6 +76,13 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); + /* + * The MPDU length bits are reserved on all but 2.4 GHz and get set via + * VHT (5 GHz) or HE (6 GHz) capabilities. + */ + if (sband->band != NL80211_BAND_2GHZ) + return; + switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0], IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) { case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454: From 285df995f90e3d61d97f327d34b9659d92313314 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Fri, 28 Feb 2025 15:04:20 +0100 Subject: [PATCH 0877/1090] i2c: omap: fix IRQ storms On the GTA04A5 writing a reset command to the gyroscope causes IRQ storms because NACK IRQs are enabled and therefore triggered but not acked. Sending a reset command to the gyroscope by i2cset 1 0x69 0x14 0xb6 with an additional debug print in the ISR (not the thread) itself causes [ 363.353515] i2c i2c-1: ioctl, cmd=0x720, arg=0xbe801b00 [ 363.359039] omap_i2c 48072000.i2c: addr: 0x0069, len: 2, flags: 0x0, stop: 1 [ 363.366180] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x1110) [ 363.371673] omap_i2c 48072000.i2c: IRQ (ISR = 0x0010) [ 363.376892] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) [ 363.382263] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) [ 363.387664] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) repeating till infinity [...] (0x2 = NACK, 0x100 = Bus free, which is not enabled) Apparently no other IRQ bit gets set, so this stalls. Do not ignore enabled interrupts and make sure they are acked. If the NACK IRQ is not needed, it should simply not enabled, but according to the above log, caring about it is necessary unless the Bus free IRQ is enabled and handled. The assumption that is will always come with a ARDY IRQ, which was the idea behind ignoring it, proves wrong. It is true for simple reads from an unused address. To still avoid the i2cdetect trouble which is the reason for commit c770657bd261 ("i2c: omap: Fix standard mode false ACK readings"), avoid doing much about NACK in omap_i2c_xfer_data() which is used by both IRQ mode and polling mode, so also the false detection fix is extended to polling usage and IRQ storms are avoided. By changing this, the hardirq handler is not needed anymore to filter stuff. The mentioned gyro reset now just causes a -ETIMEDOUT instead of hanging the system. Fixes: c770657bd261 ("i2c: omap: Fix standard mode false ACK readings"). CC: stable@kernel.org Signed-off-by: Andreas Kemnade Tested-by: Nishanth Menon Reviewed-by: Aniket Limaye Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250228140420.379498-1-andreas@kemnade.info --- drivers/i2c/busses/i2c-omap.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 92faf03d64cf..f18c3e74b076 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1048,23 +1048,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *omap, u8 num_bytes, return 0; } -static irqreturn_t -omap_i2c_isr(int irq, void *dev_id) -{ - struct omap_i2c_dev *omap = dev_id; - irqreturn_t ret = IRQ_HANDLED; - u16 mask; - u16 stat; - - stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG); - mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG) & ~OMAP_I2C_STAT_NACK; - - if (stat & mask) - ret = IRQ_WAKE_THREAD; - - return ret; -} - static int omap_i2c_xfer_data(struct omap_i2c_dev *omap) { u16 bits; @@ -1095,8 +1078,13 @@ static int omap_i2c_xfer_data(struct omap_i2c_dev *omap) } if (stat & OMAP_I2C_STAT_NACK) { - err |= OMAP_I2C_STAT_NACK; + omap->cmd_err |= OMAP_I2C_STAT_NACK; omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK); + + if (!(stat & ~OMAP_I2C_STAT_NACK)) { + err = -EAGAIN; + break; + } } if (stat & OMAP_I2C_STAT_AL) { @@ -1472,7 +1460,7 @@ omap_i2c_probe(struct platform_device *pdev) IRQF_NO_SUSPEND, pdev->name, omap); else r = devm_request_threaded_irq(&pdev->dev, omap->irq, - omap_i2c_isr, omap_i2c_isr_thread, + NULL, omap_i2c_isr_thread, IRQF_NO_SUSPEND | IRQF_ONESHOT, pdev->name, omap); From 9b5463f349d019a261f1e80803447efca3126151 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 3 Mar 2025 20:53:08 +0100 Subject: [PATCH 0878/1090] i2c: ali1535: Fix an error handling path in ali1535_probe() If i2c_add_adapter() fails, the request_region() call in ali1535_setup() must be undone by a corresponding release_region() call, as done in the remove function. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Christophe JAILLET Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/0daf63d7a2ce74c02e2664ba805bbfadab7d25e5.1741031571.git.christophe.jaillet@wanadoo.fr --- drivers/i2c/busses/i2c-ali1535.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 544c94e86b89..1eac35838040 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -485,6 +485,8 @@ MODULE_DEVICE_TABLE(pci, ali1535_ids); static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (ali1535_setup(dev)) { dev_warn(&dev->dev, "ALI1535 not detected, module not inserted.\n"); @@ -496,7 +498,15 @@ static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name), "SMBus ALI1535 adapter at %04x", ali1535_offset); - return i2c_add_adapter(&ali1535_adapter); + ret = i2c_add_adapter(&ali1535_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(ali1535_smba, ALI1535_SMB_IOSIZE); + return ret; } static void ali1535_remove(struct pci_dev *dev) From 6e55caaf30c88209d097e575a169b1dface1ab69 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 3 Mar 2025 20:58:06 +0100 Subject: [PATCH 0879/1090] i2c: ali15x3: Fix an error handling path in ali15x3_probe() If i2c_add_adapter() fails, the request_region() call in ali15x3_setup() must be undone by a corresponding release_region() call, as done in the remove function. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Christophe JAILLET Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/9b2090cbcc02659f425188ea05f2e02745c4e67b.1741031878.git.christophe.jaillet@wanadoo.fr --- drivers/i2c/busses/i2c-ali15x3.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 4761c7208102..418d11266671 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -472,6 +472,8 @@ MODULE_DEVICE_TABLE (pci, ali15x3_ids); static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (ali15x3_setup(dev)) { dev_err(&dev->dev, "ALI15X3 not detected, module not inserted.\n"); @@ -483,7 +485,15 @@ static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name), "SMBus ALI15X3 adapter at %04x", ali15x3_smba); - return i2c_add_adapter(&ali15x3_adapter); + ret = i2c_add_adapter(&ali15x3_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); + return ret; } static void ali15x3_remove(struct pci_dev *dev) From 2b22459792fcb4def9f0936d64575ac11a95a58d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 3 Mar 2025 21:26:54 +0100 Subject: [PATCH 0880/1090] i2c: sis630: Fix an error handling path in sis630_probe() If i2c_add_adapter() fails, the request_region() call in sis630_setup() must be undone by a corresponding release_region() call, as done in the remove function. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/3d607601f2c38e896b10207963c6ab499ca5c307.1741033587.git.christophe.jaillet@wanadoo.fr Signed-off-by: Andi Shyti --- drivers/i2c/busses/i2c-sis630.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 3505cf29cedd..a19c3d251804 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -509,6 +509,8 @@ MODULE_DEVICE_TABLE(pci, sis630_ids); static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) { + int ret; + if (sis630_setup(dev)) { dev_err(&dev->dev, "SIS630 compatible bus not detected, " @@ -522,7 +524,15 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) snprintf(sis630_adapter.name, sizeof(sis630_adapter.name), "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS); - return i2c_add_adapter(&sis630_adapter); + ret = i2c_add_adapter(&sis630_adapter); + if (ret) + goto release_region; + + return 0; + +release_region: + release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION); + return ret; } static void sis630_remove(struct pci_dev *dev) From 87fa872a1ecf542efc66a9184127faf03037f827 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Mar 2025 11:02:25 +0100 Subject: [PATCH 0881/1090] ASoC: samsung: speyside: Free gpiod table We create a gpio descriptor table but it needs to be free:ed when the module is removed. Add a devm_ action to do the job. Suggested-by: Andy Shevchenko Fixes: da9146c19b17 ("ASoC: samsung: speyside: Convert to GPIO descriptor") Signed-off-by: Linus Walleij Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250312-cleanup-table-v1-1-1d9a14464482@linaro.org Signed-off-by: Mark Brown --- sound/soc/samsung/speyside.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index f781e2be2fd4..9262e5626584 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -347,6 +347,11 @@ static struct gpiod_lookup_table wm8996_gpiod_table = { }, }; +static void speyside_gpiod_table_action(void *data) +{ + gpiod_remove_lookup_table(&wm8996_gpiod_table); +} + static int speyside_probe(struct platform_device *pdev) { struct snd_soc_card *card = &speyside; @@ -355,6 +360,11 @@ static int speyside_probe(struct platform_device *pdev) card->dev = &pdev->dev; gpiod_add_lookup_table(&wm8996_gpiod_table); + ret = devm_add_action_or_reset(&pdev->dev, speyside_gpiod_table_action, + NULL); + if (ret) + return ret; + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n"); From 9bce6b5f8987678b9c6c1fe433af6b5fe41feadc Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Tue, 11 Mar 2025 19:43:59 +0900 Subject: [PATCH 0882/1090] block: change blk_mq_add_to_batch() third argument type to bool Commit 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions") modified the evaluation criteria for the third argument, 'ioerror', in the blk_mq_add_to_batch() function. Initially, the function had checked if 'ioerror' equals zero. Following the commit, it started checking for negative error values, with the presumption that such values, for instance -EIO, would be passed in. However, blk_mq_add_to_batch() callers do not pass negative error values. Instead, they pass status codes defined in various ways: - NVMe PCI and Apple drivers pass NVMe status code - virtio_blk driver passes the virtblk request header status byte - null_blk driver passes blk_status_t These codes are either zero or positive, therefore the revised check fails to function as intended. Specifically, with the NVMe PCI driver, this modification led to the failure of the blktests test case nvme/039. In this test scenario, errors are artificially injected to the NVMe driver, resulting in positive NVMe status codes passed to blk_mq_add_to_batch(), which unexpectedly processes the failed I/O in a batch. Hence the failure. To correct the ioerror check within blk_mq_add_to_batch(), make all callers to uniformly pass the argument as boolean. Modify the callers to check their specific status codes and pass the boolean value 'is_error'. Also describe the arguments of blK_mq_add_to_batch as kerneldoc. Fixes: 1f47ed294a2b ("block: cleanup and fix batch completion adding conditions") Signed-off-by: Shin'ichiro Kawasaki Link: https://lore.kernel.org/r/20250311104359.1767728-3-shinichiro.kawasaki@wdc.com [axboe: fold in documentation update] Signed-off-by: Jens Axboe --- drivers/block/null_blk/main.c | 4 ++-- drivers/block/virtio_blk.c | 5 +++-- drivers/nvme/host/apple.c | 3 ++- drivers/nvme/host/pci.c | 5 +++-- include/linux/blk-mq.h | 16 ++++++++++++---- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index d94ef37480bd..fdc7a0b2af10 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1549,8 +1549,8 @@ static int null_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) cmd = blk_mq_rq_to_pdu(req); cmd->error = null_process_cmd(cmd, req_op(req), blk_rq_pos(req), blk_rq_sectors(req)); - if (!blk_mq_add_to_batch(req, iob, (__force int) cmd->error, - blk_mq_end_request_batch)) + if (!blk_mq_add_to_batch(req, iob, cmd->error != BLK_STS_OK, + blk_mq_end_request_batch)) blk_mq_end_request(req, cmd->error); nr++; } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index a4af39fc7ea2..286cab5e5368 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -1207,11 +1207,12 @@ static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) { struct request *req = blk_mq_rq_from_pdu(vbr); + u8 status = virtblk_vbr_status(vbr); found++; if (!blk_mq_complete_request_remote(req) && - !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr), - virtblk_complete_batch)) + !blk_mq_add_to_batch(req, iob, status != VIRTIO_BLK_S_OK, + virtblk_complete_batch)) virtblk_request_done(req); } diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c index a060f69558e7..8971aca41e63 100644 --- a/drivers/nvme/host/apple.c +++ b/drivers/nvme/host/apple.c @@ -599,7 +599,8 @@ static inline void apple_nvme_handle_cqe(struct apple_nvme_queue *q, } if (!nvme_try_complete_req(req, cqe->status, cqe->result) && - !blk_mq_add_to_batch(req, iob, nvme_req(req)->status, + !blk_mq_add_to_batch(req, iob, + nvme_req(req)->status != NVME_SC_SUCCESS, apple_nvme_complete_batch)) apple_nvme_complete_rq(req); } diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 640590b21728..75de86e235ad 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1130,8 +1130,9 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail); if (!nvme_try_complete_req(req, cqe->status, cqe->result) && - !blk_mq_add_to_batch(req, iob, nvme_req(req)->status, - nvme_pci_complete_batch)) + !blk_mq_add_to_batch(req, iob, + nvme_req(req)->status != NVME_SC_SUCCESS, + nvme_pci_complete_batch)) nvme_pci_complete_rq(req); } diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 71f4f0cc3dac..aba9c24486aa 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -852,12 +852,20 @@ static inline bool blk_mq_is_reserved_rq(struct request *rq) return rq->rq_flags & RQF_RESV; } -/* +/** + * blk_mq_add_to_batch() - add a request to the completion batch + * @req: The request to add to batch + * @iob: The batch to add the request + * @is_error: Specify true if the request failed with an error + * @complete: The completaion handler for the request + * * Batched completions only work when there is no I/O error and no special * ->end_io handler. + * + * Return: true when the request was added to the batch, otherwise false */ static inline bool blk_mq_add_to_batch(struct request *req, - struct io_comp_batch *iob, int ioerror, + struct io_comp_batch *iob, bool is_error, void (*complete)(struct io_comp_batch *)) { /* @@ -865,7 +873,7 @@ static inline bool blk_mq_add_to_batch(struct request *req, * 1) No batch container * 2) Has scheduler data attached * 3) Not a passthrough request and end_io set - * 4) Not a passthrough request and an ioerror + * 4) Not a passthrough request and failed with an error */ if (!iob) return false; @@ -874,7 +882,7 @@ static inline bool blk_mq_add_to_batch(struct request *req, if (!blk_rq_is_passthrough(req)) { if (req->end_io) return false; - if (ioerror < 0) + if (is_error) return false; } From d653bfeb07ebb3499c403404c21ac58a16531607 Mon Sep 17 00:00:00 2001 From: Kohei Enju Date: Sun, 9 Mar 2025 17:07:38 +0900 Subject: [PATCH 0883/1090] netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in insert_tree() Since commit b36e4523d4d5 ("netfilter: nf_conncount: fix garbage collection confirm race"), `cpu` and `jiffies32` were introduced to the struct nf_conncount_tuple. The commit made nf_conncount_add() initialize `conn->cpu` and `conn->jiffies32` when allocating the struct. In contrast, count_tree() was not changed to initialize them. By commit 34848d5c896e ("netfilter: nf_conncount: Split insert and traversal"), count_tree() was split and the relevant allocation code now resides in insert_tree(). Initialize `conn->cpu` and `conn->jiffies32` in insert_tree(). BUG: KMSAN: uninit-value in find_or_evict net/netfilter/nf_conncount.c:117 [inline] BUG: KMSAN: uninit-value in __nf_conncount_add+0xd9c/0x2850 net/netfilter/nf_conncount.c:143 find_or_evict net/netfilter/nf_conncount.c:117 [inline] __nf_conncount_add+0xd9c/0x2850 net/netfilter/nf_conncount.c:143 count_tree net/netfilter/nf_conncount.c:438 [inline] nf_conncount_count+0x82f/0x1e80 net/netfilter/nf_conncount.c:521 connlimit_mt+0x7f6/0xbd0 net/netfilter/xt_connlimit.c:72 __nft_match_eval net/netfilter/nft_compat.c:403 [inline] nft_match_eval+0x1a5/0x300 net/netfilter/nft_compat.c:433 expr_call_ops_eval net/netfilter/nf_tables_core.c:240 [inline] nft_do_chain+0x426/0x2290 net/netfilter/nf_tables_core.c:288 nft_do_chain_ipv4+0x1a5/0x230 net/netfilter/nft_chain_filter.c:23 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xf4/0x400 net/netfilter/core.c:626 nf_hook_slow_list+0x24d/0x860 net/netfilter/core.c:663 NF_HOOK_LIST include/linux/netfilter.h:350 [inline] ip_sublist_rcv+0x17b7/0x17f0 net/ipv4/ip_input.c:633 ip_list_rcv+0x9ef/0xa40 net/ipv4/ip_input.c:669 __netif_receive_skb_list_ptype net/core/dev.c:5936 [inline] __netif_receive_skb_list_core+0x15c5/0x1670 net/core/dev.c:5983 __netif_receive_skb_list net/core/dev.c:6035 [inline] netif_receive_skb_list_internal+0x1085/0x1700 net/core/dev.c:6126 netif_receive_skb_list+0x5a/0x460 net/core/dev.c:6178 xdp_recv_frames net/bpf/test_run.c:280 [inline] xdp_test_run_batch net/bpf/test_run.c:361 [inline] bpf_test_run_xdp_live+0x2e86/0x3480 net/bpf/test_run.c:390 bpf_prog_test_run_xdp+0xf1d/0x1ae0 net/bpf/test_run.c:1316 bpf_prog_test_run+0x5e5/0xa30 kernel/bpf/syscall.c:4407 __sys_bpf+0x6aa/0xd90 kernel/bpf/syscall.c:5813 __do_sys_bpf kernel/bpf/syscall.c:5902 [inline] __se_sys_bpf kernel/bpf/syscall.c:5900 [inline] __ia32_sys_bpf+0xa0/0xe0 kernel/bpf/syscall.c:5900 ia32_sys_call+0x394d/0x4180 arch/x86/include/generated/asm/syscalls_32.h:358 do_syscall_32_irqs_on arch/x86/entry/common.c:165 [inline] __do_fast_syscall_32+0xb0/0x110 arch/x86/entry/common.c:387 do_fast_syscall_32+0x38/0x80 arch/x86/entry/common.c:412 do_SYSENTER_32+0x1f/0x30 arch/x86/entry/common.c:450 entry_SYSENTER_compat_after_hwframe+0x84/0x8e Uninit was created at: slab_post_alloc_hook mm/slub.c:4121 [inline] slab_alloc_node mm/slub.c:4164 [inline] kmem_cache_alloc_noprof+0x915/0xe10 mm/slub.c:4171 insert_tree net/netfilter/nf_conncount.c:372 [inline] count_tree net/netfilter/nf_conncount.c:450 [inline] nf_conncount_count+0x1415/0x1e80 net/netfilter/nf_conncount.c:521 connlimit_mt+0x7f6/0xbd0 net/netfilter/xt_connlimit.c:72 __nft_match_eval net/netfilter/nft_compat.c:403 [inline] nft_match_eval+0x1a5/0x300 net/netfilter/nft_compat.c:433 expr_call_ops_eval net/netfilter/nf_tables_core.c:240 [inline] nft_do_chain+0x426/0x2290 net/netfilter/nf_tables_core.c:288 nft_do_chain_ipv4+0x1a5/0x230 net/netfilter/nft_chain_filter.c:23 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xf4/0x400 net/netfilter/core.c:626 nf_hook_slow_list+0x24d/0x860 net/netfilter/core.c:663 NF_HOOK_LIST include/linux/netfilter.h:350 [inline] ip_sublist_rcv+0x17b7/0x17f0 net/ipv4/ip_input.c:633 ip_list_rcv+0x9ef/0xa40 net/ipv4/ip_input.c:669 __netif_receive_skb_list_ptype net/core/dev.c:5936 [inline] __netif_receive_skb_list_core+0x15c5/0x1670 net/core/dev.c:5983 __netif_receive_skb_list net/core/dev.c:6035 [inline] netif_receive_skb_list_internal+0x1085/0x1700 net/core/dev.c:6126 netif_receive_skb_list+0x5a/0x460 net/core/dev.c:6178 xdp_recv_frames net/bpf/test_run.c:280 [inline] xdp_test_run_batch net/bpf/test_run.c:361 [inline] bpf_test_run_xdp_live+0x2e86/0x3480 net/bpf/test_run.c:390 bpf_prog_test_run_xdp+0xf1d/0x1ae0 net/bpf/test_run.c:1316 bpf_prog_test_run+0x5e5/0xa30 kernel/bpf/syscall.c:4407 __sys_bpf+0x6aa/0xd90 kernel/bpf/syscall.c:5813 __do_sys_bpf kernel/bpf/syscall.c:5902 [inline] __se_sys_bpf kernel/bpf/syscall.c:5900 [inline] __ia32_sys_bpf+0xa0/0xe0 kernel/bpf/syscall.c:5900 ia32_sys_call+0x394d/0x4180 arch/x86/include/generated/asm/syscalls_32.h:358 do_syscall_32_irqs_on arch/x86/entry/common.c:165 [inline] __do_fast_syscall_32+0xb0/0x110 arch/x86/entry/common.c:387 do_fast_syscall_32+0x38/0x80 arch/x86/entry/common.c:412 do_SYSENTER_32+0x1f/0x30 arch/x86/entry/common.c:450 entry_SYSENTER_compat_after_hwframe+0x84/0x8e Reported-by: syzbot+83fed965338b573115f7@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=83fed965338b573115f7 Fixes: b36e4523d4d5 ("netfilter: nf_conncount: fix garbage collection confirm race") Signed-off-by: Kohei Enju Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conncount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index ebe38ed2e6f4..913ede2f57f9 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -377,6 +377,8 @@ restart: conn->tuple = *tuple; conn->zone = *zone; + conn->cpu = raw_smp_processor_id(); + conn->jiffies32 = (u32)jiffies; memcpy(rbconn->key, key, sizeof(u32) * data->keylen); nf_conncount_list_init(&rbconn->list); From c21b02fd9cbf15aed6e32c89e0fd70070281e3d1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 11 Mar 2025 12:52:45 +0100 Subject: [PATCH 0884/1090] selftests: netfilter: skip br_netfilter queue tests if kernel is tainted These scripts fail if the kernel is tainted which leads to wrong test failure reports in CI environments when an unrelated test triggers some splat. Check taint state at start of script and SKIP if its already dodgy. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- tools/testing/selftests/net/netfilter/br_netfilter.sh | 7 +++++++ .../testing/selftests/net/netfilter/br_netfilter_queue.sh | 7 +++++++ tools/testing/selftests/net/netfilter/nft_queue.sh | 1 + 3 files changed, 15 insertions(+) diff --git a/tools/testing/selftests/net/netfilter/br_netfilter.sh b/tools/testing/selftests/net/netfilter/br_netfilter.sh index c28379a965d8..1559ba275105 100755 --- a/tools/testing/selftests/net/netfilter/br_netfilter.sh +++ b/tools/testing/selftests/net/netfilter/br_netfilter.sh @@ -13,6 +13,12 @@ source lib.sh checktool "nft --version" "run test without nft tool" +read t < /proc/sys/kernel/tainted +if [ "$t" -ne 0 ];then + echo SKIP: kernel is tainted + exit $ksft_skip +fi + cleanup() { cleanup_all_ns } @@ -165,6 +171,7 @@ if [ "$t" -eq 0 ];then echo PASS: kernel not tainted else echo ERROR: kernel is tainted + dmesg ret=1 fi diff --git a/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh b/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh index 6a764d70ab06..4788641717d9 100755 --- a/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh +++ b/tools/testing/selftests/net/netfilter/br_netfilter_queue.sh @@ -4,6 +4,12 @@ source lib.sh checktool "nft --version" "run test without nft tool" +read t < /proc/sys/kernel/tainted +if [ "$t" -ne 0 ];then + echo SKIP: kernel is tainted + exit $ksft_skip +fi + cleanup() { cleanup_all_ns } @@ -72,6 +78,7 @@ if [ "$t" -eq 0 ];then echo PASS: kernel not tainted else echo ERROR: kernel is tainted + dmesg exit 1 fi diff --git a/tools/testing/selftests/net/netfilter/nft_queue.sh b/tools/testing/selftests/net/netfilter/nft_queue.sh index 785e3875a6da..784d1b46912b 100755 --- a/tools/testing/selftests/net/netfilter/nft_queue.sh +++ b/tools/testing/selftests/net/netfilter/nft_queue.sh @@ -593,6 +593,7 @@ EOF echo "PASS: queue program exiting while packets queued" else echo "TAINT: queue program exiting while packets queued" + dmesg ret=1 fi } From 80b78c39eb86e6b55f56363b709eb817527da5aa Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 10 Mar 2025 10:45:53 +0300 Subject: [PATCH 0885/1090] ipvs: prevent integer overflow in do_ip_vs_get_ctl() The get->num_services variable is an unsigned int which is controlled by the user. The struct_size() function ensures that the size calculation does not overflow an unsigned long, however, we are saving the result to an int so the calculation can overflow. Both "len" and "get->num_services" come from the user. This check is just a sanity check to help the user and ensure they are using the API correctly. An integer overflow here is not a big deal. This has no security impact. Save the result from struct_size() type size_t to fix this integer overflow bug. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Dan Carpenter Acked-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7d13110ce188..0633276d96bf 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -3091,12 +3091,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IP_VS_SO_GET_SERVICES: { struct ip_vs_get_services *get; - int size; + size_t size; get = (struct ip_vs_get_services *)arg; size = struct_size(get, entrytable, get->num_services); if (*len != size) { - pr_err("length: %u != %u\n", *len, size); + pr_err("length: %u != %zu\n", *len, size); ret = -EINVAL; goto out; } @@ -3132,12 +3132,12 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) case IP_VS_SO_GET_DESTS: { struct ip_vs_get_dests *get; - int size; + size_t size; get = (struct ip_vs_get_dests *)arg; size = struct_size(get, entrytable, get->num_dests); if (*len != size) { - pr_err("length: %u != %u\n", *len, size); + pr_err("length: %u != %zu\n", *len, size); ret = -EINVAL; goto out; } From d9e7c172a7f247f7ef0b151fa8c8f044b6a2a070 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Feb 2025 15:40:58 +0100 Subject: [PATCH 0886/1090] media: rtl2832_sdr: assign vb2 lock before vb2_queue_init Commit c780d01cf1a6 ("media: vb2: vb2_core_queue_init(): sanity check lock and wait_prepare/finish") added a sanity check to ensure that if there are no wait_prepare/finish callbacks set by the driver, then the vb2_queue lock must be set, since otherwise the vb2 core cannot do correct locking. The rtl2832_sdr.c triggered this warning: it turns out that while the driver does set this lock, it sets it too late. So move it up to before the vb2_queue_init() call. Reported-by: Arthur Marsh Closes: https://lore.kernel.org/linux-media/20241211042355.8479-1-user@am64/ Fixes: 8fcd2795d22a ("media: rtl2832_sdr: drop vb2_ops_wait_prepare/finish") Cc: stable@vger.kernel.org Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Hans Verkuil --- drivers/media/dvb-frontends/rtl2832_sdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index 05254d8717db..0357624968f1 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -1363,6 +1363,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) dev->vb_queue.ops = &rtl2832_sdr_vb2_ops; dev->vb_queue.mem_ops = &vb2_vmalloc_memops; dev->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + dev->vb_queue.lock = &dev->vb_queue_lock; ret = vb2_queue_init(&dev->vb_queue); if (ret) { dev_err(&pdev->dev, "Could not initialize vb2 queue\n"); @@ -1421,7 +1422,6 @@ static int rtl2832_sdr_probe(struct platform_device *pdev) /* Init video_device structure */ dev->vdev = rtl2832_sdr_template; dev->vdev.queue = &dev->vb_queue; - dev->vdev.queue->lock = &dev->vb_queue_lock; video_set_drvdata(&dev->vdev, dev); /* Register the v4l2_device structure */ From 18e0885bd2ca738407036434418a26a58394a60e Mon Sep 17 00:00:00 2001 From: Boon Khai Ng Date: Wed, 12 Mar 2025 11:05:44 +0800 Subject: [PATCH 0887/1090] USB: serial: ftdi_sio: add support for Altera USB Blaster 3 The Altera USB Blaster 3, available as both a cable and an on-board solution, is primarily used for programming and debugging FPGAs. It interfaces with host software such as Quartus Programmer, System Console, SignalTap, and Nios Debugger. The device utilizes either an FT2232 or FT4232 chip. Enabling the support for various configurations of the on-board USB Blaster 3 by including the appropriate VID/PID pairs, allowing it to function as a serial device via ftdi_sio. Note that this check-in does not include support for the cable solution, as it does not support UART functionality. The supported configurations are determined by the hardware design and include: 1) PID 0x6022, FT2232, 1 JTAG port (Port A) + Port B as UART 2) PID 0x6025, FT4232, 1 JTAG port (Port A) + Port C as UART 3) PID 0x6026, FT4232, 1 JTAG port (Port A) + Port C, D as UART 4) PID 0x6029, FT4232, 1 JTAG port (Port B) + Port C as UART 5) PID 0x602a, FT4232, 1 JTAG port (Port B) + Port C, D as UART 6) PID 0x602c, FT4232, 1 JTAG port (Port A) + Port B as UART 7) PID 0x602d, FT4232, 1 JTAG port (Port A) + Port B, C as UART 8) PID 0x602e, FT4232, 1 JTAG port (Port A) + Port B, C, D as UART These configurations allow for flexibility in how the USB Blaster 3 is used, depending on the specific needs of the hardware design. Signed-off-by: Boon Khai Ng Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/ftdi_sio.c | 14 ++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e07c5e3eb18c..9b34e23b7091 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1079,6 +1079,20 @@ static const struct usb_device_id id_table_combined[] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* GMC devices */ { USB_DEVICE(GMC_VID, GMC_Z216C_PID) }, + /* Altera USB Blaster 3 */ + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6022_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6025_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 3) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6029_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 3) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602C_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 2) }, + { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5ee60ba2a73c..52be47d684ea 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1612,3 +1612,16 @@ */ #define GMC_VID 0x1cd7 #define GMC_Z216C_PID 0x0217 /* GMC Z216C Adapter IR-USB */ + +/* + * Altera USB Blaster 3 (http://www.altera.com). + */ +#define ALTERA_VID 0x09fb +#define ALTERA_UB3_6022_PID 0x6022 +#define ALTERA_UB3_6025_PID 0x6025 +#define ALTERA_UB3_6026_PID 0x6026 +#define ALTERA_UB3_6029_PID 0x6029 +#define ALTERA_UB3_602A_PID 0x602a +#define ALTERA_UB3_602C_PID 0x602c +#define ALTERA_UB3_602D_PID 0x602d +#define ALTERA_UB3_602E_PID 0x602e From 066e053fe208a3b83ee89dc5a192146add688861 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:47 +0100 Subject: [PATCH 0888/1090] fsnotify: add pre-content hooks on mmap() Pre-content hooks in page faults introduces potential deadlock of HSM handler in userspace with filesystem freezing. The requirement with pre-content event is that for every accessed file range an event covering at least this range will be generated at least once before the file data is accesses. In preparation to disabling pre-content event hooks on page faults, add pre-content hooks at mmap() variants for the entire mmaped range, so HSM can fill content when user requests to map a portion of the file. Note that exec() variant also calls vm_mmap_pgoff() internally to map code sections, so pre-content hooks are also generated in this case. Link: https://lore.kernel.org/linux-fsdevel/7ehxrhbvehlrjwvrduoxsao5k3x4aw275patsb3krkwuq573yv@o2hskrfawbnc/ Suggested-by: Josef Bacik Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-2-amir73il@gmail.com --- include/linux/fsnotify.h | 21 +++++++++++++++++++++ mm/util.c | 3 +++ 2 files changed, 24 insertions(+) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 6a33288bd6a1..83d3ac97f826 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -170,6 +170,21 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask, return fsnotify_path(&file->f_path, FS_ACCESS_PERM); } +/* + * fsnotify_mmap_perm - permission hook before mmap of file range + */ +static inline int fsnotify_mmap_perm(struct file *file, int prot, + const loff_t off, size_t len) +{ + /* + * mmap() generates only pre-content events. + */ + if (!file || likely(!FMODE_FSNOTIFY_HSM(file->f_mode))) + return 0; + + return fsnotify_pre_content(&file->f_path, &off, len); +} + /* * fsnotify_truncate_perm - permission hook before file truncate */ @@ -223,6 +238,12 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask, return 0; } +static inline int fsnotify_mmap_perm(struct file *file, int prot, + const loff_t off, size_t len) +{ + return 0; +} + static inline int fsnotify_truncate_perm(const struct path *path, loff_t length) { return 0; diff --git a/mm/util.c b/mm/util.c index b6b9684a1438..8c965474d329 100644 --- a/mm/util.c +++ b/mm/util.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -569,6 +570,8 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, LIST_HEAD(uf); ret = security_mmap_file(file, prot, flag); + if (!ret) + ret = fsnotify_mmap_perm(file, prot, pgoff >> PAGE_SHIFT, len); if (!ret) { if (mmap_write_lock_killable(mm)) return -EINTR; From 0882ca4eecfe8b0013f339144acf886a0a0de41f Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Wed, 5 Mar 2025 13:14:55 +0800 Subject: [PATCH 0889/1090] drm/amd/amdkfd: Evict all queues even HWS remove queue failed [Why] If reset is detected and kfd need to evict working queues, HWS moving queue will be failed. Then remaining queues are not evicted and in active state. After reset done, kfd uses HWS to termination remaining activated queues but HWS is resetted. So remove queue will be failed again. [How] Keep removing all queues even if HWS returns failed. It will not affect cpsch as it checks reset_domain->sem. v2: If any queue failed, evict queue returns error. v3: Declare err inside the if-block. Reviewed-by: Felix Kuehling Signed-off-by: Yifan Zha Signed-off-by: Alex Deucher (cherry picked from commit 42c854b8fb0cce512534aa2b7141948e80c6ebb0) Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index d4593374e7a1..34c2c42c0f95 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1230,11 +1230,13 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, decrement_queue_count(dqm, qpd, q); if (dqm->dev->kfd->shared_resources.enable_mes) { - retval = remove_queue_mes(dqm, q, qpd); - if (retval) { + int err; + + err = remove_queue_mes(dqm, q, qpd); + if (err) { dev_err(dev, "Failed to evict queue %d\n", q->properties.queue_id); - goto out; + retval = err; } } } From 6cc30748e17ea2a64051ceaf83a8372484e597f1 Mon Sep 17 00:00:00 2001 From: Natalie Vock Date: Mon, 10 Mar 2025 18:08:05 +0100 Subject: [PATCH 0890/1090] drm/amdgpu: NULL-check BO's backing store when determining GFX12 PTE flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PRT BOs may not have any backing store, so bo->tbo.resource will be NULL. Check for that before dereferencing. Fixes: 0cce5f285d9a ("drm/amdkfd: Check correct memory types for is_system variable") Reviewed-by: Christian König Signed-off-by: Natalie Vock Signed-off-by: Alex Deucher (cherry picked from commit 3e3fcd29b505cebed659311337ea03b7698767fc) Cc: stable@vger.kernel.org # 6.12.x --- drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index b749f1c3f6a9..0fb88e6d5d54 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -528,8 +528,9 @@ static void gmc_v12_0_get_vm_pte(struct amdgpu_device *adev, bo_adev = amdgpu_ttm_adev(bo->tbo.bdev); coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT; - is_system = (bo->tbo.resource->mem_type == TTM_PL_TT) || - (bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT); + is_system = bo->tbo.resource && + (bo->tbo.resource->mem_type == TTM_PL_TT || + bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT); if (bo && bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC) *flags |= AMDGPU_PTE_DCC; From 0c3057a5a04d07120b3d0ec9c79568fceb9c921e Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 6 Mar 2025 15:23:54 -0800 Subject: [PATCH 0891/1090] net_sched: Prevent creation of classes with TC_H_ROOT The function qdisc_tree_reduce_backlog() uses TC_H_ROOT as a termination condition when traversing up the qdisc tree to update parent backlog counters. However, if a class is created with classid TC_H_ROOT, the traversal terminates prematurely at this class instead of reaching the actual root qdisc, causing parent statistics to be incorrectly maintained. In case of DRR, this could lead to a crash as reported by Mingi Cho. Prevent the creation of any Qdisc class with classid TC_H_ROOT (0xFFFFFFFF) across all qdisc types, as suggested by Jamal. Reported-by: Mingi Cho Signed-off-by: Cong Wang Reviewed-by: Simon Horman Fixes: 066a3b5b2346 ("[NET_SCHED] sch_api: fix qdisc_tree_decrease_qlen() loop") Link: https://patch.msgid.link/20250306232355.93864-2-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski --- net/sched/sch_api.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index e3e91cf867eb..6c625dcd0651 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -2254,6 +2254,12 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, return -EOPNOTSUPP; } + /* Prevent creation of traffic classes with classid TC_H_ROOT */ + if (clid == TC_H_ROOT) { + NL_SET_ERR_MSG(extack, "Cannot create traffic class with classid TC_H_ROOT"); + return -EINVAL; + } + new_cl = cl; err = -EOPNOTSUPP; if (cops->change) From bb7737de5f593155aabbca283f4822176f4e7d6b Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 6 Mar 2025 15:23:55 -0800 Subject: [PATCH 0892/1090] selftests/tc-testing: Add a test case for DRR class with TC_H_ROOT Integrate the reproduer from Mingi to TDC. All test results: 1..4 ok 1 0385 - Create DRR with default setting ok 2 2375 - Delete DRR with handle ok 3 3092 - Show DRR class ok 4 4009 - Reject creation of DRR class with classid TC_H_ROOT Cc: Mingi Cho Signed-off-by: Cong Wang Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250306232355.93864-3-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski --- .../tc-testing/tc-tests/qdiscs/drr.json | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/drr.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/drr.json index 7126ec3485cb..2b61d8d79bde 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/drr.json +++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/drr.json @@ -61,5 +61,30 @@ "teardown": [ "$TC qdisc del dev $DUMMY handle 1: root" ] + }, + { + "id": "4009", + "name": "Reject creation of DRR class with classid TC_H_ROOT", + "category": [ + "qdisc", + "drr" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DUMMY root handle ffff: drr", + "$TC filter add dev $DUMMY parent ffff: basic classid ffff:1", + "$TC class add dev $DUMMY parent ffff: classid ffff:1 drr", + "$TC filter add dev $DUMMY parent ffff: prio 1 u32 match u16 0x0000 0xfe00 at 2 flowid ffff:ffff" + ], + "cmdUnderTest": "$TC class add dev $DUMMY parent ffff: classid ffff:ffff drr", + "expExitCode": "2", + "verifyCmd": "$TC class show dev $DUMMY", + "matchPattern": "class drr ffff:ffff", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DUMMY root" + ] } ] From 3bcde88d381a336ff252d67867c186ee602e6656 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 12 Mar 2025 17:21:31 -0400 Subject: [PATCH 0893/1090] bcachefs: fix tiny leak in bch2_dev_add() Signed-off-by: Kent Overstreet --- fs/bcachefs/super.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 6d97d412fed9..0459c875e189 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1811,7 +1811,11 @@ int bch2_dev_add(struct bch_fs *c, const char *path) goto err_late; up_write(&c->state_lock); - return 0; +out: + printbuf_exit(&label); + printbuf_exit(&errbuf); + bch_err_fn(c, ret); + return ret; err_unlock: mutex_unlock(&c->sb_lock); @@ -1820,10 +1824,7 @@ err: if (ca) bch2_dev_free(ca); bch2_free_super(&sb); - printbuf_exit(&label); - printbuf_exit(&errbuf); - bch_err_fn(c, ret); - return ret; + goto out; err_late: up_write(&c->state_lock); ca = NULL; From 0102fbf52b93e609fec0dab53b1fb4fe69113f5e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 11 Mar 2025 18:56:31 +0100 Subject: [PATCH 0894/1090] gpiolib: don't check the retval of get_direction() when registering a chip During chip registration we should neither check the return value of gc->get_direction() nor hold the SRCU lock when calling it. The former is because pin controllers may have pins set to alternate functions and return errors from their get_direction() callbacks. That's alright - we should default to the safe INPUT state and not bail-out. The latter is not needed because we haven't registered the chip yet so there's nothing to protect against dynamic removal. In fact: we currently hit a lockdep splat. Revert to calling the gc->get_direction() callback directly and *not* checking its value. Fixes: 9d846b1aebbe ("gpiolib: check the return value of gpio_chip::get_direction()") Reported-by: Marek Szyprowski Closes: https://lore.kernel.org/all/81f890fc-6688-42f0-9756-567efc8bb97a@samsung.com/ Reviewed-by: Andy Shevchenko Tested-by: Marek Szyprowski Link: https://lore.kernel.org/r/20250226-retval-fixes-v2-1-c8dc57182441@linaro.org Tested-by: Gene C Link: https://lore.kernel.org/r/20250311175631.83779-1-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8741600af7ef..de708d081858 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1056,24 +1056,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, desc->gdev = gdev; - if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) { - ret = gc->get_direction(gc, desc_index); - if (ret < 0) - /* - * FIXME: Bail-out here once all GPIO drivers - * are updated to not return errors in - * situations that can be considered normal - * operation. - */ - dev_warn(&gdev->dev, - "%s: get_direction failed: %d\n", - __func__, ret); - - assign_bit(FLAG_IS_OUT, &desc->flags, !ret); - } else { + /* + * We would typically want to check the return value of + * get_direction() here but we must not check the return value + * and bail-out as pin controllers can have pins configured to + * alternate functions and return -EINVAL. Also: there's no + * need to take the SRCU lock here. + */ + if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) + assign_bit(FLAG_IS_OUT, &desc->flags, + !gc->get_direction(gc, desc_index)); + else assign_bit(FLAG_IS_OUT, &desc->flags, !gc->direction_input); - } } ret = of_gpiochip_add(gc); From dcb73cbaaeb39c9fd00bf2e019f911725945e2fe Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 11 Mar 2025 15:31:43 +0100 Subject: [PATCH 0895/1090] gpio: cdev: use raw notifier for line state events We use a notifier to implement the mechanism of informing the user-space about changes in GPIO line status. We register with the notifier when the GPIO character device file is opened and unregister when the last reference to the associated file descriptor is dropped. Since commit fcc8b637c542 ("gpiolib: switch the line state notifier to atomic") we use the atomic notifier variant. Atomic notifiers call rcu_synchronize in atomic_notifier_chain_unregister() which caused a significant performance regression in some circumstances, observed by user-space when calling close() on the GPIO device file descriptor. Replace the atomic notifier with the raw variant and provide synchronization with a read-write spinlock. Fixes: fcc8b637c542 ("gpiolib: switch the line state notifier to atomic") Reported-by: David Jander Closes: https://lore.kernel.org/all/20250311110034.53959031@erd003.prtnl/ Tested-by: David Jander Tested-by: Kent Gibson Link: https://lore.kernel.org/r/20250311-gpiolib-line-state-raw-notifier-v2-1-138374581e1e@linaro.org Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-cdev.c | 15 +++++++++------ drivers/gpio/gpiolib.c | 8 +++++--- drivers/gpio/gpiolib.h | 5 ++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 40f76a90fd7d..107d75558b5a 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2729,8 +2729,9 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) cdev->gdev = gpio_device_get(gdev); cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; - ret = atomic_notifier_chain_register(&gdev->line_state_notifier, - &cdev->lineinfo_changed_nb); + scoped_guard(write_lock_irqsave, &gdev->line_state_lock) + ret = raw_notifier_chain_register(&gdev->line_state_notifier, + &cdev->lineinfo_changed_nb); if (ret) goto out_free_bitmap; @@ -2754,8 +2755,9 @@ out_unregister_device_notifier: blocking_notifier_chain_unregister(&gdev->device_notifier, &cdev->device_unregistered_nb); out_unregister_line_notifier: - atomic_notifier_chain_unregister(&gdev->line_state_notifier, - &cdev->lineinfo_changed_nb); + scoped_guard(write_lock_irqsave, &gdev->line_state_lock) + raw_notifier_chain_unregister(&gdev->line_state_notifier, + &cdev->lineinfo_changed_nb); out_free_bitmap: gpio_device_put(gdev); bitmap_free(cdev->watched_lines); @@ -2779,8 +2781,9 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file) blocking_notifier_chain_unregister(&gdev->device_notifier, &cdev->device_unregistered_nb); - atomic_notifier_chain_unregister(&gdev->line_state_notifier, - &cdev->lineinfo_changed_nb); + scoped_guard(write_lock_irqsave, &gdev->line_state_lock) + raw_notifier_chain_unregister(&gdev->line_state_notifier, + &cdev->lineinfo_changed_nb); bitmap_free(cdev->watched_lines); gpio_device_put(gdev); kfree(cdev); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index de708d081858..0c00ed2ab431 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1025,7 +1025,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, } } - ATOMIC_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); + rwlock_init(&gdev->line_state_lock); + RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); ret = init_srcu_struct(&gdev->srcu); @@ -4188,8 +4189,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep); void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action) { - atomic_notifier_call_chain(&desc->gdev->line_state_notifier, - action, desc); + guard(read_lock_irqsave)(&desc->gdev->line_state_lock); + + raw_notifier_call_chain(&desc->gdev->line_state_notifier, action, desc); } /** diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 147156ec502b..c129a03e2040 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ * @list: links gpio_device:s together for traversal * @line_state_notifier: used to notify subscribers about lines being * requested, released or reconfigured + * @line_state_lock: RW-spinlock protecting the line state notifier * @line_state_wq: used to emit line state events from a separate thread in * process context * @device_notifier: used to notify character device wait queues about the GPIO @@ -72,7 +74,8 @@ struct gpio_device { const char *label; void *data; struct list_head list; - struct atomic_notifier_head line_state_notifier; + struct raw_notifier_head line_state_notifier; + rwlock_t line_state_lock; struct workqueue_struct *line_state_wq; struct blocking_notifier_head device_notifier; struct srcu_struct srcu; From 6edd78af9506bb182518da7f6feebd75655d9a0e Mon Sep 17 00:00:00 2001 From: Alexey Kashavkin Date: Sun, 2 Mar 2025 00:14:36 +0300 Subject: [PATCH 0896/1090] netfilter: nft_exthdr: fix offset with ipv4_find_option() There is an incorrect calculation in the offset variable which causes the nft_skb_copy_to_reg() function to always return -EFAULT. Adding the start variable is redundant. In the __ip_options_compile() function the correct offset is specified when finding the function. There is no need to add the size of the iphdr structure to the offset. Fixes: dbb5281a1f84 ("netfilter: nf_tables: add support for matching IPv4 options") Signed-off-by: Alexey Kashavkin Reviewed-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_exthdr.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c index b8d03364566c..c74012c99125 100644 --- a/net/netfilter/nft_exthdr.c +++ b/net/netfilter/nft_exthdr.c @@ -85,7 +85,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb, unsigned char optbuf[sizeof(struct ip_options) + 40]; struct ip_options *opt = (struct ip_options *)optbuf; struct iphdr *iph, _iph; - unsigned int start; bool found = false; __be32 info; int optlen; @@ -93,7 +92,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb, iph = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (!iph) return -EBADMSG; - start = sizeof(struct iphdr); optlen = iph->ihl * 4 - (int)sizeof(struct iphdr); if (optlen <= 0) @@ -103,7 +101,7 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb, /* Copy the options since __ip_options_compile() modifies * the options. */ - if (skb_copy_bits(skb, start, opt->__data, optlen)) + if (skb_copy_bits(skb, sizeof(struct iphdr), opt->__data, optlen)) return -EBADMSG; opt->optlen = optlen; @@ -118,18 +116,18 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb, found = target == IPOPT_SSRR ? opt->is_strictroute : !opt->is_strictroute; if (found) - *offset = opt->srr + start; + *offset = opt->srr; break; case IPOPT_RR: if (!opt->rr) break; - *offset = opt->rr + start; + *offset = opt->rr; found = true; break; case IPOPT_RA: if (!opt->router_alert) break; - *offset = opt->router_alert + start; + *offset = opt->router_alert; found = true; break; default: From 183185a18ff96751db52a46ccf93fff3a1f42815 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 7 Mar 2025 20:28:53 +0100 Subject: [PATCH 0897/1090] gre: Fix IPv6 link-local address generation. Use addrconf_addr_gen() to generate IPv6 link-local addresses on GRE devices in most cases and fall back to using add_v4_addrs() only in case the GRE configuration is incompatible with addrconf_addr_gen(). GRE used to use addrconf_addr_gen() until commit e5dd729460ca ("ip/ip6_gre: use the same logic as SIT interfaces when computing v6LL address") restricted this use to gretap and ip6gretap devices, and created add_v4_addrs() (borrowed from SIT) for non-Ethernet GRE ones. The original problem came when commit 9af28511be10 ("addrconf: refuse isatap eui64 for INADDR_ANY") made __ipv6_isatap_ifid() fail when its addr parameter was 0. The commit says that this would create an invalid address, however, I couldn't find any RFC saying that the generated interface identifier would be wrong. Anyway, since gre over IPv4 devices pass their local tunnel address to __ipv6_isatap_ifid(), that commit broke their IPv6 link-local address generation when the local address was unspecified. Then commit e5dd729460ca ("ip/ip6_gre: use the same logic as SIT interfaces when computing v6LL address") tried to fix that case by defining add_v4_addrs() and calling it to generate the IPv6 link-local address instead of using addrconf_addr_gen() (apart for gretap and ip6gretap devices, which would still use the regular addrconf_addr_gen(), since they have a MAC address). That broke several use cases because add_v4_addrs() isn't properly integrated into the rest of IPv6 Neighbor Discovery code. Several of these shortcomings have been fixed over time, but add_v4_addrs() remains broken on several aspects. In particular, it doesn't send any Router Sollicitations, so the SLAAC process doesn't start until the interface receives a Router Advertisement. Also, add_v4_addrs() mostly ignores the address generation mode of the interface (/proc/sys/net/ipv6/conf/*/addr_gen_mode), thus breaking the IN6_ADDR_GEN_MODE_RANDOM and IN6_ADDR_GEN_MODE_STABLE_PRIVACY cases. Fix the situation by using add_v4_addrs() only in the specific scenario where the normal method would fail. That is, for interfaces that have all of the following characteristics: * run over IPv4, * transport IP packets directly, not Ethernet (that is, not gretap interfaces), * tunnel endpoint is INADDR_ANY (that is, 0), * device address generation mode is EUI64. In all other cases, revert back to the regular addrconf_addr_gen(). Also, remove the special case for ip6gre interfaces in add_v4_addrs(), since ip6gre devices now always use addrconf_addr_gen() instead. Fixes: e5dd729460ca ("ip/ip6_gre: use the same logic as SIT interfaces when computing v6LL address") Signed-off-by: Guillaume Nault Reviewed-by: Ido Schimmel Link: https://patch.msgid.link/559c32ce5c9976b269e6337ac9abb6a96abe5096.1741375285.git.gnault@redhat.com Signed-off-by: Paolo Abeni --- net/ipv6/addrconf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ac8cc1076536..8b6258819dad 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3209,16 +3209,13 @@ static void add_v4_addrs(struct inet6_dev *idev) struct in6_addr addr; struct net_device *dev; struct net *net = dev_net(idev->dev); - int scope, plen, offset = 0; + int scope, plen; u32 pflags = 0; ASSERT_RTNL(); memset(&addr, 0, sizeof(struct in6_addr)); - /* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */ - if (idev->dev->addr_len == sizeof(struct in6_addr)) - offset = sizeof(struct in6_addr) - 4; - memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4); + memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4); if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) { scope = IPV6_ADDR_COMPATv4; @@ -3529,7 +3526,13 @@ static void addrconf_gre_config(struct net_device *dev) return; } - if (dev->type == ARPHRD_ETHER) { + /* Generate the IPv6 link-local address using addrconf_addr_gen(), + * unless we have an IPv4 GRE device not bound to an IP address and + * which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this + * case). Such devices fall back to add_v4_addrs() instead. + */ + if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 && + idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) { addrconf_addr_gen(idev, true); return; } From 6f50175ccad4278ed3a9394c00b797b75441bd6e Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Fri, 7 Mar 2025 20:28:58 +0100 Subject: [PATCH 0898/1090] selftests: Add IPv6 link-local address generation tests for GRE devices. GRE devices have their special code for IPv6 link-local address generation that has been the source of several regressions in the past. Add selftest to check that all gre, ip6gre, gretap and ip6gretap get an IPv6 link-link local address in accordance with the net.ipv6.conf..addr_gen_mode sysctl. Signed-off-by: Guillaume Nault Reviewed-by: Ido Schimmel Tested-by: Ido Schimmel Reviewed-by: Petr Machata Link: https://patch.msgid.link/2d6772af8e1da9016b2180ec3f8d9ee99f470c77.1741375285.git.gnault@redhat.com Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/Makefile | 1 + .../testing/selftests/net/gre_ipv6_lladdr.sh | 177 ++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100755 tools/testing/selftests/net/gre_ipv6_lladdr.sh diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 73ee88d6b043..5916f3b81c39 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -31,6 +31,7 @@ TEST_PROGS += veth.sh TEST_PROGS += ioam6.sh TEST_PROGS += gro.sh TEST_PROGS += gre_gso.sh +TEST_PROGS += gre_ipv6_lladdr.sh TEST_PROGS += cmsg_so_mark.sh TEST_PROGS += cmsg_so_priority.sh TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh diff --git a/tools/testing/selftests/net/gre_ipv6_lladdr.sh b/tools/testing/selftests/net/gre_ipv6_lladdr.sh new file mode 100755 index 000000000000..5b34f6e1f831 --- /dev/null +++ b/tools/testing/selftests/net/gre_ipv6_lladdr.sh @@ -0,0 +1,177 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +source ./lib.sh + +PAUSE_ON_FAIL="no" + +# The trap function handler +# +exit_cleanup_all() +{ + cleanup_all_ns + + exit "${EXIT_STATUS}" +} + +# Add fake IPv4 and IPv6 networks on the loopback device, to be used as +# underlay by future GRE devices. +# +setup_basenet() +{ + ip -netns "${NS0}" link set dev lo up + ip -netns "${NS0}" address add dev lo 192.0.2.10/24 + ip -netns "${NS0}" address add dev lo 2001:db8::10/64 nodad +} + +# Check if network device has an IPv6 link-local address assigned. +# +# Parameters: +# +# * $1: The network device to test +# * $2: An extra regular expression that should be matched (to verify the +# presence of extra attributes) +# * $3: The expected return code from grep (to allow checking the absence of +# a link-local address) +# * $4: The user visible name for the scenario being tested +# +check_ipv6_ll_addr() +{ + local DEV="$1" + local EXTRA_MATCH="$2" + local XRET="$3" + local MSG="$4" + + RET=0 + set +e + ip -netns "${NS0}" -6 address show dev "${DEV}" scope link | grep "fe80::" | grep -q "${EXTRA_MATCH}" + check_err_fail "${XRET}" $? "" + log_test "${MSG}" + set -e +} + +# Create a GRE device and verify that it gets an IPv6 link-local address as +# expected. +# +# Parameters: +# +# * $1: The device type (gre, ip6gre, gretap or ip6gretap) +# * $2: The local underlay IP address (can be an IPv4, an IPv6 or "any") +# * $3: The remote underlay IP address (can be an IPv4, an IPv6 or "any") +# * $4: The IPv6 interface identifier generation mode to use for the GRE +# device (eui64, none, stable-privacy or random). +# +test_gre_device() +{ + local GRE_TYPE="$1" + local LOCAL_IP="$2" + local REMOTE_IP="$3" + local MODE="$4" + local ADDR_GEN_MODE + local MATCH_REGEXP + local MSG + + ip link add netns "${NS0}" name gretest type "${GRE_TYPE}" local "${LOCAL_IP}" remote "${REMOTE_IP}" + + case "${MODE}" in + "eui64") + ADDR_GEN_MODE=0 + MATCH_REGEXP="" + MSG="${GRE_TYPE}, mode: 0 (EUI64), ${LOCAL_IP} -> ${REMOTE_IP}" + XRET=0 + ;; + "none") + ADDR_GEN_MODE=1 + MATCH_REGEXP="" + MSG="${GRE_TYPE}, mode: 1 (none), ${LOCAL_IP} -> ${REMOTE_IP}" + XRET=1 # No link-local address should be generated + ;; + "stable-privacy") + ADDR_GEN_MODE=2 + MATCH_REGEXP="stable-privacy" + MSG="${GRE_TYPE}, mode: 2 (stable privacy), ${LOCAL_IP} -> ${REMOTE_IP}" + XRET=0 + # Initialise stable_secret (required for stable-privacy mode) + ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.stable_secret="2001:db8::abcd" + ;; + "random") + ADDR_GEN_MODE=3 + MATCH_REGEXP="stable-privacy" + MSG="${GRE_TYPE}, mode: 3 (random), ${LOCAL_IP} -> ${REMOTE_IP}" + XRET=0 + ;; + esac + + # Check that IPv6 link-local address is generated when device goes up + ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}" + ip -netns "${NS0}" link set dev gretest up + check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "config: ${MSG}" + + # Now disable link-local address generation + ip -netns "${NS0}" link set dev gretest down + ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode=1 + ip -netns "${NS0}" link set dev gretest up + + # Check that link-local address generation works when re-enabled while + # the device is already up + ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}" + check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "update: ${MSG}" + + ip -netns "${NS0}" link del dev gretest +} + +test_gre4() +{ + local GRE_TYPE + local MODE + + for GRE_TYPE in "gre" "gretap"; do + printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n" + + for MODE in "eui64" "none" "stable-privacy" "random"; do + test_gre_device "${GRE_TYPE}" 192.0.2.10 192.0.2.11 "${MODE}" + test_gre_device "${GRE_TYPE}" any 192.0.2.11 "${MODE}" + test_gre_device "${GRE_TYPE}" 192.0.2.10 any "${MODE}" + done + done +} + +test_gre6() +{ + local GRE_TYPE + local MODE + + for GRE_TYPE in "ip6gre" "ip6gretap"; do + printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n" + + for MODE in "eui64" "none" "stable-privacy" "random"; do + test_gre_device "${GRE_TYPE}" 2001:db8::10 2001:db8::11 "${MODE}" + test_gre_device "${GRE_TYPE}" any 2001:db8::11 "${MODE}" + test_gre_device "${GRE_TYPE}" 2001:db8::10 any "${MODE}" + done + done +} + +usage() +{ + echo "Usage: $0 [-p]" + exit 1 +} + +while getopts :p o +do + case $o in + p) PAUSE_ON_FAIL="yes";; + *) usage;; + esac +done + +setup_ns NS0 + +set -e +trap exit_cleanup_all EXIT + +setup_basenet + +test_gre4 +test_gre6 From a1e64addf3ff9257b45b78bc7d743781c3f41340 Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Sat, 8 Mar 2025 01:45:59 +0100 Subject: [PATCH 0899/1090] net: openvswitch: remove misbehaving actions length check The actions length check is unreliable and produces different results depending on the initial length of the provided netlink attribute and the composition of the actual actions inside of it. For example, a user can add 4088 empty clone() actions without triggering -EMSGSIZE, on attempt to add 4089 such actions the operation will fail with the -EMSGSIZE verdict. However, if another 16 KB of other actions will be *appended* to the previous 4089 clone() actions, the check passes and the flow is successfully installed into the openvswitch datapath. The reason for a such a weird behavior is the way memory is allocated. When ovs_flow_cmd_new() is invoked, it calls ovs_nla_copy_actions(), that in turn calls nla_alloc_flow_actions() with either the actual length of the user-provided actions or the MAX_ACTIONS_BUFSIZE. The function adds the size of the sw_flow_actions structure and then the actually allocated memory is rounded up to the closest power of two. So, if the user-provided actions are larger than MAX_ACTIONS_BUFSIZE, then MAX_ACTIONS_BUFSIZE + sizeof(*sfa) rounded up is 32K + 24 -> 64K. Later, while copying individual actions, we look at ksize(), which is 64K, so this way the MAX_ACTIONS_BUFSIZE check is not actually triggered and the user can easily allocate almost 64 KB of actions. However, when the initial size is less than MAX_ACTIONS_BUFSIZE, but the actions contain ones that require size increase while copying (such as clone() or sample()), then the limit check will be performed during the reserve_sfa_size() and the user will not be allowed to create actions that yield more than 32 KB internally. This is one part of the problem. The other part is that it's not actually possible for the userspace application to know beforehand if the particular set of actions will be rejected or not. Certain actions require more space in the internal representation, e.g. an empty clone() takes 4 bytes in the action list passed in by the user, but it takes 12 bytes in the internal representation due to an extra nested attribute, and some actions require less space in the internal representations, e.g. set(tunnel(..)) normally takes 64+ bytes in the action list provided by the user, but only needs to store a single pointer in the internal implementation, since all the data is stored in the tunnel_info structure instead. And the action size limit is applied to the internal representation, not to the action list passed by the user. So, it's not possible for the userpsace application to predict if the certain combination of actions will be rejected or not, because it is not possible for it to calculate how much space these actions will take in the internal representation without knowing kernel internals. All that is causing random failures in ovs-vswitchd in userspace and inability to handle certain traffic patterns as a result. For example, it is reported that adding a bit more than a 1100 VMs in an OpenStack setup breaks the network due to OVS not being able to handle ARP traffic anymore in some cases (it tries to install a proper datapath flow, but the kernel rejects it with -EMSGSIZE, even though the action list isn't actually that large.) Kernel behavior must be consistent and predictable in order for the userspace application to use it in a reasonable way. ovs-vswitchd has a mechanism to re-direct parts of the traffic and partially handle it in userspace if the required action list is oversized, but that doesn't work properly if we can't actually tell if the action list is oversized or not. Solution for this is to check the size of the user-provided actions instead of the internal representation. This commit just removes the check from the internal part because there is already an implicit size check imposed by the netlink protocol. The attribute can't be larger than 64 KB. Realistically, we could reduce the limit to 32 KB, but we'll be risking to break some existing setups that rely on the fact that it's possible to create nearly 64 KB action lists today. Vast majority of flows in real setups are below 100-ish bytes. So removal of the limit will not change real memory consumption on the system. The absolutely worst case scenario is if someone adds a flow with 64 KB of empty clone() actions. That will yield a 192 KB in the internal representation consuming 256 KB block of memory. However, that list of actions is not meaningful and also a no-op. Real world very large action lists (that can occur for a rare cases of BUM traffic handling) are unlikely to contain a large number of clones and will likely have a lot of tunnel attributes making the internal representation comparable in size to the original action list. So, it should be fine to just remove the limit. Commit in the 'Fixes' tag is the first one that introduced the difference between internal representation and the user-provided action lists, but there were many more afterwards that lead to the situation we have today. Fixes: 7d5437c709de ("openvswitch: Add tunneling interface.") Signed-off-by: Ilya Maximets Reviewed-by: Aaron Conole Link: https://patch.msgid.link/20250308004609.2881861-1-i.maximets@ovn.org Signed-off-by: Paolo Abeni --- net/openvswitch/flow_netlink.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 881ddd3696d5..95e0dd14dc1a 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -2317,14 +2317,10 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb) OVS_FLOW_ATTR_MASK, true, skb); } -#define MAX_ACTIONS_BUFSIZE (32 * 1024) - static struct sw_flow_actions *nla_alloc_flow_actions(int size) { struct sw_flow_actions *sfa; - WARN_ON_ONCE(size > MAX_ACTIONS_BUFSIZE); - sfa = kmalloc(kmalloc_size_roundup(sizeof(*sfa) + size), GFP_KERNEL); if (!sfa) return ERR_PTR(-ENOMEM); @@ -2480,15 +2476,6 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2); - if (new_acts_size > MAX_ACTIONS_BUFSIZE) { - if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) { - OVS_NLERR(log, "Flow action size exceeds max %u", - MAX_ACTIONS_BUFSIZE); - return ERR_PTR(-EMSGSIZE); - } - new_acts_size = MAX_ACTIONS_BUFSIZE; - } - acts = nla_alloc_flow_actions(new_acts_size); if (IS_ERR(acts)) return ERR_CAST(acts); @@ -3545,7 +3532,7 @@ int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, int err; u32 mpls_label_count = 0; - *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE)); + *sfa = nla_alloc_flow_actions(nla_len(attr)); if (IS_ERR(*sfa)) return PTR_ERR(*sfa); From 1063ae07383c0ddc5bcce170260c143825846b03 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Sat, 8 Mar 2025 13:05:43 -0500 Subject: [PATCH 0900/1090] Revert "openvswitch: switch to per-action label counting in conntrack" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, ovs_ct_set_labels() is only called for confirmed conntrack entries (ct) within ovs_ct_commit(). However, if the conntrack entry does not have the labels_ext extension, attempting to allocate it in ovs_ct_get_conn_labels() for a confirmed entry triggers a warning in nf_ct_ext_add(): WARN_ON(nf_ct_is_confirmed(ct)); This happens when the conntrack entry is created externally before OVS increments net->ct.labels_used. The issue has become more likely since commit fcb1aa5163b1 ("openvswitch: switch to per-action label counting in conntrack"), which changed to use per-action label counting and increment net->ct.labels_used when a flow with ct action is added. Since there’s no straightforward way to fully resolve this issue at the moment, this reverts the commit to avoid breaking existing use cases. Fixes: fcb1aa5163b1 ("openvswitch: switch to per-action label counting in conntrack") Reported-by: Jianbo Liu Signed-off-by: Xin Long Acked-by: Aaron Conole Link: https://patch.msgid.link/1bdeb2f3a812bca016a225d3de714427b2cd4772.1741457143.git.lucien.xin@gmail.com Signed-off-by: Paolo Abeni --- net/openvswitch/conntrack.c | 30 ++++++++++++++++++------------ net/openvswitch/datapath.h | 3 +++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 3bb4810234aa..e573e9221302 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1368,8 +1368,11 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr) attr == OVS_KEY_ATTR_CT_MARK) return true; if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && - attr == OVS_KEY_ATTR_CT_LABELS) - return true; + attr == OVS_KEY_ATTR_CT_LABELS) { + struct ovs_net *ovs_net = net_generic(net, ovs_net_id); + + return ovs_net->xt_label; + } return false; } @@ -1378,7 +1381,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, const struct sw_flow_key *key, struct sw_flow_actions **sfa, bool log) { - unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE; struct ovs_conntrack_info ct_info; const char *helper = NULL; u16 family; @@ -1407,12 +1409,6 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, return -ENOMEM; } - if (nf_connlabels_get(net, n_bits - 1)) { - nf_ct_tmpl_free(ct_info.ct); - OVS_NLERR(log, "Failed to set connlabel length"); - return -EOPNOTSUPP; - } - if (ct_info.timeout[0]) { if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto, ct_info.timeout)) @@ -1581,7 +1577,6 @@ static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info) if (ct_info->ct) { if (ct_info->timeout[0]) nf_ct_destroy_timeout(ct_info->ct); - nf_connlabels_put(nf_ct_net(ct_info->ct)); nf_ct_tmpl_free(ct_info->ct); } } @@ -2006,9 +2001,17 @@ struct genl_family dp_ct_limit_genl_family __ro_after_init = { int ovs_ct_init(struct net *net) { -#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) + unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE; struct ovs_net *ovs_net = net_generic(net, ovs_net_id); + if (nf_connlabels_get(net, n_bits - 1)) { + ovs_net->xt_label = false; + OVS_NLERR(true, "Failed to set connlabel length"); + } else { + ovs_net->xt_label = true; + } + +#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) return ovs_ct_limit_init(net, ovs_net); #else return 0; @@ -2017,9 +2020,12 @@ int ovs_ct_init(struct net *net) void ovs_ct_exit(struct net *net) { -#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) struct ovs_net *ovs_net = net_generic(net, ovs_net_id); +#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) ovs_ct_limit_exit(net, ovs_net); #endif + + if (ovs_net->xt_label) + nf_connlabels_put(net); } diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 365b9bb7f546..9ca6231ea647 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -160,6 +160,9 @@ struct ovs_net { #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT) struct ovs_ct_limit_info *ct_limit_info; #endif + + /* Module reference for configuring conntrack. */ + bool xt_label; }; /** From 03ebae19925519cca5b314443c6082e0aeaa6321 Mon Sep 17 00:00:00 2001 From: Yevgeny Kliteynik Date: Tue, 11 Mar 2025 00:01:39 +0200 Subject: [PATCH 0901/1090] net/mlx5: DR, use the right action structs for STEv3 Some actions in ConnectX-8 (STEv3) have different structure, and they are handled separately in ste_ctx_v3. This separate handling was missing two actions: INSERT_HDR and REMOVE_HDR, which broke SWS for Linux Bridge. This patch resolves the issue by introducing dedicated callbacks for the insert and remove header functions, with version-specific implementations for each STE variant. Fixes: 4d617b57574f ("net/mlx5: DR, add support for ConnectX-8 steering") Signed-off-by: Yevgeny Kliteynik Reviewed-by: Itamar Gozlan Reviewed-by: Mark Bloch Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/1741644104-97767-2-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- .../mellanox/mlx5/core/steering/sws/dr_ste.h | 4 ++ .../mlx5/core/steering/sws/dr_ste_v1.c | 52 ++++++++++--------- .../mlx5/core/steering/sws/dr_ste_v1.h | 4 ++ .../mlx5/core/steering/sws/dr_ste_v2.c | 2 + .../mlx5/core/steering/sws/dr_ste_v3.c | 42 +++++++++++++++ 5 files changed, 79 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h index 5f409dc30aca..3d5afc832fa5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h @@ -210,6 +210,10 @@ struct mlx5dr_ste_ctx { void (*set_encap_l3)(u8 *hw_ste_p, u8 *frst_s_action, u8 *scnd_d_action, u32 reformat_id, int size); + void (*set_insert_hdr)(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, + u8 anchor, u8 offset, int size); + void (*set_remove_hdr)(u8 *hw_ste_p, u8 *s_action, u8 anchor, + u8 offset, int size); /* Send */ void (*prepare_for_postsend)(u8 *hw_ste_p, u32 ste_size); }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c index 7f83d77c43ef..6447efbae00d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c @@ -266,10 +266,10 @@ void dr_ste_v1_set_encap(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, int size) dr_ste_v1_set_reparse(hw_ste_p); } -static void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, - u32 reformat_id, - u8 anchor, u8 offset, - int size) +void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, + u32 reformat_id, + u8 anchor, u8 offset, + int size) { MLX5_SET(ste_double_action_insert_with_ptr_v1, d_action, action_id, DR_STE_V1_ACTION_ID_INSERT_POINTER); @@ -286,9 +286,9 @@ static void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, dr_ste_v1_set_reparse(hw_ste_p); } -static void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action, - u8 anchor, u8 offset, - int size) +void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action, + u8 anchor, u8 offset, + int size) { MLX5_SET(ste_single_action_remove_header_size_v1, s_action, action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE); @@ -584,11 +584,11 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action); action_sz = DR_STE_ACTION_TRIPLE_SZ; } - dr_ste_v1_set_insert_hdr(last_ste, action, - attr->reformat.id, - attr->reformat.param_0, - attr->reformat.param_1, - attr->reformat.size); + ste_ctx->set_insert_hdr(last_ste, action, + attr->reformat.id, + attr->reformat.param_0, + attr->reformat.param_1, + attr->reformat.size); action_sz -= DR_STE_ACTION_DOUBLE_SZ; action += DR_STE_ACTION_DOUBLE_SZ; } else if (action_type_set[DR_ACTION_TYP_REMOVE_HDR]) { @@ -597,10 +597,10 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action); action_sz = DR_STE_ACTION_TRIPLE_SZ; } - dr_ste_v1_set_remove_hdr(last_ste, action, - attr->reformat.param_0, - attr->reformat.param_1, - attr->reformat.size); + ste_ctx->set_remove_hdr(last_ste, action, + attr->reformat.param_0, + attr->reformat.param_1, + attr->reformat.size); action_sz -= DR_STE_ACTION_SINGLE_SZ; action += DR_STE_ACTION_SINGLE_SZ; } @@ -792,11 +792,11 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx, action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action); action_sz = DR_STE_ACTION_TRIPLE_SZ; } - dr_ste_v1_set_insert_hdr(last_ste, action, - attr->reformat.id, - attr->reformat.param_0, - attr->reformat.param_1, - attr->reformat.size); + ste_ctx->set_insert_hdr(last_ste, action, + attr->reformat.id, + attr->reformat.param_0, + attr->reformat.param_1, + attr->reformat.size); action_sz -= DR_STE_ACTION_DOUBLE_SZ; action += DR_STE_ACTION_DOUBLE_SZ; allow_modify_hdr = false; @@ -808,10 +808,10 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx, allow_modify_hdr = true; allow_ctr = true; } - dr_ste_v1_set_remove_hdr(last_ste, action, - attr->reformat.param_0, - attr->reformat.param_1, - attr->reformat.size); + ste_ctx->set_remove_hdr(last_ste, action, + attr->reformat.param_0, + attr->reformat.param_1, + attr->reformat.size); action_sz -= DR_STE_ACTION_SINGLE_SZ; action += DR_STE_ACTION_SINGLE_SZ; } @@ -2200,6 +2200,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v1 = { .set_pop_vlan = &dr_ste_v1_set_pop_vlan, .set_rx_decap = &dr_ste_v1_set_rx_decap, .set_encap_l3 = &dr_ste_v1_set_encap_l3, + .set_insert_hdr = &dr_ste_v1_set_insert_hdr, + .set_remove_hdr = &dr_ste_v1_set_remove_hdr, /* Send */ .prepare_for_postsend = &dr_ste_v1_prepare_for_postsend, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h index a8d9e308d339..591c20c95a6a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h @@ -156,6 +156,10 @@ void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num); void dr_ste_v1_set_encap_l3(u8 *hw_ste_p, u8 *frst_s_action, u8 *scnd_d_action, u32 reformat_id, int size); void dr_ste_v1_set_rx_decap(u8 *hw_ste_p, u8 *s_action); +void dr_ste_v1_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, + u8 anchor, u8 offset, int size); +void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action, u8 anchor, + u8 offset, int size); void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, struct mlx5dr_domain *dmn, u8 *action_type_set, u32 actions_caps, u8 *last_ste, struct mlx5dr_ste_actions_attr *attr, u32 *added_stes); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c index 0882dba0f64b..d0ebaf820d42 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c @@ -69,6 +69,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v2 = { .set_pop_vlan = &dr_ste_v1_set_pop_vlan, .set_rx_decap = &dr_ste_v1_set_rx_decap, .set_encap_l3 = &dr_ste_v1_set_encap_l3, + .set_insert_hdr = &dr_ste_v1_set_insert_hdr, + .set_remove_hdr = &dr_ste_v1_set_remove_hdr, /* Send */ .prepare_for_postsend = &dr_ste_v1_prepare_for_postsend, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c index cc60ce1d274e..e468a9ae44e8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c @@ -79,6 +79,46 @@ static void dr_ste_v3_set_rx_decap(u8 *hw_ste_p, u8 *s_action) dr_ste_v1_set_reparse(hw_ste_p); } +static void dr_ste_v3_set_insert_hdr(u8 *hw_ste_p, u8 *d_action, + u32 reformat_id, u8 anchor, + u8 offset, int size) +{ + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + action_id, DR_STE_V1_ACTION_ID_INSERT_POINTER); + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + start_anchor, anchor); + + /* The hardware expects here size and offset in words (2 byte) */ + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + size, size / 2); + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + start_offset, offset / 2); + + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + pointer, reformat_id); + MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, + attributes, DR_STE_V1_ACTION_INSERT_PTR_ATTR_NONE); + + dr_ste_v1_set_reparse(hw_ste_p); +} + +static void dr_ste_v3_set_remove_hdr(u8 *hw_ste_p, u8 *s_action, + u8 anchor, u8 offset, int size) +{ + MLX5_SET(ste_single_action_remove_header_size_v3, s_action, + action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE); + MLX5_SET(ste_single_action_remove_header_size_v3, s_action, + start_anchor, anchor); + + /* The hardware expects here size and offset in words (2 byte) */ + MLX5_SET(ste_single_action_remove_header_size_v3, s_action, + remove_size, size / 2); + MLX5_SET(ste_single_action_remove_header_size_v3, s_action, + start_offset, offset / 2); + + dr_ste_v1_set_reparse(hw_ste_p); +} + static int dr_ste_v3_set_action_decap_l3_list(void *data, u32 data_sz, u8 *hw_action, u32 hw_action_sz, @@ -211,6 +251,8 @@ static struct mlx5dr_ste_ctx ste_ctx_v3 = { .set_pop_vlan = &dr_ste_v3_set_pop_vlan, .set_rx_decap = &dr_ste_v3_set_rx_decap, .set_encap_l3 = &dr_ste_v3_set_encap_l3, + .set_insert_hdr = &dr_ste_v3_set_insert_hdr, + .set_remove_hdr = &dr_ste_v3_set_remove_hdr, /* Send */ .prepare_for_postsend = &dr_ste_v1_prepare_for_postsend, }; From 521992337f67f71ce4436b98bc32563ddb1a5ce3 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Tue, 11 Mar 2025 00:01:40 +0200 Subject: [PATCH 0902/1090] net/mlx5: HWS, Rightsize bwc matcher priority The bwc layer was clamping the matcher priority from 32 bits to 16 bits. This didn't show up until a matcher was resized, since the initial native matcher was created using the correct 32 bit value. The fix also reorders fields to avoid some padding. Fixes: 2111bb970c78 ("net/mlx5: HWS, added backward-compatible API handling") Signed-off-by: Vlad Dogaru Reviewed-by: Yevgeny Kliteynik Reviewed-by: Mark Bloch Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/1741644104-97767-3-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h index f9f569131dde..47f7ed141553 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h @@ -24,8 +24,8 @@ struct mlx5hws_bwc_matcher { struct mlx5hws_matcher *matcher; struct mlx5hws_match_template *mt; struct mlx5hws_action_template *at[MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM]; + u32 priority; u8 num_of_at; - u16 priority; u8 size_log; atomic_t num_of_rules; struct list_head *rules; From 32d2724db5b2361ab293427ccd5c24f4f2bcca14 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 11 Mar 2025 00:01:41 +0200 Subject: [PATCH 0903/1090] net/mlx5: Fix incorrect IRQ pool usage when releasing IRQs mlx5_irq_pool_get() is a getter for completion IRQ pool only. However, after the cited commit, mlx5_irq_pool_get() is called during ctrl IRQ release flow to retrieve the pool, resulting in the use of an incorrect IRQ pool. Hence, use the newly introduced mlx5_irq_get_pool() getter to retrieve the correct IRQ pool based on the IRQ itself. While at it, rename mlx5_irq_pool_get() to mlx5_irq_table_get_comp_irq_pool() which accurately reflects its purpose and improves code readability. Fixes: 0477d5168bbb ("net/mlx5: Expose SFs IRQs") Signed-off-by: Shay Drory Reviewed-by: Maher Sanalla Signed-off-by: Tariq Toukan Reviewed-by: Michal Swiatkowski Link: https://patch.msgid.link/1741644104-97767-4-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +- .../net/ethernet/mellanox/mlx5/core/irq_affinity.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h | 4 +++- drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 13 ++++++++++--- drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 2b229b6226c6..dfb079e59d85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -871,8 +871,8 @@ static void comp_irq_release_sf(struct mlx5_core_dev *dev, u16 vecidx) static int comp_irq_request_sf(struct mlx5_core_dev *dev, u16 vecidx) { + struct mlx5_irq_pool *pool = mlx5_irq_table_get_comp_irq_pool(dev); struct mlx5_eq_table *table = dev->priv.eq_table; - struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev); struct irq_affinity_desc af_desc = {}; struct mlx5_irq *irq; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c index 1477db7f5307..2691d88cdee1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/irq_affinity.c @@ -175,7 +175,7 @@ unlock: void mlx5_irq_affinity_irq_release(struct mlx5_core_dev *dev, struct mlx5_irq *irq) { - struct mlx5_irq_pool *pool = mlx5_irq_pool_get(dev); + struct mlx5_irq_pool *pool = mlx5_irq_get_pool(irq); int cpu; cpu = cpumask_first(mlx5_irq_get_affinity_mask(irq)); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h index 0881e961d8b1..586688da9940 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h @@ -10,12 +10,15 @@ struct mlx5_irq; struct cpu_rmap; +struct mlx5_irq_pool; int mlx5_irq_table_init(struct mlx5_core_dev *dev); void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev); int mlx5_irq_table_create(struct mlx5_core_dev *dev); void mlx5_irq_table_destroy(struct mlx5_core_dev *dev); void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev); +struct mlx5_irq_pool * +mlx5_irq_table_get_comp_irq_pool(struct mlx5_core_dev *dev); int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table); int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table); struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev); @@ -38,7 +41,6 @@ struct cpumask *mlx5_irq_get_affinity_mask(struct mlx5_irq *irq); int mlx5_irq_get_index(struct mlx5_irq *irq); int mlx5_irq_get_irq(const struct mlx5_irq *irq); -struct mlx5_irq_pool; #ifdef CONFIG_MLX5_SF struct mlx5_irq *mlx5_irq_affinity_irq_request_auto(struct mlx5_core_dev *dev, struct cpumask *used_cpus, u16 vecidx); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index d9362eabc6a1..2c5f850c31f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -378,6 +378,11 @@ int mlx5_irq_get_index(struct mlx5_irq *irq) return irq->map.index; } +struct mlx5_irq_pool *mlx5_irq_get_pool(struct mlx5_irq *irq) +{ + return irq->pool; +} + /* irq_pool API */ /* requesting an irq from a given pool according to given index */ @@ -405,18 +410,20 @@ static struct mlx5_irq_pool *sf_ctrl_irq_pool_get(struct mlx5_irq_table *irq_tab return irq_table->sf_ctrl_pool; } -static struct mlx5_irq_pool *sf_irq_pool_get(struct mlx5_irq_table *irq_table) +static struct mlx5_irq_pool * +sf_comp_irq_pool_get(struct mlx5_irq_table *irq_table) { return irq_table->sf_comp_pool; } -struct mlx5_irq_pool *mlx5_irq_pool_get(struct mlx5_core_dev *dev) +struct mlx5_irq_pool * +mlx5_irq_table_get_comp_irq_pool(struct mlx5_core_dev *dev) { struct mlx5_irq_table *irq_table = mlx5_irq_table_get(dev); struct mlx5_irq_pool *pool = NULL; if (mlx5_core_is_sf(dev)) - pool = sf_irq_pool_get(irq_table); + pool = sf_comp_irq_pool_get(irq_table); /* In some configs, there won't be a pool of SFs IRQs. Hence, returning * the PF IRQs pool in case the SF pool doesn't exist. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h index c4d377f8df30..cc064425fe16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.h @@ -28,7 +28,6 @@ struct mlx5_irq_pool { struct mlx5_core_dev *dev; }; -struct mlx5_irq_pool *mlx5_irq_pool_get(struct mlx5_core_dev *dev); static inline bool mlx5_irq_pool_is_sf_pool(struct mlx5_irq_pool *pool) { return !strncmp("mlx5_sf", pool->name, strlen("mlx5_sf")); @@ -40,5 +39,6 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, int mlx5_irq_get_locked(struct mlx5_irq *irq); int mlx5_irq_read_locked(struct mlx5_irq *irq); int mlx5_irq_put(struct mlx5_irq *irq); +struct mlx5_irq_pool *mlx5_irq_get_pool(struct mlx5_irq *irq); #endif /* __PCI_IRQ_H__ */ From 32966984bee1defd9f5a8f9be274d7c32f911ba1 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 11 Mar 2025 00:01:42 +0200 Subject: [PATCH 0904/1090] net/mlx5: Lag, Check shared fdb before creating MultiPort E-Switch Currently, MultiPort E-Switch is requesting to create a LAG with shared FDB without checking the LAG is supporting shared FDB. Add the check. Fixes: a32327a3a02c ("net/mlx5: Lag, Control MultiPort E-Switch single FDB mode") Signed-off-by: Shay Drory Reviewed-by: Mark Bloch Signed-off-by: Tariq Toukan Reviewed-by: Michal Swiatkowski Link: https://patch.msgid.link/1741644104-97767-5-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index cea5aa314f6c..ed2ba272946b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -951,7 +951,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); } -static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) +bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev) { int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); struct mlx5_core_dev *dev; @@ -1038,7 +1038,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) } if (do_bond && !__mlx5_lag_is_active(ldev)) { - bool shared_fdb = mlx5_shared_fdb_supported(ldev); + bool shared_fdb = mlx5_lag_shared_fdb_supported(ldev); roce_lag = mlx5_lag_is_roce_lag(ldev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index 01cf72366947..c2f256bb2bc2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -92,6 +92,7 @@ mlx5_lag_is_ready(struct mlx5_lag *ldev) return test_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags); } +bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev); bool mlx5_lag_check_prereq(struct mlx5_lag *ldev); void mlx5_modify_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c index ffac0bd6c895..1770297a112e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c @@ -83,7 +83,8 @@ static int enable_mpesw(struct mlx5_lag *ldev) if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || - !mlx5_lag_check_prereq(ldev)) + !mlx5_lag_check_prereq(ldev) || + !mlx5_lag_shared_fdb_supported(ldev)) return -EOPNOTSUPP; err = mlx5_mpesw_metadata_set(ldev); From 4b8eeed4fb105770ce6dc84a2c6ef953c7b71cbb Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Tue, 11 Mar 2025 00:01:43 +0200 Subject: [PATCH 0905/1090] net/mlx5: Bridge, fix the crash caused by LAG state check When removing LAG device from bridge, NETDEV_CHANGEUPPER event is triggered. Driver finds the lower devices (PFs) to flush all the offloaded entries. And mlx5_lag_is_shared_fdb is checked, it returns false if one of PF is unloaded. In such case, mlx5_esw_bridge_lag_rep_get() and its caller return NULL, instead of the alive PF, and the flush is skipped. Besides, the bridge fdb entry's lastuse is updated in mlx5 bridge event handler. But this SWITCHDEV_FDB_ADD_TO_BRIDGE event can be ignored in this case because the upper interface for bond is deleted, and the entry will never be aged because lastuse is never updated. To make things worse, as the entry is alive, mlx5 bridge workqueue keeps sending that event, which is then handled by kernel bridge notifier. It causes the following crash when accessing the passed bond netdev which is already destroyed. To fix this issue, remove such checks. LAG state is already checked in commit 15f8f168952f ("net/mlx5: Bridge, verify LAG state when adding bond to bridge"), driver still need to skip offload if LAG becomes invalid state after initialization. Oops: stack segment: 0000 [#1] SMP CPU: 3 UID: 0 PID: 23695 Comm: kworker/u40:3 Tainted: G OE 6.11.0_mlnx #1 Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Workqueue: mlx5_bridge_wq mlx5_esw_bridge_update_work [mlx5_core] RIP: 0010:br_switchdev_event+0x2c/0x110 [bridge] Code: 44 00 00 48 8b 02 48 f7 00 00 02 00 00 74 69 41 54 55 53 48 83 ec 08 48 8b a8 08 01 00 00 48 85 ed 74 4a 48 83 fe 02 48 89 d3 <4c> 8b 65 00 74 23 76 49 48 83 fe 05 74 7e 48 83 fe 06 75 2f 0f b7 RSP: 0018:ffffc900092cfda0 EFLAGS: 00010297 RAX: ffff888123bfe000 RBX: ffffc900092cfe08 RCX: 00000000ffffffff RDX: ffffc900092cfe08 RSI: 0000000000000001 RDI: ffffffffa0c585f0 RBP: 6669746f6e690a30 R08: 0000000000000000 R09: ffff888123ae92c8 R10: 0000000000000000 R11: fefefefefefefeff R12: ffff888123ae9c60 R13: 0000000000000001 R14: ffffc900092cfe08 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88852c980000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f15914c8734 CR3: 0000000002830005 CR4: 0000000000770ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: ? __die_body+0x1a/0x60 ? die+0x38/0x60 ? do_trap+0x10b/0x120 ? do_error_trap+0x64/0xa0 ? exc_stack_segment+0x33/0x50 ? asm_exc_stack_segment+0x22/0x30 ? br_switchdev_event+0x2c/0x110 [bridge] ? sched_balance_newidle.isra.149+0x248/0x390 notifier_call_chain+0x4b/0xa0 atomic_notifier_call_chain+0x16/0x20 mlx5_esw_bridge_update+0xec/0x170 [mlx5_core] mlx5_esw_bridge_update_work+0x19/0x40 [mlx5_core] process_scheduled_works+0x81/0x390 worker_thread+0x106/0x250 ? bh_worker+0x110/0x110 kthread+0xb7/0xe0 ? kthread_park+0x80/0x80 ret_from_fork+0x2d/0x50 ? kthread_park+0x80/0x80 ret_from_fork_asm+0x11/0x20 Fixes: ff9b7521468b ("net/mlx5: Bridge, support LAG") Signed-off-by: Jianbo Liu Reviewed-by: Vlad Buslov Signed-off-by: Tariq Toukan Reviewed-by: Michal Swiatkowski Link: https://patch.msgid.link/1741644104-97767-6-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- .../net/ethernet/mellanox/mlx5/core/en/rep/bridge.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c index 5d128c5b4529..0f5d7ea8956f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c @@ -48,15 +48,10 @@ mlx5_esw_bridge_lag_rep_get(struct net_device *dev, struct mlx5_eswitch *esw) struct list_head *iter; netdev_for_each_lower_dev(dev, lower, iter) { - struct mlx5_core_dev *mdev; - struct mlx5e_priv *priv; - if (!mlx5e_eswitch_rep(lower)) continue; - priv = netdev_priv(lower); - mdev = priv->mdev; - if (mlx5_lag_is_shared_fdb(mdev) && mlx5_esw_bridge_dev_same_esw(lower, esw)) + if (mlx5_esw_bridge_dev_same_esw(lower, esw)) return lower; } @@ -125,7 +120,7 @@ static bool mlx5_esw_bridge_is_local(struct net_device *dev, struct net_device * priv = netdev_priv(rep); mdev = priv->mdev; if (netif_is_lag_master(dev)) - return mlx5_lag_is_shared_fdb(mdev) && mlx5_lag_is_master(mdev); + return mlx5_lag_is_master(mdev); return true; } @@ -455,6 +450,9 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, if (!rep) return NOTIFY_DONE; + if (netif_is_lag_master(dev) && !mlx5_lag_is_shared_fdb(esw->dev)) + return NOTIFY_DONE; + switch (event) { case SWITCHDEV_FDB_ADD_TO_BRIDGE: fdb_info = container_of(info, From e92df790d07a8eea873efcb84776e7b71f81c7d5 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Tue, 11 Mar 2025 00:01:44 +0200 Subject: [PATCH 0906/1090] net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices mlx5_eswitch_get_vepa returns -EPERM if the device lacks eswitch_manager capability, blocking mlx5e_bridge_getlink from retrieving VEPA mode. Since mlx5e_bridge_getlink implements ndo_bridge_getlink, returning -EPERM causes bridge link show to fail instead of skipping devices without this capability. To avoid this, return -EOPNOTSUPP from mlx5e_bridge_getlink when mlx5_eswitch_get_vepa fails, ensuring the command continues processing other devices while ignoring those without the necessary capability. Fixes: 4b89251de024 ("net/mlx5: Support ndo bridge_setlink and getlink") Signed-off-by: Carolina Jubran Reviewed-by: Jianbo Liu Signed-off-by: Tariq Toukan Reviewed-by: Michal Swiatkowski Link: https://patch.msgid.link/1741644104-97767-7-git-send-email-tariqt@nvidia.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a814b63ed97e..8fcaee381b0e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5132,11 +5132,9 @@ static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5_core_dev *mdev = priv->mdev; u8 mode, setting; - int err; - err = mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting); - if (err) - return err; + if (mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting)) + return -EOPNOTSUPP; mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB; return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, From 3e64bb2ae7d9f2b3a8259d4d6b86ed1984d5460a Mon Sep 17 00:00:00 2001 From: Shradha Gupta Date: Tue, 11 Mar 2025 03:17:40 -0700 Subject: [PATCH 0907/1090] net: mana: cleanup mana struct after debugfs_remove() When on a MANA VM hibernation is triggered, as part of hibernate_snapshot(), mana_gd_suspend() and mana_gd_resume() are called. If during this mana_gd_resume(), a failure occurs with HWC creation, mana_port_debugfs pointer does not get reinitialized and ends up pointing to older, cleaned-up dentry. Further in the hibernation path, as part of power_down(), mana_gd_shutdown() is triggered. This call, unaware of the failures in resume, tries to cleanup the already cleaned up mana_port_debugfs value and hits the following bug: [ 191.359296] mana 7870:00:00.0: Shutdown was called [ 191.359918] BUG: kernel NULL pointer dereference, address: 0000000000000098 [ 191.360584] #PF: supervisor write access in kernel mode [ 191.361125] #PF: error_code(0x0002) - not-present page [ 191.361727] PGD 1080ea067 P4D 0 [ 191.362172] Oops: Oops: 0002 [#1] SMP NOPTI [ 191.362606] CPU: 11 UID: 0 PID: 1674 Comm: bash Not tainted 6.14.0-rc5+ #2 [ 191.363292] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 11/21/2024 [ 191.364124] RIP: 0010:down_write+0x19/0x50 [ 191.364537] Code: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 55 48 89 e5 53 48 89 fb e8 de cd ff ff 31 c0 ba 01 00 00 00 48 0f b1 13 75 16 65 48 8b 05 88 24 4c 6a 48 89 43 08 48 8b 5d [ 191.365867] RSP: 0000:ff45fbe0c1c037b8 EFLAGS: 00010246 [ 191.366350] RAX: 0000000000000000 RBX: 0000000000000098 RCX: ffffff8100000000 [ 191.366951] RDX: 0000000000000001 RSI: 0000000000000064 RDI: 0000000000000098 [ 191.367600] RBP: ff45fbe0c1c037c0 R08: 0000000000000000 R09: 0000000000000001 [ 191.368225] R10: ff45fbe0d2b01000 R11: 0000000000000008 R12: 0000000000000000 [ 191.368874] R13: 000000000000000b R14: ff43dc27509d67c0 R15: 0000000000000020 [ 191.369549] FS: 00007dbc5001e740(0000) GS:ff43dc663f380000(0000) knlGS:0000000000000000 [ 191.370213] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 191.370830] CR2: 0000000000000098 CR3: 0000000168e8e002 CR4: 0000000000b73ef0 [ 191.371557] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 191.372192] DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400 [ 191.372906] Call Trace: [ 191.373262] [ 191.373621] ? show_regs+0x64/0x70 [ 191.374040] ? __die+0x24/0x70 [ 191.374468] ? page_fault_oops+0x290/0x5b0 [ 191.374875] ? do_user_addr_fault+0x448/0x800 [ 191.375357] ? exc_page_fault+0x7a/0x160 [ 191.375971] ? asm_exc_page_fault+0x27/0x30 [ 191.376416] ? down_write+0x19/0x50 [ 191.376832] ? down_write+0x12/0x50 [ 191.377232] simple_recursive_removal+0x4a/0x2a0 [ 191.377679] ? __pfx_remove_one+0x10/0x10 [ 191.378088] debugfs_remove+0x44/0x70 [ 191.378530] mana_detach+0x17c/0x4f0 [ 191.378950] ? __flush_work+0x1e2/0x3b0 [ 191.379362] ? __cond_resched+0x1a/0x50 [ 191.379787] mana_remove+0xf2/0x1a0 [ 191.380193] mana_gd_shutdown+0x3b/0x70 [ 191.380642] pci_device_shutdown+0x3a/0x80 [ 191.381063] device_shutdown+0x13e/0x230 [ 191.381480] kernel_power_off+0x35/0x80 [ 191.381890] hibernate+0x3c6/0x470 [ 191.382312] state_store+0xcb/0xd0 [ 191.382734] kobj_attr_store+0x12/0x30 [ 191.383211] sysfs_kf_write+0x3e/0x50 [ 191.383640] kernfs_fop_write_iter+0x140/0x1d0 [ 191.384106] vfs_write+0x271/0x440 [ 191.384521] ksys_write+0x72/0xf0 [ 191.384924] __x64_sys_write+0x19/0x20 [ 191.385313] x64_sys_call+0x2b0/0x20b0 [ 191.385736] do_syscall_64+0x79/0x150 [ 191.386146] ? __mod_memcg_lruvec_state+0xe7/0x240 [ 191.386676] ? __lruvec_stat_mod_folio+0x79/0xb0 [ 191.387124] ? __pfx_lru_add+0x10/0x10 [ 191.387515] ? queued_spin_unlock+0x9/0x10 [ 191.387937] ? do_anonymous_page+0x33c/0xa00 [ 191.388374] ? __handle_mm_fault+0xcf3/0x1210 [ 191.388805] ? __count_memcg_events+0xbe/0x180 [ 191.389235] ? handle_mm_fault+0xae/0x300 [ 191.389588] ? do_user_addr_fault+0x559/0x800 [ 191.390027] ? irqentry_exit_to_user_mode+0x43/0x230 [ 191.390525] ? irqentry_exit+0x1d/0x30 [ 191.390879] ? exc_page_fault+0x86/0x160 [ 191.391235] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 191.391745] RIP: 0033:0x7dbc4ff1c574 [ 191.392111] Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d d5 ea 0e 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89 [ 191.393412] RSP: 002b:00007ffd95a23ab8 EFLAGS: 00000202 ORIG_RAX: 0000000000000001 [ 191.393990] RAX: ffffffffffffffda RBX: 0000000000000005 RCX: 00007dbc4ff1c574 [ 191.394594] RDX: 0000000000000005 RSI: 00005a6eeadb0ce0 RDI: 0000000000000001 [ 191.395215] RBP: 00007ffd95a23ae0 R08: 00007dbc50003b20 R09: 0000000000000000 [ 191.395805] R10: 0000000000000001 R11: 0000000000000202 R12: 0000000000000005 [ 191.396404] R13: 00005a6eeadb0ce0 R14: 00007dbc500045c0 R15: 00007dbc50001ee0 [ 191.396987] To fix this, we explicitly set such mana debugfs variables to NULL after debugfs_remove() is called. Fixes: 6607c17c6c5e ("net: mana: Enable debugfs files for MANA device") Cc: stable@vger.kernel.org Signed-off-by: Shradha Gupta Reviewed-by: Haiyang Zhang Reviewed-by: Michal Kubiak Link: https://patch.msgid.link/1741688260-28922-1-git-send-email-shradhagupta@linux.microsoft.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/microsoft/mana/gdma_main.c | 11 ++++++++++- drivers/net/ethernet/microsoft/mana/mana_en.c | 10 ++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c index be95336ce089..11457b6296cc 100644 --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c @@ -1547,6 +1547,7 @@ unmap_bar: * adapter-MTU file and apc->mana_pci_debugfs folder. */ debugfs_remove_recursive(gc->mana_pci_debugfs); + gc->mana_pci_debugfs = NULL; pci_iounmap(pdev, bar0_va); free_gc: pci_set_drvdata(pdev, NULL); @@ -1569,6 +1570,8 @@ static void mana_gd_remove(struct pci_dev *pdev) debugfs_remove_recursive(gc->mana_pci_debugfs); + gc->mana_pci_debugfs = NULL; + pci_iounmap(pdev, gc->bar0_va); vfree(gc); @@ -1622,6 +1625,8 @@ static void mana_gd_shutdown(struct pci_dev *pdev) debugfs_remove_recursive(gc->mana_pci_debugfs); + gc->mana_pci_debugfs = NULL; + pci_disable_device(pdev); } @@ -1648,8 +1653,10 @@ static int __init mana_driver_init(void) mana_debugfs_root = debugfs_create_dir("mana", NULL); err = pci_register_driver(&mana_driver); - if (err) + if (err) { debugfs_remove(mana_debugfs_root); + mana_debugfs_root = NULL; + } return err; } @@ -1659,6 +1666,8 @@ static void __exit mana_driver_exit(void) pci_unregister_driver(&mana_driver); debugfs_remove(mana_debugfs_root); + + mana_debugfs_root = NULL; } module_init(mana_driver_init); diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index aa1e47233fe5..ae76ecc7a5d3 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -738,12 +738,11 @@ static const struct net_device_ops mana_devops = { static void mana_cleanup_port_context(struct mana_port_context *apc) { /* - * at this point all dir/files under the vport directory - * are already cleaned up. - * We are sure the apc->mana_port_debugfs remove will not - * cause any freed memory access issues + * make sure subsequent cleanup attempts don't end up removing already + * cleaned dentry pointer */ debugfs_remove(apc->mana_port_debugfs); + apc->mana_port_debugfs = NULL; kfree(apc->rxqs); apc->rxqs = NULL; } @@ -1254,6 +1253,7 @@ static void mana_destroy_eq(struct mana_context *ac) return; debugfs_remove_recursive(ac->mana_eqs_debugfs); + ac->mana_eqs_debugfs = NULL; for (i = 0; i < gc->max_num_queues; i++) { eq = ac->eqs[i].eq; @@ -1914,6 +1914,7 @@ static void mana_destroy_txq(struct mana_port_context *apc) for (i = 0; i < apc->num_queues; i++) { debugfs_remove_recursive(apc->tx_qp[i].mana_tx_debugfs); + apc->tx_qp[i].mana_tx_debugfs = NULL; napi = &apc->tx_qp[i].tx_cq.napi; if (apc->tx_qp[i].txq.napi_initialized) { @@ -2099,6 +2100,7 @@ static void mana_destroy_rxq(struct mana_port_context *apc, return; debugfs_remove_recursive(rxq->mana_rx_debugfs); + rxq->mana_rx_debugfs = NULL; napi = &rxq->rx_cq.napi; From a935b3f981809272d2649ad9c27a751685137846 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Mar 2025 18:05:16 +0200 Subject: [PATCH 0908/1090] ASoC: SOF: ipc4-topology: Allocate ref_params on stack Currently the compiler (clang 19.1.7) is not happy about the size of the stack frame in sof_ipc4_prepare_copier_module: sound/soc/sof/ipc4-topology.c:1800:1: error: stack frame size (1288) exceeds limit (1024) in 'sof_ipc4_prepare_copier_module' [-Werror,-Wframe-larger-than] 1800 | sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ^ Work around this by allocating ref_params on stack, as it looks the biggest variable on stack right now. Note, this only happens when compile for 32-bit machines (x86_32 in my case). Signed-off-by: Andy Shevchenko Acked-by: Peter Ujfalusi Link: https://patch.msgid.link/20250312160516.3864295-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f14b8ef8d0b0..540ba140e155 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -7,6 +7,7 @@ // // #include +#include #include #include #include @@ -1807,8 +1808,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_copier_data *copier_data; int input_fmt_index, output_fmt_index; - struct snd_pcm_hw_params ref_params; struct sof_ipc4_copier *ipc4_copier; + struct snd_pcm_hw_params *ref_params __free(kfree) = NULL; struct snd_sof_dai *dai; u32 gtw_cfg_config_length; u32 dma_config_tlv_size = 0; @@ -1885,9 +1886,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = *fe_params; + ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); else - ref_params = *pipeline_params; + ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1924,8 +1927,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * In case of capture the ref_params returned will be used to * find the input configuration of the copier. */ - ref_params = *fe_params; - ret = sof_ipc4_prepare_dai_copier(sdev, dai, &ref_params, dir); + ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; + + ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); if (ret < 0) return ret; @@ -1934,7 +1940,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * input configuration of the copier. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = *pipeline_params; + memcpy(ref_params, pipeline_params, sizeof(*ref_params)); break; } @@ -1946,7 +1952,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, ipc4_copier = (struct sof_ipc4_copier *)swidget->private; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - ref_params = *pipeline_params; + + ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; break; } @@ -1959,7 +1968,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, - &ref_params, available_fmt); + ref_params, available_fmt); if (input_fmt_index < 0) return input_fmt_index; From 4490fe973669360efaef7350aeb9706f70164176 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 5 Mar 2025 21:44:02 -0600 Subject: [PATCH 0909/1090] platform/x86/amd: pmf: Fix missing hidden options for Smart PC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amd_pmf_get_slider_info() checks the current profile to report correct value to the TA inputs. If hidden options are in use then the wrong values will be reported to TA. Add the two compat options PLATFORM_PROFILE_BALANCED_PERFORMANCE and PLATFORM_PROFILE_QUIET for this use. Reported-by: Yijun Shen Fixes: 9a43102daf64d ("platform/x86/amd: pmf: Add balanced-performance to hidden choices") Fixes: 44e94fece5170 ("platform/x86/amd: pmf: Add 'quiet' to hidden choices") Signed-off-by: Mario Limonciello Acked-by: Shyam Sundar S K Link: https://lore.kernel.org/r/20250306034402.50478-1-superm1@kernel.org Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/spc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c index f34f3130c330..1d90f9382024 100644 --- a/drivers/platform/x86/amd/pmf/spc.c +++ b/drivers/platform/x86/amd/pmf/spc.c @@ -219,12 +219,14 @@ static int amd_pmf_get_slider_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_ switch (dev->current_profile) { case PLATFORM_PROFILE_PERFORMANCE: + case PLATFORM_PROFILE_BALANCED_PERFORMANCE: val = TA_BEST_PERFORMANCE; break; case PLATFORM_PROFILE_BALANCED: val = TA_BETTER_PERFORMANCE; break; case PLATFORM_PROFILE_LOW_POWER: + case PLATFORM_PROFILE_QUIET: val = TA_BEST_BATTERY; break; default: From fc99045effa81fdf509c2a97cbb7e6e8f2fd4443 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Wed, 12 Mar 2025 10:51:31 -0300 Subject: [PATCH 0910/1090] smb: client: fix regression with guest option When mounting a CIFS share with 'guest' mount option, mount.cifs(8) will set empty password= and password2= options. Currently we only handle empty strings from user= and password= options, so the mount will fail with cifs: Bad value for 'password2' Fix this by handling empty string from password2= option as well. Link: https://bbs.archlinux.org/viewtopic.php?id=303927 Reported-by: Adam Williamson Closes: https://lore.kernel.org/r/83c00b5fea81c07f6897a5dd3ef50fd3b290f56c.camel@redhat.com Fixes: 35f834265e0d ("smb3: fix broken reconnect when password changing on the server by allowing password rotation") Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (Red Hat) Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index e9b286d9a7ba..457452b4d42d 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -171,6 +171,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_string("username", Opt_user), fsparam_string("pass", Opt_pass), fsparam_string("password", Opt_pass), + fsparam_string("pass2", Opt_pass2), fsparam_string("password2", Opt_pass2), fsparam_string("ip", Opt_ip), fsparam_string("addr", Opt_ip), @@ -1131,6 +1132,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, } else if (!strcmp("user", param->key) || !strcmp("username", param->key)) { skip_parsing = true; opt = Opt_user; + } else if (!strcmp("pass2", param->key) || !strcmp("password2", param->key)) { + skip_parsing = true; + opt = Opt_pass2; } } From 7489161b1852390b4413d57f2457cd40b34da6cc Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Tue, 11 Mar 2025 17:22:03 +0300 Subject: [PATCH 0911/1090] cifs: Fix integer overflow while processing acregmax mount option User-provided mount parameter acregmax of type u32 is intended to have an upper limit, but before it is validated, the value is converted from seconds to jiffies which can lead to an integer overflow. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 5780464614f6 ("cifs: Add new parameter "acregmax" for distinct file and directory metadata timeout") Signed-off-by: Murad Masimov Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index 457452b4d42d..5f3c5967a0f5 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -1344,11 +1344,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, } break; case Opt_acregmax: - ctx->acregmax = HZ * result.uint_32; - if (ctx->acregmax > CIFS_MAX_ACTIMEO) { + if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { cifs_errorf(fc, "acregmax too large\n"); goto cifs_parse_mount_err; } + ctx->acregmax = HZ * result.uint_32; break; case Opt_acdirmax: ctx->acdirmax = HZ * result.uint_32; From 5b29891f91dfb8758baf1e2217bef4b16b2b165b Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Tue, 11 Mar 2025 17:22:04 +0300 Subject: [PATCH 0912/1090] cifs: Fix integer overflow while processing acdirmax mount option User-provided mount parameter acdirmax of type u32 is intended to have an upper limit, but before it is validated, the value is converted from seconds to jiffies which can lead to an integer overflow. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 4c9f948142a5 ("cifs: Add new mount parameter "acdirmax" to allow caching directory metadata") Signed-off-by: Murad Masimov Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index 5f3c5967a0f5..c983021c406b 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -1351,11 +1351,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->acregmax = HZ * result.uint_32; break; case Opt_acdirmax: - ctx->acdirmax = HZ * result.uint_32; - if (ctx->acdirmax > CIFS_MAX_ACTIMEO) { + if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { cifs_errorf(fc, "acdirmax too large\n"); goto cifs_parse_mount_err; } + ctx->acdirmax = HZ * result.uint_32; break; case Opt_actimeo: if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) { From 64f690ee22c99e16084e0e45181b2a1eed2fa149 Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Tue, 11 Mar 2025 17:22:05 +0300 Subject: [PATCH 0913/1090] cifs: Fix integer overflow while processing actimeo mount option User-provided mount parameter actimeo of type u32 is intended to have an upper limit, but before it is validated, the value is converted from seconds to jiffies which can lead to an integer overflow. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 6d20e8406f09 ("cifs: add attribute cache timeout (actimeo) tunable") Signed-off-by: Murad Masimov Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index c983021c406b..85b062e7f48d 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -1358,7 +1358,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->acdirmax = HZ * result.uint_32; break; case Opt_actimeo: - if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) { + if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) { cifs_errorf(fc, "timeout too large\n"); goto cifs_parse_mount_err; } From d5a30fddfe2f2e540f6c43b59cf701809995faef Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Tue, 11 Mar 2025 17:22:06 +0300 Subject: [PATCH 0914/1090] cifs: Fix integer overflow while processing closetimeo mount option User-provided mount parameter closetimeo of type u32 is intended to have an upper limit, but before it is validated, the value is converted from seconds to jiffies which can lead to an integer overflow. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 5efdd9122eff ("smb3: allow deferred close timeout to be configurable") Signed-off-by: Murad Masimov Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index 85b062e7f48d..8c73d4d60d1a 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -1370,11 +1370,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->acdirmax = ctx->acregmax = HZ * result.uint_32; break; case Opt_closetimeo: - ctx->closetimeo = HZ * result.uint_32; - if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) { + if (result.uint_32 > SMB3_MAX_DCLOSETIMEO / HZ) { cifs_errorf(fc, "closetimeo too large\n"); goto cifs_parse_mount_err; } + ctx->closetimeo = HZ * result.uint_32; break; case Opt_echo_interval: ctx->echo_interval = result.uint_32; From 605b249ea96770ac4fac4b8510a99e0f8442be5e Mon Sep 17 00:00:00 2001 From: Henrique Carvalho Date: Tue, 11 Mar 2025 15:23:59 -0300 Subject: [PATCH 0915/1090] smb: client: Fix match_session bug preventing session reuse Fix a bug in match_session() that can causes the session to not be reused in some cases. Reproduction steps: mount.cifs //server/share /mnt/a -o credentials=creds mount.cifs //server/share /mnt/b -o credentials=creds,sec=ntlmssp cat /proc/fs/cifs/DebugData | grep SessionId | wc -l mount.cifs //server/share /mnt/b -o credentials=creds,sec=ntlmssp mount.cifs //server/share /mnt/a -o credentials=creds cat /proc/fs/cifs/DebugData | grep SessionId | wc -l Cc: stable@vger.kernel.org Reviewed-by: Enzo Matsumiya Signed-off-by: Henrique Carvalho Signed-off-by: Steve French --- fs/smb/client/connect.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index f917de020dd5..73f93a35eedd 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -1825,9 +1825,8 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx, bool match_super) { - if (ctx->sectype != Unspecified && - ctx->sectype != ses->sectype) - return 0; + struct TCP_Server_Info *server = ses->server; + enum securityEnum ctx_sec, ses_sec; if (!match_super && ctx->dfs_root_ses != ses->dfs_root_ses) return 0; @@ -1839,11 +1838,20 @@ static int match_session(struct cifs_ses *ses, if (ses->chan_max < ctx->max_channels) return 0; - switch (ses->sectype) { + ctx_sec = server->ops->select_sectype(server, ctx->sectype); + ses_sec = server->ops->select_sectype(server, ses->sectype); + + if (ctx_sec != ses_sec) + return 0; + + switch (ctx_sec) { + case IAKerb: case Kerberos: if (!uid_eq(ctx->cred_uid, ses->cred_uid)) return 0; break; + case NTLMv2: + case RawNTLMSSP: default: /* NULL username means anonymous session */ if (ses->user_name == NULL) { From bc71aab4513f7fecd23c051703ef5adea2230a54 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:48 +0100 Subject: [PATCH 0916/1090] Revert "ext4: add pre-content fsnotify hook for DAX faults" This reverts commit bb480760ffc7018e21ee6f60241c2b99ff26ee0e. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-3-amir73il@gmail.com --- fs/ext4/file.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index a5205149adba..3bd96c3d4cd0 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -756,9 +756,6 @@ retry: return VM_FAULT_SIGBUS; } } else { - result = filemap_fsnotify_fault(vmf); - if (unlikely(result)) - return result; filemap_invalidate_lock_shared(mapping); } result = dax_iomap_fault(vmf, order, &pfn, &error, &ext4_iomap_ops); From 27773ce1776279ed3220a34d2e6bfcecaee7fc66 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:49 +0100 Subject: [PATCH 0917/1090] Revert "xfs: add pre-content fsnotify hook for DAX faults" This reverts commit 7f4796a46571ced5d3d5b0942e1bfea1eedaaecd. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-4-amir73il@gmail.com --- fs/xfs/xfs_file.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f7a7d89c345e..9a435b1ff264 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1451,9 +1451,6 @@ xfs_dax_read_fault( trace_xfs_read_fault(ip, order); - ret = filemap_fsnotify_fault(vmf); - if (unlikely(ret)) - return ret; xfs_ilock(ip, XFS_MMAPLOCK_SHARED); ret = xfs_dax_fault_locked(vmf, order, false); xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); @@ -1482,16 +1479,6 @@ xfs_write_fault( vm_fault_t ret; trace_xfs_write_fault(ip, order); - /* - * Usually we get here from ->page_mkwrite callback but in case of DAX - * we will get here also for ordinary write fault. Handle HSM - * notifications for that case. - */ - if (IS_DAX(inode)) { - ret = filemap_fsnotify_fault(vmf); - if (unlikely(ret)) - return ret; - } sb_start_pagefault(inode->i_sb); file_update_time(vmf->vma->vm_file); From 955fbe0ef19df4197595a98d0906c94025c4beef Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:50 +0100 Subject: [PATCH 0918/1090] Revert "fsnotify: generate pre-content permission event on page fault" This reverts commit 8392bc2ff8c8bf7c4c5e6dfa71ccd893a3c046f6. In the use case of buffered write whose input buffer is mmapped file on a filesystem with a pre-content mark, the prefaulting of the buffer can happen under the filesystem freeze protection (obtained in vfs_write()) which breaks assumptions of pre-content hook and introduces potential deadlock of HSM handler in userspace with filesystem freezing. Now that we have pre-content hooks at file mmap() time, disable the pre-content event hooks on page fault to avoid the potential deadlock. Reported-by: syzbot+7229071b47908b19d5b7@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-fsdevel/7ehxrhbvehlrjwvrduoxsao5k3x4aw275patsb3krkwuq573yv@o2hskrfawbnc/ Fixes: 8392bc2ff8c8 ("fsnotify: generate pre-content permission event on page fault") Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-5-amir73il@gmail.com --- include/linux/mm.h | 1 - mm/filemap.c | 74 ---------------------------------------------- mm/nommu.c | 7 ----- 3 files changed, 82 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 7b1068ddcbb7..8483e09aeb2c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3420,7 +3420,6 @@ extern vm_fault_t filemap_fault(struct vm_fault *vmf); extern vm_fault_t filemap_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); extern vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf); -extern vm_fault_t filemap_fsnotify_fault(struct vm_fault *vmf); extern unsigned long stack_guard_gap; /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ diff --git a/mm/filemap.c b/mm/filemap.c index 2974691fdfad..ff5fcdd96136 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include "internal.h" @@ -3336,48 +3335,6 @@ static vm_fault_t filemap_fault_recheck_pte_none(struct vm_fault *vmf) return ret; } -/** - * filemap_fsnotify_fault - maybe emit a pre-content event. - * @vmf: struct vm_fault containing details of the fault. - * - * If we have a pre-content watch on this file we will emit an event for this - * range. If we return anything the fault caller should return immediately, we - * will return VM_FAULT_RETRY if we had to emit an event, which will trigger the - * fault again and then the fault handler will run the second time through. - * - * Return: a bitwise-OR of %VM_FAULT_ codes, 0 if nothing happened. - */ -vm_fault_t filemap_fsnotify_fault(struct vm_fault *vmf) -{ - struct file *fpin = NULL; - int mask = (vmf->flags & FAULT_FLAG_WRITE) ? MAY_WRITE : MAY_ACCESS; - loff_t pos = vmf->pgoff >> PAGE_SHIFT; - size_t count = PAGE_SIZE; - int err; - - /* - * We already did this and now we're retrying with everything locked, - * don't emit the event and continue. - */ - if (vmf->flags & FAULT_FLAG_TRIED) - return 0; - - /* No watches, we're done. */ - if (likely(!FMODE_FSNOTIFY_HSM(vmf->vma->vm_file->f_mode))) - return 0; - - fpin = maybe_unlock_mmap_for_io(vmf, fpin); - if (!fpin) - return VM_FAULT_SIGBUS; - - err = fsnotify_file_area_perm(fpin, mask, &pos, count); - fput(fpin); - if (err) - return VM_FAULT_SIGBUS; - return VM_FAULT_RETRY; -} -EXPORT_SYMBOL_GPL(filemap_fsnotify_fault); - /** * filemap_fault - read in file data for page fault handling * @vmf: struct vm_fault containing details of the fault @@ -3481,37 +3438,6 @@ retry_find: * or because readahead was otherwise unable to retrieve it. */ if (unlikely(!folio_test_uptodate(folio))) { - /* - * If this is a precontent file we have can now emit an event to - * try and populate the folio. - */ - if (!(vmf->flags & FAULT_FLAG_TRIED) && - unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) { - loff_t pos = folio_pos(folio); - size_t count = folio_size(folio); - - /* We're NOWAIT, we have to retry. */ - if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) { - folio_unlock(folio); - goto out_retry; - } - - if (mapping_locked) - filemap_invalidate_unlock_shared(mapping); - mapping_locked = false; - - folio_unlock(folio); - fpin = maybe_unlock_mmap_for_io(vmf, fpin); - if (!fpin) - goto out_retry; - - error = fsnotify_file_area_perm(fpin, MAY_ACCESS, &pos, - count); - if (error) - ret = VM_FAULT_SIGBUS; - goto out_retry; - } - /* * If the invalidate lock is not held, the folio was in cache * and uptodate and now it is not. Strange but possible since we diff --git a/mm/nommu.c b/mm/nommu.c index baa79abdaf03..9cb6e99215e2 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1613,13 +1613,6 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, } EXPORT_SYMBOL(remap_vmalloc_range); -vm_fault_t filemap_fsnotify_fault(struct vm_fault *vmf) -{ - BUG(); - return 0; -} -EXPORT_SYMBOL_GPL(filemap_fsnotify_fault); - vm_fault_t filemap_fault(struct vm_fault *vmf) { BUG(); From 4f4dc3a9378bc2e6bcf331ee9e65a21abf67e7e0 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:51 +0100 Subject: [PATCH 0919/1090] Revert "mm: don't allow huge faults for files with pre content watches" This reverts commit 20bf82a898b65c129af76deb96a1b415d3098a28. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-6-amir73il@gmail.com --- mm/memory.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index b9661ccfa64f..fb7b8dc75167 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -76,7 +76,6 @@ #include #include #include -#include #include @@ -5750,17 +5749,8 @@ out_map: static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; - if (vma_is_anonymous(vma)) return do_huge_pmd_anonymous_page(vmf); - /* - * Currently we just emit PAGE_SIZE for our fault events, so don't allow - * a huge fault if we have a pre content watch on this file. This would - * be trivial to support, but there would need to be tests to ensure - * this works properly and those don't exist currently. - */ - if (unlikely(FMODE_FSNOTIFY_HSM(vma->vm_file->f_mode))) - return VM_FAULT_FALLBACK; if (vma->vm_ops->huge_fault) return vma->vm_ops->huge_fault(vmf, PMD_ORDER); return VM_FAULT_FALLBACK; @@ -5784,9 +5774,6 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf) } if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { - /* See comment in create_huge_pmd. */ - if (unlikely(FMODE_FSNOTIFY_HSM(vma->vm_file->f_mode))) - goto split; if (vma->vm_ops->huge_fault) { ret = vma->vm_ops->huge_fault(vmf, PMD_ORDER); if (!(ret & VM_FAULT_FALLBACK)) @@ -5809,9 +5796,6 @@ static vm_fault_t create_huge_pud(struct vm_fault *vmf) /* No support for anonymous transparent PUD pages yet */ if (vma_is_anonymous(vma)) return VM_FAULT_FALLBACK; - /* See comment in create_huge_pmd. */ - if (unlikely(FMODE_FSNOTIFY_HSM(vma->vm_file->f_mode))) - return VM_FAULT_FALLBACK; if (vma->vm_ops->huge_fault) return vma->vm_ops->huge_fault(vmf, PUD_ORDER); #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ @@ -5829,9 +5813,6 @@ static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud) if (vma_is_anonymous(vma)) goto split; if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) { - /* See comment in create_huge_pmd. */ - if (unlikely(FMODE_FSNOTIFY_HSM(vma->vm_file->f_mode))) - goto split; if (vma->vm_ops->huge_fault) { ret = vma->vm_ops->huge_fault(vmf, PUD_ORDER); if (!(ret & VM_FAULT_FALLBACK)) From 252256e416deb255607f0c4a69e7cfec079e5d61 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 12 Mar 2025 08:38:52 +0100 Subject: [PATCH 0920/1090] Revert "fanotify: disable readahead if we have pre-content watches" This reverts commit fac84846a28c0950d4433118b3dffd44306df62d. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara Link: https://patch.msgid.link/20250312073852.2123409-7-amir73il@gmail.com --- mm/filemap.c | 12 ------------ mm/readahead.c | 14 -------------- 2 files changed, 26 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index ff5fcdd96136..6d616bb9001e 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3197,14 +3197,6 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) unsigned long vm_flags = vmf->vma->vm_flags; unsigned int mmap_miss; - /* - * If we have pre-content watches we need to disable readahead to make - * sure that we don't populate our mapping with 0 filled pages that we - * never emitted an event for. - */ - if (unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) - return fpin; - #ifdef CONFIG_TRANSPARENT_HUGEPAGE /* Use the readahead code, even if readahead is disabled */ if ((vm_flags & VM_HUGEPAGE) && HPAGE_PMD_ORDER <= MAX_PAGECACHE_ORDER) { @@ -3273,10 +3265,6 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf, struct file *fpin = NULL; unsigned int mmap_miss; - /* See comment in do_sync_mmap_readahead. */ - if (unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) - return fpin; - /* If we don't want any read-ahead, don't bother */ if (vmf->vma->vm_flags & VM_RAND_READ || !ra->ra_pages) return fpin; diff --git a/mm/readahead.c b/mm/readahead.c index 220155a5c964..6a4e96b69702 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -128,7 +128,6 @@ #include #include #include -#include #include "internal.h" @@ -558,15 +557,6 @@ void page_cache_sync_ra(struct readahead_control *ractl, unsigned long max_pages, contig_count; pgoff_t prev_index, miss; - /* - * If we have pre-content watches we need to disable readahead to make - * sure that we don't find 0 filled pages in cache that we never emitted - * events for. Filesystems supporting HSM must make sure to not call - * this function with ractl->file unset for files handled by HSM. - */ - if (ractl->file && unlikely(FMODE_FSNOTIFY_HSM(ractl->file->f_mode))) - return; - /* * Even if readahead is disabled, issue this request as readahead * as we'll need it to satisfy the requested range. The forced @@ -645,10 +635,6 @@ void page_cache_async_ra(struct readahead_control *ractl, if (!ra->ra_pages) return; - /* See the comment in page_cache_sync_ra. */ - if (ractl->file && unlikely(FMODE_FSNOTIFY_HSM(ractl->file->f_mode))) - return; - /* * Same bit is used for PG_readahead and PG_reclaim. */ From 69a5a13a22b1def29dce62b5b7c86e6098c20c68 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 13 Mar 2025 09:56:07 -0400 Subject: [PATCH 0921/1090] bcachefs: target_congested -> get_random_u32_below() get_random_u32_below() has a better algorithm than bch2_rand_range(), it just didn't exist at the time. Signed-off-by: Kent Overstreet --- fs/bcachefs/io_read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index 726da68073e2..aa91fcf51eec 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -59,7 +59,7 @@ static bool bch2_target_congested(struct bch_fs *c, u16 target) } rcu_read_unlock(); - return bch2_rand_range(nr * CONGESTED_MAX) < total; + return get_random_u32_below(nr * CONGESTED_MAX) < total; } #else From 9c18ea7ffee090b47afaa7dc41903fb1b436d7bd Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 13 Mar 2025 11:16:28 -0400 Subject: [PATCH 0922/1090] bcachefs: bch2_get_random_u64_below() steal the (clever) algorithm from get_random_u32_below() this fixes a bug where we were passing roundup_pow_of_two() a 64 bit number - we're squaring device latencies now: [ +1.681698] ------------[ cut here ]------------ [ +0.000010] UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 [ +0.000011] shift exponent 64 is too large for 64-bit type 'long unsigned int' [ +0.000011] CPU: 1 UID: 0 PID: 196 Comm: kworker/u32:13 Not tainted 6.14.0-rc6-dave+ #10 [ +0.000012] Hardware name: ASUS System Product Name/PRIME B460I-PLUS, BIOS 1301 07/13/2021 [ +0.000005] Workqueue: events_unbound __bch2_read_endio [bcachefs] [ +0.000354] Call Trace: [ +0.000005] [ +0.000007] dump_stack_lvl+0x5d/0x80 [ +0.000018] ubsan_epilogue+0x5/0x30 [ +0.000008] __ubsan_handle_shift_out_of_bounds.cold+0x61/0xe6 [ +0.000011] bch2_rand_range.cold+0x17/0x20 [bcachefs] [ +0.000231] bch2_bkey_pick_read_device+0x547/0x920 [bcachefs] [ +0.000229] __bch2_read_extent+0x1e4/0x18e0 [bcachefs] [ +0.000241] ? bch2_btree_iter_peek_slot+0x3df/0x800 [bcachefs] [ +0.000180] ? bch2_read_retry_nodecode+0x270/0x330 [bcachefs] [ +0.000230] bch2_read_retry_nodecode+0x270/0x330 [bcachefs] [ +0.000230] bch2_rbio_retry+0x1fa/0x600 [bcachefs] [ +0.000224] ? bch2_printbuf_make_room+0x71/0xb0 [bcachefs] [ +0.000243] ? bch2_read_csum_err+0x4a4/0x610 [bcachefs] [ +0.000278] bch2_read_csum_err+0x4a4/0x610 [bcachefs] [ +0.000227] ? __bch2_read_endio+0x58b/0x870 [bcachefs] [ +0.000220] __bch2_read_endio+0x58b/0x870 [bcachefs] [ +0.000268] ? try_to_wake_up+0x31c/0x7f0 [ +0.000011] ? process_one_work+0x176/0x330 [ +0.000008] process_one_work+0x176/0x330 [ +0.000008] worker_thread+0x252/0x390 [ +0.000008] ? __pfx_worker_thread+0x10/0x10 [ +0.000006] kthread+0xec/0x230 [ +0.000011] ? __pfx_kthread+0x10/0x10 [ +0.000009] ret_from_fork+0x31/0x50 [ +0.000009] ? __pfx_kthread+0x10/0x10 [ +0.000008] ret_from_fork_asm+0x1a/0x30 [ +0.000012] [ +0.000046] ---[ end trace ]--- Reported-by: Roland Vet Signed-off-by: Kent Overstreet --- fs/bcachefs/extents.c | 2 +- fs/bcachefs/util.c | 23 ++++++++++++++--------- fs/bcachefs/util.h | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 05d5f71a7ca9..2d8042f853dc 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -99,7 +99,7 @@ static inline bool ptr_better(struct bch_fs *c, /* Pick at random, biased in favor of the faster device: */ - return bch2_rand_range(l1 + l2) > l1; + return bch2_get_random_u64_below(l1 + l2) > l1; } if (bch2_force_reconstruct_read) diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index e0a876cbaa6b..8e3ab4bf79a9 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -653,19 +653,24 @@ int bch2_bio_alloc_pages(struct bio *bio, size_t size, gfp_t gfp_mask) return 0; } -size_t bch2_rand_range(size_t max) +u64 bch2_get_random_u64_below(u64 ceil) { - size_t rand; + if (ceil <= U32_MAX) + return __get_random_u32_below(ceil); - if (!max) - return 0; + /* this is the same (clever) algorithm as in __get_random_u32_below() */ + u64 rand = get_random_u64(); + u64 mult = ceil * rand; - do { - rand = get_random_long(); - rand &= roundup_pow_of_two(max) - 1; - } while (rand >= max); + if (unlikely(mult < ceil)) { + u64 bound = -ceil % ceil; + while (unlikely(mult < bound)) { + rand = get_random_u64(); + mult = ceil * rand; + } + } - return rand; + return mul_u64_u64_shr(ceil, rand, 64); } void memcpy_to_bio(struct bio *dst, struct bvec_iter dst_iter, const void *src) diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index e7c3541b38f3..f4a4783219d9 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -401,7 +401,7 @@ do { \ _ret; \ }) -size_t bch2_rand_range(size_t); +u64 bch2_get_random_u64_below(u64); void memcpy_to_bio(struct bio *, struct bvec_iter, const void *); void memcpy_from_bio(void *, struct bio *, struct bvec_iter); From 57e9417f69839cb10f7ffca684c38acd28ceb57b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 8 Mar 2025 10:50:08 -0500 Subject: [PATCH 0923/1090] dm-flakey: Fix memory corruption in optional corrupt_bio_byte feature Fix memory corruption due to incorrect parameter being passed to bio_init Signed-off-by: Kent Overstreet Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org # v6.5+ Fixes: 1d9a94389853 ("dm flakey: clone pages on write bio before corrupting them") --- drivers/md/dm-flakey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 731467d4ed10..b690905ab89f 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -426,7 +426,7 @@ static struct bio *clone_bio(struct dm_target *ti, struct flakey_c *fc, struct b if (!clone) return NULL; - bio_init(clone, fc->dev->bdev, bio->bi_inline_vecs, nr_iovecs, bio->bi_opf); + bio_init(clone, fc->dev->bdev, clone->bi_inline_vecs, nr_iovecs, bio->bi_opf); clone->bi_iter.bi_sector = flakey_map_sector(ti, bio->bi_iter.bi_sector); clone->bi_private = bio; From a2ab25529bbcea51b5e01dded79f45aeb94f644a Mon Sep 17 00:00:00 2001 From: Ajay Kaher Date: Thu, 13 Mar 2025 17:31:11 +0000 Subject: [PATCH 0924/1090] x86/vmware: Parse MP tables for SEV-SNP enabled guests under VMware hypervisors Under VMware hypervisors, SEV-SNP enabled VMs are fundamentally able to boot without UEFI, but this regressed a year ago due to: 0f4a1e80989a ("x86/sev: Skip ROM range scans and validation for SEV-SNP guests") In this case, mpparse_find_mptable() has to be called to parse MP tables which contains the necessary boot information. [ mingo: Updated the changelog. ] Fixes: 0f4a1e80989a ("x86/sev: Skip ROM range scans and validation for SEV-SNP guests") Co-developed-by: Ye Li Signed-off-by: Ye Li Signed-off-by: Ajay Kaher Signed-off-by: Ingo Molnar Tested-by: Ye Li Reviewed-by: Kevin Loughlin Acked-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20250313173111.10918-1-ajay.kaher@broadcom.com --- arch/x86/kernel/cpu/vmware.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 00189cdeb775..cb3f900c46fc 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -429,6 +430,9 @@ static void __init vmware_platform_setup(void) pr_warn("Failed to get TSC freq from the hypervisor\n"); } + if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && !efi_enabled(EFI_BOOT)) + x86_init.mpparse.find_mptable = mpparse_find_mptable; + vmware_paravirt_ops_setup(); #ifdef CONFIG_X86_IO_APIC From 25a83f870b8a25a4b10bf5ba474a017ed5a72e7d Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Thu, 27 Feb 2025 22:07:28 +1000 Subject: [PATCH 0925/1090] ASoC: dt-bindings: tas27xx: add compatible for SN012776 The TI SN012776 is a variant of TAS2764 found in Apple Silicon Macs. It continues Apple's long-standing policy of getting vendors to spin out subtly incompatible and Apple-exclusive variants of their publicly available parts. Reviewed-by: Neal Gompa Acked-by: Rob Herring (Arm) Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-1-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ti,tas27xx.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml index 5447482179c1..fcaae848e78a 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml @@ -24,6 +24,7 @@ properties: enum: - ti,tas2764 - ti,tas2780 + - ti,sn012776 # Apple variant of TAS2764 reg: maxItems: 1 From ce9233937f3233e277ff23395e61ea690c769bef Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Thu, 27 Feb 2025 22:07:29 +1000 Subject: [PATCH 0926/1090] ASoC: dt-bindings: tas2770: add compatible for TAS5770L A variant of TAS2770 known as TAS5770L is found in Apple Silicon Macs. Reviewed-by: Neal Gompa Acked-by: Rob Herring (Arm) Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-2-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ti,tas2770.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml index 5e7aea43aced..8eab98a0f7a2 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml @@ -23,6 +23,7 @@ properties: compatible: enum: - ti,tas2770 + - ti,tas5770l # Apple variant reg: maxItems: 1 From ad18392962df46a858432839cc6bcaf2ede7cc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:30 +1000 Subject: [PATCH 0927/1090] ASoC: tas2764: Extend driver to SN012776 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SN012776 is a speaker amp chip found in Apple's 2021 laptops. It appears similar and more-or-less compatible to TAS2764. Extend the TAS2764 driver with some SN012776 specifics and configure the chip assuming it's in one of the Apple machines. Reviewed-by: Neal Gompa Signed-off-by: Martin PoviÅ¡er Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-3-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 43 +++++++++++++++++++++++++++++++++++--- sound/soc/codecs/tas2764.h | 3 +++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index c0a1d0c2a938..d9b4f898789f 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,11 @@ #include "tas2764.h" +enum tas2764_devid { + DEVID_TAS2764 = 0, + DEVID_SN012776 = 1 +}; + struct tas2764_priv { struct snd_soc_component *component; struct gpio_desc *reset_gpio; @@ -30,7 +36,8 @@ struct tas2764_priv { struct regmap *regmap; struct device *dev; int irq; - + enum tas2764_devid devid; + int v_sense_slot; int i_sense_slot; @@ -533,10 +540,16 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = { }, }; +static uint8_t sn012776_bop_presets[] = { + 0x01, 0x32, 0x02, 0x22, 0x83, 0x2d, 0x80, 0x02, 0x06, + 0x32, 0x46, 0x30, 0x02, 0x06, 0x38, 0x40, 0x30, 0x02, + 0x06, 0x3e, 0x37, 0x30, 0xff, 0xe6 +}; + static int tas2764_codec_probe(struct snd_soc_component *component) { struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); - int ret; + int ret, i; tas2764->component = component; @@ -585,6 +598,27 @@ static int tas2764_codec_probe(struct snd_soc_component *component) if (ret < 0) return ret; + switch (tas2764->devid) { + case DEVID_SN012776: + ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, + TAS2764_PWR_CTRL_BOP_SRC, + TAS2764_PWR_CTRL_BOP_SRC); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(sn012776_bop_presets); i++) { + ret = snd_soc_component_write(component, + TAS2764_BOP_CFG0 + i, + sn012776_bop_presets[i]); + + if (ret < 0) + return ret; + } + break; + default: + break; + } + return 0; } @@ -716,6 +750,8 @@ static int tas2764_i2c_probe(struct i2c_client *client) if (!tas2764) return -ENOMEM; + tas2764->devid = (enum tas2764_devid)of_device_get_match_data(&client->dev); + tas2764->dev = &client->dev; tas2764->irq = client->irq; i2c_set_clientdata(client, tas2764); @@ -752,7 +788,8 @@ MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id tas2764_of_match[] = { - { .compatible = "ti,tas2764" }, + { .compatible = "ti,tas2764", .data = (void *)DEVID_TAS2764 }, + { .compatible = "ti,sn012776", .data = (void *)DEVID_SN012776 }, {}, }; MODULE_DEVICE_TABLE(of, tas2764_of_match); diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h index 9490f2686e38..69c0f91cb423 100644 --- a/sound/soc/codecs/tas2764.h +++ b/sound/soc/codecs/tas2764.h @@ -29,6 +29,7 @@ #define TAS2764_PWR_CTRL_ACTIVE 0x0 #define TAS2764_PWR_CTRL_MUTE BIT(0) #define TAS2764_PWR_CTRL_SHUTDOWN BIT(1) +#define TAS2764_PWR_CTRL_BOP_SRC BIT(7) #define TAS2764_VSENSE_POWER_EN 3 #define TAS2764_ISENSE_POWER_EN 4 @@ -116,4 +117,6 @@ #define TAS2764_INT_CLK_CFG TAS2764_REG(0x0, 0x5c) #define TAS2764_INT_CLK_CFG_IRQZ_CLR BIT(2) +#define TAS2764_BOP_CFG0 TAS2764_REG(0X0, 0x1d) + #endif /* __TAS2764__ */ From f8d5f28e3f2ece5a1392205022afe30c87107a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:31 +1000 Subject: [PATCH 0928/1090] ASoC: tas2764: Add control concerning overcurrent events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add control to expose the option of autoretry behavior on overcurrent events in the codec. Reviewed-by: Neal Gompa Signed-off-by: Martin PoviÅ¡er Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-4-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 9 +++++++++ sound/soc/codecs/tas2764.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index d9b4f898789f..08aa7ee34256 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -634,12 +634,21 @@ static SOC_ENUM_SINGLE_DECL( tas2764_hpf_enum, TAS2764_DC_BLK0, TAS2764_DC_BLK0_HPF_FREQ_PB_SHIFT, tas2764_hpf_texts); +static const char * const tas2764_oce_texts[] = { + "Disable", "Retry", +}; + +static SOC_ENUM_SINGLE_DECL( + tas2764_oce_enum, TAS2764_MISC_CFG1, + TAS2764_MISC_CFG1_OCE_RETRY_SHIFT, tas2764_oce_texts); + static const struct snd_kcontrol_new tas2764_snd_controls[] = { SOC_SINGLE_TLV("Speaker Volume", TAS2764_DVC, 0, TAS2764_DVC_MAX, 1, tas2764_playback_volume), SOC_SINGLE_TLV("Amp Gain Volume", TAS2764_CHNL_0, 1, 0x14, 0, tas2764_digital_tlv), SOC_ENUM("HPF Corner Frequency", tas2764_hpf_enum), + SOC_ENUM("OCE Handling", tas2764_oce_enum), }; static const struct snd_soc_component_driver soc_component_driver_tas2764 = { diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h index 69c0f91cb423..3251dc0106e0 100644 --- a/sound/soc/codecs/tas2764.h +++ b/sound/soc/codecs/tas2764.h @@ -44,6 +44,10 @@ #define TAS2764_CHNL_0 TAS2764_REG(0X0, 0x03) +/* Miscellaneous */ +#define TAS2764_MISC_CFG1 TAS2764_REG(0x0, 0x06) +#define TAS2764_MISC_CFG1_OCE_RETRY_SHIFT 5 + /* TDM Configuration Reg0 */ #define TAS2764_TDM_CFG0 TAS2764_REG(0X0, 0x08) #define TAS2764_TDM_CFG0_SMP_MASK BIT(5) From 6553ee024b4452ef861de10605156c9d79e208ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:32 +1000 Subject: [PATCH 0929/1090] ASoC: tas2770: Factor out set_ivsense_slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new explicit function for the setting of I/V sense TDM slots. Reviewed-by: Neal Gompa Signed-off-by: Martin PoviÅ¡er Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-5-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 40 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 863c3f672ba9..4a86fcec0c1e 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -189,6 +189,31 @@ static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction) return tas2770_update_pwr_ctrl(tas2770); } +static int tas2770_set_ivsense_transmit(struct tas2770_priv *tas2770, + int i_slot, int v_slot) +{ + struct snd_soc_component *component = tas2770->component; + int ret; + + ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5, + TAS2770_TDM_CFG_REG5_VSNS_MASK | + TAS2770_TDM_CFG_REG5_50_MASK, + TAS2770_TDM_CFG_REG5_VSNS_ENABLE | + v_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6, + TAS2770_TDM_CFG_REG6_ISNS_MASK | + TAS2770_TDM_CFG_REG6_50_MASK, + TAS2770_TDM_CFG_REG6_ISNS_ENABLE | + i_slot); + if (ret < 0) + return ret; + + return 0; +} + static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) { int ret; @@ -221,19 +246,8 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) if (ret < 0) return ret; - ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5, - TAS2770_TDM_CFG_REG5_VSNS_MASK | - TAS2770_TDM_CFG_REG5_50_MASK, - TAS2770_TDM_CFG_REG5_VSNS_ENABLE | - tas2770->v_sense_slot); - if (ret < 0) - return ret; - - ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6, - TAS2770_TDM_CFG_REG6_ISNS_MASK | - TAS2770_TDM_CFG_REG6_50_MASK, - TAS2770_TDM_CFG_REG6_ISNS_ENABLE | - tas2770->i_sense_slot); + ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, + tas2770->v_sense_slot); if (ret < 0) return ret; From f0066c8d1d3298e9f9d136a365139bac733e84c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:33 +1000 Subject: [PATCH 0930/1090] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The former code sets the V slot from inside set_bitwidth according to the bitwidth of the PCM format. That's wrong, since: * It overrides the V slot parsed from DT binding. * The V slot is set shifted behind the I slot by the length of the PCM bitwidth, but the PCM bitwidth has no assured relation to the TDM slot width. Replace the former logic by setting up the I/V sense transmission only in case of both I/V slots being specified in devicetree, and never override those values. In case the slots are left unspecified, disable the transmission completely. There's an improbable case someone is relying on the old behavior, but if so, that's a setup that only works by accident, and cannot be sanely supported going forward. There's no indication anyone is consuming the I/V sense data up to today, so break the former behavior. Reviewed-by: Neal Gompa Signed-off-by: Martin PoviÅ¡er Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-6-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 4a86fcec0c1e..7f219df8be70 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -224,19 +224,16 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_16BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 2; break; case SNDRV_PCM_FORMAT_S24_LE: ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_24BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 4; break; case SNDRV_PCM_FORMAT_S32_LE: ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_32BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 4; break; default: @@ -246,11 +243,6 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) if (ret < 0) return ret; - ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, - tas2770->v_sense_slot); - if (ret < 0) - return ret; - return 0; } @@ -505,6 +497,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component) { struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component); + int ret; tas2770->component = component; @@ -516,6 +509,14 @@ static int tas2770_codec_probe(struct snd_soc_component *component) tas2770_reset(tas2770); regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap); + if (tas2770->i_sense_slot != -1 && tas2770->v_sense_slot != -1) { + ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, + tas2770->v_sense_slot); + + if (ret < 0) + return ret; + } + return 0; } @@ -643,7 +644,7 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770) dev_info(tas2770->dev, "Property %s is missing setting default slot\n", "ti,imon-slot-no"); - tas2770->i_sense_slot = 0; + tas2770->i_sense_slot = -1; } rc = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", @@ -652,7 +653,7 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770) dev_info(tas2770->dev, "Property %s is missing setting default slot\n", "ti,vmon-slot-no"); - tas2770->v_sense_slot = 2; + tas2770->v_sense_slot = -1; } tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); From 7bda89a2489fb012c4c63f3338827ad1f35c8880 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sat, 15 Feb 2025 11:02:23 +1300 Subject: [PATCH 0931/1090] ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios Devices integrating Allwinner SoCs may use line-out or headphone jacks with jack detection circuits attached to a GPIO. Support defining these in DTs. A number of Anbernic devices featuring the H700 SoC use this mechanism to switch between a headphone jack and an internal speaker, so add these to the allowed routing items. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin Reviewed-by: Rob Herring (Arm) -- Changelog v1..v2: - Remove vendor prefix from hp-det-gpios Changelog v2..v3: - Add Reviewed-by tag Reviewed-by: Rob Herring (Arm) Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-2-ryan@testtoast.com Signed-off-by: Mark Brown --- .../bindings/sound/allwinner,sun4i-a10-codec.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml index ccae64ce3071..b4eca702febc 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml @@ -102,6 +102,10 @@ properties: maxItems: 1 description: GPIO to enable the external amplifier + hp-det-gpios: + maxItems: 1 + description: GPIO for headphone/line-out detection + required: - "#sound-dai-cells" - compatible @@ -251,8 +255,10 @@ allOf: allwinner,audio-routing: items: enum: + - Headphone - LINEOUT - Line Out + - Speaker dmas: items: From ae5f76d4044d1580849316c49290678605e0889d Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:24 +1300 Subject: [PATCH 0932/1090] ASoC: sun4i-codec: correct dapm widgets and controls for h616 The previous H616 support patch added a single LINEOUT DAPM pin switch to the card controls. As the codec in this SoC only has a single route, this seemed reasonable at the time, however is redundant given the existing DAPM codec widget definitions controlling the digital and analog sides of the codec. It is also insufficient to describe the scenario where separate components (muxes, jack detection etc) are used to modify the audio route external to the SoC. For example the Anbernic RG(##)XX series of devices uses a headphone jack detection switch, GPIO-controlled speaker amplifier and a passive external mux chip to route audio. Remove the redundant LINEOUT card control, and add a Speaker pin switch control and Headphone DAPM widget to allow control of the above hardware. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-3-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 886b3fa537d2..f24bbefeb392 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1916,10 +1916,11 @@ static const struct snd_soc_component_driver sun50i_h616_codec_codec = { }; static const struct snd_kcontrol_new sun50i_h616_card_controls[] = { - SOC_DAPM_PIN_SWITCH("LINEOUT"), + SOC_DAPM_PIN_SWITCH("Speaker"), }; static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), }; From a149377c033afe6557c50892ebbfc0e8b7e2e253 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:25 +1300 Subject: [PATCH 0933/1090] ASoC: sun4i-codec: support hp-det-gpios property Add support for GPIO headphone detection with the hp-det-gpios property. In order for this to properly disable the path upon removal of headphones, the output must be labelled Headphone which is a common sink in the driver. Describe a headphone jack and detection GPIO in the driver, check for a corresponding device tree node, and enable jack detection in a new machine init function if described. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin -- Changelog v1..v2: - Separate DAPM changes into separate patch and add rationale. Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-4-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index f24bbefeb392..3701f56c7275 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -331,6 +332,7 @@ struct sun4i_codec { struct clk *clk_module; struct reset_control *rst; struct gpio_desc *gpio_pa; + struct gpio_desc *gpio_hp; /* ADC_FIFOC register is at different offset on different SoCs */ struct regmap_field *reg_adc_fifoc; @@ -1583,6 +1585,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = { .ops = &dummy_dai_ops, }; +static struct snd_soc_jack sun4i_headphone_jack; + +static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = { + { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, +}; + +static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = { + .name = "hp-det", + .report = SND_JACK_HEADPHONE, + .debounce_time = 150, +}; + +static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); + int ret; + + if (scodec->gpio_hp) { + ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", + SND_JACK_HEADPHONE, + &sun4i_headphone_jack, + sun4i_headphone_jack_pins, + ARRAY_SIZE(sun4i_headphone_jack_pins)); + if (ret) { + dev_err(rtd->dev, + "Headphone jack creation failed: %d\n", ret); + return ret; + } + + sun4i_headphone_jack_gpio.desc = scodec->gpio_hp; + ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1, + &sun4i_headphone_jack_gpio); + + if (ret) { + dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret); + return ret; + } + } + + return 0; +} + static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, int *num_links) { @@ -1608,6 +1653,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, link->codecs->name = dev_name(dev); link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; + link->init = sun4i_codec_machine_init; *num_links = 1; @@ -2302,6 +2348,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); + if (IS_ERR(scodec->gpio_hp)) { + ret = PTR_ERR(scodec->gpio_hp); + dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n"); + return ret; + } + /* reg_field setup */ scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev, scodec->regmap, From d389719fb4ece17ea28c0cf908066815d3ab0e25 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:27 +1300 Subject: [PATCH 0934/1090] ASoC: sun4i-codec: add h616 card long_name Adding jack detection requires sound servers to act on the emitted events, which are described by ALSA Use Case Manager configurations in userspace. These configurations include the long card name in the file path (falling back to card->name if this is not present), so add a long card name for the H616 without spaces, making UCM referencing easier. The corresponding ALSA UCM patch is here (now merged): https://github.com/alsa-project/alsa-ucm-conf/pull/491 Signed-off-by: Ryan Walklin -- Changelog v1..v2: - Separate patch for card->long_name - Note UCM patch link Changelog v2..v3: - Add card->long_name rather than change existing card->name Link: https://patch.msgid.link/20250214220247.10810-6-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 3701f56c7275..93733ff2e32a 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -2013,6 +2013,7 @@ static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev) card->dev = dev; card->owner = THIS_MODULE; card->name = "H616 Audio Codec"; + card->long_name = "h616-audio-codec"; card->driver_name = "sun4i-codec"; card->controls = sun50i_h616_card_controls; card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls); From f2865c6300d75a9f187dd7918d248e010970fd44 Mon Sep 17 00:00:00 2001 From: Amit Sunil Dhamne Date: Mon, 10 Mar 2025 19:19:07 -0700 Subject: [PATCH 0935/1090] usb: typec: tcpm: fix state transition for SNK_WAIT_CAPABILITIES state in run_state_machine() A subtle error got introduced while manually fixing merge conflict in tcpm.c for commit 85c4efbe6088 ("Merge v6.12-rc6 into usb-next"). As a result of this error, the next state is unconditionally set to SNK_WAIT_CAPABILITIES_TIMEOUT while handling SNK_WAIT_CAPABILITIES state in run_state_machine(...). Fix this by setting new state of TCPM state machine to `upcoming_state` (that is set to different values based on conditions). Cc: stable@vger.kernel.org Fixes: 85c4efbe60888 ("Merge v6.12-rc6 into usb-next") Signed-off-by: Amit Sunil Dhamne Reviewed-by: Badhri Jagan Sridharan Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250310-fix-snk-wait-timeout-v6-14-rc6-v1-1-5db14475798f@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 6bf1a22c785a..62ca4a0ec55b 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -5117,16 +5117,16 @@ static void run_state_machine(struct tcpm_port *port) */ if (port->vbus_never_low) { port->vbus_never_low = false; - tcpm_set_state(port, SNK_SOFT_RESET, - port->timings.sink_wait_cap_time); + upcoming_state = SNK_SOFT_RESET; } else { if (!port->self_powered) upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT; else upcoming_state = hard_reset_state(port); - tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT, - port->timings.sink_wait_cap_time); } + + tcpm_set_state(port, upcoming_state, + port->timings.sink_wait_cap_time); break; case SNK_WAIT_CAPABILITIES_TIMEOUT: /* From 0b4ffbe4888a2c71185eaf5c1a02dd3586a9bc04 Mon Sep 17 00:00:00 2001 From: Tengda Wu Date: Fri, 14 Mar 2025 06:53:35 +0000 Subject: [PATCH 0936/1090] tracing: Correct the refcount if the hist/hist_debug file fails to open The function event_{hist,hist_debug}_open() maintains the refcount of 'file->tr' and 'file' through tracing_open_file_tr(). However, it does not roll back these counts on subsequent failure paths, resulting in a refcount leak. A very obvious case is that if the hist/hist_debug file belongs to a specific instance, the refcount leak will prevent the deletion of that instance, as it relies on the condition 'tr->ref == 1' within __remove_instance(). Fix this by calling tracing_release_file_tr() on all failure paths in event_{hist,hist_debug}_open() to correct the refcount. Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Zheng Yejian Link: https://lore.kernel.org/20250314065335.1202817-1-wutengda@huaweicloud.com Fixes: 1cc111b9cddc ("tracing: Fix uaf issue when open the hist or hist_debug file") Signed-off-by: Tengda Wu Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events_hist.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index ad7419e24055..53dc6719181e 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5689,12 +5689,16 @@ static int event_hist_open(struct inode *inode, struct file *file) guard(mutex)(&event_mutex); event_file = event_file_data(file); - if (!event_file) - return -ENODEV; + if (!event_file) { + ret = -ENODEV; + goto err; + } hist_file = kzalloc(sizeof(*hist_file), GFP_KERNEL); - if (!hist_file) - return -ENOMEM; + if (!hist_file) { + ret = -ENOMEM; + goto err; + } hist_file->file = file; hist_file->last_act = get_hist_hit_count(event_file); @@ -5702,9 +5706,14 @@ static int event_hist_open(struct inode *inode, struct file *file) /* Clear private_data to avoid warning in single_open() */ file->private_data = NULL; ret = single_open(file, hist_show, hist_file); - if (ret) + if (ret) { kfree(hist_file); + goto err; + } + return 0; +err: + tracing_release_file_tr(inode, file); return ret; } @@ -5979,7 +5988,10 @@ static int event_hist_debug_open(struct inode *inode, struct file *file) /* Clear private_data to avoid warning in single_open() */ file->private_data = NULL; - return single_open(file, hist_debug_show, file); + ret = single_open(file, hist_debug_show, file); + if (ret) + tracing_release_file_tr(inode, file); + return ret; } const struct file_operations event_hist_debug_fops = { From ca3ac4bf4dc307cea5781dccccf41c1d14c2f82f Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Mon, 3 Mar 2025 18:02:32 +0000 Subject: [PATCH 0937/1090] xfs: Use abs_diff instead of XFS_ABSDIFF We have a central definition for this function since 2023, used by a number of different parts of the kernel. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Carlos Maiolino Reviewed-by: Eric Sandeen Signed-off-by: Carlos Maiolino --- fs/xfs/libxfs/xfs_alloc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3d33e17f2e5c..7839efe050bf 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -33,8 +33,6 @@ struct kmem_cache *xfs_extfree_item_cache; struct workqueue_struct *xfs_alloc_wq; -#define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) - #define XFSA_FIXUP_BNO_OK 1 #define XFSA_FIXUP_CNT_OK 2 @@ -410,8 +408,8 @@ xfs_alloc_compute_diff( if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) { if (newlen1 < newlen2 || (newlen1 == newlen2 && - XFS_ABSDIFF(newbno1, wantbno) > - XFS_ABSDIFF(newbno2, wantbno))) + abs_diff(newbno1, wantbno) > + abs_diff(newbno2, wantbno))) newbno1 = newbno2; } else if (newbno2 != NULLAGBLOCK) newbno1 = newbno2; @@ -427,7 +425,7 @@ xfs_alloc_compute_diff( } else newbno1 = freeend - wantlen; *newbnop = newbno1; - return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno); + return newbno1 == NULLAGBLOCK ? 0 : abs_diff(newbno1, wantbno); } /* From 03fc0a2dc9f8c292fad8a1bcfb6d1f0dec1824be Mon Sep 17 00:00:00 2001 From: Ike Panhc Date: Fri, 14 Mar 2025 12:57:32 +0800 Subject: [PATCH 0938/1090] MAINTAINERS: Update Ike Panhc's email address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I am no longer at Canonical and update with my personal email address. Signed-off-by: Ike Panhc Link: https://lore.kernel.org/r/20250314045732.389973-1-ike.pan@canonical.com Signed-off-by: Ilpo Järvinen --- .mailmap | 1 + MAINTAINERS | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index ae0adc499f4a..449c5e3a5d26 100644 --- a/.mailmap +++ b/.mailmap @@ -281,6 +281,7 @@ Henrik Rydberg Herbert Xu Huacai Chen Huacai Chen +Ike Panhc J. Bruce Fields J. Bruce Fields Jacob Shin diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..bb4c069cc1e9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11140,7 +11140,7 @@ S: Maintained F: drivers/i2c/busses/i2c-icy.c IDEAPAD LAPTOP EXTRAS DRIVER -M: Ike Panhc +M: Ike Panhc L: platform-driver-x86@vger.kernel.org S: Maintained W: http://launchpad.net/ideapad-laptop From 90fd9ad5b0c981693c8512d9da01f14fb6596e9d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 14 Mar 2025 09:54:43 -0400 Subject: [PATCH 0939/1090] bcachefs: Change btree wb assert to runtime error We just had a report of the assert for "btree in write buffer for non-write buffer btree" popping during the 6.14 upgrade. - 150TB filesystem, after a reboot the upgrade was able to continue from where it left off, so no major damage. But with 6.14 about to come out we want to get this tracked down asap, and need more data if other users hit this. Convert the BUG_ON() to an emergency read-only, and print out btree, the key itself, and stack trace from the original write buffer update (which did not have this check before). Reported-by: Stijn Tintel Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update.h | 8 ++++++++ fs/bcachefs/btree_write_buffer.c | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_update.h b/fs/bcachefs/btree_update.h index 8f22ef9a7651..47d8690f01bf 100644 --- a/fs/bcachefs/btree_update.h +++ b/fs/bcachefs/btree_update.h @@ -126,10 +126,18 @@ bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s) int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *); +int bch2_btree_write_buffer_insert_err(struct btree_trans *, + enum btree_id, struct bkey_i *); + static inline int __must_check bch2_trans_update_buffered(struct btree_trans *trans, enum btree_id btree, struct bkey_i *k) { + if (unlikely(!btree_type_uses_write_buffer(btree))) { + int ret = bch2_btree_write_buffer_insert_err(trans, btree, k); + dump_stack(); + return ret; + } /* * Most updates skip the btree write buffer until journal replay is * finished because synchronization with journal replay relies on having diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index b56c4987b8c9..2c09d19dd621 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c @@ -264,6 +264,22 @@ out: BUG_ON(wb->sorted.size < wb->flushing.keys.nr); } +int bch2_btree_write_buffer_insert_err(struct btree_trans *trans, + enum btree_id btree, struct bkey_i *k) +{ + struct bch_fs *c = trans->c; + struct printbuf buf = PRINTBUF; + + prt_printf(&buf, "attempting to do write buffer update on non wb btree="); + bch2_btree_id_to_text(&buf, btree); + prt_str(&buf, "\n"); + bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k)); + + bch2_fs_inconsistent(c, "%s", buf.buf); + printbuf_exit(&buf); + return -EROFS; +} + static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) { struct bch_fs *c = trans->c; @@ -312,7 +328,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) darray_for_each(wb->sorted, i) { struct btree_write_buffered_key *k = &wb->flushing.keys.data[i->idx]; - BUG_ON(!btree_type_uses_write_buffer(k->btree)); + if (unlikely(!btree_type_uses_write_buffer(k->btree))) { + ret = bch2_btree_write_buffer_insert_err(trans, k->btree, &k->k); + goto err; + } for (struct wb_key_ref *n = i + 1; n < min(i + 4, &darray_top(wb->sorted)); n++) prefetch(&wb->flushing.keys.data[n->idx]); From 1a2b74d0a2a46c219b25fdb0efcf9cd7f55cfe5e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 14 Mar 2025 18:20:20 -0400 Subject: [PATCH 0940/1090] bcachefs: fix build on 32 bit in get_random_u64_below() bare 64 bit divides not allowed, whoops arm-linux-gnueabi-ld: drivers/char/random.o: in function `__get_random_u64_below': drivers/char/random.c:602:(.text+0xc70): undefined reference to `__aeabi_uldivmod' Signed-off-by: Kent Overstreet --- fs/bcachefs/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index 8e3ab4bf79a9..da2cd11b3025 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -663,7 +663,8 @@ u64 bch2_get_random_u64_below(u64 ceil) u64 mult = ceil * rand; if (unlikely(mult < ceil)) { - u64 bound = -ceil % ceil; + u64 bound; + div64_u64_rem(-ceil, ceil, &bound); while (unlikely(mult < bound)) { rand = get_random_u64(); mult = ceil * rand; From 4701f33a10702d5fc577c32434eb62adde0a1ae1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Mar 2025 12:55:17 -1000 Subject: [PATCH 0941/1090] Linux 6.14-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d6a9ec8a2ac..50694bbbf828 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 14 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Baby Opossum Posse # *DOCUMENTATION* From 399f9bd01644c827be8bfca1236ec9b4c211ccbe Mon Sep 17 00:00:00 2001 From: Weidong Wang Date: Wed, 12 Mar 2025 20:00:59 +0800 Subject: [PATCH 0942/1090] ASoC: dt-bindings: Add schema for "awinic,aw88166" Add the awinic,aw88166 property to support the aw88166 chip. Signed-off-by: Weidong Wang Acked-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250312120100.9730-2-wangweidong.a@awinic.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/awinic,aw88395.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml index 6676406bf2de..bb92d6ca3144 100644 --- a/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml +++ b/Documentation/devicetree/bindings/sound/awinic,aw88395.yaml @@ -19,6 +19,7 @@ properties: enum: - awinic,aw88081 - awinic,aw88083 + - awinic,aw88166 - awinic,aw88261 - awinic,aw88395 - awinic,aw88399 From 94e412c28e6144b86d669e4d7ecb6b097431eede Mon Sep 17 00:00:00 2001 From: Weidong Wang Date: Wed, 12 Mar 2025 20:01:00 +0800 Subject: [PATCH 0943/1090] ASoC: codecs: Add aw88166 amplifier driver The driver is for amplifiers aw88166 of Awinic Technology Corporation. The AW88166 is a high efficiency digital Smart K audio amplifier Signed-off-by: Weidong Wang Link: https://patch.msgid.link/20250312120100.9730-3-wangweidong.a@awinic.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 13 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/aw88166.c | 1933 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/aw88166.h | 534 ++++++++++ 4 files changed, 2482 insertions(+) create mode 100644 sound/soc/codecs/aw88166.c create mode 100644 sound/soc/codecs/aw88166.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ee35f3aa5521..40bb7a1d44bc 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -58,6 +58,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_AW87390 imply SND_SOC_AW88395 imply SND_SOC_AW88081 + imply SND_SOC_AW88166 imply SND_SOC_AW88261 imply SND_SOC_AW88399 imply SND_SOC_BT_SCO @@ -678,6 +679,18 @@ config SND_SOC_AW88395 digital Smart K audio amplifier with an integrated 10V smart boost convert. +config SND_SOC_AW88166 + tristate "Soc Audio for awinic aw88166" + depends on I2C + select REGMAP_I2C + select GPIOLIB + select SND_SOC_AW88395_LIB + help + This option enables support for aw88166 Smart PA. + The awinic AW88166 is an I2S/TDM input, high efficiency + digital Smart K audio amplifier with sound quality + enhancement algorithms and speaker protection. + config SND_SOC_AW88261 tristate "Soc Audio for awinic aw88261" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d7ad795603c1..10f726066b6c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -53,6 +53,7 @@ snd-soc-aw88081-y := aw88081.o snd-soc-aw88395-lib-y := aw88395/aw88395_lib.o snd-soc-aw88395-y := aw88395/aw88395.o \ aw88395/aw88395_device.o +snd-soc-aw88166-y := aw88166.o snd-soc-aw88261-y := aw88261.o snd-soc-aw88399-y := aw88399.o snd-soc-bd28623-y := bd28623.o @@ -470,6 +471,7 @@ obj-$(CONFIG_SND_SOC_AW87390) += snd-soc-aw87390.o obj-$(CONFIG_SND_SOC_AW88081) += snd-soc-aw88081.o obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o +obj-$(CONFIG_SND_SOC_AW88166) +=snd-soc-aw88166.o obj-$(CONFIG_SND_SOC_AW88261) +=snd-soc-aw88261.o obj-$(CONFIG_SND_SOC_AW88399) += snd-soc-aw88399.o obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o diff --git a/sound/soc/codecs/aw88166.c b/sound/soc/codecs/aw88166.c new file mode 100644 index 000000000000..6c50c4a18b6a --- /dev/null +++ b/sound/soc/codecs/aw88166.c @@ -0,0 +1,1933 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// aw88166.c -- ALSA SoC AW88166 codec support +// +// Copyright (c) 2025 AWINIC Technology CO., LTD +// +// Author: Weidong Wang +// + +#include +#include +#include +#include +#include +#include +#include "aw88166.h" +#include "aw88395/aw88395_device.h" + +struct aw88166 { + struct aw_device *aw_pa; + struct mutex lock; + struct gpio_desc *reset_gpio; + struct delayed_work start_work; + struct regmap *regmap; + struct aw_container *aw_cfg; + + unsigned int check_val; + unsigned int crc_init_val; + unsigned int vcalb_init_val; + unsigned int re_init_val; + unsigned int dither_st; + bool phase_sync; +}; + +static const struct regmap_config aw88166_remap_config = { + .val_bits = 16, + .reg_bits = 8, + .max_register = AW88166_REG_MAX, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_BIG, +}; + +static int aw_dev_dsp_write_16bit(struct aw_device *aw_dev, + unsigned short dsp_addr, unsigned int dsp_data) +{ + int ret; + + ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr); + if (ret) { + dev_err(aw_dev->dev, "%s write addr error, ret=%d", __func__, ret); + return ret; + } + + ret = regmap_write(aw_dev->regmap, AW88166_DSPMDAT_REG, (u16)dsp_data); + if (ret) { + dev_err(aw_dev->dev, "%s write data error, ret=%d", __func__, ret); + return ret; + } + + return 0; +} + +static int aw_dev_dsp_read_16bit(struct aw_device *aw_dev, + unsigned short dsp_addr, unsigned int *dsp_data) +{ + unsigned int temp_data; + int ret; + + ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr); + if (ret) { + dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret); + return ret; + } + + ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data); + if (ret) { + dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); + return ret; + } + *dsp_data = temp_data; + + return 0; +} + +static int aw_dev_dsp_read_32bit(struct aw_device *aw_dev, + unsigned short dsp_addr, unsigned int *dsp_data) +{ + unsigned int temp_data; + int ret; + + ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, dsp_addr); + if (ret) { + dev_err(aw_dev->dev, "%s write error, ret=%d", __func__, ret); + return ret; + } + + ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data); + if (ret) { + dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); + return ret; + } + *dsp_data = temp_data; + + ret = regmap_read(aw_dev->regmap, AW88166_DSPMDAT_REG, &temp_data); + if (ret) { + dev_err(aw_dev->dev, "%s read error, ret=%d", __func__, ret); + return ret; + } + *dsp_data |= (temp_data << 16); + + return 0; +} + +static int aw_dev_dsp_read(struct aw_device *aw_dev, + unsigned short dsp_addr, unsigned int *dsp_data, unsigned char data_type) +{ + u32 reg_value; + int ret; + + mutex_lock(&aw_dev->dsp_lock); + switch (data_type) { + case AW88166_DSP_16_DATA: + ret = aw_dev_dsp_read_16bit(aw_dev, dsp_addr, dsp_data); + if (ret) + dev_err(aw_dev->dev, "read dsp_addr[0x%x] 16-bit failed", (u32)dsp_addr); + break; + case AW88166_DSP_32_DATA: + ret = aw_dev_dsp_read_32bit(aw_dev, dsp_addr, dsp_data); + if (ret) + dev_err(aw_dev->dev, "read dsp_addr[0x%x] 32-bit failed", (u32)dsp_addr); + break; + default: + dev_err(aw_dev->dev, "data type[%d] unsupported", data_type); + ret = -EINVAL; + break; + } + + /* clear dsp chip select state */ + if (regmap_read(aw_dev->regmap, AW88166_ID_REG, ®_value)) + dev_err(aw_dev->dev, "%s fail to clear chip state. ret=%d\n", __func__, ret); + mutex_unlock(&aw_dev->dsp_lock); + + return ret; +} + +static void aw_dev_pwd(struct aw_device *aw_dev, bool pwd) +{ + int ret; + + if (pwd) + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_PWDN_MASK, AW88166_PWDN_POWER_DOWN_VALUE); + else + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_PWDN_MASK, AW88166_PWDN_WORKING_VALUE); + + if (ret) + dev_dbg(aw_dev->dev, "%s failed", __func__); +} + +static void aw_dev_get_int_status(struct aw_device *aw_dev, unsigned short *int_status) +{ + unsigned int reg_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88166_SYSINT_REG, ®_val); + if (ret) + dev_err(aw_dev->dev, "read interrupt reg fail, ret=%d", ret); + else + *int_status = reg_val; + + dev_dbg(aw_dev->dev, "read interrupt reg=0x%04x", *int_status); +} + +static void aw_dev_clear_int_status(struct aw_device *aw_dev) +{ + u16 int_status; + + /* read int status and clear */ + aw_dev_get_int_status(aw_dev, &int_status); + /* make sure int status is clear */ + aw_dev_get_int_status(aw_dev, &int_status); + if (int_status) + dev_dbg(aw_dev->dev, "int status(%d) is not cleaned.\n", int_status); +} + +static int aw_dev_get_iis_status(struct aw_device *aw_dev) +{ + unsigned int reg_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88166_SYSST_REG, ®_val); + if (ret) + return ret; + if ((reg_val & AW88166_BIT_PLL_CHECK) != AW88166_BIT_PLL_CHECK) { + dev_err(aw_dev->dev, "check pll lock fail, reg_val:0x%04x", reg_val); + return -EINVAL; + } + + return 0; +} + +static int aw_dev_check_mode1_pll(struct aw_device *aw_dev) +{ + int ret, i; + + for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) { + ret = aw_dev_get_iis_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode1 iis signal check error"); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + } else { + return 0; + } + } + + return -EPERM; +} + +static int aw_dev_check_mode2_pll(struct aw_device *aw_dev) +{ + unsigned int reg_val; + int ret, i; + + ret = regmap_read(aw_dev->regmap, AW88166_PLLCTRL2_REG, ®_val); + if (ret) + return ret; + + reg_val &= (~AW88166_CCO_MUX_MASK); + if (reg_val == AW88166_CCO_MUX_DIVIDED_VALUE) { + dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); + return -EPERM; + } + + /* change mode2 */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_PLLCTRL2_REG, + ~AW88166_CCO_MUX_MASK, AW88166_CCO_MUX_DIVIDED_VALUE); + if (ret) + return ret; + + for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) { + ret = aw_dev_get_iis_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 iis signal check error"); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + } else { + break; + } + } + + /* change mode1 */ + regmap_update_bits(aw_dev->regmap, AW88166_PLLCTRL2_REG, + ~AW88166_CCO_MUX_MASK, AW88166_CCO_MUX_BYPASS_VALUE); + if (ret == 0) { + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) { + ret = aw_dev_get_iis_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error"); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + } else { + break; + } + } + } + + return ret; +} + +static int aw_dev_check_syspll(struct aw_device *aw_dev) +{ + int ret; + + ret = aw_dev_check_mode1_pll(aw_dev); + if (ret) { + dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); + ret = aw_dev_check_mode2_pll(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "mode2 check iis failed"); + return ret; + } + } + + return 0; +} + +static int aw_dev_check_sysst(struct aw_device *aw_dev) +{ + unsigned int check_val; + unsigned int reg_val; + int ret, i; + + ret = regmap_read(aw_dev->regmap, AW88166_PWMCTRL3_REG, ®_val); + if (ret) + return ret; + + if (reg_val & (~AW88166_NOISE_GATE_EN_MASK)) + check_val = AW88166_BIT_SYSST_NOSWS_CHECK; + else + check_val = AW88166_BIT_SYSST_SWS_CHECK; + + for (i = 0; i < AW88166_DEV_SYSST_CHECK_MAX; i++) { + ret = regmap_read(aw_dev->regmap, AW88166_SYSST_REG, ®_val); + if (ret) + return ret; + + if ((reg_val & (~AW88166_BIT_SYSST_CHECK_MASK) & check_val) != check_val) { + dev_err(aw_dev->dev, "check sysst fail, cnt=%d, reg_val=0x%04x, check:0x%x", + i, reg_val, AW88166_BIT_SYSST_NOSWS_CHECK); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + } else { + return 0; + } + } + + return -EPERM; +} + +static void aw_dev_amppd(struct aw_device *aw_dev, bool amppd) +{ + int ret; + + if (amppd) + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_AMPPD_MASK, AW88166_AMPPD_POWER_DOWN_VALUE); + else + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_AMPPD_MASK, AW88166_AMPPD_WORKING_VALUE); + + if (ret) + dev_dbg(aw_dev->dev, "%s failed", __func__); +} + +static void aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable) +{ + int ret; + + if (is_enable) + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_DSPBY_MASK, AW88166_DSPBY_WORKING_VALUE); + else + ret = regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_DSPBY_MASK, AW88166_DSPBY_BYPASS_VALUE); + + if (ret) + dev_dbg(aw_dev->dev, "%s failed\n", __func__); +} + +static int aw88166_dev_get_icalk(struct aw88166 *aw88166, int16_t *icalk) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + unsigned int efrm_reg_val, efrl_reg_val; + uint16_t ef_isn_geslp, ef_isn_h5bits; + uint16_t icalk_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88166_EFRM2_REG, &efrm_reg_val); + if (ret) + return ret; + + ef_isn_geslp = (efrm_reg_val & (~AW88166_EF_ISN_GESLP_MASK)) >> + AW88166_EF_ISN_GESLP_SHIFT; + + ret = regmap_read(aw_dev->regmap, AW88166_EFRL_REG, &efrl_reg_val); + if (ret) + return ret; + + ef_isn_h5bits = (efrl_reg_val & (~AW88166_EF_ISN_H5BITS_MASK)) >> + AW88166_EF_ISN_H5BITS_SHIFT; + + if (aw88166->check_val == AW_EF_AND_CHECK) + icalk_val = ef_isn_geslp & (ef_isn_h5bits | AW88166_EF_ISN_H5BITS_SIGN_MASK); + else + icalk_val = ef_isn_geslp | (ef_isn_h5bits & (~AW88166_EF_ISN_H5BITS_SIGN_MASK)); + + if (icalk_val & (~AW88166_ICALK_SIGN_MASK)) + icalk_val = icalk_val | AW88166_ICALK_NEG_MASK; + *icalk = (int16_t)icalk_val; + + return 0; +} + +static int aw88166_dev_get_vcalk(struct aw88166 *aw88166, int16_t *vcalk) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + unsigned int efrm_reg_val, efrl_reg_val; + uint16_t ef_vsn_geslp, ef_vsn_h3bits; + uint16_t vcalk_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88166_EFRM2_REG, &efrm_reg_val); + if (ret) + return ret; + + ef_vsn_geslp = (efrm_reg_val & (~AW88166_EF_VSN_GESLP_MASK)) >> + AW88166_EF_VSN_GESLP_SHIFT; + + ret = regmap_read(aw_dev->regmap, AW88166_EFRL_REG, &efrl_reg_val); + if (ret) + return ret; + + ef_vsn_h3bits = (efrl_reg_val & (~AW88166_EF_VSN_H3BITS_MASK)) >> + AW88166_EF_VSN_H3BITS_SHIFT; + + if (aw88166->check_val == AW_EF_AND_CHECK) + vcalk_val = ef_vsn_geslp & (ef_vsn_h3bits | AW88166_EF_VSN_H3BITS_SIGN_MASK); + else + vcalk_val = ef_vsn_geslp | (ef_vsn_h3bits & (~AW88166_EF_VSN_H3BITS_SIGN_MASK)); + + if (vcalk_val & (~AW88166_VCALK_SIGN_MASK)) + vcalk_val = vcalk_val | AW88166_VCALK_NEG_MASK; + *vcalk = (int16_t)vcalk_val; + + return 0; +} + +static int aw88166_dev_set_vcalb(struct aw88166 *aw88166) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + int32_t ical_k, vcal_k, vcalb; + int16_t icalk, vcalk; + unsigned int reg_val; + int ret; + + ret = aw88166_dev_get_icalk(aw88166, &icalk); + if (ret) { + dev_err(aw_dev->dev, "get icalk failed\n"); + return ret; + } + ical_k = icalk * AW88166_ICABLK_FACTOR + AW88166_CABL_BASE_VALUE; + + ret = aw88166_dev_get_vcalk(aw88166, &vcalk); + if (ret) { + dev_err(aw_dev->dev, "get vbcalk failed\n"); + return ret; + } + vcal_k = vcalk * AW88166_VCABLK_FACTOR + AW88166_CABL_BASE_VALUE; + + vcalb = AW88166_VCALB_ACCURACY * AW88166_VSCAL_FACTOR / + AW88166_ISCAL_FACTOR * ical_k / vcal_k * aw88166->vcalb_init_val; + + vcalb = vcalb >> AW88166_VCALB_ADJ_FACTOR; + reg_val = (uint32_t)vcalb; + + regmap_write(aw_dev->regmap, AW88166_DSPVCALB_REG, reg_val); + + return 0; +} + +static int aw_dev_init_vcalb_update(struct aw88166 *aw88166, int flag) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + int ret; + + switch (flag) { + case AW88166_RECOVERY_SEC_DATA: + ret = regmap_write(aw_dev->regmap, AW88166_DSPVCALB_REG, aw88166->vcalb_init_val); + break; + case AW88166_RECORD_SEC_DATA: + ret = regmap_read(aw_dev->regmap, AW88166_DSPVCALB_REG, &aw88166->vcalb_init_val); + break; + default: + dev_err(aw_dev->dev, "unsupported type:%d\n", flag); + ret = -EINVAL; + break; + } + + return ret; +} + +static int aw_dev_init_re_update(struct aw88166 *aw88166, int flag) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + unsigned int re_temp_h, re_temp_l; + int ret; + + switch (flag) { + case AW88166_RECOVERY_SEC_DATA: + ret = regmap_write(aw_dev->regmap, AW88166_ACR1_REG, aw88166->re_init_val >> 16); + if (ret) + return ret; + ret = regmap_write(aw_dev->regmap, AW88166_ACR2_REG, + (uint16_t)aw88166->re_init_val); + if (ret) + return ret; + break; + case AW88166_RECORD_SEC_DATA: + ret = regmap_read(aw_dev->regmap, AW88166_ACR1_REG, &re_temp_h); + if (ret) + return ret; + ret = regmap_read(aw_dev->regmap, AW88166_ACR2_REG, &re_temp_l); + if (ret) + return ret; + aw88166->re_init_val = (re_temp_h << 16) + re_temp_l; + break; + default: + dev_err(aw_dev->dev, "unsupported type:%d\n", flag); + ret = -EINVAL; + break; + } + + return ret; +} + +static void aw_dev_backup_sec_record(struct aw88166 *aw88166) +{ + aw_dev_init_vcalb_update(aw88166, AW88166_RECORD_SEC_DATA); + aw_dev_init_re_update(aw88166, AW88166_RECOVERY_SEC_DATA); +} + +static void aw_dev_backup_sec_recovery(struct aw88166 *aw88166) +{ + aw_dev_init_vcalb_update(aw88166, AW88166_RECOVERY_SEC_DATA); + aw_dev_init_re_update(aw88166, AW88166_RECOVERY_SEC_DATA); +} + +static int aw_dev_update_cali_re(struct aw_cali_desc *cali_desc) +{ + struct aw_device *aw_dev = + container_of(cali_desc, struct aw_device, cali_desc); + uint16_t re_lbits, re_hbits; + u32 cali_re; + int ret; + + if ((aw_dev->cali_desc.cali_re >= AW88166_CALI_RE_MAX) || + (aw_dev->cali_desc.cali_re <= AW88166_CALI_RE_MIN)) + return -EINVAL; + + cali_re = AW88166_SHOW_RE_TO_DSP_RE((aw_dev->cali_desc.cali_re + + aw_dev->cali_desc.ra), AW88166_DSP_RE_SHIFT); + + re_hbits = (cali_re & (~AW88166_CALI_RE_HBITS_MASK)) >> AW88166_CALI_RE_HBITS_SHIFT; + re_lbits = (cali_re & (~AW88166_CALI_RE_LBITS_MASK)) >> AW88166_CALI_RE_LBITS_SHIFT; + + ret = regmap_write(aw_dev->regmap, AW88166_ACR1_REG, re_hbits); + if (ret) { + dev_err(aw_dev->dev, "set cali re error"); + return ret; + } + + ret = regmap_write(aw_dev->regmap, AW88166_ACR2_REG, re_lbits); + if (ret) + dev_err(aw_dev->dev, "set cali re error"); + + return ret; +} + +static int aw_dev_fw_crc_check(struct aw_device *aw_dev) +{ + uint16_t check_val, fw_len_val; + unsigned int reg_val; + int ret; + + /* calculate fw_end_addr */ + fw_len_val = ((aw_dev->dsp_fw_len / AW_FW_ADDR_LEN) - 1) + AW88166_CRC_FW_BASE_ADDR; + + /* write fw_end_addr to crc_end_addr */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_END_ADDR_MASK, fw_len_val); + if (ret) + return ret; + /* enable fw crc check */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_CODE_EN_MASK, AW88166_CRC_CODE_EN_ENABLE_VALUE); + + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + + /* read crc check result */ + regmap_read(aw_dev->regmap, AW88166_HAGCST_REG, ®_val); + if (ret) + return ret; + + check_val = (reg_val & (~AW88166_CRC_CHECK_BITS_MASK)) >> AW88166_CRC_CHECK_START_BIT; + + /* disable fw crc check */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_CODE_EN_MASK, AW88166_CRC_CODE_EN_DISABLE_VALUE); + if (ret) + return ret; + + if (check_val != AW88166_CRC_CHECK_PASS_VAL) { + dev_err(aw_dev->dev, "%s failed, check_val 0x%x != 0x%x\n", + __func__, check_val, AW88166_CRC_CHECK_PASS_VAL); + ret = -EINVAL; + } + + return ret; +} + +static int aw_dev_cfg_crc_check(struct aw_device *aw_dev) +{ + uint16_t check_val, cfg_len_val; + unsigned int reg_val; + int ret; + + /* calculate cfg end addr */ + cfg_len_val = ((aw_dev->dsp_cfg_len / AW_FW_ADDR_LEN) - 1) + AW88166_CRC_CFG_BASE_ADDR; + + /* write cfg_end_addr to crc_end_addr */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_END_ADDR_MASK, cfg_len_val); + if (ret) + return ret; + + /* enable cfg crc check */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_CFG_EN_MASK, AW88166_CRC_CFG_EN_ENABLE_VALUE); + if (ret) + return ret; + + usleep_range(AW88166_1000_US, AW88166_1000_US + 10); + + /* read crc check result */ + ret = regmap_read(aw_dev->regmap, AW88166_HAGCST_REG, ®_val); + if (ret) + return ret; + + check_val = (reg_val & (~AW88166_CRC_CHECK_BITS_MASK)) >> AW88166_CRC_CHECK_START_BIT; + + /* disable cfg crc check */ + ret = regmap_update_bits(aw_dev->regmap, AW88166_CRCCTRL_REG, + ~AW88166_CRC_CFG_EN_MASK, AW88166_CRC_CFG_EN_DISABLE_VALUE); + if (ret) + return ret; + + if (check_val != AW88166_CRC_CHECK_PASS_VAL) { + dev_err(aw_dev->dev, "crc_check failed, check val 0x%x != 0x%x\n", + check_val, AW88166_CRC_CHECK_PASS_VAL); + ret = -EINVAL; + } + + return ret; +} + +static int aw_dev_hw_crc_check(struct aw88166 *aw88166) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + int ret; + + ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG, + ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_BYPASS_VALUE); + if (ret) + return ret; + + ret = aw_dev_fw_crc_check(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "fw_crc_check failed\n"); + goto crc_check_failed; + } + + ret = aw_dev_cfg_crc_check(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "cfg_crc_check failed\n"); + goto crc_check_failed; + } + + ret = regmap_write(aw_dev->regmap, AW88166_CRCCTRL_REG, aw88166->crc_init_val); + if (ret) + return ret; + + ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG, + ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_WORK_VALUE); + + return ret; + +crc_check_failed: + regmap_update_bits(aw_dev->regmap, AW88166_I2SCFG1_REG, + ~AW88166_RAM_CG_BYP_MASK, AW88166_RAM_CG_BYP_WORK_VALUE); + return ret; +} + +static void aw_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) +{ + int ret; + + if (flag) + ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCTRL3_REG, + ~AW88166_I2STXEN_MASK, AW88166_I2STXEN_ENABLE_VALUE); + else + ret = regmap_update_bits(aw_dev->regmap, AW88166_I2SCTRL3_REG, + ~AW88166_I2STXEN_MASK, AW88166_I2STXEN_DISABLE_VALUE); + + if (ret) + dev_dbg(aw_dev->dev, "%s failed", __func__); +} + +static int aw_dev_get_dsp_status(struct aw_device *aw_dev) +{ + unsigned int reg_val; + int ret; + + ret = regmap_read(aw_dev->regmap, AW88166_WDT_REG, ®_val); + if (ret) + return ret; + if (!(reg_val & (~AW88166_WDT_CNT_MASK))) + return -EPERM; + + return 0; +} + +static int aw_dev_dsp_check(struct aw_device *aw_dev) +{ + int ret, i; + + switch (aw_dev->dsp_cfg) { + case AW88166_DEV_DSP_BYPASS: + dev_dbg(aw_dev->dev, "dsp bypass"); + ret = 0; + break; + case AW88166_DEV_DSP_WORK: + aw_dev_dsp_enable(aw_dev, false); + aw_dev_dsp_enable(aw_dev, true); + usleep_range(AW88166_1000_US, AW88166_1000_US + 10); + for (i = 0; i < AW88166_DEV_DSP_CHECK_MAX; i++) { + ret = aw_dev_get_dsp_status(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "dsp wdt status error=%d", ret); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + } + } + break; + default: + dev_err(aw_dev->dev, "unknown dsp cfg=%d", aw_dev->dsp_cfg); + ret = -EINVAL; + break; + } + + return ret; +} + +static int aw_dev_set_volume(struct aw_device *aw_dev, unsigned int value) +{ + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; + unsigned int reg_value; + u16 real_value; + int ret; + + real_value = min((value + vol_desc->init_volume), (unsigned int)AW88166_MUTE_VOL); + + ret = regmap_read(aw_dev->regmap, AW88166_SYSCTRL2_REG, ®_value); + if (ret) + return ret; + + dev_dbg(aw_dev->dev, "value 0x%x , reg:0x%x", value, real_value); + + real_value = (real_value << AW88166_VOL_START_BIT) | (reg_value & AW88166_VOL_MASK); + + ret = regmap_write(aw_dev->regmap, AW88166_SYSCTRL2_REG, real_value); + + return ret; +} + +static void aw_dev_fade_in(struct aw_device *aw_dev) +{ + struct aw_volume_desc *desc = &aw_dev->volume_desc; + u16 fade_in_vol = desc->ctl_volume; + int fade_step = aw_dev->fade_step; + int i; + + if (fade_step == 0 || aw_dev->fade_in_time == 0) { + aw_dev_set_volume(aw_dev, fade_in_vol); + return; + } + + for (i = AW88166_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { + aw_dev_set_volume(aw_dev, i); + usleep_range(aw_dev->fade_in_time, aw_dev->fade_in_time + 10); + } + + if (i != fade_in_vol) + aw_dev_set_volume(aw_dev, fade_in_vol); +} + +static void aw_dev_fade_out(struct aw_device *aw_dev) +{ + struct aw_volume_desc *desc = &aw_dev->volume_desc; + int fade_step = aw_dev->fade_step; + int i; + + if (fade_step == 0 || aw_dev->fade_out_time == 0) { + aw_dev_set_volume(aw_dev, AW88166_MUTE_VOL); + return; + } + + for (i = desc->ctl_volume; i <= AW88166_MUTE_VOL; i += fade_step) { + aw_dev_set_volume(aw_dev, i); + usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); + } + + if (i != AW88166_MUTE_VOL) { + aw_dev_set_volume(aw_dev, AW88166_MUTE_VOL); + usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); + } +} + +static void aw88166_dev_mute(struct aw_device *aw_dev, bool is_mute) +{ + if (is_mute) { + aw_dev_fade_out(aw_dev); + regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_HMUTE_MASK, AW88166_HMUTE_ENABLE_VALUE); + } else { + regmap_update_bits(aw_dev->regmap, AW88166_SYSCTRL_REG, + ~AW88166_HMUTE_MASK, AW88166_HMUTE_DISABLE_VALUE); + aw_dev_fade_in(aw_dev); + } +} + +static void aw88166_dev_set_dither(struct aw88166 *aw88166, bool dither) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + + if (dither) + regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG, + ~AW88166_DITHER_EN_MASK, AW88166_DITHER_EN_ENABLE_VALUE); + else + regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG, + ~AW88166_DITHER_EN_MASK, AW88166_DITHER_EN_DISABLE_VALUE); +} + +static int aw88166_dev_start(struct aw88166 *aw88166) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + int ret; + + if (aw_dev->status == AW88166_DEV_PW_ON) { + dev_dbg(aw_dev->dev, "already power on"); + return 0; + } + + aw88166_dev_set_dither(aw88166, false); + + /* power on */ + aw_dev_pwd(aw_dev, false); + usleep_range(AW88166_2000_US, AW88166_2000_US + 10); + + ret = aw_dev_check_syspll(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "pll check failed cannot start\n"); + goto pll_check_fail; + } + + /* amppd on */ + aw_dev_amppd(aw_dev, false); + usleep_range(AW88166_1000_US, AW88166_1000_US + 50); + + /* check i2s status */ + ret = aw_dev_check_sysst(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "sysst check failed\n"); + goto sysst_check_fail; + } + + if (aw_dev->dsp_cfg == AW88166_DEV_DSP_WORK) { + aw_dev_backup_sec_recovery(aw88166); + ret = aw_dev_hw_crc_check(aw88166); + if (ret) { + dev_err(aw_dev->dev, "dsp crc check failed\n"); + goto crc_check_fail; + } + aw_dev_dsp_enable(aw_dev, false); + aw88166_dev_set_vcalb(aw88166); + aw_dev_update_cali_re(&aw_dev->cali_desc); + ret = aw_dev_dsp_check(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "dsp status check failed\n"); + goto dsp_check_fail; + } + } else { + dev_dbg(aw_dev->dev, "start pa with dsp bypass"); + } + + /* enable tx feedback */ + aw_dev_i2s_tx_enable(aw_dev, true); + + if (aw88166->dither_st == AW88166_DITHER_EN_ENABLE_VALUE) + aw88166_dev_set_dither(aw88166, true); + + /* close mute */ + aw88166_dev_mute(aw_dev, false); + /* clear inturrupt */ + aw_dev_clear_int_status(aw_dev); + aw_dev->status = AW88166_DEV_PW_ON; + + return 0; + +dsp_check_fail: +crc_check_fail: + aw_dev_dsp_enable(aw_dev, false); +sysst_check_fail: + aw_dev_clear_int_status(aw_dev); + aw_dev_amppd(aw_dev, true); +pll_check_fail: + aw_dev_pwd(aw_dev, true); + aw_dev->status = AW88166_DEV_PW_OFF; + + return ret; +} + +static int aw_dev_dsp_update_container(struct aw_device *aw_dev, + unsigned char *data, unsigned int len, unsigned short base) +{ + u32 tmp_len; + int i, ret; + + mutex_lock(&aw_dev->dsp_lock); + ret = regmap_write(aw_dev->regmap, AW88166_DSPMADD_REG, base); + if (ret) + goto error_operation; + + for (i = 0; i < len; i += AW88166_MAX_RAM_WRITE_BYTE_SIZE) { + if ((len - i) < AW88166_MAX_RAM_WRITE_BYTE_SIZE) + tmp_len = len - i; + else + tmp_len = AW88166_MAX_RAM_WRITE_BYTE_SIZE; + + ret = regmap_raw_write(aw_dev->regmap, AW88166_DSPMDAT_REG, + &data[i], tmp_len); + if (ret) + goto error_operation; + } + mutex_unlock(&aw_dev->dsp_lock); + + return 0; + +error_operation: + mutex_unlock(&aw_dev->dsp_lock); + return ret; +} + +static int aw_dev_get_ra(struct aw_cali_desc *cali_desc) +{ + struct aw_device *aw_dev = + container_of(cali_desc, struct aw_device, cali_desc); + u32 dsp_ra; + int ret; + + ret = aw_dev_dsp_read(aw_dev, AW88166_DSP_REG_CFG_ADPZ_RA, + &dsp_ra, AW88166_DSP_32_DATA); + if (ret) { + dev_err(aw_dev->dev, "read ra error\n"); + return ret; + } + + cali_desc->ra = AW88166_DSP_RE_TO_SHOW_RE(dsp_ra, + AW88166_DSP_RE_SHIFT); + + return 0; +} + +static int aw_dev_dsp_update_cfg(struct aw_device *aw_dev, + unsigned char *data, unsigned int len) +{ + int ret; + + dev_dbg(aw_dev->dev, "dsp config len:%d", len); + + if (!len || !data) { + dev_err(aw_dev->dev, "dsp config data is null or len is 0\n"); + return -EINVAL; + } + + ret = aw_dev_dsp_update_container(aw_dev, data, len, AW88166_DSP_CFG_ADDR); + if (ret) + return ret; + + aw_dev->dsp_cfg_len = len; + + ret = aw_dev_get_ra(&aw_dev->cali_desc); + + return ret; +} + +static int aw_dev_dsp_update_fw(struct aw_device *aw_dev, + unsigned char *data, unsigned int len) +{ + int ret; + + dev_dbg(aw_dev->dev, "dsp firmware len:%d", len); + + if (!len || !data) { + dev_err(aw_dev->dev, "dsp firmware data is null or len is 0\n"); + return -EINVAL; + } + + aw_dev->dsp_fw_len = len; + ret = aw_dev_dsp_update_container(aw_dev, data, len, AW88166_DSP_FW_ADDR); + + return ret; +} + +static int aw_dev_check_sram(struct aw_device *aw_dev) +{ + unsigned int reg_val; + + mutex_lock(&aw_dev->dsp_lock); + /* read dsp_rom_check_reg */ + aw_dev_dsp_read_16bit(aw_dev, AW88166_DSP_ROM_CHECK_ADDR, ®_val); + if (reg_val != AW88166_DSP_ROM_CHECK_DATA) { + dev_err(aw_dev->dev, "check dsp rom failed, read[0x%x] != check[0x%x]\n", + reg_val, AW88166_DSP_ROM_CHECK_DATA); + goto error; + } + + /* check dsp_cfg_base_addr */ + aw_dev_dsp_write_16bit(aw_dev, AW88166_DSP_CFG_ADDR, AW88166_DSP_ODD_NUM_BIT_TEST); + aw_dev_dsp_read_16bit(aw_dev, AW88166_DSP_CFG_ADDR, ®_val); + if (reg_val != AW88166_DSP_ODD_NUM_BIT_TEST) { + dev_err(aw_dev->dev, "check dsp cfg failed, read[0x%x] != write[0x%x]\n", + reg_val, AW88166_DSP_ODD_NUM_BIT_TEST); + goto error; + } + mutex_unlock(&aw_dev->dsp_lock); + + return 0; +error: + mutex_unlock(&aw_dev->dsp_lock); + return -EPERM; +} + +static void aw_dev_select_memclk(struct aw_device *aw_dev, unsigned char flag) +{ + int ret; + + switch (flag) { + case AW88166_DEV_MEMCLK_PLL: + ret = regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG, + ~AW88166_MEM_CLKSEL_MASK, + AW88166_MEM_CLKSEL_DAPHCLK_VALUE); + if (ret) + dev_err(aw_dev->dev, "memclk select pll failed\n"); + break; + case AW88166_DEV_MEMCLK_OSC: + ret = regmap_update_bits(aw_dev->regmap, AW88166_DBGCTRL_REG, + ~AW88166_MEM_CLKSEL_MASK, + AW88166_MEM_CLKSEL_OSCCLK_VALUE); + if (ret) + dev_err(aw_dev->dev, "memclk select OSC failed\n"); + break; + default: + dev_err(aw_dev->dev, "unknown memclk config, flag=0x%x\n", flag); + break; + } +} + +static int aw_dev_update_reg_container(struct aw88166 *aw88166, + unsigned char *data, unsigned int len) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; + u16 read_vol, reg_val; + int data_len, i, ret; + int16_t *reg_data; + u8 reg_addr; + + reg_data = (int16_t *)data; + data_len = len >> 1; + + if (data_len & 0x1) { + dev_err(aw_dev->dev, "data len:%d unsupported\n", data_len); + return -EINVAL; + } + + for (i = 0; i < data_len; i += 2) { + reg_addr = reg_data[i]; + reg_val = reg_data[i + 1]; + + if (reg_addr == AW88166_DSPVCALB_REG) { + aw88166->vcalb_init_val = reg_val; + continue; + } + + if (reg_addr == AW88166_SYSCTRL_REG) { + if (reg_val & (~AW88166_DSPBY_MASK)) + aw_dev->dsp_cfg = AW88166_DEV_DSP_BYPASS; + else + aw_dev->dsp_cfg = AW88166_DEV_DSP_WORK; + + reg_val &= (AW88166_HMUTE_MASK | AW88166_PWDN_MASK | + AW88166_DSPBY_MASK); + reg_val |= (AW88166_HMUTE_ENABLE_VALUE | AW88166_PWDN_POWER_DOWN_VALUE | + AW88166_DSPBY_BYPASS_VALUE); + } + + if (reg_addr == AW88166_I2SCTRL3_REG) { + reg_val &= AW88166_I2STXEN_MASK; + reg_val |= AW88166_I2STXEN_DISABLE_VALUE; + } + + if (reg_addr == AW88166_SYSCTRL2_REG) { + read_vol = (reg_val & (~AW88166_VOL_MASK)) >> + AW88166_VOL_START_BIT; + aw_dev->volume_desc.init_volume = read_vol; + } + + if (reg_addr == AW88166_DBGCTRL_REG) { + if ((reg_val & (~AW88166_EF_DBMD_MASK)) == AW88166_EF_DBMD_OR_VALUE) + aw88166->check_val = AW_EF_OR_CHECK; + else + aw88166->check_val = AW_EF_AND_CHECK; + + aw88166->dither_st = reg_val & (~AW88166_DITHER_EN_MASK); + } + + if (reg_addr == AW88166_ACR1_REG) { + aw88166->re_init_val |= (uint32_t)reg_val << 16; + continue; + } + + if (reg_addr == AW88166_ACR2_REG) { + aw88166->re_init_val |= (uint32_t)reg_val; + continue; + } + + if (reg_addr == AW88166_CRCCTRL_REG) + aw88166->crc_init_val = reg_val; + + ret = regmap_write(aw_dev->regmap, reg_addr, reg_val); + if (ret) + return ret; + } + + aw_dev_pwd(aw_dev, false); + usleep_range(AW88166_1000_US, AW88166_1000_US + 10); + + if (aw_dev->prof_cur != aw_dev->prof_index) + vol_desc->ctl_volume = 0; + else + aw_dev_set_volume(aw_dev, vol_desc->ctl_volume); + + return 0; +} + +static int aw_dev_reg_update(struct aw88166 *aw88166, + unsigned char *data, unsigned int len) +{ + int ret; + + if (!len || !data) { + dev_err(aw88166->aw_pa->dev, "reg data is null or len is 0\n"); + return -EINVAL; + } + + ret = aw_dev_update_reg_container(aw88166, data, len); + if (ret) + dev_err(aw88166->aw_pa->dev, "reg update failed\n"); + + return ret; +} + +static int aw88166_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name) +{ + struct aw_prof_info *prof_info = &aw_dev->prof_info; + struct aw_prof_desc *prof_desc; + + if ((index >= aw_dev->prof_info.count) || (index < 0)) { + dev_err(aw_dev->dev, "index[%d] overflow count[%d]\n", + index, aw_dev->prof_info.count); + return -EINVAL; + } + + prof_desc = &aw_dev->prof_info.prof_desc[index]; + + *prof_name = prof_info->prof_name_list[prof_desc->id]; + + return 0; +} + +static int aw88166_dev_get_prof_data(struct aw_device *aw_dev, int index, + struct aw_prof_desc **prof_desc) +{ + if ((index >= aw_dev->prof_info.count) || (index < 0)) { + dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n", + __func__, index, aw_dev->prof_info.count); + return -EINVAL; + } + + *prof_desc = &aw_dev->prof_info.prof_desc[index]; + + return 0; +} + +static int aw88166_dev_fw_update(struct aw88166 *aw88166, bool up_dsp_fw_en, bool force_up_en) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + struct aw_prof_desc *prof_index_desc; + struct aw_sec_data_desc *sec_desc; + char *prof_name; + int ret; + + if ((aw_dev->prof_cur == aw_dev->prof_index) && + (force_up_en == AW88166_FORCE_UPDATE_OFF)) { + dev_dbg(aw_dev->dev, "scene no change, not update"); + return 0; + } + + if (aw_dev->fw_status == AW88166_DEV_FW_FAILED) { + dev_err(aw_dev->dev, "fw status[%d] error\n", aw_dev->fw_status); + return -EPERM; + } + + ret = aw88166_dev_get_prof_name(aw_dev, aw_dev->prof_index, &prof_name); + if (ret) + return ret; + + dev_dbg(aw_dev->dev, "start update %s", prof_name); + + ret = aw88166_dev_get_prof_data(aw_dev, aw_dev->prof_index, &prof_index_desc); + if (ret) + return ret; + + /* update reg */ + sec_desc = prof_index_desc->sec_desc; + ret = aw_dev_reg_update(aw88166, sec_desc[AW88395_DATA_TYPE_REG].data, + sec_desc[AW88395_DATA_TYPE_REG].len); + if (ret) { + dev_err(aw_dev->dev, "update reg failed\n"); + return ret; + } + + aw88166_dev_mute(aw_dev, true); + + if (aw_dev->dsp_cfg == AW88166_DEV_DSP_WORK) + aw_dev_dsp_enable(aw_dev, false); + + aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_OSC); + + ret = aw_dev_check_sram(aw_dev); + if (ret) { + dev_err(aw_dev->dev, "check sram failed\n"); + goto error; + } + + aw_dev_backup_sec_recovery(aw88166); + + if (up_dsp_fw_en) { + dev_dbg(aw_dev->dev, "fw_ver: [%x]", prof_index_desc->fw_ver); + ret = aw_dev_dsp_update_fw(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_FW].data, + sec_desc[AW88395_DATA_TYPE_DSP_FW].len); + if (ret) { + dev_err(aw_dev->dev, "update dsp fw failed\n"); + goto error; + } + } + + /* update dsp config */ + ret = aw_dev_dsp_update_cfg(aw_dev, sec_desc[AW88395_DATA_TYPE_DSP_CFG].data, + sec_desc[AW88395_DATA_TYPE_DSP_CFG].len); + if (ret) { + dev_err(aw_dev->dev, "update dsp cfg failed\n"); + goto error; + } + + aw_dev_backup_sec_record(aw88166); + + aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL); + + aw_dev->prof_cur = aw_dev->prof_index; + + return 0; + +error: + aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL); + return ret; +} + +static void aw88166_start_pa(struct aw88166 *aw88166) +{ + int ret, i; + + for (i = 0; i < AW88166_START_RETRIES; i++) { + ret = aw88166_dev_start(aw88166); + if (ret) { + dev_err(aw88166->aw_pa->dev, "aw88166 device start failed. retry = %d", i); + ret = aw88166_dev_fw_update(aw88166, AW88166_DSP_FW_UPDATE_ON, true); + if (ret) { + dev_err(aw88166->aw_pa->dev, "fw update failed"); + continue; + } + } else { + dev_dbg(aw88166->aw_pa->dev, "start success\n"); + break; + } + } +} + +static void aw88166_startup_work(struct work_struct *work) +{ + struct aw88166 *aw88166 = + container_of(work, struct aw88166, start_work.work); + + mutex_lock(&aw88166->lock); + aw88166_start_pa(aw88166); + mutex_unlock(&aw88166->lock); +} + +static void aw88166_start(struct aw88166 *aw88166, bool sync_start) +{ + int ret; + + if (aw88166->aw_pa->fw_status != AW88166_DEV_FW_OK) + return; + + if (aw88166->aw_pa->status == AW88166_DEV_PW_ON) + return; + + ret = aw88166_dev_fw_update(aw88166, AW88166_DSP_FW_UPDATE_OFF, aw88166->phase_sync); + if (ret) { + dev_err(aw88166->aw_pa->dev, "fw update failed\n"); + return; + } + + if (sync_start == AW88166_SYNC_START) + aw88166_start_pa(aw88166); + else + queue_delayed_work(system_wq, + &aw88166->start_work, + AW88166_START_WORK_DELAY_MS); +} + +static int aw_dev_check_sysint(struct aw_device *aw_dev) +{ + u16 reg_val; + + aw_dev_get_int_status(aw_dev, ®_val); + if (reg_val & AW88166_BIT_SYSINT_CHECK) { + dev_err(aw_dev->dev, "pa stop check fail:0x%04x\n", reg_val); + return -EINVAL; + } + + return 0; +} + +static int aw88166_stop(struct aw_device *aw_dev) +{ + struct aw_sec_data_desc *dsp_cfg = + &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_CFG]; + struct aw_sec_data_desc *dsp_fw = + &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_FW]; + int int_st; + + if (aw_dev->status == AW88166_DEV_PW_OFF) { + dev_dbg(aw_dev->dev, "already power off"); + return 0; + } + + aw_dev->status = AW88166_DEV_PW_OFF; + + aw88166_dev_mute(aw_dev, true); + usleep_range(AW88166_4000_US, AW88166_4000_US + 100); + + aw_dev_i2s_tx_enable(aw_dev, false); + usleep_range(AW88166_1000_US, AW88166_1000_US + 100); + + int_st = aw_dev_check_sysint(aw_dev); + + aw_dev_dsp_enable(aw_dev, false); + + aw_dev_amppd(aw_dev, true); + + if (int_st) { + aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_OSC); + aw_dev_dsp_update_fw(aw_dev, dsp_fw->data, dsp_fw->len); + aw_dev_dsp_update_cfg(aw_dev, dsp_cfg->data, dsp_cfg->len); + aw_dev_select_memclk(aw_dev, AW88166_DEV_MEMCLK_PLL); + } + + aw_dev_pwd(aw_dev, true); + + return 0; +} + +static struct snd_soc_dai_driver aw88166_dai[] = { + { + .name = "aw88166-aif", + .id = 1, + .playback = { + .stream_name = "Speaker_Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AW88166_RATES, + .formats = AW88166_FORMATS, + }, + .capture = { + .stream_name = "Speaker_Capture", + .channels_min = 1, + .channels_max = 2, + .rates = AW88166_RATES, + .formats = AW88166_FORMATS, + }, + }, +}; + +static int aw88166_get_fade_in_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + struct aw_device *aw_dev = aw88166->aw_pa; + + ucontrol->value.integer.value[0] = aw_dev->fade_in_time; + + return 0; +} + +static int aw88166_set_fade_in_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct aw_device *aw_dev = aw88166->aw_pa; + int time; + + time = ucontrol->value.integer.value[0]; + + if (time < mc->min || time > mc->max) + return -EINVAL; + + if (time != aw_dev->fade_in_time) { + aw_dev->fade_in_time = time; + return 1; + } + + return 0; +} + +static int aw88166_get_fade_out_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + struct aw_device *aw_dev = aw88166->aw_pa; + + ucontrol->value.integer.value[0] = aw_dev->fade_out_time; + + return 0; +} + +static int aw88166_set_fade_out_time(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct aw_device *aw_dev = aw88166->aw_pa; + int time; + + time = ucontrol->value.integer.value[0]; + if (time < mc->min || time > mc->max) + return -EINVAL; + + if (time != aw_dev->fade_out_time) { + aw_dev->fade_out_time = time; + return 1; + } + + return 0; +} + +static int aw88166_dev_set_profile_index(struct aw_device *aw_dev, int index) +{ + /* check the index whether is valid */ + if ((index >= aw_dev->prof_info.count) || (index < 0)) + return -EINVAL; + /* check the index whether change */ + if (aw_dev->prof_index == index) + return -EINVAL; + + aw_dev->prof_index = index; + dev_dbg(aw_dev->dev, "set prof[%s]", + aw_dev->prof_info.prof_name_list[aw_dev->prof_info.prof_desc[index].id]); + + return 0; +} + +static int aw88166_profile_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + char *prof_name, *name; + int count, ret; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + + count = aw88166->aw_pa->prof_info.count; + if (count <= 0) { + uinfo->value.enumerated.items = 0; + return 0; + } + + uinfo->value.enumerated.items = count; + + if (uinfo->value.enumerated.item >= count) + uinfo->value.enumerated.item = count - 1; + + name = uinfo->value.enumerated.name; + count = uinfo->value.enumerated.item; + + ret = aw88166_dev_get_prof_name(aw88166->aw_pa, count, &prof_name); + if (ret) { + strscpy(uinfo->value.enumerated.name, "null", + strlen("null") + 1); + return 0; + } + + strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name)); + + return 0; +} + +static int aw88166_profile_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = aw88166->aw_pa->prof_index; + + return 0; +} + +static int aw88166_profile_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + int ret; + + mutex_lock(&aw88166->lock); + ret = aw88166_dev_set_profile_index(aw88166->aw_pa, ucontrol->value.integer.value[0]); + if (ret) { + dev_dbg(codec->dev, "profile index does not change"); + mutex_unlock(&aw88166->lock); + return 0; + } + + if (aw88166->aw_pa->status) { + aw88166_stop(aw88166->aw_pa); + aw88166_start(aw88166, AW88166_SYNC_START); + } + + mutex_unlock(&aw88166->lock); + + return 1; +} + +static int aw88166_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + struct aw_volume_desc *vol_desc = &aw88166->aw_pa->volume_desc; + + ucontrol->value.integer.value[0] = vol_desc->ctl_volume; + + return 0; +} + +static int aw88166_volume_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + struct aw_volume_desc *vol_desc = &aw88166->aw_pa->volume_desc; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int value; + + value = ucontrol->value.integer.value[0]; + if (value < mc->min || value > mc->max) + return -EINVAL; + + if (vol_desc->ctl_volume != value) { + vol_desc->ctl_volume = value; + aw_dev_set_volume(aw88166->aw_pa, vol_desc->ctl_volume); + + return 1; + } + + return 0; +} + +static int aw88166_get_fade_step(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = aw88166->aw_pa->fade_step; + + return 0; +} + +static int aw88166_set_fade_step(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int value; + + value = ucontrol->value.integer.value[0]; + if (value < mc->min || value > mc->max) + return -EINVAL; + + if (aw88166->aw_pa->fade_step != value) { + aw88166->aw_pa->fade_step = value; + return 1; + } + + return 0; +} + +static int aw88166_re_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + struct aw_device *aw_dev = aw88166->aw_pa; + + ucontrol->value.integer.value[0] = aw_dev->cali_desc.cali_re; + + return 0; +} + +static int aw88166_re_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct aw_device *aw_dev = aw88166->aw_pa; + int value; + + value = ucontrol->value.integer.value[0]; + if (value < mc->min || value > mc->max) + return -EINVAL; + + if (aw_dev->cali_desc.cali_re != value) { + aw_dev->cali_desc.cali_re = value; + return 1; + } + + return 0; +} + +static int aw88166_dev_init(struct aw88166 *aw88166, struct aw_container *aw_cfg) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + int ret; + + ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); + if (ret) { + dev_err(aw_dev->dev, "aw_dev acf parse failed\n"); + return -EINVAL; + } + aw_dev->fade_in_time = AW88166_1000_US / 10; + aw_dev->fade_out_time = AW88166_1000_US >> 1; + aw_dev->prof_cur = aw_dev->prof_info.prof_desc[0].id; + aw_dev->prof_index = aw_dev->prof_info.prof_desc[0].id; + + ret = aw88166_dev_fw_update(aw88166, AW88166_FORCE_UPDATE_ON, AW88166_DSP_FW_UPDATE_ON); + if (ret) { + dev_err(aw_dev->dev, "fw update failed ret = %d\n", ret); + return ret; + } + + aw88166_dev_mute(aw_dev, true); + + /* close tx feedback */ + aw_dev_i2s_tx_enable(aw_dev, false); + usleep_range(AW88166_1000_US, AW88166_1000_US + 100); + + /* enable amppd */ + aw_dev_amppd(aw_dev, true); + + /* close dsp */ + aw_dev_dsp_enable(aw_dev, false); + /* set power down */ + aw_dev_pwd(aw_dev, true); + + return 0; +} + +static int aw88166_request_firmware_file(struct aw88166 *aw88166) +{ + const struct firmware *cont = NULL; + int ret; + + aw88166->aw_pa->fw_status = AW88166_DEV_FW_FAILED; + + ret = request_firmware(&cont, AW88166_ACF_FILE, aw88166->aw_pa->dev); + if (ret) { + dev_err(aw88166->aw_pa->dev, "request [%s] failed!\n", AW88166_ACF_FILE); + return ret; + } + + dev_dbg(aw88166->aw_pa->dev, "loaded %s - size: %zu\n", + AW88166_ACF_FILE, cont ? cont->size : 0); + + aw88166->aw_cfg = devm_kzalloc(aw88166->aw_pa->dev, + struct_size(aw88166->aw_cfg, data, cont->size), GFP_KERNEL); + if (!aw88166->aw_cfg) { + release_firmware(cont); + return -ENOMEM; + } + aw88166->aw_cfg->len = (int)cont->size; + memcpy(aw88166->aw_cfg->data, cont->data, cont->size); + release_firmware(cont); + + ret = aw88395_dev_load_acf_check(aw88166->aw_pa, aw88166->aw_cfg); + if (ret) { + dev_err(aw88166->aw_pa->dev, "load [%s] failed!\n", AW88166_ACF_FILE); + return ret; + } + + mutex_lock(&aw88166->lock); + /* aw device init */ + ret = aw88166_dev_init(aw88166, aw88166->aw_cfg); + if (ret) + dev_err(aw88166->aw_pa->dev, "dev init failed\n"); + mutex_unlock(&aw88166->lock); + + return ret; +} + +static const struct snd_kcontrol_new aw88166_controls[] = { + SOC_SINGLE_EXT("PCM Playback Volume", AW88166_SYSCTRL2_REG, + 6, AW88166_MUTE_VOL, 0, aw88166_volume_get, + aw88166_volume_set), + SOC_SINGLE_EXT("Fade Step", 0, 0, AW88166_MUTE_VOL, 0, + aw88166_get_fade_step, aw88166_set_fade_step), + SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, + aw88166_get_fade_in_time, aw88166_set_fade_in_time), + SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, + aw88166_get_fade_out_time, aw88166_set_fade_out_time), + SOC_SINGLE_EXT("Calib", 0, 0, AW88166_CALI_RE_MAX, 0, + aw88166_re_get, aw88166_re_set), + AW88166_PROFILE_EXT("AW88166 Profile Set", aw88166_profile_info, + aw88166_profile_get, aw88166_profile_set), +}; + +static int aw88166_playback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + + mutex_lock(&aw88166->lock); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + aw88166_start(aw88166, AW88166_ASYNC_START); + break; + case SND_SOC_DAPM_POST_PMD: + aw88166_stop(aw88166->aw_pa); + break; + default: + break; + } + mutex_unlock(&aw88166->lock); + + return 0; +} + +static const struct snd_soc_dapm_widget aw88166_dapm_widgets[] = { + /* playback */ + SND_SOC_DAPM_AIF_IN_E("AIF_RX", "Speaker_Playback", 0, SND_SOC_NOPM, 0, 0, + aw88166_playback_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUTPUT("DAC Output"), + + /* capture */ + SND_SOC_DAPM_AIF_OUT("AIF_TX", "Speaker_Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_INPUT("ADC Input"), +}; + +static const struct snd_soc_dapm_route aw88166_audio_map[] = { + {"DAC Output", NULL, "AIF_RX"}, + {"AIF_TX", NULL, "ADC Input"}, +}; + +static int aw88166_codec_probe(struct snd_soc_component *component) +{ + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(component); + int ret; + + INIT_DELAYED_WORK(&aw88166->start_work, aw88166_startup_work); + + ret = aw88166_request_firmware_file(aw88166); + if (ret) + dev_err(aw88166->aw_pa->dev, "%s failed\n", __func__); + + return ret; +} + +static void aw88166_codec_remove(struct snd_soc_component *aw_codec) +{ + struct aw88166 *aw88166 = snd_soc_component_get_drvdata(aw_codec); + + cancel_delayed_work_sync(&aw88166->start_work); +} + +static const struct snd_soc_component_driver soc_codec_dev_aw88166 = { + .probe = aw88166_codec_probe, + .remove = aw88166_codec_remove, + .dapm_widgets = aw88166_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aw88166_dapm_widgets), + .dapm_routes = aw88166_audio_map, + .num_dapm_routes = ARRAY_SIZE(aw88166_audio_map), + .controls = aw88166_controls, + .num_controls = ARRAY_SIZE(aw88166_controls), +}; + +static void aw88166_hw_reset(struct aw88166 *aw88166) +{ + if (aw88166->reset_gpio) { + gpiod_set_value_cansleep(aw88166->reset_gpio, 1); + usleep_range(AW88166_1000_US, AW88166_1000_US + 10); + gpiod_set_value_cansleep(aw88166->reset_gpio, 0); + usleep_range(AW88166_1000_US, AW88166_1000_US + 10); + } +} + +static void aw88166_parse_channel_dt(struct aw88166 *aw88166) +{ + struct aw_device *aw_dev = aw88166->aw_pa; + struct device_node *np = aw_dev->dev->of_node; + u32 channel_value; + + of_property_read_u32(np, "awinic,audio-channel", &channel_value); + aw_dev->channel = channel_value; + aw88166->phase_sync = of_property_read_bool(np, "awinic,sync-flag"); +} + +static int aw88166_init(struct aw88166 *aw88166, struct i2c_client *i2c, struct regmap *regmap) +{ + struct aw_device *aw_dev; + unsigned int chip_id; + int ret; + + ret = regmap_read(regmap, AW88166_ID_REG, &chip_id); + if (ret) { + dev_err(&i2c->dev, "%s read chipid error. ret = %d\n", __func__, ret); + return ret; + } + + aw_dev = devm_kzalloc(&i2c->dev, sizeof(*aw_dev), GFP_KERNEL); + if (!aw_dev) + return -ENOMEM; + aw88166->aw_pa = aw_dev; + + aw_dev->i2c = i2c; + aw_dev->dev = &i2c->dev; + aw_dev->regmap = regmap; + mutex_init(&aw_dev->dsp_lock); + + aw_dev->chip_id = chip_id; + aw_dev->acf = NULL; + aw_dev->prof_info.prof_desc = NULL; + aw_dev->prof_info.count = 0; + aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; + aw_dev->channel = AW88166_DEV_DEFAULT_CH; + aw_dev->fw_status = AW88166_DEV_FW_FAILED; + + aw_dev->fade_step = AW88166_VOLUME_STEP_DB; + aw_dev->volume_desc.ctl_volume = AW88166_VOL_DEFAULT_VALUE; + + aw88166_parse_channel_dt(aw88166); + + return 0; +} + +static int aw88166_i2c_probe(struct i2c_client *i2c) +{ + struct aw88166 *aw88166; + int ret; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) + return dev_err_probe(&i2c->dev, -ENXIO, "check_functionality failed\n"); + + aw88166 = devm_kzalloc(&i2c->dev, sizeof(*aw88166), GFP_KERNEL); + if (!aw88166) + return -ENOMEM; + + mutex_init(&aw88166->lock); + + i2c_set_clientdata(i2c, aw88166); + + aw88166->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(aw88166->reset_gpio)) + return dev_err_probe(&i2c->dev, PTR_ERR(aw88166->reset_gpio), + "reset gpio not defined\n"); + aw88166_hw_reset(aw88166); + + aw88166->regmap = devm_regmap_init_i2c(i2c, &aw88166_remap_config); + if (IS_ERR(aw88166->regmap)) + return dev_err_probe(&i2c->dev, PTR_ERR(aw88166->regmap), + "failed to init regmap\n"); + + /* aw pa init */ + ret = aw88166_init(aw88166, i2c, aw88166->regmap); + if (ret) + return ret; + + return devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_aw88166, + aw88166_dai, ARRAY_SIZE(aw88166_dai)); +} + +static const struct i2c_device_id aw88166_i2c_id[] = { + { AW88166_I2C_NAME }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aw88166_i2c_id); + +static struct i2c_driver aw88166_i2c_driver = { + .driver = { + .name = AW88166_I2C_NAME, + }, + .probe = aw88166_i2c_probe, + .id_table = aw88166_i2c_id, +}; +module_i2c_driver(aw88166_i2c_driver); + +MODULE_DESCRIPTION("ASoC AW88166 Smart PA Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/aw88166.h b/sound/soc/codecs/aw88166.h new file mode 100644 index 000000000000..3a53ba0ac625 --- /dev/null +++ b/sound/soc/codecs/aw88166.h @@ -0,0 +1,534 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// aw88166.h -- ALSA SoC AW88166 codec support +// +// Copyright (c) 2025 AWINIC Technology CO., LTD +// +// Author: Weidong Wang +// + +#ifndef __AW88166_H__ +#define __AW88166_H__ + +/* registers list */ +#define AW88166_ID_REG (0x00) +#define AW88166_SYSST_REG (0x01) +#define AW88166_SYSINT_REG (0x02) +#define AW88166_SYSINTM_REG (0x03) +#define AW88166_SYSCTRL_REG (0x04) +#define AW88166_SYSCTRL2_REG (0x05) +#define AW88166_I2SCTRL1_REG (0x06) +#define AW88166_I2SCTRL2_REG (0x07) +#define AW88166_I2SCTRL3_REG (0x08) +#define AW88166_DACCFG1_REG (0x09) +#define AW88166_DACCFG2_REG (0x0A) +#define AW88166_DACCFG3_REG (0x0B) +#define AW88166_DACCFG4_REG (0x0C) +#define AW88166_DACCFG5_REG (0x0D) +#define AW88166_DACCFG6_REG (0x0E) +#define AW88166_DACCFG7_REG (0x0F) +#define AW88166_MPDCFG1_REG (0x10) +#define AW88166_MPDCFG2_REG (0x11) +#define AW88166_MPDCFG3_REG (0x12) +#define AW88166_MPDCFG4_REG (0x13) +#define AW88166_PWMCTRL1_REG (0x14) +#define AW88166_PWMCTRL2_REG (0x15) +#define AW88166_PWMCTRL3_REG (0x16) +#define AW88166_I2SCFG1_REG (0x17) +#define AW88166_DBGCTRL_REG (0x18) +#define AW88166_HAGCST_REG (0x20) +#define AW88166_VBAT_REG (0x21) +#define AW88166_TEMP_REG (0x22) +#define AW88166_PVDD_REG (0x23) +#define AW88166_ISNDAT_REG (0x24) +#define AW88166_I2SINT_REG (0x25) +#define AW88166_I2SCAPCNT_REG (0x26) +#define AW88166_ANASTA1_REG (0x27) +#define AW88166_ANASTA2_REG (0x28) +#define AW88166_ANASTA3_REG (0x29) +#define AW88166_TESTDET_REG (0x2A) +#define AW88166_TESTIN_REG (0x38) +#define AW88166_TESTOUT_REG (0x39) +#define AW88166_MEMTEST_REG (0x3A) +#define AW88166_DSPMADD_REG (0x40) +#define AW88166_DSPMDAT_REG (0x41) +#define AW88166_WDT_REG (0x42) +#define AW88166_ACR1_REG (0x43) +#define AW88166_ACR2_REG (0x44) +#define AW88166_ASR1_REG (0x45) +#define AW88166_ASR2_REG (0x46) +#define AW88166_DSPCFG_REG (0x47) +#define AW88166_ASR3_REG (0x48) +#define AW88166_ASR4_REG (0x49) +#define AW88166_DSPVCALB_REG (0x4A) +#define AW88166_CRCCTRL_REG (0x4B) +#define AW88166_DSPDBG1_REG (0x4C) +#define AW88166_DSPDBG2_REG (0x4D) +#define AW88166_DSPDBG3_REG (0x4E) +#define AW88166_ISNCTRL1_REG (0x50) +#define AW88166_PLLCTRL1_REG (0x51) +#define AW88166_PLLCTRL2_REG (0x52) +#define AW88166_PLLCTRL3_REG (0x53) +#define AW88166_CDACTRL1_REG (0x54) +#define AW88166_CDACTRL2_REG (0x55) +#define AW88166_CDACTRL3_REG (0x56) +#define AW88166_SADCCTRL1_REG (0x57) +#define AW88166_SADCCTRL2_REG (0x58) +#define AW88166_BOPCTRL1_REG (0x59) +#define AW88166_BOPCTRL2_REG (0x5A) +#define AW88166_BOPCTRL3_REG (0x5B) +#define AW88166_BOPCTRL4_REG (0x5C) +#define AW88166_BOPCTRL5_REG (0x5D) +#define AW88166_BOPCTRL6_REG (0x5E) +#define AW88166_BOPCTRL7_REG (0x5F) +#define AW88166_BSTCTRL1_REG (0x60) +#define AW88166_BSTCTRL2_REG (0x61) +#define AW88166_BSTCTRL3_REG (0x62) +#define AW88166_BSTCTRL4_REG (0x63) +#define AW88166_BSTCTRL5_REG (0x64) +#define AW88166_BSTCTRL6_REG (0x65) +#define AW88166_DSMCFG1_REG (0x66) +#define AW88166_DSMCFG2_REG (0x67) +#define AW88166_DSMCFG3_REG (0x68) +#define AW88166_DSMCFG4_REG (0x69) +#define AW88166_DSMCFG5_REG (0x6A) +#define AW88166_DSMCFG6_REG (0x6B) +#define AW88166_DSMCFG7_REG (0x6C) +#define AW88166_DSMCFG8_REG (0x6D) +#define AW88166_TESTCTRL1_REG (0x70) +#define AW88166_TESTCTRL2_REG (0x71) +#define AW88166_EFCTRL1_REG (0x72) +#define AW88166_EFCTRL2_REG (0x73) +#define AW88166_EFWH_REG (0x74) +#define AW88166_EFWM2_REG (0x75) +#define AW88166_EFWM1_REG (0x76) +#define AW88166_EFRH_REG (0x77) +#define AW88166_EFRM2_REG (0x78) +#define AW88166_EFRM1_REG (0x79) +#define AW88166_EFRL_REG (0x7A) +#define AW88166_TM_REG (0x7C) +#define AW88166_TM2_REG (0x7D) + +#define AW88166_REG_MAX (0x7E) +#define AW88166_MUTE_VOL (1023) + +#define AW88166_DSP_CFG_ADDR (0x9B00) +#define AW88166_DSP_REG_CFG_ADPZ_RA (0x9B68) +#define AW88166_DSP_FW_ADDR (0x8980) +#define AW88166_DSP_ROM_CHECK_ADDR (0x1F40) + +#define AW88166_CALI_RE_HBITS_MASK (~(0xFFFF0000)) +#define AW88166_CALI_RE_HBITS_SHIFT (16) + +#define AW88166_CALI_RE_LBITS_MASK (~(0xFFFF)) +#define AW88166_CALI_RE_LBITS_SHIFT (0) + +#define AW88166_I2STXEN_START_BIT (9) +#define AW88166_I2STXEN_BITS_LEN (1) +#define AW88166_I2STXEN_MASK \ + (~(((1<> (shift)) +#define AW88166_SHOW_RE_TO_DSP_RE(re, shift) (((re) << shift) / (1000)) + +#define AW88166_DSP_ODD_NUM_BIT_TEST (0x5555) +#define AW88166_DSP_ROM_CHECK_DATA (0xFF99) + +#define AW88166_DEV_DEFAULT_CH (0) +#define AW88166_DEV_DSP_CHECK_MAX (5) +#define AW88166_MAX_RAM_WRITE_BYTE_SIZE (128) +#define AW_FW_ADDR_LEN (4) +#define AW88166_CRC_CHECK_PASS_VAL (0x4) +#define AW88166_CRC_CFG_BASE_ADDR (0xD80) +#define AW88166_CRC_FW_BASE_ADDR (0x4C0) +#define AW88166_DEV_SYSST_CHECK_MAX (10) +#define AW88166_START_RETRIES (5) +#define AW88166_START_WORK_DELAY_MS (0) +#define FADE_TIME_MAX 100000 +#define FADE_TIME_MIN 0 +#define AW88166_CHIP_ID (0x2066) +#define AW88166_I2C_NAME "aw88166" +#define AW88166_ACF_FILE "aw88166_acf.bin" + +#define AW88166_RATES (SNDRV_PCM_RATE_8000_48000 | \ + SNDRV_PCM_RATE_96000) +#define AW88166_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define AW88166_PROFILE_EXT(xname, profile_info, profile_get, profile_set) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .info = profile_info, \ + .get = profile_get, \ + .put = profile_set, \ +} + +enum { + AW_EF_AND_CHECK = 0, + AW_EF_OR_CHECK, +}; + +enum { + AW88166_DSP_FW_UPDATE_OFF = 0, + AW88166_DSP_FW_UPDATE_ON = 1, +}; + +enum { + AW88166_FORCE_UPDATE_OFF = 0, + AW88166_FORCE_UPDATE_ON = 1, +}; + +enum { + AW88166_1000_US = 1000, + AW88166_2000_US = 2000, + AW88166_3000_US = 3000, + AW88166_4000_US = 4000, +}; + +enum AW88166_DEV_STATUS { + AW88166_DEV_PW_OFF = 0, + AW88166_DEV_PW_ON, +}; + +enum AW88166_DEV_FW_STATUS { + AW88166_DEV_FW_FAILED = 0, + AW88166_DEV_FW_OK, +}; + +enum AW88166_DEV_MEMCLK { + AW88166_DEV_MEMCLK_OSC = 0, + AW88166_DEV_MEMCLK_PLL = 1, +}; + +enum AW88166_DEV_DSP_CFG { + AW88166_DEV_DSP_WORK = 0, + AW88166_DEV_DSP_BYPASS = 1, +}; + +enum { + AW88166_DSP_16_DATA = 0, + AW88166_DSP_32_DATA = 1, +}; + +enum { + AW88166_SYNC_START = 0, + AW88166_ASYNC_START, +}; + +enum { + AW88166_RECORD_SEC_DATA = 0, + AW88166_RECOVERY_SEC_DATA = 1, +}; + +#endif From 3fec903f2cb18805b1ef22a0e310498020c1f15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:15 -0300 Subject: [PATCH 0944/1090] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a mediatek,accdet phandle property to allow getting a reference to the MT6359 ACCDET block, which is responsible for detecting jack insertion/removal. Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Rob Herring (Arm) Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-1-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml index 8c77e7f68ad7..76d5a437dc8f 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml @@ -40,6 +40,14 @@ properties: hardware that provides additional audio functionalities if present. The AFE will link to ADSP when the phandle is provided. + mediatek,accdet: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The phandle to the MT6359 accessory detection block, which detects audio + jack insertion and removal. This property should only be present if the + accdet block is actually wired to the audio jack pins and to be used for + jack detection. + patternProperties: "^dai-link-[0-9]+$": type: object From cf536e2622e2b0a60c99e799995b6e9acf539c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:16 -0300 Subject: [PATCH 0945/1090] ASoC: mediatek: common: Handle mediatek,accdet property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle the optional mediatek,accdet property. When present, retrieve the sound component from its phandle, so the machine sound driver can use it to register the audio jack and initialize the MT6359 ACCDET for jack detection. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-2-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soc-card.h | 1 + .../mediatek/common/mtk-soundcard-driver.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h index 3f6e24dd22df..a1d2794ac1f7 100644 --- a/sound/soc/mediatek/common/mtk-soc-card.h +++ b/sound/soc/mediatek/common/mtk-soc-card.h @@ -16,6 +16,7 @@ struct mtk_soc_card_data { const struct mtk_sof_priv *sof_priv; struct list_head sof_dai_link_list; struct mtk_platform_card_data *card_data; + struct snd_soc_component *accdet; void *mach_priv; }; diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index f4314dddc460..713a368f79cf 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -8,6 +8,7 @@ #include #include +#include #include #include "mtk-dsp-sof-common.h" @@ -192,7 +193,9 @@ EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops); int mtk_soundcard_common_probe(struct platform_device *pdev) { - struct device_node *platform_node, *adsp_node; + struct device_node *platform_node, *adsp_node, *accdet_node; + struct snd_soc_component *accdet_comp; + struct platform_device *accdet_pdev; const struct mtk_soundcard_pdata *pdata; struct mtk_soc_card_data *soc_card_data; struct snd_soc_dai_link *orig_dai_link, *dai_link; @@ -250,6 +253,20 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) soc_card_data->card_data->jacks = jacks; + accdet_node = of_parse_phandle(pdev->dev.of_node, "mediatek,accdet", 0); + if (accdet_node) { + accdet_pdev = of_find_device_by_node(accdet_node); + if (accdet_pdev) { + accdet_comp = snd_soc_lookup_component(&accdet_pdev->dev, NULL); + if (accdet_comp) + soc_card_data->accdet = accdet_comp; + else + dev_err(&pdev->dev, "No sound component found from mediatek,accdet property\n"); + } else { + dev_err(&pdev->dev, "No device found from mediatek,accdet property\n"); + } + } + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); if (!platform_node) return dev_err_probe(&pdev->dev, -EINVAL, From 0116a7d84b32537a10d9bea1fd1bfc06577ef527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:17 -0300 Subject: [PATCH 0946/1090] ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker failures in the machine sound drivers calling it when CONFIG_SND_SOC_MT6359_ACCDET is not enabled. Suggested-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359-accdet.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h index c234f2f4276a..78ada3a5bfae 100644 --- a/sound/soc/codecs/mt6359-accdet.h +++ b/sound/soc/codecs/mt6359-accdet.h @@ -123,6 +123,15 @@ struct mt6359_accdet { struct workqueue_struct *jd_workqueue; }; +#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET) int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *jack); +#else +static inline int +mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack) +{ + return -EOPNOTSUPP; +} +#endif #endif From f35d834d67adbbf121ee4397376d9eac21d99a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:18 -0300 Subject: [PATCH 0947/1090] ASoC: mediatek: mt8188-mt6359: Add accdet headset jack detect support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable headset jack detection for MT8188 platforms that use the MT6359 ACCDET block for it, indicated by the mediatek,accdet property in DT. For those platforms, register a jack and initialize the ACCDET block to report jack events through it. Co-developed-by: Zoran Zhan Signed-off-by: Zoran Zhan Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-4-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-mt6359.c | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index 420b1427b71d..20dc9470ba76 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -17,6 +17,7 @@ #include "mt8188-afe-common.h" #include "../../codecs/nau8825.h" #include "../../codecs/mt6359.h" +#include "../../codecs/mt6359-accdet.h" #include "../../codecs/rt5682.h" #include "../common/mtk-afe-platform-driver.h" #include "../common/mtk-soundcard-driver.h" @@ -271,6 +272,17 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = { }, }; +static struct snd_soc_jack_pin mt8188_headset_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Ext Spk"), }; @@ -506,6 +518,35 @@ static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) return 0; } +static int mt8188_mt6359_accdet_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET]; + int ret; + + if (!soc_card_data->accdet) + return 0; + + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + jack, mt8188_headset_jack_pins, + ARRAY_SIZE(mt8188_headset_jack_pins)); + if (ret) { + dev_err(rtd->dev, "Headset Jack create failed: %d\n", ret); + return ret; + } + + ret = mt6359_accdet_enable_jack_detect(soc_card_data->accdet, jack); + if (ret) { + dev_err(rtd->dev, "Headset Jack enable failed: %d\n", ret); + return ret; + } + + return 0; +} + static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *cmpnt_codec = @@ -518,6 +559,8 @@ static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd) /* mtkaif calibration */ mt8188_mt6359_mtkaif_calibration(rtd); + mt8188_mt6359_accdet_init(rtd); + return 0; } From 98dba9dab5d9af3c25e61a5d751bc943fec3f918 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Mar 2025 14:31:50 +0100 Subject: [PATCH 0948/1090] ASoC: pcm1681: Drop unused include This driver includes the legacy GPIO header but does not use any symbols from it so drop the include. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250312-pcm-codecs-v1-1-41ffc4f8fc5c@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/pcm1681.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index fc152496d5dc..a1ec881d7084 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include From ef5aa8bd22372dd67b7fe19613b86181cd765af8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Mar 2025 14:31:51 +0100 Subject: [PATCH 0949/1090] ASoC: pcm3008: Convert to GPIO descriptors This converts the PCM3008 driver to look up the GPIO lines using descriptors. Apparently there are no in-tree users of the platform data struct, so users need to adopt. New users can associate the GPIO lines with the platform device "pcm3008-codec". Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250312-pcm-codecs-v1-2-41ffc4f8fc5c@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3008.c | 61 ++++++++++++++++++++------------------ sound/soc/codecs/pcm3008.h | 19 ------------ 2 files changed, 32 insertions(+), 48 deletions(-) delete mode 100644 sound/soc/codecs/pcm3008.h diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 09c6c1326833..d3d2e7f40170 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -22,17 +22,22 @@ #include #include -#include "pcm3008.h" +struct pcm3008 { + struct gpio_desc *dem0_pin; + struct gpio_desc *dem1_pin; + struct gpio_desc *pdad_pin; + struct gpio_desc *pdda_pin; +}; static int pcm3008_dac_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct pcm3008_setup_data *setup = component->dev->platform_data; + struct pcm3008 *pcm = component->dev->platform_data; - gpio_set_value_cansleep(setup->pdda_pin, - SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value_cansleep(pcm->pdda_pin, + SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -42,10 +47,10 @@ static int pcm3008_adc_ev(struct snd_soc_dapm_widget *w, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct pcm3008_setup_data *setup = component->dev->platform_data; + struct pcm3008 *pcm = component->dev->platform_data; - gpio_set_value_cansleep(setup->pdad_pin, - SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value_cansleep(pcm->pdad_pin, + SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -106,11 +111,13 @@ static const struct snd_soc_component_driver soc_component_dev_pcm3008 = { static int pcm3008_codec_probe(struct platform_device *pdev) { - struct pcm3008_setup_data *setup = pdev->dev.platform_data; - int ret; + struct device *dev = &pdev->dev; + struct pcm3008 *pcm; - if (!setup) - return -EINVAL; + pcm = devm_kzalloc(dev, sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + platform_set_drvdata(pdev, pcm); /* DEM1 DEM0 DE-EMPHASIS_MODE * Low Low De-emphasis 44.1 kHz ON @@ -120,30 +127,26 @@ static int pcm3008_codec_probe(struct platform_device *pdev) */ /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ - ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin, - GPIOF_OUT_INIT_HIGH, "codec_dem0"); - if (ret != 0) - return ret; + pcm->dem0_pin = devm_gpiod_get(dev, "dem0", GPIOD_OUT_HIGH); + if (IS_ERR(pcm->dem0_pin)) + return PTR_ERR(pcm->dem0_pin); /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ - ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin, - GPIOF_OUT_INIT_LOW, "codec_dem1"); - if (ret != 0) - return ret; + pcm->dem1_pin = devm_gpiod_get(dev, "dem1", GPIOD_OUT_LOW); + if (IS_ERR(pcm->dem1_pin)) + return PTR_ERR(pcm->dem1_pin); /* Configure PDAD GPIO. */ - ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin, - GPIOF_OUT_INIT_LOW, "codec_pdad"); - if (ret != 0) - return ret; + pcm->pdad_pin = devm_gpiod_get(dev, "pdad", GPIOD_OUT_LOW); + if (IS_ERR(pcm->pdad_pin)) + return PTR_ERR(pcm->pdad_pin); /* Configure PDDA GPIO. */ - ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin, - GPIOF_OUT_INIT_LOW, "codec_pdda"); - if (ret != 0) - return ret; + pcm->pdda_pin = devm_gpiod_get(dev, "pdda", GPIOD_OUT_LOW); + if (IS_ERR(pcm->pdda_pin)) + return PTR_ERR(pcm->pdda_pin); - return devm_snd_soc_register_component(&pdev->dev, + return devm_snd_soc_register_component(dev, &soc_component_dev_pcm3008, &pcm3008_dai, 1); } diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h deleted file mode 100644 index f7f4fbbd89db..000000000000 --- a/sound/soc/codecs/pcm3008.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * PCM3008 ALSA SoC Layer - * - * Author: Hugo Villeneuve - * Copyright (C) 2008 Lyrtech inc - */ - -#ifndef __LINUX_SND_SOC_PCM3008_H -#define __LINUX_SND_SOC_PCM3008_H - -struct pcm3008_setup_data { - unsigned dem0_pin; - unsigned dem1_pin; - unsigned pdad_pin; - unsigned pdda_pin; -}; - -#endif From 17fdf318f5fbe5c27353ae917c0c5a2899d9c259 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Mar 2025 14:31:52 +0100 Subject: [PATCH 0950/1090] ASoC: pcm6240: Drop bogus code handling IRQ as GPIO The current code for the IRQ in pcm6240 makes no sense: it looks up an IRQ with of_irq_get(), treat it as a GPIO by issuing gpio_request(), gpio_direction_input() and gpio_to_irq() on it. This is just wrong, if the device tree assigns the IRQ from a GPIO number this is just incorrect: it is clearly stated that GPIO providers and IRQ providers are orthogonal. It is possible to look up an IRQ to a corresponding GPIO line but this is taking an IRQ and pretending it's a GPIO, which is just semantically wrong. Drop the offending code and treat the IRQ that we get from the device tree as any other IRQ, see for example other codec drivers. The DT bindings for this codec does not have any in-tree DTS files, which may explain why things are weird. As a bonus, this moves the driver away from the legacy include. Signed-off-by: Linus Walleij Link: https://patch.msgid.link/20250312-pcm-codecs-v1-3-41ffc4f8fc5c@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/pcm6240.c | 28 +++++++--------------------- sound/soc/codecs/pcm6240.h | 7 +------ 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c index 4ff39e0b95b2..b2bd2f172ae7 100644 --- a/sound/soc/codecs/pcm6240.c +++ b/sound/soc/codecs/pcm6240.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -2035,10 +2035,8 @@ static const struct regmap_config pcmdevice_i2c_regmap = { static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev) { - if (gpio_is_valid(pcm_dev->irq_info.gpio)) { - gpio_free(pcm_dev->irq_info.gpio); - free_irq(pcm_dev->irq_info.nmb, pcm_dev); - } + if (pcm_dev->irq) + free_irq(pcm_dev->irq, pcm_dev); mutex_destroy(&pcm_dev->codec_lock); } @@ -2109,7 +2107,7 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) ndev = 1; dev_addrs[0] = i2c->addr; } - pcm_dev->irq_info.gpio = of_irq_get(np, 0); + pcm_dev->irq = of_irq_get(np, 0); for (i = 0; i < ndev; i++) pcm_dev->addr[i] = dev_addrs[i]; @@ -2132,22 +2130,10 @@ static int pcmdevice_i2c_probe(struct i2c_client *i2c) if (pcm_dev->chip_id == PCM1690) goto skip_interrupt; - if (gpio_is_valid(pcm_dev->irq_info.gpio)) { - dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio); - - ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ"); - if (!ret) { - int gpio = pcm_dev->irq_info.gpio; - - gpio_direction_input(gpio); - pcm_dev->irq_info.nmb = gpio_to_irq(gpio); - - } else - dev_err(pcm_dev->dev, "%s: GPIO %d request error\n", - __func__, pcm_dev->irq_info.gpio); + if (pcm_dev->irq) { + dev_dbg(pcm_dev->dev, "irq = %d", pcm_dev->irq); } else - dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n", - pcm_dev->irq_info.gpio); + dev_err(pcm_dev->dev, "No irq provided\n"); skip_interrupt: ret = devm_snd_soc_register_component(&i2c->dev, diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h index 1e125bb97286..2d8f9e798139 100644 --- a/sound/soc/codecs/pcm6240.h +++ b/sound/soc/codecs/pcm6240.h @@ -208,11 +208,6 @@ struct pcmdevice_regbin { struct pcmdevice_config_info **cfg_info; }; -struct pcmdevice_irqinfo { - int gpio; - int nmb; -}; - struct pcmdevice_priv { struct snd_soc_component *component; struct i2c_client *client; @@ -221,7 +216,7 @@ struct pcmdevice_priv { struct gpio_desc *hw_rst; struct regmap *regmap; struct pcmdevice_regbin regbin; - struct pcmdevice_irqinfo irq_info; + int irq; unsigned int addr[PCMDEVICE_MAX_I2C_DEVICES]; unsigned int chip_id; int cur_conf; From 988adcb73669a4015974da9057d43226ddc1aa9d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:00 +0000 Subject: [PATCH 0951/1090] ASoC: SDCA: Tidy up initialization write parsing Slightly neaten up the initialization write code to overlay a struct rather than shifting the pointer along manually. This also removes the Sparse warning: sound/soc/sdca/sdca_functions.c:233:36: warning: cast to restricted __le32 Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_functions.c | 47 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 091d55abe109..133cbde17ef4 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -186,14 +187,18 @@ void sdca_lookup_functions(struct sdw_slave *slave) } EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA"); +struct raw_init_write { + __le32 addr; + u8 val; +} __packed; + static int find_sdca_init_table(struct device *dev, struct fwnode_handle *function_node, struct sdca_function_data *function) { + struct raw_init_write *raw __free(kfree) = NULL; struct sdca_init_write *init_write; - int write_size = sizeof(init_write->addr) + sizeof(init_write->val); - u8 *init_list, *init_iter; - int num_init_writes; + int i, num_init_writes; num_init_writes = fwnode_property_count_u8(function_node, "mipi-sdca-function-initialization-table"); @@ -203,7 +208,7 @@ static int find_sdca_init_table(struct device *dev, dev_err(dev, "%pfwP: failed to read initialization table: %d\n", function_node, num_init_writes); return num_init_writes; - } else if (num_init_writes % write_size != 0) { + } else if (num_init_writes % sizeof(*raw) != 0) { dev_err(dev, "%pfwP: init table size invalid\n", function_node); return -EINVAL; } else if (num_init_writes > SDCA_MAX_INIT_COUNT) { @@ -211,34 +216,28 @@ static int find_sdca_init_table(struct device *dev, return -EINVAL; } - init_write = devm_kcalloc(dev, num_init_writes / write_size, - sizeof(*init_write), GFP_KERNEL); - if (!init_write) - return -ENOMEM; - - init_list = kcalloc(num_init_writes, sizeof(*init_list), GFP_KERNEL); - if (!init_list) + raw = kzalloc(num_init_writes, GFP_KERNEL); + if (!raw) return -ENOMEM; fwnode_property_read_u8_array(function_node, "mipi-sdca-function-initialization-table", - init_list, num_init_writes); + (u8 *)raw, num_init_writes); + + num_init_writes /= sizeof(*raw); + + init_write = devm_kcalloc(dev, num_init_writes, sizeof(*init_write), GFP_KERNEL); + if (!init_write) + return -ENOMEM; + + for (i = 0; i < num_init_writes; i++) { + init_write[i].addr = le32_to_cpu(raw[i].addr); + init_write[i].val = raw[i].val; + } function->num_init_table = num_init_writes; function->init_table = init_write; - for (init_iter = init_list; init_iter < init_list + num_init_writes;) { - u32 *addr = (u32 *)init_iter; - - init_write->addr = le32_to_cpu(*addr); - init_iter += sizeof(init_write->addr); - - init_write->val = *init_iter; - init_iter += sizeof(init_write->val); - } - - kfree(init_list); - return 0; } From 0d16daa9405ef7de5c278183d4079013f39a51ac Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:01 +0000 Subject: [PATCH 0952/1090] ASoC: SDCA: Use __free() to manage local buffers Use the cleanup.h helpers to manage some local buffers, this cleans up the error paths a little. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_functions.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 133cbde17ef4..4ee98d8fe89e 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -913,9 +913,9 @@ static int find_sdca_entity_pde(struct device *dev, { static const int mult_delay = 3; struct sdca_entity_pde *power = &entity->pde; + u32 *delay_list __free(kfree) = NULL; struct sdca_pde_delay *delays; int num_delays; - u32 *delay_list; int i, j; num_delays = fwnode_property_count_u32(entity_node, @@ -962,8 +962,6 @@ static int find_sdca_entity_pde(struct device *dev, power->num_max_delay = num_delays; power->max_delay = delays; - kfree(delay_list); - return 0; } @@ -1022,8 +1020,8 @@ static int find_sdca_entities(struct device *dev, struct fwnode_handle *function_node, struct sdca_function_data *function) { + u32 *entity_list __free(kfree) = NULL; struct sdca_entity *entities; - u32 *entity_list; int num_entities; int i, ret; @@ -1054,8 +1052,6 @@ static int find_sdca_entities(struct device *dev, for (i = 0; i < num_entities; i++) entities[i].id = entity_list[i]; - kfree(entity_list); - /* now read subproperties */ for (i = 0; i < num_entities; i++) { char entity_property[SDCA_PROPERTY_LENGTH]; @@ -1170,8 +1166,8 @@ static int find_sdca_entity_connection_pde(struct device *dev, struct sdca_entity *entity) { struct sdca_entity_pde *power = &entity->pde; + u32 *managed_list __free(kfree) = NULL; struct sdca_entity **managed; - u32 *managed_list; int num_managed; int i; @@ -1205,15 +1201,12 @@ static int find_sdca_entity_connection_pde(struct device *dev, if (!managed[i]) { dev_err(dev, "%s: failed to find entity with id %#x\n", entity->label, managed_list[i]); - kfree(managed_list); return -EINVAL; } dev_info(dev, "%s -> %s\n", managed[i]->label, entity->label); } - kfree(managed_list); - power->num_managed = num_managed; power->managed = managed; @@ -1453,9 +1446,9 @@ static int find_sdca_clusters(struct device *dev, struct fwnode_handle *function_node, struct sdca_function_data *function) { + u32 *cluster_list __free(kfree) = NULL; struct sdca_cluster *clusters; int num_clusters; - u32 *cluster_list; int i, ret; num_clusters = fwnode_property_count_u32(function_node, "mipi-sdca-cluster-id-list"); @@ -1484,8 +1477,6 @@ static int find_sdca_clusters(struct device *dev, for (i = 0; i < num_clusters; i++) clusters[i].id = cluster_list[i]; - kfree(cluster_list); - /* now read subproperties */ for (i = 0; i < num_clusters; i++) { char cluster_property[SDCA_PROPERTY_LENGTH]; From 49680c9f13b64c13e79e1312c7616d0ab9775e4a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:02 +0000 Subject: [PATCH 0953/1090] ASoC: SDCA: Allow naming of imp def controls Implementation defined controls will not be present in the large list of known controls for SDCA. The driver should not return an error for these, because it is perfectly legal to have implementation defined controls. Update the handling to instead generate a generic name. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_functions.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 4ee98d8fe89e..1e36dd20d7ab 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -241,7 +241,8 @@ static int find_sdca_init_table(struct device *dev, return 0; } -static const char *find_sdca_control_label(const struct sdca_entity *entity, +static const char *find_sdca_control_label(struct device *dev, + const struct sdca_entity *entity, const struct sdca_control *control) { switch (SDCA_CTL_TYPE(entity->type, control->sel)) { @@ -530,7 +531,7 @@ static const char *find_sdca_control_label(const struct sdca_entity *entity, case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_SDCA_VERSION): return SDCA_CTL_DEVICE_SDCA_VERSION_NAME; default: - return NULL; + return devm_kasprintf(dev, GFP_KERNEL, "Imp-Def %#x", control->sel); } } @@ -739,12 +740,9 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti if (!ret) control->interrupt_position = tmp; - control->label = find_sdca_control_label(entity, control); - if (!control->label) { - dev_err(dev, "%s: control %#x: name not found\n", - entity->label, control->sel); - return -EINVAL; - } + control->label = find_sdca_control_label(dev, entity, control); + if (!control->label) + return -ENOMEM; control->nbits = find_sdca_control_bits(entity, control); From 2a4667f3d589524bd2fbfe4f7dc0e2f12b832e10 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:03 +0000 Subject: [PATCH 0954/1090] ASoC: SDCA: Add type flag for Controls SDCA Controls come in a variety of data formats, to simplify later parsing work out this data type as the control is parsed and stash it for later use. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 23 +++++ sound/soc/sdca/sdca_functions.c | 173 ++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index f001ab643fed..ca0376903e87 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -600,6 +600,27 @@ enum sdca_entity0_controls { #define SDCA_CTL_DEVICE_VERSION_NAME "Device Version" #define SDCA_CTL_DEVICE_SDCA_VERSION_NAME "Device SDCA Version" +/** + * enum sdca_control_datatype - SDCA Control Data Types + * + * Data Types as described in the SDCA specification v1.0 section + * 7.3. + */ +enum sdca_control_datatype { + SDCA_CTL_DATATYPE_ONEBIT, + SDCA_CTL_DATATYPE_INTEGER, + SDCA_CTL_DATATYPE_SPEC_ENCODED_VALUE, + SDCA_CTL_DATATYPE_BCD, + SDCA_CTL_DATATYPE_Q7P8DB, + SDCA_CTL_DATATYPE_BYTEINDEX, + SDCA_CTL_DATATYPE_POSTURENUMBER, + SDCA_CTL_DATATYPE_DP_INDEX, + SDCA_CTL_DATATYPE_BITINDEX, + SDCA_CTL_DATATYPE_BITMAP, + SDCA_CTL_DATATYPE_GUID, + SDCA_CTL_DATATYPE_IMPDEF, +}; + /** * enum sdca_access_mode - SDCA Control access mode * @@ -653,6 +674,7 @@ struct sdca_control_range { * @cn_list: A bitmask showing the valid Control Numbers within this Control, * Control Numbers typically represent channels. * @range: Buffer describing valid range of values for the Control. + * @type: Format of the data in the Control. * @mode: Access mode of the Control. * @layers: Bitmask of access layers of the Control. * @deferrable: Indicates if the access to the Control can be deferred. @@ -669,6 +691,7 @@ struct sdca_control { u64 cn_list; struct sdca_control_range range; + enum sdca_control_datatype type; enum sdca_access_mode mode; u8 layers; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 1e36dd20d7ab..0cc25fb9679b 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -603,6 +603,178 @@ static unsigned int find_sdca_control_bits(const struct sdca_entity *entity, } } +static enum sdca_control_datatype +find_sdca_control_datatype(const struct sdca_entity *entity, + const struct sdca_control *control) +{ + switch (SDCA_CTL_TYPE(entity->type, control->sel)) { + case SDCA_CTL_TYPE_S(XU, BYPASS): + case SDCA_CTL_TYPE_S(MFPU, BYPASS): + case SDCA_CTL_TYPE_S(FU, MUTE): + case SDCA_CTL_TYPE_S(FU, AGC): + case SDCA_CTL_TYPE_S(FU, BASS_BOOST): + case SDCA_CTL_TYPE_S(FU, LOUDNESS): + return SDCA_CTL_DATATYPE_ONEBIT; + case SDCA_CTL_TYPE_S(IT, LATENCY): + case SDCA_CTL_TYPE_S(OT, LATENCY): + case SDCA_CTL_TYPE_S(MU, LATENCY): + case SDCA_CTL_TYPE_S(SU, LATENCY): + case SDCA_CTL_TYPE_S(FU, LATENCY): + case SDCA_CTL_TYPE_S(XU, LATENCY): + case SDCA_CTL_TYPE_S(CRU, LATENCY): + case SDCA_CTL_TYPE_S(UDMPU, LATENCY): + case SDCA_CTL_TYPE_S(MFPU, LATENCY): + case SDCA_CTL_TYPE_S(SMPU, LATENCY): + case SDCA_CTL_TYPE_S(SAPU, LATENCY): + case SDCA_CTL_TYPE_S(PPU, LATENCY): + case SDCA_CTL_TYPE_S(SU, SELECTOR): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_0): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_1): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_2): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_3): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_4): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_5): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_6): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_7): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_8): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_9): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_10): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_11): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_12): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_13): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_14): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_15): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_16): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_17): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_18): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_19): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_20): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_21): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_22): + case SDCA_CTL_TYPE_S(UDMPU, OPAQUESET_23): + case SDCA_CTL_TYPE_S(SAPU, PROTECTION_MODE): + case SDCA_CTL_TYPE_S(SMPU, HIST_BUFFER_PREAMBLE): + case SDCA_CTL_TYPE_S(XU, FDL_HOST_REQUEST): + case SDCA_CTL_TYPE_S(XU, XU_ID): + case SDCA_CTL_TYPE_S(CX, CLOCK_SELECT): + case SDCA_CTL_TYPE_S(TG, TONE_DIVIDER): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_MANUFACTURER_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_EXTENSION_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_MANUFACTURER_ID): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_PART_ID): + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(XU, FDL_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SPE, AUTHTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SPE, AUTHRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(MFPU, AE_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, HIST_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, DTODTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SMPU, DTODRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SAPU, DTODTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(SAPU, DTODRX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(HIDE, HIDTX_MESSAGELENGTH): + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGEOFFSET): + case SDCA_CTL_TYPE_S(HIDE, HIDRX_MESSAGELENGTH): + return SDCA_CTL_DATATYPE_INTEGER; + case SDCA_CTL_TYPE_S(IT, MIC_BIAS): + case SDCA_CTL_TYPE_S(SMPU, HIST_BUFFER_MODE): + case SDCA_CTL_TYPE_S(PDE, REQUESTED_PS): + case SDCA_CTL_TYPE_S(PDE, ACTUAL_PS): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_TYPE): + return SDCA_CTL_DATATYPE_SPEC_ENCODED_VALUE; + case SDCA_CTL_TYPE_S(XU, XU_VERSION): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_SDCA_VERSION): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_VERSION): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_EXTENSION_VERSION): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_VERSION): + case SDCA_CTL_TYPE_S(ENTITY_0, DEVICE_SDCA_VERSION): + return SDCA_CTL_DATATYPE_BCD; + case SDCA_CTL_TYPE_S(FU, CHANNEL_VOLUME): + case SDCA_CTL_TYPE_S(FU, GAIN): + case SDCA_CTL_TYPE_S(MU, MIXER): + case SDCA_CTL_TYPE_S(PPU, HORIZONTALBALANCE): + case SDCA_CTL_TYPE_S(PPU, VERTICALBALANCE): + case SDCA_CTL_TYPE_S(MFPU, ULTRASOUND_LEVEL): + case SDCA_CTL_TYPE_S(UDMPU, ACOUSTIC_ENERGY_LEVEL_MONITOR): + case SDCA_CTL_TYPE_S(UDMPU, ULTRASOUND_LOOP_GAIN): + return SDCA_CTL_DATATYPE_Q7P8DB; + case SDCA_CTL_TYPE_S(IT, USAGE): + case SDCA_CTL_TYPE_S(OT, USAGE): + case SDCA_CTL_TYPE_S(IT, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(CRU, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(UDMPU, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(MFPU, CLUSTERINDEX): + case SDCA_CTL_TYPE_S(MFPU, CENTER_FREQUENCY_INDEX): + case SDCA_CTL_TYPE_S(MFPU, AE_NUMBER): + case SDCA_CTL_TYPE_S(SAPU, OPAQUESETREQ_INDEX): + case SDCA_CTL_TYPE_S(XU, FDL_SET_INDEX): + case SDCA_CTL_TYPE_S(CS, SAMPLERATEINDEX): + case SDCA_CTL_TYPE_S(GE, SELECTED_MODE): + case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): + return SDCA_CTL_DATATYPE_BYTEINDEX; + case SDCA_CTL_TYPE_S(PPU, POSTURENUMBER): + return SDCA_CTL_DATATYPE_POSTURENUMBER; + case SDCA_CTL_TYPE_S(IT, DATAPORT_SELECTOR): + case SDCA_CTL_TYPE_S(OT, DATAPORT_SELECTOR): + return SDCA_CTL_DATATYPE_DP_INDEX; + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_READY): + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_ENABLE): + case SDCA_CTL_TYPE_S(MFPU, ALGORITHM_PREPARE): + case SDCA_CTL_TYPE_S(SAPU, PROTECTION_STATUS): + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_ENABLE): + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_STATUS): + case SDCA_CTL_TYPE_S(SMPU, TRIGGER_READY): + case SDCA_CTL_TYPE_S(SPE, PRIVACY_POLICY): + case SDCA_CTL_TYPE_S(SPE, PRIVACY_OWNER): + return SDCA_CTL_DATATYPE_BITINDEX; + case SDCA_CTL_TYPE_S(IT, KEEP_ALIVE): + case SDCA_CTL_TYPE_S(OT, KEEP_ALIVE): + case SDCA_CTL_TYPE_S(IT, NDAI_STREAM): + case SDCA_CTL_TYPE_S(OT, NDAI_STREAM): + case SDCA_CTL_TYPE_S(IT, NDAI_CATEGORY): + case SDCA_CTL_TYPE_S(OT, NDAI_CATEGORY): + case SDCA_CTL_TYPE_S(IT, NDAI_CODINGTYPE): + case SDCA_CTL_TYPE_S(OT, NDAI_CODINGTYPE): + case SDCA_CTL_TYPE_S(IT, NDAI_PACKETTYPE): + case SDCA_CTL_TYPE_S(OT, NDAI_PACKETTYPE): + case SDCA_CTL_TYPE_S(SMPU, HIST_ERROR): + case SDCA_CTL_TYPE_S(XU, FDL_STATUS): + case SDCA_CTL_TYPE_S(CS, CLOCK_VALID): + case SDCA_CTL_TYPE_S(SPE, PRIVACY_LOCKSTATE): + case SDCA_CTL_TYPE_S(ENTITY_0, COMMIT_GROUP_MASK): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS): + case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_ACTION): + case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SPE, AUTHTX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SPE, AUTHRX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(MFPU, AE_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SMPU, HIST_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SMPU, DTODTX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SMPU, DTODRX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SAPU, DTODTX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(SAPU, DTODRX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER): + case SDCA_CTL_TYPE_S(HIDE, HIDRX_CURRENTOWNER): + return SDCA_CTL_DATATYPE_BITMAP; + case SDCA_CTL_TYPE_S(IT, MATCHING_GUID): + case SDCA_CTL_TYPE_S(OT, MATCHING_GUID): + case SDCA_CTL_TYPE_S(ENTITY_0, MATCHING_GUID): + return SDCA_CTL_DATATYPE_GUID; + default: + return SDCA_CTL_DATATYPE_IMPDEF; + } +} + static int find_sdca_control_range(struct device *dev, struct fwnode_handle *control_node, struct sdca_control_range *range) @@ -744,6 +916,7 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti if (!control->label) return -ENOMEM; + control->type = find_sdca_control_datatype(entity, control); control->nbits = find_sdca_control_bits(entity, control); dev_info(dev, "%s: %s: control %#x mode %#x layers %#x cn %#llx int %d value %#x %s\n", From 1bcbb88bedb17804491e692a3f1a38223e09152c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:04 +0000 Subject: [PATCH 0955/1090] ASoC: SDCA: Add SDCA Control Range data access helper SDCA Ranges are two dimensional arrays of data associated with controls, add a helper to provide an x,y access mechanism to the data and a helper to locate a specific value inside a range. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index ca0376903e87..d7489e3c7e47 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -1136,6 +1136,25 @@ struct sdca_function_data { unsigned int busy_max_delay; }; +static inline u32 sdca_range(struct sdca_control_range *range, + unsigned int col, unsigned int row) +{ + return range->data[(row * range->cols) + col]; +} + +static inline u32 sdca_range_search(struct sdca_control_range *range, + int search_col, int value, int result_col) +{ + int i; + + for (i = 0; i < range->rows; i++) { + if (sdca_range(range, search_col, i) == value) + return sdca_range(range, result_col, i); + } + + return 0; +} + int sdca_parse_function(struct device *dev, struct sdca_function_desc *desc, struct sdca_function_data *function); From d1cd13f80dc6c8525c539a28d4eb1df913d542de Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 12 Mar 2025 17:22:05 +0000 Subject: [PATCH 0956/1090] ASoC: SDCA: Add support for GE Entity properties Add support for parsing the Group Entity properties from DisCo/ACPI. Group Entities allow control of several other Entities, typically Selector Units, from a single control. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250312172205.4152686-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_function.h | 48 ++++++++++++ sound/soc/sdca/sdca_functions.c | 129 ++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index d7489e3c7e47..253654568a41 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -44,6 +44,11 @@ struct sdca_function_desc; */ #define SDCA_MAX_DELAY_COUNT 256 +/* + * Sanity check on size of affected controls data, can be expanded if needed. + */ +#define SDCA_MAX_AFFECTED_COUNT 2048 + /** * enum sdca_function_type - SDCA Function Type codes * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. @@ -927,11 +932,51 @@ enum sdca_entity_type { SDCA_ENTITY_TYPE_HIDE = 0x31, }; +/** + * struct sdca_ge_control - control entry in the affected controls list + * @id: Entity ID of the Control affected. + * @sel: Control Selector of the Control affected. + * @cn: Control Number of the Control affected. + * @val: Value written to Control for this Mode. + */ +struct sdca_ge_control { + int id; + int sel; + int cn; + int val; +}; + +/** + * struct sdca_ge_mode - mode entry in the affected controls list + * @controls: Dynamically allocated array of controls written for this Mode. + * @num_controls: Number of controls written in this Mode. + * @val: GE Selector Mode value. + */ +struct sdca_ge_mode { + struct sdca_ge_control *controls; + int num_controls; + int val; +}; + +/** + * struct sdca_entity_ge - information specific to Group Entities + * @kctl: ALSA control pointer that can be used by linked Entities. + * @modes: Dynamically allocated array of Modes and the Controls written + * in each mode. + * @num_modes: Number of Modes. + */ +struct sdca_entity_ge { + struct snd_kcontrol_new *kctl; + struct sdca_ge_mode *modes; + int num_modes; +}; + /** * struct sdca_entity - information for one SDCA Entity * @label: String such as "OT 12". * @id: Identifier used for addressing. * @type: Type code for the Entity. + * @group: Pointer to Group Entity controlling this one, NULL if N/A. * @sources: Dynamically allocated array pointing to each input Entity * connected to this Entity. * @controls: Dynamically allocated array of Controls. @@ -940,12 +985,14 @@ enum sdca_entity_type { * @iot: Input/Output Terminal specific Entity properties. * @cs: Clock Source specific Entity properties. * @pde: Power Domain Entity specific Entity properties. + * @ge: Group Entity specific Entity properties. */ struct sdca_entity { const char *label; int id; enum sdca_entity_type type; + struct sdca_entity *group; struct sdca_entity **sources; struct sdca_control *controls; int num_sources; @@ -954,6 +1001,7 @@ struct sdca_entity { struct sdca_entity_iot iot; struct sdca_entity_cs cs; struct sdca_entity_pde pde; + struct sdca_entity_ge ge; }; }; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 0cc25fb9679b..c8efdc5301b5 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -1136,6 +1136,92 @@ static int find_sdca_entity_pde(struct device *dev, return 0; } +struct raw_ge_mode { + u8 val; + u8 num_controls; + struct { + u8 id; + u8 sel; + u8 cn; + __le32 val; + } __packed controls[] __counted_by(num_controls); +} __packed; + +static int find_sdca_entity_ge(struct device *dev, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + struct sdca_entity_ge *group = &entity->ge; + u8 *affected_list __free(kfree) = NULL; + u8 *affected_iter; + int num_affected; + int i, j; + + num_affected = fwnode_property_count_u8(entity_node, + "mipi-sdca-ge-selectedmode-controls-affected"); + if (!num_affected || num_affected == -EINVAL) { + return 0; + } else if (num_affected < 0) { + dev_err(dev, "%s: failed to read affected controls: %d\n", + entity->label, num_affected); + return num_affected; + } else if (num_affected > SDCA_MAX_AFFECTED_COUNT) { + dev_err(dev, "%s: maximum affected controls size exceeded\n", + entity->label); + return -EINVAL; + } + + affected_list = kcalloc(num_affected, sizeof(*affected_list), GFP_KERNEL); + if (!affected_list) + return -ENOMEM; + + fwnode_property_read_u8_array(entity_node, + "mipi-sdca-ge-selectedmode-controls-affected", + affected_list, num_affected); + + group->num_modes = *affected_list; + affected_iter = affected_list + 1; + + group->modes = devm_kcalloc(dev, group->num_modes, sizeof(*group->modes), + GFP_KERNEL); + if (!group->modes) + return -ENOMEM; + + for (i = 0; i < group->num_modes; i++) { + struct raw_ge_mode *raw = (struct raw_ge_mode *)affected_iter; + struct sdca_ge_mode *mode = &group->modes[i]; + + affected_iter += sizeof(*raw); + if (affected_iter > affected_list + num_affected) + goto bad_list; + + mode->val = raw->val; + mode->num_controls = raw->num_controls; + + affected_iter += mode->num_controls * sizeof(raw->controls[0]); + if (affected_iter > affected_list + num_affected) + goto bad_list; + + mode->controls = devm_kcalloc(dev, mode->num_controls, + sizeof(*mode->controls), GFP_KERNEL); + if (!mode->controls) + return -ENOMEM; + + for (j = 0; j < mode->num_controls; j++) { + mode->controls[j].id = raw->controls[j].id; + mode->controls[j].sel = raw->controls[j].sel; + mode->controls[j].cn = raw->controls[j].cn; + mode->controls[j].val = le32_to_cpu(raw->controls[j].val); + } + } + + return 0; + +bad_list: + dev_err(dev, "%s: malformed affected controls list\n", entity->label); + return -EINVAL; +} + static int find_sdca_entity(struct device *dev, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, @@ -1174,6 +1260,9 @@ static int find_sdca_entity(struct device *dev, case SDCA_ENTITY_TYPE_PDE: ret = find_sdca_entity_pde(dev, entity_node, entity); break; + case SDCA_ENTITY_TYPE_GE: + ret = find_sdca_entity_ge(dev, entity_node, entity); + break; default: break; } @@ -1384,6 +1473,42 @@ static int find_sdca_entity_connection_pde(struct device *dev, return 0; } +static int find_sdca_entity_connection_ge(struct device *dev, + struct sdca_function_data *function, + struct fwnode_handle *entity_node, + struct sdca_entity *entity) +{ + int i, j; + + for (i = 0; i < entity->ge.num_modes; i++) { + struct sdca_ge_mode *mode = &entity->ge.modes[i]; + + for (j = 0; j < mode->num_controls; j++) { + struct sdca_ge_control *affected = &mode->controls[j]; + struct sdca_entity *managed; + + managed = find_sdca_entity_by_id(function, affected->id); + if (!managed) { + dev_err(dev, "%s: failed to find entity with id %#x\n", + entity->label, affected->id); + return -EINVAL; + } + + if (managed->group && managed->group != entity) { + dev_err(dev, + "%s: entity controlled by two groups %s, %s\n", + managed->label, managed->group->label, + entity->label); + return -EINVAL; + } + + managed->group = entity; + } + } + + return 0; +} + static int find_sdca_entity_connection(struct device *dev, struct sdca_function_data *function, struct fwnode_handle *entity_node, @@ -1404,6 +1529,10 @@ static int find_sdca_entity_connection(struct device *dev, ret = find_sdca_entity_connection_pde(dev, function, entity_node, entity); break; + case SDCA_ENTITY_TYPE_GE: + ret = find_sdca_entity_connection_ge(dev, function, + entity_node, entity); + break; default: ret = 0; break; From 1458fae110c85d98d356496e4eb120f6de0e3a7e Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Wed, 12 Mar 2025 11:35:09 +0800 Subject: [PATCH 0957/1090] ASoC: ti: davinci-i2s: remove unnecessary NULL check before clk_disable_unprepare() clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL. Remove unneeded NULL check for dev->ext_clk here. Signed-off-by: Chen Ni Link: https://patch.msgid.link/20250312033509.1235268-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index d682b98d6848..059967f0e632 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -892,8 +892,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_disable_ext_clk: - if (dev->ext_clk) - clk_disable_unprepare(dev->ext_clk); + clk_disable_unprepare(dev->ext_clk); err_disable_clk: clk_disable_unprepare(dev->clk); @@ -908,8 +907,7 @@ static void davinci_i2s_remove(struct platform_device *pdev) clk_disable_unprepare(dev->clk); - if (dev->ext_clk) - clk_disable_unprepare(dev->ext_clk); + clk_disable_unprepare(dev->ext_clk); } static const struct of_device_id davinci_i2s_match[] __maybe_unused = { From f37ab219a3336ef787ce4babd20510f060f6f48d Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Wed, 12 Mar 2025 11:26:00 +0800 Subject: [PATCH 0958/1090] ASoC: mt8365: remove unnecessary NULL check before clk_disable_unprepare() clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL. Remove unneeded NULL check for clk here. Signed-off-by: Chen Ni Link: https://patch.msgid.link/20250312032600.1235158-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8365/mt8365-afe-clk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c index 8a0af2ea8546..7078c01ba19b 100644 --- a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c +++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c @@ -49,8 +49,7 @@ int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe) void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk) { - if (clk) - clk_disable_unprepare(clk); + clk_disable_unprepare(clk); } int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, From 0ec6bd16705fe21d6429d6b8f7981eae2142bba8 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 10 Mar 2025 20:57:14 -0500 Subject: [PATCH 0959/1090] ASoC: sma1307: Add NULL check in sma1307_setting_loaded() All varibale allocated by kzalloc and devm_kzalloc could be NULL. Multiple pointer checks and their cleanup are added. This issue is found by our static analysis tool Signed-off-by: Chenyuan Yang Link: https://patch.msgid.link/20250311015714.1333857-1-chenyuan0y@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/sma1307.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index dac17da9cedd..f5c303d4bb62 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1723,6 +1723,11 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil } data = kzalloc(fw->size, GFP_KERNEL); + if (!data) { + release_firmware(fw); + sma1307->set.status = false; + return; + } size = fw->size >> 2; memcpy(data, fw->data, fw->size); @@ -1736,6 +1741,12 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil sma1307->set.header = devm_kzalloc(sma1307->dev, sma1307->set.header_size, GFP_KERNEL); + if (!sma1307->set.header) { + kfree(data); + sma1307->set.status = false; + return; + } + memcpy(sma1307->set.header, data, sma1307->set.header_size * sizeof(int)); @@ -1751,6 +1762,13 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil sma1307->set.def = devm_kzalloc(sma1307->dev, sma1307->set.def_size * sizeof(int), GFP_KERNEL); + if (!sma1307->set.def) { + kfree(data); + kfree(sma1307->set.header); + sma1307->set.status = false; + return; + } + memcpy(sma1307->set.def, &data[sma1307->set.header_size], sma1307->set.def_size * sizeof(int)); @@ -1763,6 +1781,16 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil = devm_kzalloc(sma1307->dev, sma1307->set.mode_size * 2 * sizeof(int), GFP_KERNEL); + if (!sma1307->set.mode_set[i]) { + kfree(data); + kfree(sma1307->set.header); + kfree(sma1307->set.def); + for (int j = 0; j < i; j++) + kfree(sma1307->set.mode_set[j]); + sma1307->set.status = false; + return; + } + for (int j = 0; j < sma1307->set.mode_size; j++) { sma1307->set.mode_set[i][2 * j] = data[offset + ((num_mode + 1) * j)]; From f1d742c35b659fb0122da0a8ff09ad9309cb29d8 Mon Sep 17 00:00:00 2001 From: Ritu Chaudhary Date: Tue, 11 Mar 2025 06:20:10 +0000 Subject: [PATCH 0960/1090] ASoC: tegra: Use non-atomic timeout for ADX status register ADX startup() callback uses atomic poll timeout on ADX status register. This is unnecessary because: - The startup() callback itself is non-atomic. - The subsequent timeout call in the same function already uses a non-atomic version. Using atomic version can hog CPU when it is not really needed, so replace it with non-atomic version. Fixes: a99ab6f395a9e ("ASoC: tegra: Add Tegra210 based ADX driver") Signed-off-by: Ritu Chaudhary Signed-off-by: Sheetal Link: https://patch.msgid.link/20250311062010.33412-1-sheetal@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_adx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 0aa93b948378..3c10e09976ad 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. +// SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. // All rights reserved. // // tegra210_adx.c - Tegra210 ADX driver @@ -57,8 +57,8 @@ static int tegra210_adx_startup(struct snd_pcm_substream *substream, int err; /* Ensure if ADX status is disabled */ - err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS, - val, !(val & 0x1), 10, 10000); + err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_STATUS, + val, !(val & 0x1), 10, 10000); if (err < 0) { dev_err(dai->dev, "failed to stop ADX, err = %d\n", err); return err; From 9aa499f28ef8aeda82556dd204bc42dc96e2f1e4 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Wed, 12 Mar 2025 11:43:37 +0800 Subject: [PATCH 0961/1090] ASoC: tlv320adc3xxx: remove unnecessary NULL check before clk_disable_unprepare() clk_disable_unprepare() already checks NULL by using IS_ERR_OR_NULL. Remove unneeded NULL check for adc3xxx->mclk here. Signed-off-by: Chen Ni Link: https://patch.msgid.link/20250312034337.1235378-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adc3xxx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index 1a50ff675244..191e067ed1c9 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -1493,8 +1493,7 @@ static void adc3xxx_i2c_remove(struct i2c_client *client) { struct adc3xxx *adc3xxx = i2c_get_clientdata(client); - if (adc3xxx->mclk) - clk_disable_unprepare(adc3xxx->mclk); + clk_disable_unprepare(adc3xxx->mclk); adc3xxx_free_gpio(adc3xxx); snd_soc_unregister_component(&client->dev); } From 02026aabaa8225bd7dfdcb8ae106453e002cb0a8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Mar 2025 13:11:43 +0300 Subject: [PATCH 0962/1090] ASoC: amd: acp: Fix leak in acp_pci_probe() There needs to be some cleanup on this error path. We can't just return directly. Fixes: aaf7a668bb38 ("ASoC: amd: acp: Add new interrupt handle callbacks in acp_common_hw_ops") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/3dad80cb-e177-45aa-97ac-df9c98a47d94@stanley.mountain Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 9322379cb36f..123524f90d6c 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -183,7 +183,7 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id IRQF_SHARED, "ACP_I2S_IRQ", chip); if (ret) { dev_err(&pci->dev, "ACP I2S IRQ request failed %d\n", ret); - return ret; + goto de_init; } check_acp_config(pci, chip); From ede6445d5405edb418c05582d46d12687b632236 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Mar 2025 02:02:11 +0000 Subject: [PATCH 0963/1090] ASoC: soc-pcm: tidyup function name to snd_soc_dpcm_be_can_xxx() We have similar but different function names snd_soc_dpcm_fe_can_xxx() snd_soc_dpcm_be_can_xxx() snd_soc_dpcm_can_be_xxx() ~~~~~~ Let's unified these to can_xx Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87plip7ie4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 403edd2fd8cf..4308a6cbb2e6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -36,7 +36,7 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, /* is the current PCM operation for this FE ? */ #if 0 -static int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream) +static int snd_soc_dpcm_can_fe_update(struct snd_soc_pcm_runtime *fe, int stream) { if (fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) return 1; @@ -45,7 +45,7 @@ static int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream #endif /* is the current PCM operation for this BE ? */ -static int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe, +static int snd_soc_dpcm_can_be_update(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream) { if ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) || @@ -1632,7 +1632,7 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, return; /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; if (be->dpcm[stream].users == 0) { @@ -1682,7 +1682,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) } /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; /* first time the dpcm is open ? */ @@ -2007,7 +2007,7 @@ void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) snd_soc_dpcm_get_substream(be, stream); /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; /* only free hw when no longer used - check all FEs */ @@ -2073,7 +2073,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) be_substream = snd_soc_dpcm_get_substream(be, stream); /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; /* copy params for each dpcm */ @@ -2118,7 +2118,7 @@ unwind: be = dpcm->be; be_substream = snd_soc_dpcm_get_substream(be, stream); - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; /* only allow hw_free() if no connected FEs are running */ @@ -2188,7 +2188,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, snd_pcm_stream_lock_irqsave_nested(be_substream, flags); /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) goto next; dev_dbg(be->dev, "ASoC: trigger BE %s cmd %d\n", @@ -2465,7 +2465,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) snd_soc_dpcm_get_substream(be, stream); /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; if (!snd_soc_dpcm_can_be_prepared(fe, be, stream)) @@ -2623,7 +2623,7 @@ disconnect: struct snd_soc_pcm_runtime *be = dpcm->be; /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + if (!snd_soc_dpcm_can_be_update(fe, be, stream)) continue; if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE || From 3e330acf4efd63876d673c046cd073a1d4ed57a8 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 26 Feb 2025 16:50:50 +0800 Subject: [PATCH 0964/1090] ASoC: codecs: wcd937x: fix a potential memory leak in wcd937x_soc_codec_probe() When snd_soc_dapm_new_controls() or snd_soc_dapm_add_routes() fails, wcd937x_soc_codec_probe() returns without releasing 'wcd937x->clsh_info', which is allocated by wcd_clsh_ctrl_alloc. Add wcd_clsh_ctrl_free() to prevent potential memory leak. Fixes: 313e978df7fc ("ASoC: codecs: wcd937x: add audio routing and Kconfig") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Link: https://patch.msgid.link/20250226085050.3584898-1-haoxiang_li2024@163.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd937x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index e8d3fddbc7b1..ff8bb01edf42 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -2571,6 +2571,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_dapm_widgets)); if (ret < 0) { dev_err(component->dev, "Failed to add snd_ctls\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } @@ -2578,6 +2579,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_audio_map)); if (ret < 0) { dev_err(component->dev, "Failed to add routes\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } } From 3cab1fc85f9d381de6767fe97299eecdb8c868fa Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Wed, 12 Mar 2025 15:26:35 +0800 Subject: [PATCH 0965/1090] ASoC: cs35l56: Remove redundant 'flush_workqueue()' calls 'destroy_workqueue()' already drains the queue before destroying it, so there is no need to flush it explicitly. Remove the redundant 'flush_workqueue()' calls. This was generated with coccinelle: @@ expression E; @@ -flush_workqueue(E); destroy_workqueue(E); Signed-off-by: Chen Ni Link: https://patch.msgid.link/20250312072635.1429870-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 735a1e487c6f..b3158a84b87a 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1441,7 +1441,6 @@ void cs35l56_remove(struct cs35l56_private *cs35l56) if (cs35l56->base.irq) devm_free_irq(cs35l56->base.dev, cs35l56->base.irq, &cs35l56->base); - flush_workqueue(cs35l56->dsp_wq); destroy_workqueue(cs35l56->dsp_wq); pm_runtime_dont_use_autosuspend(cs35l56->base.dev); From 958448bfee503d24e706605f01b98d3ce547d1bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:23 +0100 Subject: [PATCH 0966/1090] ASoC: au1x: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Use the new DEFINE_SIMPLE_DEV_PM_OPS() macro instead of open code together with pm_ptr(), which allows us dropping CONFIG_PM ifdefs. Merely a cleanup, there should be no actual code change. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 17 +++-------------- sound/soc/au1x/psc-ac97.c | 17 +++-------------- sound/soc/au1x/psc-i2s.c | 17 +++-------------- 3 files changed, 9 insertions(+), 42 deletions(-) diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index 7d296f29dade..57735004f416 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -279,7 +279,6 @@ static void au1xi2s_drvremove(struct platform_device *pdev) WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ } -#ifdef CONFIG_PM static int au1xi2s_drvsuspend(struct device *dev) { struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); @@ -294,23 +293,13 @@ static int au1xi2s_drvresume(struct device *dev) return 0; } -static const struct dev_pm_ops au1xi2sc_pmops = { - .suspend = au1xi2s_drvsuspend, - .resume = au1xi2s_drvresume, -}; - -#define AU1XI2SC_PMOPS (&au1xi2sc_pmops) - -#else - -#define AU1XI2SC_PMOPS NULL - -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(au1xi2sc_pmops, au1xi2s_drvsuspend, + au1xi2s_drvresume); static struct platform_driver au1xi2s_driver = { .driver = { .name = "alchemy-i2sc", - .pm = AU1XI2SC_PMOPS, + .pm = pm_ptr(&au1xi2sc_pmops), }, .probe = au1xi2s_drvprobe, .remove = au1xi2s_drvremove, diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 8a59a50978b9..94698e08a513 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -436,7 +436,6 @@ static void au1xpsc_ac97_drvremove(struct platform_device *pdev) au1xpsc_ac97_workdata = NULL; /* MDEV */ } -#ifdef CONFIG_PM static int au1xpsc_ac97_drvsuspend(struct device *dev) { struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); @@ -467,23 +466,13 @@ static int au1xpsc_ac97_drvresume(struct device *dev) return 0; } -static const struct dev_pm_ops au1xpscac97_pmops = { - .suspend = au1xpsc_ac97_drvsuspend, - .resume = au1xpsc_ac97_drvresume, -}; - -#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops - -#else - -#define AU1XPSCAC97_PMOPS NULL - -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(au1xpscac97_pmops, au1xpsc_ac97_drvsuspend, + au1xpsc_ac97_drvresume); static struct platform_driver au1xpsc_ac97_driver = { .driver = { .name = "au1xpsc_ac97", - .pm = AU1XPSCAC97_PMOPS, + .pm = pm_ptr(&au1xpscac97_pmops), }, .probe = au1xpsc_ac97_drvprobe, .remove = au1xpsc_ac97_drvremove, diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index bee013555e7a..bf59105fcb7a 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -354,7 +354,6 @@ static void au1xpsc_i2s_drvremove(struct platform_device *pdev) wmb(); /* drain writebuffer */ } -#ifdef CONFIG_PM static int au1xpsc_i2s_drvsuspend(struct device *dev) { struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); @@ -385,23 +384,13 @@ static int au1xpsc_i2s_drvresume(struct device *dev) return 0; } -static const struct dev_pm_ops au1xpsci2s_pmops = { - .suspend = au1xpsc_i2s_drvsuspend, - .resume = au1xpsc_i2s_drvresume, -}; - -#define AU1XPSCI2S_PMOPS &au1xpsci2s_pmops - -#else - -#define AU1XPSCI2S_PMOPS NULL - -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(au1xpsci2s_pmops, au1xpsc_i2s_drvsuspend, + au1xpsc_i2s_drvresume); static struct platform_driver au1xpsc_i2s_driver = { .driver = { .name = "au1xpsc_i2s", - .pm = AU1XPSCI2S_PMOPS, + .pm = pm_ptr(&au1xpsci2s_pmops), }, .probe = au1xpsc_i2s_drvprobe, .remove = au1xpsc_i2s_drvremove, From 5f3aeb44694fbd6ebc8790cfcf157f2f7f072207 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:24 +0100 Subject: [PATCH 0967/1090] ASoC: ak4375: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS () and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-3-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/ak4375.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/ak4375.c b/sound/soc/codecs/ak4375.c index 3ee5a5c3c5fe..452559d8c97b 100644 --- a/sound/soc/codecs/ak4375.c +++ b/sound/soc/codecs/ak4375.c @@ -438,7 +438,7 @@ static int ak4375_power_on(struct ak4375_priv *ak4375) return 0; } -static int __maybe_unused ak4375_runtime_suspend(struct device *dev) +static int ak4375_runtime_suspend(struct device *dev) { struct ak4375_priv *ak4375 = dev_get_drvdata(dev); @@ -448,7 +448,7 @@ static int __maybe_unused ak4375_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused ak4375_runtime_resume(struct device *dev) +static int ak4375_runtime_resume(struct device *dev) { struct ak4375_priv *ak4375 = dev_get_drvdata(dev); int ret; @@ -490,9 +490,8 @@ static const struct ak4375_drvdata ak4375_drvdata = { }; static const struct dev_pm_ops ak4375_pm = { - SET_RUNTIME_PM_OPS(ak4375_runtime_suspend, ak4375_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(ak4375_runtime_suspend, ak4375_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static int ak4375_i2c_probe(struct i2c_client *i2c) @@ -594,7 +593,7 @@ MODULE_DEVICE_TABLE(of, ak4375_of_match); static struct i2c_driver ak4375_i2c_driver = { .driver = { .name = "ak4375", - .pm = &ak4375_pm, + .pm = pm_ptr(&ak4375_pm), .of_match_table = ak4375_of_match, }, .probe = ak4375_i2c_probe, From 9f9c8e9064ea8ceb13540a283f08550c097bb673 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:25 +0100 Subject: [PATCH 0968/1090] ASoC: ak4458: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes and CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-4-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index d472d9952628..5f3a68dfe7bd 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -639,8 +639,7 @@ static void ak4458_reset(struct ak4458_priv *ak4458, bool active) } } -#ifdef CONFIG_PM -static int __maybe_unused ak4458_runtime_suspend(struct device *dev) +static int ak4458_runtime_suspend(struct device *dev) { struct ak4458_priv *ak4458 = dev_get_drvdata(dev); @@ -656,7 +655,7 @@ static int __maybe_unused ak4458_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused ak4458_runtime_resume(struct device *dev) +static int ak4458_runtime_resume(struct device *dev) { struct ak4458_priv *ak4458 = dev_get_drvdata(dev); int ret; @@ -678,7 +677,6 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev) return regcache_sync(ak4458->regmap); } -#endif /* CONFIG_PM */ static const struct snd_soc_component_driver soc_codec_dev_ak4458 = { .controls = ak4458_snd_controls, @@ -727,9 +725,8 @@ static const struct ak4458_drvdata ak4497_drvdata = { }; static const struct dev_pm_ops ak4458_pm = { - SET_RUNTIME_PM_OPS(ak4458_runtime_suspend, ak4458_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(ak4458_runtime_suspend, ak4458_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static int ak4458_i2c_probe(struct i2c_client *i2c) @@ -805,7 +802,7 @@ MODULE_DEVICE_TABLE(of, ak4458_of_match); static struct i2c_driver ak4458_i2c_driver = { .driver = { .name = "ak4458", - .pm = &ak4458_pm, + .pm = pm_ptr(&ak4458_pm), .of_match_table = ak4458_of_match, }, .probe = ak4458_i2c_probe, From 5ef209dcdc3fe8f9661a80af4c8ed7a2326c9206 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:26 +0100 Subject: [PATCH 0969/1090] ASoC: ak5558: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-5-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 6c767609f95d..683f3e472f50 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -342,7 +342,7 @@ static void ak5558_remove(struct snd_soc_component *component) ak5558_reset(ak5558, true); } -static int __maybe_unused ak5558_runtime_suspend(struct device *dev) +static int ak5558_runtime_suspend(struct device *dev) { struct ak5558_priv *ak5558 = dev_get_drvdata(dev); @@ -354,7 +354,7 @@ static int __maybe_unused ak5558_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused ak5558_runtime_resume(struct device *dev) +static int ak5558_runtime_resume(struct device *dev) { struct ak5558_priv *ak5558 = dev_get_drvdata(dev); int ret; @@ -376,9 +376,8 @@ static int __maybe_unused ak5558_runtime_resume(struct device *dev) } static const struct dev_pm_ops ak5558_pm = { - SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct snd_soc_component_driver soc_codec_dev_ak5558 = { @@ -495,7 +494,7 @@ static struct i2c_driver ak5558_i2c_driver = { .driver = { .name = "ak5558", .of_match_table = of_match_ptr(ak5558_i2c_dt_ids), - .pm = &ak5558_pm, + .pm = pm_ptr(&ak5558_pm), }, .probe = ak5558_i2c_probe, .remove = ak5558_i2c_remove, From 5b73cae57a02ff461c260e68193ce973062cc0bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:27 +0100 Subject: [PATCH 0970/1090] ASoC: cs35l32: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-6-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l32.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 6d78fa953c89..0bb4bdb3deec 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -504,7 +504,6 @@ static void cs35l32_i2c_remove(struct i2c_client *i2c_client) gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); } -#ifdef CONFIG_PM static int cs35l32_runtime_suspend(struct device *dev) { struct cs35l32_private *cs35l32 = dev_get_drvdata(dev); @@ -543,11 +542,9 @@ static int cs35l32_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops cs35l32_runtime_pm = { - SET_RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume, NULL) }; static const struct of_device_id cs35l32_of_match[] = { @@ -567,7 +564,7 @@ MODULE_DEVICE_TABLE(i2c, cs35l32_id); static struct i2c_driver cs35l32_i2c_driver = { .driver = { .name = "cs35l32", - .pm = &cs35l32_runtime_pm, + .pm = pm_ptr(&cs35l32_runtime_pm), .of_match_table = cs35l32_of_match, }, .id_table = cs35l32_id, From 7d1d8f90e456e2945cd3a1a4a429fdb634ec6f42 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:28 +0100 Subject: [PATCH 0971/1090] ASoC: cs35l33: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-7-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l33.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 02a420659a33..c927592f90c9 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -853,7 +853,7 @@ static const struct regmap_config cs35l33_regmap = { .use_single_write = true, }; -static int __maybe_unused cs35l33_runtime_resume(struct device *dev) +static int cs35l33_runtime_resume(struct device *dev) { struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); int ret; @@ -891,7 +891,7 @@ err: return ret; } -static int __maybe_unused cs35l33_runtime_suspend(struct device *dev) +static int cs35l33_runtime_suspend(struct device *dev) { struct cs35l33_private *cs35l33 = dev_get_drvdata(dev); @@ -909,9 +909,7 @@ static int __maybe_unused cs35l33_runtime_suspend(struct device *dev) } static const struct dev_pm_ops cs35l33_pm_ops = { - SET_RUNTIME_PM_OPS(cs35l33_runtime_suspend, - cs35l33_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs35l33_runtime_suspend, cs35l33_runtime_resume, NULL) }; static int cs35l33_get_hg_data(const struct device_node *np, @@ -1273,7 +1271,7 @@ MODULE_DEVICE_TABLE(i2c, cs35l33_id); static struct i2c_driver cs35l33_i2c_driver = { .driver = { .name = "cs35l33", - .pm = &cs35l33_pm_ops, + .pm = pm_ptr(&cs35l33_pm_ops), .of_match_table = cs35l33_of_match, }, From 1d6128f56c01a417ee3c9d80b4c205da6399d661 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:29 +0100 Subject: [PATCH 0972/1090] ASoC: cs35l34: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-8-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l34.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index 6d098bfd38f6..a5a8075598ff 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -1116,7 +1116,7 @@ static void cs35l34_i2c_remove(struct i2c_client *client) cs35l34->core_supplies); } -static int __maybe_unused cs35l34_runtime_resume(struct device *dev) +static int cs35l34_runtime_resume(struct device *dev) { struct cs35l34_private *cs35l34 = dev_get_drvdata(dev); int ret; @@ -1149,7 +1149,7 @@ err: return ret; } -static int __maybe_unused cs35l34_runtime_suspend(struct device *dev) +static int cs35l34_runtime_suspend(struct device *dev) { struct cs35l34_private *cs35l34 = dev_get_drvdata(dev); @@ -1165,9 +1165,7 @@ static int __maybe_unused cs35l34_runtime_suspend(struct device *dev) } static const struct dev_pm_ops cs35l34_pm_ops = { - SET_RUNTIME_PM_OPS(cs35l34_runtime_suspend, - cs35l34_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs35l34_runtime_suspend, cs35l34_runtime_resume, NULL) }; static const struct of_device_id cs35l34_of_match[] = { @@ -1185,7 +1183,7 @@ MODULE_DEVICE_TABLE(i2c, cs35l34_id); static struct i2c_driver cs35l34_i2c_driver = { .driver = { .name = "cs35l34", - .pm = &cs35l34_pm_ops, + .pm = pm_ptr(&cs35l34_pm_ops), .of_match_table = cs35l34_of_match, }, From fd24b93ebaa1be78bf683a6a0599856eda367155 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:30 +0100 Subject: [PATCH 0973/1090] ASoC: cs4234: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-9-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs4234.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c index df160db5bbb5..dda7f5b4f2fb 100644 --- a/sound/soc/codecs/cs4234.c +++ b/sound/soc/codecs/cs4234.c @@ -860,7 +860,7 @@ static void cs4234_i2c_remove(struct i2c_client *i2c_client) cs4234_shutdown(cs4234); } -static int __maybe_unused cs4234_runtime_resume(struct device *dev) +static int cs4234_runtime_resume(struct device *dev) { struct cs4234 *cs4234 = dev_get_drvdata(dev); int ret; @@ -881,7 +881,7 @@ static int __maybe_unused cs4234_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused cs4234_runtime_suspend(struct device *dev) +static int cs4234_runtime_suspend(struct device *dev) { struct cs4234 *cs4234 = dev_get_drvdata(dev); @@ -891,7 +891,7 @@ static int __maybe_unused cs4234_runtime_suspend(struct device *dev) } static const struct dev_pm_ops cs4234_pm = { - SET_RUNTIME_PM_OPS(cs4234_runtime_suspend, cs4234_runtime_resume, NULL) + RUNTIME_PM_OPS(cs4234_runtime_suspend, cs4234_runtime_resume, NULL) }; static const struct of_device_id cs4234_of_match[] = { @@ -903,7 +903,7 @@ MODULE_DEVICE_TABLE(of, cs4234_of_match); static struct i2c_driver cs4234_i2c_driver = { .driver = { .name = "cs4234", - .pm = &cs4234_pm, + .pm = pm_ptr(&cs4234_pm), .of_match_table = cs4234_of_match, }, .probe = cs4234_i2c_probe, From 227b132349825b52ded464e71271751aceb4b4c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:31 +0100 Subject: [PATCH 0974/1090] ASoC: cs42l42: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-10-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42-i2c.c | 6 +++--- sound/soc/codecs/cs42l42-sdw.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c index 8a1d5c7a61d7..98b6718ccabf 100644 --- a/sound/soc/codecs/cs42l42-i2c.c +++ b/sound/soc/codecs/cs42l42-i2c.c @@ -48,7 +48,7 @@ static void cs42l42_i2c_remove(struct i2c_client *i2c_client) cs42l42_common_remove(cs42l42); } -static int __maybe_unused cs42l42_i2c_resume(struct device *dev) +static int cs42l42_i2c_resume(struct device *dev) { int ret; @@ -62,7 +62,7 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev) } static const struct dev_pm_ops cs42l42_i2c_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume) + SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume) }; static const struct of_device_id __maybe_unused cs42l42_of_match[] = { @@ -87,7 +87,7 @@ MODULE_DEVICE_TABLE(i2c, cs42l42_id); static struct i2c_driver cs42l42_i2c_driver = { .driver = { .name = "cs42l42", - .pm = &cs42l42_i2c_pm_ops, + .pm = pm_ptr(&cs42l42_i2c_pm_ops), .of_match_table = of_match_ptr(cs42l42_of_match), .acpi_match_table = ACPI_PTR(cs42l42_acpi_match), }, diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index ae1401b250a3..f837c7eff10b 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -411,7 +411,7 @@ static const struct sdw_slave_ops cs42l42_sdw_ops = { .port_prep = cs42l42_sdw_port_prep, }; -static int __maybe_unused cs42l42_sdw_runtime_suspend(struct device *dev) +static int cs42l42_sdw_runtime_suspend(struct device *dev) { struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); @@ -426,11 +426,11 @@ static int __maybe_unused cs42l42_sdw_runtime_suspend(struct device *dev) return 0; } -static const struct reg_sequence __maybe_unused cs42l42_soft_reboot_seq[] = { +static const struct reg_sequence cs42l42_soft_reboot_seq[] = { REG_SEQ0(CS42L42_SOFT_RESET_REBOOT, 0x1e), }; -static int __maybe_unused cs42l42_sdw_handle_unattach(struct cs42l42_private *cs42l42) +static int cs42l42_sdw_handle_unattach(struct cs42l42_private *cs42l42) { struct sdw_slave *peripheral = cs42l42->sdw_peripheral; @@ -460,7 +460,7 @@ static int __maybe_unused cs42l42_sdw_handle_unattach(struct cs42l42_private *cs return 0; } -static int __maybe_unused cs42l42_sdw_runtime_resume(struct device *dev) +static int cs42l42_sdw_runtime_resume(struct device *dev) { static const unsigned int ts_dbnce_ms[] = { 0, 125, 250, 500, 750, 1000, 1250, 1500}; struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); @@ -491,7 +491,7 @@ static int __maybe_unused cs42l42_sdw_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused cs42l42_sdw_resume(struct device *dev) +static int cs42l42_sdw_resume(struct device *dev) { struct cs42l42_private *cs42l42 = dev_get_drvdata(dev); int ret; @@ -596,8 +596,8 @@ static int cs42l42_sdw_remove(struct sdw_slave *peripheral) } static const struct dev_pm_ops cs42l42_sdw_pm = { - SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_sdw_resume) - SET_RUNTIME_PM_OPS(cs42l42_sdw_runtime_suspend, cs42l42_sdw_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_sdw_resume) + RUNTIME_PM_OPS(cs42l42_sdw_runtime_suspend, cs42l42_sdw_runtime_resume, NULL) }; static const struct sdw_device_id cs42l42_sdw_id[] = { @@ -609,7 +609,7 @@ MODULE_DEVICE_TABLE(sdw, cs42l42_sdw_id); static struct sdw_driver cs42l42_sdw_driver = { .driver = { .name = "cs42l42-sdw", - .pm = &cs42l42_sdw_pm, + .pm = pm_ptr(&cs42l42_sdw_pm), }, .probe = cs42l42_sdw_probe, .remove = cs42l42_sdw_remove, From 92104ed88e7c2f1a10cb72f5372107136738c2c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:32 +0100 Subject: [PATCH 0975/1090] ASoC: cs42l51: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS(). Also, drop superfluous __maybe_unused attributes to cs42l51_suspend() and _resume() functions. Merely a cleanup, there should be no actual code change. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-11-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51-i2c.c | 2 +- sound/soc/codecs/cs42l51.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index f171bd66fcac..ba7e237619f2 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -40,7 +40,7 @@ static void cs42l51_i2c_remove(struct i2c_client *i2c) } static const struct dev_pm_ops cs42l51_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(cs42l51_suspend, cs42l51_resume) + SYSTEM_SLEEP_PM_OPS(cs42l51_suspend, cs42l51_resume) }; static struct i2c_driver cs42l51_i2c_driver = { diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 0602d03095d6..8083a339dc7b 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -805,7 +805,7 @@ void cs42l51_remove(struct device *dev) } EXPORT_SYMBOL_GPL(cs42l51_remove); -int __maybe_unused cs42l51_suspend(struct device *dev) +int cs42l51_suspend(struct device *dev) { struct cs42l51_private *cs42l51 = dev_get_drvdata(dev); @@ -816,7 +816,7 @@ int __maybe_unused cs42l51_suspend(struct device *dev) } EXPORT_SYMBOL_GPL(cs42l51_suspend); -int __maybe_unused cs42l51_resume(struct device *dev) +int cs42l51_resume(struct device *dev) { struct cs42l51_private *cs42l51 = dev_get_drvdata(dev); From 850910df7a5ce514f4b4d4d7ba4020abf9254b6d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:33 +0100 Subject: [PATCH 0976/1090] ASoC: cs42l83: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-12-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l83-i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/cs42l83-i2c.c b/sound/soc/codecs/cs42l83-i2c.c index 42c3e1efdc08..53a7fe1ab3dd 100644 --- a/sound/soc/codecs/cs42l83-i2c.c +++ b/sound/soc/codecs/cs42l83-i2c.c @@ -199,7 +199,7 @@ static void cs42l83_i2c_remove(struct i2c_client *i2c_client) cs42l42_common_remove(cs42l83); } -static int __maybe_unused cs42l83_i2c_resume(struct device *dev) +static int cs42l83_i2c_resume(struct device *dev) { int ret; @@ -213,7 +213,7 @@ static int __maybe_unused cs42l83_i2c_resume(struct device *dev) } static const struct dev_pm_ops cs42l83_i2c_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume) + SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume) }; static const struct of_device_id __maybe_unused cs42l83_of_match[] = { @@ -225,7 +225,7 @@ MODULE_DEVICE_TABLE(of, cs42l83_of_match); static struct i2c_driver cs42l83_i2c_driver = { .driver = { .name = "cs42l83", - .pm = &cs42l83_i2c_pm_ops, + .pm = pm_ptr(&cs42l83_i2c_pm_ops), .of_match_table = of_match_ptr(cs42l83_of_match), }, .probe = cs42l83_i2c_probe, From 7b7e2292e0ba84515e62147a47b79e1f81f47b1c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:34 +0100 Subject: [PATCH 0977/1090] ASoC: cs42xx8: Convert to EXPORT_GPL_DEV_PM_OPS() Use the newer EXPORT_GPL_DEV_PM_OPS() macro together with pm_ptr(), which allows us to drop superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-13-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8-i2c.c | 2 +- sound/soc/codecs/cs42xx8.c | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c index ecaebf8e1c8f..039b3ecb3b9b 100644 --- a/sound/soc/codecs/cs42xx8-i2c.c +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -61,7 +61,7 @@ MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); static struct i2c_driver cs42xx8_i2c_driver = { .driver = { .name = "cs42xx8", - .pm = &cs42xx8_pm, + .pm = pm_ptr(&cs42xx8_pm), .of_match_table = cs42xx8_of_match, }, .probe = cs42xx8_i2c_probe, diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 8887db653dbf..6a925f3f7137 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -606,7 +606,6 @@ err_enable: } EXPORT_SYMBOL_GPL(cs42xx8_probe); -#ifdef CONFIG_PM static int cs42xx8_runtime_resume(struct device *dev) { struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); @@ -665,14 +664,11 @@ static int cs42xx8_runtime_suspend(struct device *dev) return 0; } -#endif -const struct dev_pm_ops cs42xx8_pm = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) +EXPORT_GPL_DEV_PM_OPS(cs42xx8_pm) = { + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) }; -EXPORT_SYMBOL_GPL(cs42xx8_pm); MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); MODULE_AUTHOR("Freescale Semiconductor, Inc."); From 9a1d4a56565161a8bbf5b2a9d92665010303aeac Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:35 +0100 Subject: [PATCH 0978/1090] ASoC: cs43130: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-14-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs43130.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index cd535be0b4ba..d9b3d73c8388 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -2672,7 +2672,7 @@ static void cs43130_i2c_remove(struct i2c_client *client) regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies); } -static int __maybe_unused cs43130_runtime_suspend(struct device *dev) +static int cs43130_runtime_suspend(struct device *dev) { struct cs43130_private *cs43130 = dev_get_drvdata(dev); @@ -2691,7 +2691,7 @@ static int __maybe_unused cs43130_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused cs43130_runtime_resume(struct device *dev) +static int cs43130_runtime_resume(struct device *dev) { struct cs43130_private *cs43130 = dev_get_drvdata(dev); int ret; @@ -2727,8 +2727,7 @@ err: } static const struct dev_pm_ops cs43130_runtime_pm = { - SET_RUNTIME_PM_OPS(cs43130_runtime_suspend, cs43130_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs43130_runtime_suspend, cs43130_runtime_resume, NULL) }; #if IS_ENABLED(CONFIG_OF) @@ -2768,7 +2767,7 @@ static struct i2c_driver cs43130_i2c_driver = { .name = "cs43130", .of_match_table = of_match_ptr(cs43130_of_match), .acpi_match_table = ACPI_PTR(cs43130_acpi_match), - .pm = &cs43130_runtime_pm, + .pm = pm_ptr(&cs43130_runtime_pm), }, .id_table = cs43130_i2c_id, .probe = cs43130_i2c_probe, From 2492a736dd8959b8860ca7f7afcd395314c9c436 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:36 +0100 Subject: [PATCH 0979/1090] ASoC: cs4349: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-15-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs4349.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index a134ca722892..d9a9c34fffe3 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -312,7 +312,6 @@ static void cs4349_i2c_remove(struct i2c_client *client) gpiod_set_value_cansleep(cs4349->reset_gpio, 0); } -#ifdef CONFIG_PM static int cs4349_runtime_suspend(struct device *dev) { struct cs4349_private *cs4349 = dev_get_drvdata(dev); @@ -346,11 +345,9 @@ static int cs4349_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops cs4349_runtime_pm = { - SET_RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs4349_runtime_suspend, cs4349_runtime_resume, NULL) }; static const struct of_device_id cs4349_of_match[] = { @@ -371,7 +368,7 @@ static struct i2c_driver cs4349_i2c_driver = { .driver = { .name = "cs4349", .of_match_table = cs4349_of_match, - .pm = &cs4349_runtime_pm, + .pm = pm_ptr(&cs4349_runtime_pm), }, .id_table = cs4349_i2c_id, .probe = cs4349_i2c_probe, From 646443af4452793090d34da2c70d5ed126f174bd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:37 +0100 Subject: [PATCH 0980/1090] ASoC: cs53l30: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-16-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs53l30.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index aea4244fb275..61bf72681674 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -1031,7 +1031,6 @@ static void cs53l30_i2c_remove(struct i2c_client *client) cs53l30->supplies); } -#ifdef CONFIG_PM static int cs53l30_runtime_suspend(struct device *dev) { struct cs53l30_private *cs53l30 = dev_get_drvdata(dev); @@ -1070,11 +1069,9 @@ static int cs53l30_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops cs53l30_runtime_pm = { - SET_RUNTIME_PM_OPS(cs53l30_runtime_suspend, cs53l30_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs53l30_runtime_suspend, cs53l30_runtime_resume, NULL) }; static const struct of_device_id cs53l30_of_match[] = { @@ -1095,7 +1092,7 @@ static struct i2c_driver cs53l30_i2c_driver = { .driver = { .name = "cs53l30", .of_match_table = cs53l30_of_match, - .pm = &cs53l30_runtime_pm, + .pm = pm_ptr(&cs53l30_runtime_pm), }, .id_table = cs53l30_id, .probe = cs53l30_i2c_probe, From 81f150d4b96d73feecda475f500f460565344255 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:38 +0100 Subject: [PATCH 0981/1090] ASoC: cx2072x: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-17-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index 8cfec8dcf839..934526f8f292 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1611,7 +1611,7 @@ static const struct regmap_config cx2072x_regmap = { .reg_write = cx2072x_reg_write, }; -static int __maybe_unused cx2072x_runtime_suspend(struct device *dev) +static int cx2072x_runtime_suspend(struct device *dev) { struct cx2072x_priv *cx2072x = dev_get_drvdata(dev); @@ -1619,7 +1619,7 @@ static int __maybe_unused cx2072x_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused cx2072x_runtime_resume(struct device *dev) +static int cx2072x_runtime_resume(struct device *dev) { struct cx2072x_priv *cx2072x = dev_get_drvdata(dev); @@ -1696,17 +1696,15 @@ MODULE_DEVICE_TABLE(acpi, cx2072x_acpi_match); #endif static const struct dev_pm_ops cx2072x_runtime_pm = { - SET_RUNTIME_PM_OPS(cx2072x_runtime_suspend, cx2072x_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(cx2072x_runtime_suspend, cx2072x_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct i2c_driver cx2072x_i2c_driver = { .driver = { .name = "cx2072x", .acpi_match_table = ACPI_PTR(cx2072x_acpi_match), - .pm = &cx2072x_runtime_pm, + .pm = pm_ptr(&cx2072x_runtime_pm), }, .probe = cx2072x_i2c_probe, .remove = cx2072x_i2c_remove, From 948cf1681e2ee077969df1e672f4c4d856059937 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:39 +0100 Subject: [PATCH 0982/1090] ASoC: da7213: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: support.opensource@diasemi.com Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-18-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index eb97ac73ec06..a4496cc26902 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -2224,7 +2224,7 @@ static void da7213_i2c_remove(struct i2c_client *i2c) pm_runtime_disable(&i2c->dev); } -static int __maybe_unused da7213_runtime_suspend(struct device *dev) +static int da7213_runtime_suspend(struct device *dev) { struct da7213_priv *da7213 = dev_get_drvdata(dev); @@ -2235,7 +2235,7 @@ static int __maybe_unused da7213_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused da7213_runtime_resume(struct device *dev) +static int da7213_runtime_resume(struct device *dev) { struct da7213_priv *da7213 = dev_get_drvdata(dev); int ret; @@ -2248,8 +2248,8 @@ static int __maybe_unused da7213_runtime_resume(struct device *dev) } static const struct dev_pm_ops da7213_pm = { - SET_RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(da7213_runtime_suspend, da7213_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct i2c_device_id da7213_i2c_id[] = { @@ -2264,7 +2264,7 @@ static struct i2c_driver da7213_i2c_driver = { .name = "da7213", .of_match_table = of_match_ptr(da7213_of_match), .acpi_match_table = ACPI_PTR(da7213_acpi_match), - .pm = &da7213_pm, + .pm = pm_ptr(&da7213_pm), }, .probe = da7213_i2c_probe, .remove = da7213_i2c_remove, From 218b32ca6c63db19ba0f4ad4fe83dc7c18e21bcb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:40 +0100 Subject: [PATCH 0983/1090] ASoC: hdac_hdmi: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-19-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 3bea5d09219a..1139a2754ca3 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -2032,7 +2032,6 @@ static void hdmi_codec_remove(struct snd_soc_component *component) pm_runtime_disable(&hdev->dev); } -#ifdef CONFIG_PM_SLEEP static int hdmi_codec_resume(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); @@ -2055,9 +2054,6 @@ static int hdmi_codec_resume(struct device *dev) hdac_hdmi_present_sense_all_pins(hdev, hdmi, false); return 0; } -#else -#define hdmi_codec_resume NULL -#endif static const struct snd_soc_component_driver hdmi_hda_codec = { .probe = hdmi_codec_probe, @@ -2227,7 +2223,6 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev) return 0; } -#ifdef CONFIG_PM static int hdac_hdmi_runtime_suspend(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); @@ -2296,14 +2291,10 @@ static int hdac_hdmi_runtime_resume(struct device *dev) return 0; } -#else -#define hdac_hdmi_runtime_suspend NULL -#define hdac_hdmi_runtime_resume NULL -#endif static const struct dev_pm_ops hdac_hdmi_pm = { - SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume) + RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume) }; static const struct hda_device_id hdmi_list[] = { @@ -2322,7 +2313,7 @@ MODULE_DEVICE_TABLE(hdaudio, hdmi_list); static struct hdac_driver hdmi_driver = { .driver = { .name = "HDMI HDA Codec", - .pm = &hdac_hdmi_pm, + .pm = pm_ptr(&hdac_hdmi_pm), }, .id_table = hdmi_list, .probe = hdac_hdmi_dev_probe, From efd74b16af66d3ab2e65a68d6ff171ae2b4ecf21 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:41 +0100 Subject: [PATCH 0984/1090] ASoC: lpass: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Srinivas Kandagatla Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-20-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 8 ++++---- sound/soc/codecs/lpass-tx-macro.c | 8 ++++---- sound/soc/codecs/lpass-va-macro.c | 8 ++++---- sound/soc/codecs/lpass-wsa-macro.c | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index febbbe073962..45a6b83808b2 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3963,7 +3963,7 @@ static const struct of_device_id rx_macro_dt_match[] = { }; MODULE_DEVICE_TABLE(of, rx_macro_dt_match); -static int __maybe_unused rx_macro_runtime_suspend(struct device *dev) +static int rx_macro_runtime_suspend(struct device *dev) { struct rx_macro *rx = dev_get_drvdata(dev); @@ -3977,7 +3977,7 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused rx_macro_runtime_resume(struct device *dev) +static int rx_macro_runtime_resume(struct device *dev) { struct rx_macro *rx = dev_get_drvdata(dev); int ret; @@ -4012,7 +4012,7 @@ err_npl: } static const struct dev_pm_ops rx_macro_pm_ops = { - SET_RUNTIME_PM_OPS(rx_macro_runtime_suspend, rx_macro_runtime_resume, NULL) + RUNTIME_PM_OPS(rx_macro_runtime_suspend, rx_macro_runtime_resume, NULL) }; static struct platform_driver rx_macro_driver = { @@ -4020,7 +4020,7 @@ static struct platform_driver rx_macro_driver = { .name = "rx_macro", .of_match_table = rx_macro_dt_match, .suppress_bind_attrs = true, - .pm = &rx_macro_pm_ops, + .pm = pm_ptr(&rx_macro_pm_ops), }, .probe = rx_macro_probe, .remove = rx_macro_remove, diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index a134584acf90..27bae58f4072 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -2400,7 +2400,7 @@ static void tx_macro_remove(struct platform_device *pdev) lpass_macro_pds_exit(tx->pds); } -static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) +static int tx_macro_runtime_suspend(struct device *dev) { struct tx_macro *tx = dev_get_drvdata(dev); @@ -2414,7 +2414,7 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tx_macro_runtime_resume(struct device *dev) +static int tx_macro_runtime_resume(struct device *dev) { struct tx_macro *tx = dev_get_drvdata(dev); int ret; @@ -2450,7 +2450,7 @@ err_npl: } static const struct dev_pm_ops tx_macro_pm_ops = { - SET_RUNTIME_PM_OPS(tx_macro_runtime_suspend, tx_macro_runtime_resume, NULL) + RUNTIME_PM_OPS(tx_macro_runtime_suspend, tx_macro_runtime_resume, NULL) }; static const struct tx_macro_data lpass_ver_9 = { @@ -2531,7 +2531,7 @@ static struct platform_driver tx_macro_driver = { .name = "tx_macro", .of_match_table = tx_macro_dt_match, .suppress_bind_attrs = true, - .pm = &tx_macro_pm_ops, + .pm = pm_ptr(&tx_macro_pm_ops), }, .probe = tx_macro_probe, .remove = tx_macro_remove, diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index c781da476240..74ada6e77526 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1674,7 +1674,7 @@ static void va_macro_remove(struct platform_device *pdev) lpass_macro_pds_exit(va->pds); } -static int __maybe_unused va_macro_runtime_suspend(struct device *dev) +static int va_macro_runtime_suspend(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); @@ -1689,7 +1689,7 @@ static int __maybe_unused va_macro_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused va_macro_runtime_resume(struct device *dev) +static int va_macro_runtime_resume(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); int ret; @@ -1717,7 +1717,7 @@ static int __maybe_unused va_macro_runtime_resume(struct device *dev) static const struct dev_pm_ops va_macro_pm_ops = { - SET_RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) + RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) }; static const struct of_device_id va_macro_dt_match[] = { @@ -1735,7 +1735,7 @@ static struct platform_driver va_macro_driver = { .name = "va_macro", .of_match_table = va_macro_dt_match, .suppress_bind_attrs = true, - .pm = &va_macro_pm_ops, + .pm = pm_ptr(&va_macro_pm_ops), }, .probe = va_macro_probe, .remove = va_macro_remove, diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index c989d82d1d3c..b261fa373e65 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2900,7 +2900,7 @@ static void wsa_macro_remove(struct platform_device *pdev) clk_disable_unprepare(wsa->fsgen); } -static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) +static int wsa_macro_runtime_suspend(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); @@ -2914,7 +2914,7 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wsa_macro_runtime_resume(struct device *dev) +static int wsa_macro_runtime_resume(struct device *dev) { struct wsa_macro *wsa = dev_get_drvdata(dev); int ret; @@ -2950,7 +2950,7 @@ err_npl: } static const struct dev_pm_ops wsa_macro_pm_ops = { - SET_RUNTIME_PM_OPS(wsa_macro_runtime_suspend, wsa_macro_runtime_resume, NULL) + RUNTIME_PM_OPS(wsa_macro_runtime_suspend, wsa_macro_runtime_resume, NULL) }; static const struct of_device_id wsa_macro_dt_match[] = { @@ -2977,7 +2977,7 @@ static struct platform_driver wsa_macro_driver = { .driver = { .name = "wsa_macro", .of_match_table = wsa_macro_dt_match, - .pm = &wsa_macro_pm_ops, + .pm = pm_ptr(&wsa_macro_pm_ops), }, .probe = wsa_macro_probe, .remove = wsa_macro_remove, From f744bcb575f7e25d871532e731398b99de32953d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:42 +0100 Subject: [PATCH 0985/1090] ASoC: max98090: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM and CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-21-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 790e2ae6dc18..22177c1ce160 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2604,7 +2604,6 @@ static void max98090_i2c_remove(struct i2c_client *client) max98090_i2c_shutdown(client); } -#ifdef CONFIG_PM static int max98090_runtime_resume(struct device *dev) { struct max98090_priv *max98090 = dev_get_drvdata(dev); @@ -2626,9 +2625,7 @@ static int max98090_runtime_suspend(struct device *dev) return 0; } -#endif -#ifdef CONFIG_PM_SLEEP static int max98090_resume(struct device *dev) { struct max98090_priv *max98090 = dev_get_drvdata(dev); @@ -2645,12 +2642,10 @@ static int max98090_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops max98090_pm = { - SET_RUNTIME_PM_OPS(max98090_runtime_suspend, - max98090_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(NULL, max98090_resume) + RUNTIME_PM_OPS(max98090_runtime_suspend, max98090_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(NULL, max98090_resume) }; #ifdef CONFIG_OF @@ -2673,7 +2668,7 @@ MODULE_DEVICE_TABLE(acpi, max98090_acpi_match); static struct i2c_driver max98090_i2c_driver = { .driver = { .name = "max98090", - .pm = &max98090_pm, + .pm = pm_ptr(&max98090_pm), .of_match_table = of_match_ptr(max98090_of_match), .acpi_match_table = ACPI_PTR(max98090_acpi_match), }, From db001865fdbc6ee446660a06f00437fbb72cfe9c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:43 +0100 Subject: [PATCH 0986/1090] ASoC: max98373: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM and CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-22-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-i2c.c | 6 ++---- sound/soc/codecs/max98373-sdw.c | 10 +++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c index 1f7ff3dbcbbe..56c4ba1f3782 100644 --- a/sound/soc/codecs/max98373-i2c.c +++ b/sound/soc/codecs/max98373-i2c.c @@ -472,7 +472,6 @@ static struct snd_soc_dai_driver max98373_dai[] = { } }; -#ifdef CONFIG_PM_SLEEP static int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); @@ -496,10 +495,9 @@ static int max98373_resume(struct device *dev) regcache_sync(max98373->regmap); return 0; } -#endif static const struct dev_pm_ops max98373_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) + SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) }; static const struct regmap_config max98373_regmap = { @@ -605,7 +603,7 @@ static struct i2c_driver max98373_i2c_driver = { .name = "max98373", .of_match_table = of_match_ptr(max98373_of_match), .acpi_match_table = ACPI_PTR(max98373_acpi_match), - .pm = &max98373_pm, + .pm = pm_ptr(&max98373_pm), }, .probe = max98373_i2c_probe, .id_table = max98373_i2c_id, diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 26860882fd91..6088278e6503 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -246,7 +246,7 @@ static const struct regmap_config max98373_sdw_regmap = { }; /* Power management functions and structure */ -static __maybe_unused int max98373_suspend(struct device *dev) +static int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); int i; @@ -262,7 +262,7 @@ static __maybe_unused int max98373_suspend(struct device *dev) #define MAX98373_PROBE_TIMEOUT 5000 -static __maybe_unused int max98373_resume(struct device *dev) +static int max98373_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct max98373_priv *max98373 = dev_get_drvdata(dev); @@ -292,8 +292,8 @@ regmap_sync: } static const struct dev_pm_ops max98373_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) - SET_RUNTIME_PM_OPS(max98373_suspend, max98373_resume, NULL) + SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) + RUNTIME_PM_OPS(max98373_suspend, max98373_resume, NULL) }; static int max98373_read_prop(struct sdw_slave *slave) @@ -874,7 +874,7 @@ static struct sdw_driver max98373_sdw_driver = { .name = "max98373", .of_match_table = of_match_ptr(max98373_of_match), .acpi_match_table = ACPI_PTR(max98373_acpi_match), - .pm = &max98373_pm, + .pm = pm_ptr(&max98373_pm), }, .probe = max98373_sdw_probe, .remove = max98373_sdw_remove, From 69b638e8d4347113183496684de5f3ac2a1db4b6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:44 +0100 Subject: [PATCH 0987/1090] ASoC: max98390: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-23-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98390.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 1bae253618fd..76296176f948 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -943,7 +943,6 @@ static int max98390_probe(struct snd_soc_component *component) return 0; } -#ifdef CONFIG_PM_SLEEP static int max98390_suspend(struct device *dev) { struct max98390_priv *max98390 = dev_get_drvdata(dev); @@ -967,10 +966,9 @@ static int max98390_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops max98390_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume) + SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume) }; static const struct snd_soc_component_driver soc_codec_dev_max98390 = { @@ -1130,7 +1128,7 @@ static struct i2c_driver max98390_i2c_driver = { .name = "max98390", .of_match_table = of_match_ptr(max98390_of_match), .acpi_match_table = ACPI_PTR(max98390_acpi_match), - .pm = &max98390_pm, + .pm = pm_ptr(&max98390_pm), }, .probe = max98390_i2c_probe, .id_table = max98390_i2c_id, From c009893bc5864d55b0b0cc349413a0eaa2bc17cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:45 +0100 Subject: [PATCH 0988/1090] ASoC: max98396: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-24-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98396.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max98396.c b/sound/soc/codecs/max98396.c index e52bb2266fa1..c1888cd83dbc 100644 --- a/sound/soc/codecs/max98396.c +++ b/sound/soc/codecs/max98396.c @@ -1571,7 +1571,6 @@ static int max98396_probe(struct snd_soc_component *component) return 0; } -#ifdef CONFIG_PM_SLEEP static int max98396_suspend(struct device *dev) { struct max98396_priv *max98396 = dev_get_drvdata(dev); @@ -1616,10 +1615,9 @@ static int max98396_resume(struct device *dev) regcache_sync(max98396->regmap); return 0; } -#endif static const struct dev_pm_ops max98396_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98396_suspend, max98396_resume) + SYSTEM_SLEEP_PM_OPS(max98396_suspend, max98396_resume) }; static const struct snd_soc_component_driver soc_codec_dev_max98396 = { @@ -1904,7 +1902,7 @@ static struct i2c_driver max98396_i2c_driver = { .name = "max98396", .of_match_table = of_match_ptr(max98396_of_match), .acpi_match_table = ACPI_PTR(max98396_acpi_match), - .pm = &max98396_pm, + .pm = pm_ptr(&max98396_pm), }, .probe = max98396_i2c_probe, .id_table = max98396_i2c_id, From b352343e448c45940116dc4a089a288fd820dee9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:46 +0100 Subject: [PATCH 0989/1090] ASoC: max98520: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unsed attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-25-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98520.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max98520.c b/sound/soc/codecs/max98520.c index 479ded22672e..adf5a898c6df 100644 --- a/sound/soc/codecs/max98520.c +++ b/sound/soc/codecs/max98520.c @@ -621,7 +621,7 @@ static int max98520_probe(struct snd_soc_component *component) return 0; } -static int __maybe_unused max98520_suspend(struct device *dev) +static int max98520_suspend(struct device *dev) { struct max98520_priv *max98520 = dev_get_drvdata(dev); @@ -630,7 +630,7 @@ static int __maybe_unused max98520_suspend(struct device *dev) return 0; } -static int __maybe_unused max98520_resume(struct device *dev) +static int max98520_resume(struct device *dev) { struct max98520_priv *max98520 = dev_get_drvdata(dev); @@ -641,7 +641,7 @@ static int __maybe_unused max98520_resume(struct device *dev) } static const struct dev_pm_ops max98520_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98520_suspend, max98520_resume) + SYSTEM_SLEEP_PM_OPS(max98520_suspend, max98520_resume) }; static const struct snd_soc_component_driver soc_codec_dev_max98520 = { @@ -752,7 +752,7 @@ static struct i2c_driver max98520_i2c_driver = { .driver = { .name = "max98520", .of_match_table = of_match_ptr(max98520_of_match), - .pm = &max98520_pm, + .pm = pm_ptr(&max98520_pm), }, .probe = max98520_i2c_probe, .id_table = max98520_i2c_id, From d0029e0a78672932367478e5b3479edfa2738ec0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:47 +0100 Subject: [PATCH 0990/1090] ASoC: max9860: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-26-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max9860.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 4015ed2c47ec..716d16daf7d7 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -539,7 +539,6 @@ static const struct snd_soc_component_driver max9860_component_driver = { .endianness = 1, }; -#ifdef CONFIG_PM static int max9860_suspend(struct device *dev) { struct max9860_priv *max9860 = dev_get_drvdata(dev); @@ -584,10 +583,9 @@ static int max9860_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops max9860_pm_ops = { - SET_RUNTIME_PM_OPS(max9860_suspend, max9860_resume, NULL) + RUNTIME_PM_OPS(max9860_suspend, max9860_resume, NULL) }; static int max9860_probe(struct i2c_client *i2c) @@ -729,7 +727,7 @@ static struct i2c_driver max9860_i2c_driver = { .driver = { .name = "max9860", .of_match_table = max9860_of_match, - .pm = &max9860_pm_ops, + .pm = pm_ptr(&max9860_pm_ops), }, }; From 113d29a94410ff292be090949c43911b11c4d32a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:48 +0100 Subject: [PATCH 0991/1090] ASoC: max98927: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-27-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/max98927.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 747aa6f1d54f..55cc18451a2d 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -731,7 +731,6 @@ static int max98927_probe(struct snd_soc_component *component) return 0; } -#ifdef CONFIG_PM_SLEEP static int max98927_suspend(struct device *dev) { struct max98927_priv *max98927 = dev_get_drvdata(dev); @@ -750,10 +749,9 @@ static int max98927_resume(struct device *dev) regcache_sync(max98927->regmap); return 0; } -#endif static const struct dev_pm_ops max98927_pm = { - SET_SYSTEM_SLEEP_PM_OPS(max98927_suspend, max98927_resume) + SYSTEM_SLEEP_PM_OPS(max98927_suspend, max98927_resume) }; static const struct snd_soc_component_driver soc_component_dev_max98927 = { @@ -902,7 +900,7 @@ static struct i2c_driver max98927_i2c_driver = { .name = "max98927", .of_match_table = of_match_ptr(max98927_of_match), .acpi_match_table = ACPI_PTR(max98927_acpi_match), - .pm = &max98927_pm, + .pm = pm_ptr(&max98927_pm), }, .probe = max98927_i2c_probe, .remove = max98927_i2c_remove, From aa912611c43006e628d14e9319402a77ab0bf97c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:49 +0100 Subject: [PATCH 0992/1090] ASoC: mt6660: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-28-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/mt6660.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index 39a57f643d81..d16bccebae52 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -529,7 +529,7 @@ static void mt6660_i2c_remove(struct i2c_client *client) mutex_destroy(&chip->io_lock); } -static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev) +static int mt6660_i2c_runtime_suspend(struct device *dev) { struct mt6660_chip *chip = dev_get_drvdata(dev); @@ -538,7 +538,7 @@ static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev) MT6660_REG_SYSTEM_CTRL, 0x01, 0x01); } -static int __maybe_unused mt6660_i2c_runtime_resume(struct device *dev) +static int mt6660_i2c_runtime_resume(struct device *dev) { struct mt6660_chip *chip = dev_get_drvdata(dev); @@ -548,8 +548,7 @@ static int __maybe_unused mt6660_i2c_runtime_resume(struct device *dev) } static const struct dev_pm_ops mt6660_dev_pm_ops = { - SET_RUNTIME_PM_OPS(mt6660_i2c_runtime_suspend, - mt6660_i2c_runtime_resume, NULL) + RUNTIME_PM_OPS(mt6660_i2c_runtime_suspend, mt6660_i2c_runtime_resume, NULL) }; static const struct of_device_id __maybe_unused mt6660_of_id[] = { @@ -568,7 +567,7 @@ static struct i2c_driver mt6660_i2c_driver = { .driver = { .name = "mt6660", .of_match_table = of_match_ptr(mt6660_of_id), - .pm = &mt6660_dev_pm_ops, + .pm = pm_ptr(&mt6660_dev_pm_ops), }, .probe = mt6660_i2c_probe, .remove = mt6660_i2c_remove, From 85e8d0f37879f8761dbd137dbdad720fbe7929ca Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:50 +0100 Subject: [PATCH 0993/1090] ASoC: pcm512x: Convert to EXPORT_GPL_DEV_PM_OPS() Use the newer EXPORT_GPL_DEV_PM_OPS() macro together with pm_ptr(), which allows us to drop superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Shenghao Ding Cc: Kevin Lu Cc: Baojun Xu Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-29-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x-i2c.c | 2 +- sound/soc/codecs/pcm512x-spi.c | 2 +- sound/soc/codecs/pcm512x.c | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index 92bcf5179779..a1d849b0c50f 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -79,7 +79,7 @@ static struct i2c_driver pcm512x_i2c_driver = { .name = "pcm512x", .of_match_table = of_match_ptr(pcm512x_of_match), .acpi_match_table = ACPI_PTR(pcm512x_acpi_match), - .pm = &pcm512x_pm_ops, + .pm = pm_ptr(&pcm512x_pm_ops), }, }; diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c index 6629b862f47d..92f7f78a4e20 100644 --- a/sound/soc/codecs/pcm512x-spi.c +++ b/sound/soc/codecs/pcm512x-spi.c @@ -58,7 +58,7 @@ static struct spi_driver pcm512x_spi_driver = { .driver = { .name = "pcm512x", .of_match_table = pcm512x_of_match, - .pm = &pcm512x_pm_ops, + .pm = pm_ptr(&pcm512x_pm_ops), }, }; diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index aa8edf87b743..007dfc0fa224 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1725,7 +1725,6 @@ void pcm512x_remove(struct device *dev) } EXPORT_SYMBOL_GPL(pcm512x_remove); -#ifdef CONFIG_PM static int pcm512x_suspend(struct device *dev) { struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); @@ -1787,12 +1786,10 @@ static int pcm512x_resume(struct device *dev) return 0; } -#endif -const struct dev_pm_ops pcm512x_pm_ops = { - SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) +EXPORT_GPL_DEV_PM_OPS(pcm512x_pm_ops) = { + RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) }; -EXPORT_SYMBOL_GPL(pcm512x_pm_ops); MODULE_DESCRIPTION("ASoC PCM512x codec driver"); MODULE_AUTHOR("Mark Brown "); From b83ab4fb2c6e7c15f769653118243b0974f4c885 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:51 +0100 Subject: [PATCH 0994/1090] ASoC: rt1017-sdca-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-30-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt1017-sdca-sdw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c index 7c8103a0d562..88fc23a4999f 100644 --- a/sound/soc/codecs/rt1017-sdca-sdw.c +++ b/sound/soc/codecs/rt1017-sdca-sdw.c @@ -758,7 +758,7 @@ static const struct sdw_device_id rt1017_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt1017_sdca_id); -static int __maybe_unused rt1017_sdca_dev_suspend(struct device *dev) +static int rt1017_sdca_dev_suspend(struct device *dev) { struct rt1017_sdca_priv *rt1017 = dev_get_drvdata(dev); @@ -772,7 +772,7 @@ static int __maybe_unused rt1017_sdca_dev_suspend(struct device *dev) #define RT1017_PROBE_TIMEOUT 5000 -static int __maybe_unused rt1017_sdca_dev_resume(struct device *dev) +static int rt1017_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1017_sdca_priv *rt1017 = dev_get_drvdata(dev); @@ -802,14 +802,14 @@ regmap_sync: } static const struct dev_pm_ops rt1017_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt1017_sdca_dev_suspend, rt1017_sdca_dev_resume) - SET_RUNTIME_PM_OPS(rt1017_sdca_dev_suspend, rt1017_sdca_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt1017_sdca_dev_suspend, rt1017_sdca_dev_resume) + RUNTIME_PM_OPS(rt1017_sdca_dev_suspend, rt1017_sdca_dev_resume, NULL) }; static struct sdw_driver rt1017_sdca_sdw_driver = { .driver = { .name = "rt1017-sdca", - .pm = &rt1017_sdca_pm, + .pm = pm_ptr(&rt1017_sdca_pm), }, .probe = rt1017_sdca_sdw_probe, .remove = rt1017_sdca_sdw_remove, From 7130c4302b9229dda655235321c34bd5e6dde82e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:52 +0100 Subject: [PATCH 0995/1090] ASoC: rt1308-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-31-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 563df483a466..ea708068f0e8 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -753,7 +753,7 @@ static const struct sdw_device_id rt1308_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt1308_id); -static int __maybe_unused rt1308_dev_suspend(struct device *dev) +static int rt1308_dev_suspend(struct device *dev) { struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); @@ -767,7 +767,7 @@ static int __maybe_unused rt1308_dev_suspend(struct device *dev) #define RT1308_PROBE_TIMEOUT 5000 -static int __maybe_unused rt1308_dev_resume(struct device *dev) +static int rt1308_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); @@ -797,14 +797,14 @@ regmap_sync: } static const struct dev_pm_ops rt1308_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt1308_dev_suspend, rt1308_dev_resume) - SET_RUNTIME_PM_OPS(rt1308_dev_suspend, rt1308_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt1308_dev_suspend, rt1308_dev_resume) + RUNTIME_PM_OPS(rt1308_dev_suspend, rt1308_dev_resume, NULL) }; static struct sdw_driver rt1308_sdw_driver = { .driver = { .name = "rt1308", - .pm = &rt1308_pm, + .pm = pm_ptr(&rt1308_pm), }, .probe = rt1308_sdw_probe, .remove = rt1308_sdw_remove, From dfe8999a4f5ca8f8c67751310d0421e1bfbbae6d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:53 +0100 Subject: [PATCH 0996/1090] ASoC: rt1316-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-32-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt1316-sdw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 22f1ed4e03f1..960b6c4f5a66 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -730,7 +730,7 @@ static const struct sdw_device_id rt1316_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt1316_id); -static int __maybe_unused rt1316_dev_suspend(struct device *dev) +static int rt1316_dev_suspend(struct device *dev) { struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); @@ -744,7 +744,7 @@ static int __maybe_unused rt1316_dev_suspend(struct device *dev) #define RT1316_PROBE_TIMEOUT 5000 -static int __maybe_unused rt1316_dev_resume(struct device *dev) +static int rt1316_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); @@ -774,14 +774,14 @@ regmap_sync: } static const struct dev_pm_ops rt1316_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume) - SET_RUNTIME_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume) + RUNTIME_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume, NULL) }; static struct sdw_driver rt1316_sdw_driver = { .driver = { .name = "rt1316-sdca", - .pm = &rt1316_pm, + .pm = pm_ptr(&rt1316_pm), }, .probe = rt1316_sdw_probe, .remove = rt1316_sdw_remove, From d0bb681f8e9a418e396e6b471866197ecc30bd00 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:54 +0100 Subject: [PATCH 0997/1090] ASoC: rt1318-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-33-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt1318-sdw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c index 319f71f5e60d..4eb636e0c9ed 100644 --- a/sound/soc/codecs/rt1318-sdw.c +++ b/sound/soc/codecs/rt1318-sdw.c @@ -807,7 +807,7 @@ static const struct sdw_device_id rt1318_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt1318_id); -static int __maybe_unused rt1318_dev_suspend(struct device *dev) +static int rt1318_dev_suspend(struct device *dev) { struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); @@ -820,7 +820,7 @@ static int __maybe_unused rt1318_dev_suspend(struct device *dev) #define RT1318_PROBE_TIMEOUT 5000 -static int __maybe_unused rt1318_dev_resume(struct device *dev) +static int rt1318_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); @@ -848,14 +848,14 @@ regmap_sync: } static const struct dev_pm_ops rt1318_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume) - SET_RUNTIME_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume) + RUNTIME_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume, NULL) }; static struct sdw_driver rt1318_sdw_driver = { .driver = { .name = "rt1318-sdca", - .pm = &rt1318_pm, + .pm = pm_ptr(&rt1318_pm), }, .probe = rt1318_sdw_probe, .remove = rt1318_sdw_remove, From 3eedadf3d7049e3ab2c49cf7f444e8f296327ba0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:55 +0100 Subject: [PATCH 0998/1090] ASoC: rt1320-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-34-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt1320-sdw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index d83b236a0450..f51ba345a16e 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -1458,7 +1458,7 @@ static const struct sdw_device_id rt1320_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt1320_id); -static int __maybe_unused rt1320_dev_suspend(struct device *dev) +static int rt1320_dev_suspend(struct device *dev) { struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); @@ -1472,7 +1472,7 @@ static int __maybe_unused rt1320_dev_suspend(struct device *dev) #define RT1320_PROBE_TIMEOUT 5000 -static int __maybe_unused rt1320_dev_resume(struct device *dev) +static int rt1320_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); @@ -1501,14 +1501,14 @@ regmap_sync: } static const struct dev_pm_ops rt1320_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume) - SET_RUNTIME_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume) + RUNTIME_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume, NULL) }; static struct sdw_driver rt1320_sdw_driver = { .driver = { .name = "rt1320-sdca", - .pm = &rt1320_pm, + .pm = pm_ptr(&rt1320_pm), }, .probe = rt1320_sdw_probe, .remove = rt1320_sdw_remove, From fdf698fa3ff22e504505a7c32f9671c5fbbd5513 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:56 +0100 Subject: [PATCH 0999/1090] ASoC: rt5514: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-35-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514-spi.c | 8 ++++---- sound/soc/codecs/rt5514.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index f475c8cfadae..54d84581ec47 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -458,7 +458,7 @@ static int rt5514_spi_probe(struct spi_device *spi) return 0; } -static int __maybe_unused rt5514_suspend(struct device *dev) +static int rt5514_suspend(struct device *dev) { int irq = to_spi_device(dev)->irq; @@ -468,7 +468,7 @@ static int __maybe_unused rt5514_suspend(struct device *dev) return 0; } -static int __maybe_unused rt5514_resume(struct device *dev) +static int rt5514_resume(struct device *dev) { struct rt5514_dsp *rt5514_dsp = dev_get_drvdata(dev); int irq = to_spi_device(dev)->irq; @@ -490,7 +490,7 @@ static int __maybe_unused rt5514_resume(struct device *dev) } static const struct dev_pm_ops rt5514_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(rt5514_suspend, rt5514_resume) + SYSTEM_SLEEP_PM_OPS(rt5514_suspend, rt5514_resume) }; static const struct of_device_id rt5514_of_match[] = { @@ -502,7 +502,7 @@ MODULE_DEVICE_TABLE(of, rt5514_of_match); static struct spi_driver rt5514_spi_driver = { .driver = { .name = "rt5514", - .pm = &rt5514_pm_ops, + .pm = pm_ptr(&rt5514_pm_ops), .of_match_table = of_match_ptr(rt5514_of_match), }, .probe = rt5514_spi_probe, diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index a7f984b5d80f..ab9d81c32be8 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -1231,7 +1231,7 @@ static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev) return 0; } -static __maybe_unused int rt5514_i2c_resume(struct device *dev) +static int rt5514_i2c_resume(struct device *dev) { struct rt5514_priv *rt5514 = dev_get_drvdata(dev); unsigned int val; @@ -1313,7 +1313,7 @@ static int rt5514_i2c_probe(struct i2c_client *i2c) } static const struct dev_pm_ops rt5514_i2_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) + SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) }; static struct i2c_driver rt5514_i2c_driver = { @@ -1321,7 +1321,7 @@ static struct i2c_driver rt5514_i2c_driver = { .name = "rt5514", .acpi_match_table = ACPI_PTR(rt5514_acpi_match), .of_match_table = of_match_ptr(rt5514_of_match), - .pm = &rt5514_i2_pm_ops, + .pm = pm_ptr(&rt5514_i2_pm_ops), }, .probe = rt5514_i2c_probe, .id_table = rt5514_i2c_id, From 71ba303a04ed5b314c88ed0c2eb771cf1df5d215 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:57 +0100 Subject: [PATCH 1000/1090] ASoC: rt5645: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-36-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 2680bcce4c95..343e3bcef0ca 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -4314,7 +4314,7 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c) gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0); } -static int __maybe_unused rt5645_sys_suspend(struct device *dev) +static int rt5645_sys_suspend(struct device *dev) { struct rt5645_priv *rt5645 = dev_get_drvdata(dev); @@ -4327,7 +4327,7 @@ static int __maybe_unused rt5645_sys_suspend(struct device *dev) return 0; } -static int __maybe_unused rt5645_sys_resume(struct device *dev) +static int rt5645_sys_resume(struct device *dev) { struct rt5645_priv *rt5645 = dev_get_drvdata(dev); @@ -4342,7 +4342,7 @@ static int __maybe_unused rt5645_sys_resume(struct device *dev) } static const struct dev_pm_ops rt5645_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt5645_sys_suspend, rt5645_sys_resume) + SYSTEM_SLEEP_PM_OPS(rt5645_sys_suspend, rt5645_sys_resume) }; static struct i2c_driver rt5645_i2c_driver = { @@ -4350,7 +4350,7 @@ static struct i2c_driver rt5645_i2c_driver = { .name = "rt5645", .of_match_table = of_match_ptr(rt5645_of_match), .acpi_match_table = ACPI_PTR(rt5645_acpi_match), - .pm = &rt5645_pm, + .pm = pm_ptr(&rt5645_pm), }, .probe = rt5645_i2c_probe, .remove = rt5645_i2c_remove, From ef57148d2cea0c267504642eaff36da3df953496 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:58 +0100 Subject: [PATCH 1001/1090] ASoC: rt5682-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-37-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 5edf11e136b4..aa229894129b 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -709,7 +709,7 @@ static const struct sdw_device_id rt5682_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt5682_id); -static int __maybe_unused rt5682_dev_suspend(struct device *dev) +static int rt5682_dev_suspend(struct device *dev) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); @@ -725,7 +725,7 @@ static int __maybe_unused rt5682_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt5682_dev_system_suspend(struct device *dev) +static int rt5682_dev_system_suspend(struct device *dev) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -753,7 +753,7 @@ static int __maybe_unused rt5682_dev_system_suspend(struct device *dev) return rt5682_dev_suspend(dev); } -static int __maybe_unused rt5682_dev_resume(struct device *dev) +static int rt5682_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt5682_priv *rt5682 = dev_get_drvdata(dev); @@ -791,14 +791,14 @@ regmap_sync: } static const struct dev_pm_ops rt5682_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_system_suspend, rt5682_dev_resume) - SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt5682_dev_system_suspend, rt5682_dev_resume) + RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL) }; static struct sdw_driver rt5682_sdw_driver = { .driver = { .name = "rt5682", - .pm = &rt5682_pm, + .pm = pm_ptr(&rt5682_pm), }, .probe = rt5682_sdw_probe, .remove = rt5682_sdw_remove, From 569f75535df2d2cdc5197033c9955bedcd2f50e6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:54:59 +0100 Subject: [PATCH 1002/1090] ASoC: rt700-sdw: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-38-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt700-sdw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 24cb895b759f..44543c0da177 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -475,7 +475,7 @@ static const struct sdw_device_id rt700_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt700_id); -static int __maybe_unused rt700_dev_suspend(struct device *dev) +static int rt700_dev_suspend(struct device *dev) { struct rt700_priv *rt700 = dev_get_drvdata(dev); @@ -490,7 +490,7 @@ static int __maybe_unused rt700_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt700_dev_system_suspend(struct device *dev) +static int rt700_dev_system_suspend(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt700_priv *rt700 = dev_get_drvdata(dev); @@ -520,7 +520,7 @@ static int __maybe_unused rt700_dev_system_suspend(struct device *dev) #define RT700_PROBE_TIMEOUT 5000 -static int __maybe_unused rt700_dev_resume(struct device *dev) +static int rt700_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt700_priv *rt700 = dev_get_drvdata(dev); @@ -551,14 +551,14 @@ regmap_sync: } static const struct dev_pm_ops rt700_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt700_dev_system_suspend, rt700_dev_resume) - SET_RUNTIME_PM_OPS(rt700_dev_suspend, rt700_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt700_dev_system_suspend, rt700_dev_resume) + RUNTIME_PM_OPS(rt700_dev_suspend, rt700_dev_resume, NULL) }; static struct sdw_driver rt700_sdw_driver = { .driver = { .name = "rt700", - .pm = &rt700_pm, + .pm = pm_ptr(&rt700_pm), }, .probe = rt700_sdw_probe, .remove = rt700_sdw_remove, From 98cdea5b7acd06e7b188ce40c7450a6240d1d0a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:00 +0100 Subject: [PATCH 1003/1090] ASoC: rt711: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-39-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca-sdw.c | 12 ++++++------ sound/soc/codecs/rt711-sdw.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index f5933d2e085e..adf05f64259b 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -380,7 +380,7 @@ static const struct sdw_device_id rt711_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt711_sdca_id); -static int __maybe_unused rt711_sdca_dev_suspend(struct device *dev) +static int rt711_sdca_dev_suspend(struct device *dev) { struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); @@ -396,7 +396,7 @@ static int __maybe_unused rt711_sdca_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt711_sdca_dev_system_suspend(struct device *dev) +static int rt711_sdca_dev_system_suspend(struct device *dev) { struct rt711_sdca_priv *rt711_sdca = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -428,7 +428,7 @@ static int __maybe_unused rt711_sdca_dev_system_suspend(struct device *dev) #define RT711_PROBE_TIMEOUT 5000 -static int __maybe_unused rt711_sdca_dev_resume(struct device *dev) +static int rt711_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); @@ -467,14 +467,14 @@ regmap_sync: } static const struct dev_pm_ops rt711_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_system_suspend, rt711_sdca_dev_resume) - SET_RUNTIME_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_system_suspend, rt711_sdca_dev_resume) + RUNTIME_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume, NULL) }; static struct sdw_driver rt711_sdca_sdw_driver = { .driver = { .name = "rt711-sdca", - .pm = &rt711_sdca_pm, + .pm = pm_ptr(&rt711_sdca_pm), }, .probe = rt711_sdca_sdw_probe, .remove = rt711_sdca_sdw_remove, diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index dfda6bb5c6f8..93a5a89a96b1 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -482,7 +482,7 @@ static const struct sdw_device_id rt711_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt711_id); -static int __maybe_unused rt711_dev_suspend(struct device *dev) +static int rt711_dev_suspend(struct device *dev) { struct rt711_priv *rt711 = dev_get_drvdata(dev); @@ -498,7 +498,7 @@ static int __maybe_unused rt711_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt711_dev_system_suspend(struct device *dev) +static int rt711_dev_system_suspend(struct device *dev) { struct rt711_priv *rt711 = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -528,7 +528,7 @@ static int __maybe_unused rt711_dev_system_suspend(struct device *dev) #define RT711_PROBE_TIMEOUT 5000 -static int __maybe_unused rt711_dev_resume(struct device *dev) +static int rt711_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt711_priv *rt711 = dev_get_drvdata(dev); @@ -564,14 +564,14 @@ regmap_sync: } static const struct dev_pm_ops rt711_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt711_dev_system_suspend, rt711_dev_resume) - SET_RUNTIME_PM_OPS(rt711_dev_suspend, rt711_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt711_dev_system_suspend, rt711_dev_resume) + RUNTIME_PM_OPS(rt711_dev_suspend, rt711_dev_resume, NULL) }; static struct sdw_driver rt711_sdw_driver = { .driver = { .name = "rt711", - .pm = &rt711_pm, + .pm = pm_ptr(&rt711_pm), }, .probe = rt711_sdw_probe, .remove = rt711_sdw_remove, From e4efc3694d8ab8cd7c0f230556d8457ad8d34899 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:01 +0100 Subject: [PATCH 1004/1090] ASoC: rt712: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-40-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca-dmic.c | 12 ++++++------ sound/soc/codecs/rt712-sdca-sdw.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c index ee5435f3a80a..db011da63bd9 100644 --- a/sound/soc/codecs/rt712-sdca-dmic.c +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -884,7 +884,7 @@ static const struct sdw_device_id rt712_sdca_dmic_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt712_sdca_dmic_id); -static int __maybe_unused rt712_sdca_dmic_dev_suspend(struct device *dev) +static int rt712_sdca_dmic_dev_suspend(struct device *dev) { struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); @@ -897,7 +897,7 @@ static int __maybe_unused rt712_sdca_dmic_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt712_sdca_dmic_dev_system_suspend(struct device *dev) +static int rt712_sdca_dmic_dev_system_suspend(struct device *dev) { struct rt712_sdca_dmic_priv *rt712_sdca = dev_get_drvdata(dev); @@ -909,7 +909,7 @@ static int __maybe_unused rt712_sdca_dmic_dev_system_suspend(struct device *dev) #define RT712_PROBE_TIMEOUT 5000 -static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev) +static int rt712_sdca_dmic_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); @@ -941,8 +941,8 @@ regmap_sync: } static const struct dev_pm_ops rt712_sdca_dmic_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dmic_dev_system_suspend, rt712_sdca_dmic_dev_resume) - SET_RUNTIME_PM_OPS(rt712_sdca_dmic_dev_suspend, rt712_sdca_dmic_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt712_sdca_dmic_dev_system_suspend, rt712_sdca_dmic_dev_resume) + RUNTIME_PM_OPS(rt712_sdca_dmic_dev_suspend, rt712_sdca_dmic_dev_resume, NULL) }; @@ -978,7 +978,7 @@ static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave) static struct sdw_driver rt712_sdca_dmic_sdw_driver = { .driver = { .name = "rt712-sdca-dmic", - .pm = &rt712_sdca_dmic_pm, + .pm = pm_ptr(&rt712_sdca_dmic_pm), }, .probe = rt712_sdca_dmic_sdw_probe, .remove = rt712_sdca_dmic_sdw_remove, diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c index b584a3f854b8..ea07131edfa2 100644 --- a/sound/soc/codecs/rt712-sdca-sdw.c +++ b/sound/soc/codecs/rt712-sdca-sdw.c @@ -400,7 +400,7 @@ static const struct sdw_device_id rt712_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt712_sdca_id); -static int __maybe_unused rt712_sdca_dev_suspend(struct device *dev) +static int rt712_sdca_dev_suspend(struct device *dev) { struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); @@ -416,7 +416,7 @@ static int __maybe_unused rt712_sdca_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt712_sdca_dev_system_suspend(struct device *dev) +static int rt712_sdca_dev_system_suspend(struct device *dev) { struct rt712_sdca_priv *rt712_sdca = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -448,7 +448,7 @@ static int __maybe_unused rt712_sdca_dev_system_suspend(struct device *dev) #define RT712_PROBE_TIMEOUT 5000 -static int __maybe_unused rt712_sdca_dev_resume(struct device *dev) +static int rt712_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); @@ -488,14 +488,14 @@ regmap_sync: } static const struct dev_pm_ops rt712_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt712_sdca_dev_system_suspend, rt712_sdca_dev_resume) - SET_RUNTIME_PM_OPS(rt712_sdca_dev_suspend, rt712_sdca_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt712_sdca_dev_system_suspend, rt712_sdca_dev_resume) + RUNTIME_PM_OPS(rt712_sdca_dev_suspend, rt712_sdca_dev_resume, NULL) }; static struct sdw_driver rt712_sdca_sdw_driver = { .driver = { .name = "rt712-sdca", - .pm = &rt712_sdca_pm, + .pm = pm_ptr(&rt712_sdca_pm), }, .probe = rt712_sdca_sdw_probe, .remove = rt712_sdca_sdw_remove, From a83d01d19ef285f279331ffb7d4c6f9a37201c15 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:02 +0100 Subject: [PATCH 1005/1090] ASoC: rt715: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-41-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca-sdw.c | 10 +++++----- sound/soc/codecs/rt715-sdw.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index c8dabb9b16b5..ce7d8955efc3 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -205,7 +205,7 @@ static const struct sdw_device_id rt715_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt715_sdca_id); -static int __maybe_unused rt715_dev_suspend(struct device *dev) +static int rt715_dev_suspend(struct device *dev) { struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); @@ -222,7 +222,7 @@ static int __maybe_unused rt715_dev_suspend(struct device *dev) #define RT715_PROBE_TIMEOUT 5000 -static int __maybe_unused rt715_dev_resume(struct device *dev) +static int rt715_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); @@ -263,14 +263,14 @@ regmap_sync: } static const struct dev_pm_ops rt715_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) - SET_RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) + RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) }; static struct sdw_driver rt715_sdw_driver = { .driver = { .name = "rt715-sdca", - .pm = &rt715_pm, + .pm = pm_ptr(&rt715_pm), }, .probe = rt715_sdca_sdw_probe, .remove = rt715_sdca_sdw_remove, diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index cd702574c84b..a3df4bbedf86 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -485,7 +485,7 @@ static const struct sdw_device_id rt715_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt715_id); -static int __maybe_unused rt715_dev_suspend(struct device *dev) +static int rt715_dev_suspend(struct device *dev) { struct rt715_priv *rt715 = dev_get_drvdata(dev); @@ -499,7 +499,7 @@ static int __maybe_unused rt715_dev_suspend(struct device *dev) #define RT715_PROBE_TIMEOUT 5000 -static int __maybe_unused rt715_dev_resume(struct device *dev) +static int rt715_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt715_priv *rt715 = dev_get_drvdata(dev); @@ -530,14 +530,14 @@ regmap_sync: } static const struct dev_pm_ops rt715_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) - SET_RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) + RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) }; static struct sdw_driver rt715_sdw_driver = { .driver = { .name = "rt715", - .pm = &rt715_pm, + .pm = pm_ptr(&rt715_pm), }, .probe = rt715_sdw_probe, .remove = rt715_sdw_remove, From 8798eaedd6d756ea58832e222840b2e387707ede Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:03 +0100 Subject: [PATCH 1006/1090] ASoC: rt721: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-42-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt721-sdca-sdw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c index c71453da088a..582b47d69278 100644 --- a/sound/soc/codecs/rt721-sdca-sdw.c +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -437,7 +437,7 @@ static const struct sdw_device_id rt721_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt721_sdca_id); -static int __maybe_unused rt721_sdca_dev_suspend(struct device *dev) +static int rt721_sdca_dev_suspend(struct device *dev) { struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); @@ -453,7 +453,7 @@ static int __maybe_unused rt721_sdca_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt721_sdca_dev_system_suspend(struct device *dev) +static int rt721_sdca_dev_system_suspend(struct device *dev) { struct rt721_sdca_priv *rt721_sdca = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -485,7 +485,7 @@ static int __maybe_unused rt721_sdca_dev_system_suspend(struct device *dev) #define RT721_PROBE_TIMEOUT 5000 -static int __maybe_unused rt721_sdca_dev_resume(struct device *dev) +static int rt721_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); @@ -524,15 +524,15 @@ regmap_sync: } static const struct dev_pm_ops rt721_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt721_sdca_dev_system_suspend, rt721_sdca_dev_resume) - SET_RUNTIME_PM_OPS(rt721_sdca_dev_suspend, rt721_sdca_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt721_sdca_dev_system_suspend, rt721_sdca_dev_resume) + RUNTIME_PM_OPS(rt721_sdca_dev_suspend, rt721_sdca_dev_resume, NULL) }; static struct sdw_driver rt721_sdca_sdw_driver = { .driver = { .name = "rt721-sdca", .owner = THIS_MODULE, - .pm = &rt721_sdca_pm, + .pm = pm_ptr(&rt721_sdca_pm), }, .probe = rt721_sdca_sdw_probe, .remove = rt721_sdca_sdw_remove, From 957e8cb375e60699c7acf52c771fad5979cef359 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:04 +0100 Subject: [PATCH 1007/1090] ASoC: rt722: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-43-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt722-sdca-sdw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 543cb32c2463..11e2e8f68a98 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -430,7 +430,7 @@ static const struct sdw_device_id rt722_sdca_id[] = { }; MODULE_DEVICE_TABLE(sdw, rt722_sdca_id); -static int __maybe_unused rt722_sdca_dev_suspend(struct device *dev) +static int rt722_sdca_dev_suspend(struct device *dev) { struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev); @@ -445,7 +445,7 @@ static int __maybe_unused rt722_sdca_dev_suspend(struct device *dev) return 0; } -static int __maybe_unused rt722_sdca_dev_system_suspend(struct device *dev) +static int rt722_sdca_dev_system_suspend(struct device *dev) { struct rt722_sdca_priv *rt722_sdca = dev_get_drvdata(dev); struct sdw_slave *slave = dev_to_sdw_dev(dev); @@ -477,7 +477,7 @@ static int __maybe_unused rt722_sdca_dev_system_suspend(struct device *dev) #define RT722_PROBE_TIMEOUT 5000 -static int __maybe_unused rt722_sdca_dev_resume(struct device *dev) +static int rt722_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev); @@ -514,14 +514,14 @@ regmap_sync: } static const struct dev_pm_ops rt722_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt722_sdca_dev_system_suspend, rt722_sdca_dev_resume) - SET_RUNTIME_PM_OPS(rt722_sdca_dev_suspend, rt722_sdca_dev_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rt722_sdca_dev_system_suspend, rt722_sdca_dev_resume) + RUNTIME_PM_OPS(rt722_sdca_dev_suspend, rt722_sdca_dev_resume, NULL) }; static struct sdw_driver rt722_sdca_sdw_driver = { .driver = { .name = "rt722-sdca", - .pm = &rt722_sdca_pm, + .pm = pm_ptr(&rt722_sdca_pm), }, .probe = rt722_sdca_sdw_probe, .remove = rt722_sdca_sdw_remove, From 9aaa57d36f387df01762ced4e362bcb89872d80b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:05 +0100 Subject: [PATCH 1008/1090] ASoC: rt9120: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-44-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rt9120.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt9120.c b/sound/soc/codecs/rt9120.c index 733a7d130a95..97f56af25577 100644 --- a/sound/soc/codecs/rt9120.c +++ b/sound/soc/codecs/rt9120.c @@ -590,7 +590,7 @@ static void rt9120_remove(struct i2c_client *i2c) pm_runtime_set_suspended(&i2c->dev); } -static int __maybe_unused rt9120_runtime_suspend(struct device *dev) +static int rt9120_runtime_suspend(struct device *dev) { struct rt9120_data *data = dev_get_drvdata(dev); @@ -603,7 +603,7 @@ static int __maybe_unused rt9120_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused rt9120_runtime_resume(struct device *dev) +static int rt9120_runtime_resume(struct device *dev) { struct rt9120_data *data = dev_get_drvdata(dev); @@ -618,7 +618,7 @@ static int __maybe_unused rt9120_runtime_resume(struct device *dev) } static const struct dev_pm_ops rt9120_pm_ops = { - SET_RUNTIME_PM_OPS(rt9120_runtime_suspend, rt9120_runtime_resume, NULL) + RUNTIME_PM_OPS(rt9120_runtime_suspend, rt9120_runtime_resume, NULL) }; static const struct of_device_id __maybe_unused rt9120_device_table[] = { @@ -631,7 +631,7 @@ static struct i2c_driver rt9120_driver = { .driver = { .name = "rt9120", .of_match_table = rt9120_device_table, - .pm = &rt9120_pm_ops, + .pm = pm_ptr(&rt9120_pm_ops), }, .probe = rt9120_probe, .remove = rt9120_remove, From 9eb264d115a55eb40b55c7481c113e6c56560700 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:06 +0100 Subject: [PATCH 1009/1090] ASoC: rtq9128: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS(), which allows us dropping ugly __maybe_unsed attributes. Merely a cleanup, there should be no actual code change. Cc: Oder Chiou Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-45-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/rtq9128.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c index aa3eadecd974..391cc03d687f 100644 --- a/sound/soc/codecs/rtq9128.c +++ b/sound/soc/codecs/rtq9128.c @@ -729,7 +729,7 @@ static int rtq9128_probe(struct i2c_client *i2c) return devm_snd_soc_register_component(dev, &rtq9128_comp_driver, &rtq9128_dai, 1); } -static int __maybe_unused rtq9128_pm_runtime_suspend(struct device *dev) +static int rtq9128_pm_runtime_suspend(struct device *dev) { struct rtq9128_data *data = dev_get_drvdata(dev); struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -746,7 +746,7 @@ static int __maybe_unused rtq9128_pm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused rtq9128_pm_runtime_resume(struct device *dev) +static int rtq9128_pm_runtime_resume(struct device *dev) { struct rtq9128_data *data = dev_get_drvdata(dev); struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -764,8 +764,8 @@ static int __maybe_unused rtq9128_pm_runtime_resume(struct device *dev) return regcache_sync(regmap); } -static const struct dev_pm_ops __maybe_unused rtq9128_pm_ops = { - SET_RUNTIME_PM_OPS(rtq9128_pm_runtime_suspend, rtq9128_pm_runtime_resume, NULL) +static const struct dev_pm_ops rtq9128_pm_ops = { + RUNTIME_PM_OPS(rtq9128_pm_runtime_suspend, rtq9128_pm_runtime_resume, NULL) }; static const struct of_device_id rtq9128_device_table[] = { From 1570c33f2f38b6dff04ee1c7d7b38d1702e81b5f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:07 +0100 Subject: [PATCH 1010/1090] ASoC: tas2552: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Shenghao Ding Cc: Kevin Lu Cc: Baojun Xu Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-46-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/tas2552.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 684d52ec6600..b56dd279d90a 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -138,7 +138,6 @@ static const struct snd_soc_dapm_route tas2552_audio_map[] = { {"ASI OUT", NULL, "DMIC"} }; -#ifdef CONFIG_PM static void tas2552_sw_shutdown(struct tas2552_data *tas2552, int sw_shutdown) { u8 cfg1_reg = 0; @@ -152,7 +151,6 @@ static void tas2552_sw_shutdown(struct tas2552_data *tas2552, int sw_shutdown) snd_soc_component_update_bits(tas2552->component, TAS2552_CFG_1, TAS2552_SWS, cfg1_reg); } -#endif static int tas2552_setup_pll(struct snd_soc_component *component, struct snd_pcm_hw_params *params) @@ -480,7 +478,6 @@ static int tas2552_mute(struct snd_soc_dai *dai, int mute, int direction) return 0; } -#ifdef CONFIG_PM static int tas2552_runtime_suspend(struct device *dev) { struct tas2552_data *tas2552 = dev_get_drvdata(dev); @@ -508,11 +505,9 @@ static int tas2552_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops tas2552_pm = { - SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume, - NULL) + RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume, NULL) }; static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = { @@ -768,7 +763,7 @@ static struct i2c_driver tas2552_i2c_driver = { .driver = { .name = "tas2552", .of_match_table = of_match_ptr(tas2552_of_match), - .pm = &tas2552_pm, + .pm = pm_ptr(&tas2552_pm), }, .probe = tas2552_probe, .remove = tas2552_i2c_remove, From 2db8e2c7c6f9cccfdcb1c710b9b3008b73eb5505 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:08 +0100 Subject: [PATCH 1011/1090] ASoC: ts3a227e: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-47-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/ts3a227e.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index b9eb59e3bfa0..5ce0db9326fd 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c @@ -399,7 +399,6 @@ static int ts3a227e_i2c_probe(struct i2c_client *i2c) return 0; } -#ifdef CONFIG_PM_SLEEP static int ts3a227e_suspend(struct device *dev) { struct ts3a227e *ts3a227e = dev_get_drvdata(dev); @@ -419,10 +418,9 @@ static int ts3a227e_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops ts3a227e_pm = { - SET_SYSTEM_SLEEP_PM_OPS(ts3a227e_suspend, ts3a227e_resume) + SYSTEM_SLEEP_PM_OPS(ts3a227e_suspend, ts3a227e_resume) }; static const struct i2c_device_id ts3a227e_i2c_ids[] = { @@ -450,7 +448,7 @@ MODULE_DEVICE_TABLE(acpi, ts3a227e_acpi_match); static struct i2c_driver ts3a227e_driver = { .driver = { .name = "ts3a227e", - .pm = &ts3a227e_pm, + .pm = pm_ptr(&ts3a227e_pm), .of_match_table = of_match_ptr(ts3a227e_of_match), .acpi_match_table = ACPI_PTR(ts3a227e_acpi_match), }, From 40a3111b8f18640885ad2041d52dc1d429cf60b1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:09 +0100 Subject: [PATCH 1012/1090] ASoC: wcd937x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-48-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wcd937x-sdw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c index 4891fa0c963f..1bfe7383b311 100644 --- a/sound/soc/codecs/wcd937x-sdw.c +++ b/sound/soc/codecs/wcd937x-sdw.c @@ -1124,7 +1124,7 @@ static const struct sdw_device_id wcd9370_slave_id[] = { }; MODULE_DEVICE_TABLE(sdw, wcd9370_slave_id); -static int __maybe_unused wcd937x_sdw_runtime_suspend(struct device *dev) +static int wcd937x_sdw_runtime_suspend(struct device *dev) { struct wcd937x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1136,7 +1136,7 @@ static int __maybe_unused wcd937x_sdw_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wcd937x_sdw_runtime_resume(struct device *dev) +static int wcd937x_sdw_runtime_resume(struct device *dev) { struct wcd937x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1149,7 +1149,7 @@ static int __maybe_unused wcd937x_sdw_runtime_resume(struct device *dev) } static const struct dev_pm_ops wcd937x_sdw_pm_ops = { - SET_RUNTIME_PM_OPS(wcd937x_sdw_runtime_suspend, wcd937x_sdw_runtime_resume, NULL) + RUNTIME_PM_OPS(wcd937x_sdw_runtime_suspend, wcd937x_sdw_runtime_resume, NULL) }; static struct sdw_driver wcd9370_codec_driver = { @@ -1159,7 +1159,7 @@ static struct sdw_driver wcd9370_codec_driver = { .id_table = wcd9370_slave_id, .driver = { .name = "wcd9370-codec", - .pm = &wcd937x_sdw_pm_ops, + .pm = pm_ptr(&wcd937x_sdw_pm_ops), } }; module_sdw_driver(wcd9370_codec_driver); From a0f0a8814ab4167992f958e804051ea4791b8603 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:10 +0100 Subject: [PATCH 1013/1090] ASoC: wcd938x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-49-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wcd938x-sdw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c index 4e2ae542cee3..cabddadc90ef 100644 --- a/sound/soc/codecs/wcd938x-sdw.c +++ b/sound/soc/codecs/wcd938x-sdw.c @@ -1311,7 +1311,7 @@ static const struct sdw_device_id wcd9380_slave_id[] = { }; MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id); -static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev) +static int wcd938x_sdw_runtime_suspend(struct device *dev) { struct wcd938x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1323,7 +1323,7 @@ static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev) +static int wcd938x_sdw_runtime_resume(struct device *dev) { struct wcd938x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1338,7 +1338,7 @@ static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev) } static const struct dev_pm_ops wcd938x_sdw_pm_ops = { - SET_RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL) + RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL) }; @@ -1349,7 +1349,7 @@ static struct sdw_driver wcd9380_codec_driver = { .id_table = wcd9380_slave_id, .driver = { .name = "wcd9380-codec", - .pm = &wcd938x_sdw_pm_ops, + .pm = pm_ptr(&wcd938x_sdw_pm_ops), } }; module_sdw_driver(wcd9380_codec_driver); From 6714a569c839c658f882b2f38bbe430a8778f261 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:11 +0100 Subject: [PATCH 1014/1090] ASoC: wcd939x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-50-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wcd939x-sdw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wcd939x-sdw.c b/sound/soc/codecs/wcd939x-sdw.c index 36868fad3e8b..f7a9323a9fea 100644 --- a/sound/soc/codecs/wcd939x-sdw.c +++ b/sound/soc/codecs/wcd939x-sdw.c @@ -1507,7 +1507,7 @@ static const struct sdw_device_id wcd9390_slave_id[] = { }; MODULE_DEVICE_TABLE(sdw, wcd9390_slave_id); -static int __maybe_unused wcd939x_sdw_runtime_suspend(struct device *dev) +static int wcd939x_sdw_runtime_suspend(struct device *dev) { struct wcd939x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1519,7 +1519,7 @@ static int __maybe_unused wcd939x_sdw_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wcd939x_sdw_runtime_resume(struct device *dev) +static int wcd939x_sdw_runtime_resume(struct device *dev) { struct wcd939x_sdw_priv *wcd = dev_get_drvdata(dev); @@ -1532,7 +1532,7 @@ static int __maybe_unused wcd939x_sdw_runtime_resume(struct device *dev) } static const struct dev_pm_ops wcd939x_sdw_pm_ops = { - SET_RUNTIME_PM_OPS(wcd939x_sdw_runtime_suspend, wcd939x_sdw_runtime_resume, NULL) + RUNTIME_PM_OPS(wcd939x_sdw_runtime_suspend, wcd939x_sdw_runtime_resume, NULL) }; static struct sdw_driver wcd9390_codec_driver = { @@ -1542,7 +1542,7 @@ static struct sdw_driver wcd9390_codec_driver = { .id_table = wcd9390_slave_id, .driver = { .name = "wcd9390-codec", - .pm = &wcd939x_sdw_pm_ops, + .pm = pm_ptr(&wcd939x_sdw_pm_ops), } }; module_sdw_driver(wcd9390_codec_driver); From 208a479d039202681f1b80a5ccbb2c72a494b55b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:12 +0100 Subject: [PATCH 1015/1090] ASoC: wm2200: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes and superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-51-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 7ed4ac5cce3c..87418c838ca0 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2429,7 +2429,6 @@ static void wm2200_i2c_remove(struct i2c_client *i2c) wm2200->core_supplies); } -#ifdef CONFIG_PM static int wm2200_runtime_suspend(struct device *dev) { struct wm2200_priv *wm2200 = dev_get_drvdata(dev); @@ -2466,11 +2465,9 @@ static int wm2200_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops wm2200_pm = { - SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, - NULL) + RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, NULL) }; static const struct i2c_device_id wm2200_i2c_id[] = { @@ -2482,7 +2479,7 @@ MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); static struct i2c_driver wm2200_i2c_driver = { .driver = { .name = "wm2200", - .pm = &wm2200_pm, + .pm = pm_ptr(&wm2200_pm), }, .probe = wm2200_i2c_probe, .remove = wm2200_i2c_remove, From adcb5d32f7318b21d2a94d9542307801cb5e08c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:13 +0100 Subject: [PATCH 1016/1090] ASoC: wm5100: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-52-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index dfeec55159a6..d9e5762324df 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2625,7 +2625,6 @@ static void wm5100_i2c_remove(struct i2c_client *i2c) gpiod_set_value_cansleep(wm5100->ldo_ena, 0); } -#ifdef CONFIG_PM static int wm5100_runtime_suspend(struct device *dev) { struct wm5100_priv *wm5100 = dev_get_drvdata(dev); @@ -2662,11 +2661,9 @@ static int wm5100_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops wm5100_pm = { - SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, - NULL) + RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, NULL) }; static const struct i2c_device_id wm5100_i2c_id[] = { @@ -2678,7 +2675,7 @@ MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); static struct i2c_driver wm5100_i2c_driver = { .driver = { .name = "wm5100", - .pm = &wm5100_pm, + .pm = pm_ptr(&wm5100_pm), }, .probe = wm5100_i2c_probe, .remove = wm5100_i2c_remove, From 30200e61f8b8a72cf87f7ccd407c54049288f7be Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:14 +0100 Subject: [PATCH 1017/1090] ASoC: wm8804: Convert to EXPORT_GPL_DEV_PM_OPS() Use the newer EXPORT_GPL_DEV_PM_OPS() macro together with pm_ptr(), which allows us to drop superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-53-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8804-i2c.c | 2 +- sound/soc/codecs/wm8804-spi.c | 2 +- sound/soc/codecs/wm8804.c | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index e80dad87219b..3380d7301b17 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c @@ -56,7 +56,7 @@ MODULE_DEVICE_TABLE(acpi, wm8804_acpi_match); static struct i2c_driver wm8804_i2c_driver = { .driver = { .name = "wm8804", - .pm = &wm8804_pm, + .pm = pm_ptr(&wm8804_pm), .of_match_table = of_match_ptr(wm8804_of_match), .acpi_match_table = ACPI_PTR(wm8804_acpi_match), }, diff --git a/sound/soc/codecs/wm8804-spi.c b/sound/soc/codecs/wm8804-spi.c index 628568724c20..cf74abfb1a2c 100644 --- a/sound/soc/codecs/wm8804-spi.c +++ b/sound/soc/codecs/wm8804-spi.c @@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, wm8804_of_match); static struct spi_driver wm8804_spi_driver = { .driver = { .name = "wm8804", - .pm = &wm8804_pm, + .pm = pm_ptr(&wm8804_pm), .of_match_table = wm8804_of_match, }, .probe = wm8804_spi_probe, diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 0a879c29eb04..48700cc25cb0 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -680,7 +680,6 @@ void wm8804_remove(struct device *dev) } EXPORT_SYMBOL_GPL(wm8804_remove); -#if IS_ENABLED(CONFIG_PM) static int wm8804_runtime_resume(struct device *dev) { struct wm8804_priv *wm8804 = dev_get_drvdata(dev); @@ -713,12 +712,10 @@ static int wm8804_runtime_suspend(struct device *dev) return 0; } -#endif -const struct dev_pm_ops wm8804_pm = { - SET_RUNTIME_PM_OPS(wm8804_runtime_suspend, wm8804_runtime_resume, NULL) +EXPORT_GPL_DEV_PM_OPS(wm8804_pm) = { + RUNTIME_PM_OPS(wm8804_runtime_suspend, wm8804_runtime_resume, NULL) }; -EXPORT_SYMBOL_GPL(wm8804_pm); MODULE_DESCRIPTION("ASoC WM8804 driver"); MODULE_AUTHOR("Dimitris Papastamos "); From 327e7dd45cea34e7a1334fcc35b9e122c05b181f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:15 +0100 Subject: [PATCH 1018/1090] ASoC: wm8962: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-54-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 0aaac24eeb5a..68f746626c33 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3850,7 +3850,6 @@ static void wm8962_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); } -#ifdef CONFIG_PM static int wm8962_runtime_resume(struct device *dev) { struct wm8962_priv *wm8962 = dev_get_drvdata(dev); @@ -3930,11 +3929,10 @@ static int wm8962_runtime_suspend(struct device *dev) return 0; } -#endif static const struct dev_pm_ops wm8962_pm = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) }; static const struct i2c_device_id wm8962_i2c_id[] = { @@ -3953,7 +3951,7 @@ static struct i2c_driver wm8962_i2c_driver = { .driver = { .name = "wm8962", .of_match_table = wm8962_of_match, - .pm = &wm8962_pm, + .pm = pm_ptr(&wm8962_pm), }, .probe = wm8962_i2c_probe, .remove = wm8962_i2c_remove, From ae5ad50b9fead07c8336a606ac36fbca9c73790d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:16 +0100 Subject: [PATCH 1019/1090] ASoC: wm8994: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: patches@opensource.cirrus.com Reviewed-by: Charles Keepax Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-55-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 69a22992c281..240ec1bed234 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -4662,7 +4662,6 @@ static void wm8994_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int wm8994_suspend(struct device *dev) { struct wm8994_priv *wm8994 = dev_get_drvdata(dev); @@ -4687,16 +4686,15 @@ static int wm8994_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops wm8994_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume) + SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume) }; static struct platform_driver wm8994_codec_driver = { .driver = { .name = "wm8994-codec", - .pm = &wm8994_pm_ops, + .pm = pm_ptr(&wm8994_pm_ops), }, .probe = wm8994_probe, .remove = wm8994_remove, From 6fb2ff498d5a2a06998e1bd61b0954fd71e6d718 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:17 +0100 Subject: [PATCH 1020/1090] ASoC: wsa881x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Srinivas Kandagatla Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-56-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wsa881x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index a3999bb6d5e2..6627d2da3722 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1169,7 +1169,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, ARRAY_SIZE(wsa881x_dais)); } -static int __maybe_unused wsa881x_runtime_suspend(struct device *dev) +static int wsa881x_runtime_suspend(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); struct wsa881x_priv *wsa881x = dev_get_drvdata(dev); @@ -1182,7 +1182,7 @@ static int __maybe_unused wsa881x_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wsa881x_runtime_resume(struct device *dev) +static int wsa881x_runtime_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -1206,7 +1206,7 @@ static int __maybe_unused wsa881x_runtime_resume(struct device *dev) } static const struct dev_pm_ops wsa881x_pm_ops = { - SET_RUNTIME_PM_OPS(wsa881x_runtime_suspend, wsa881x_runtime_resume, NULL) + RUNTIME_PM_OPS(wsa881x_runtime_suspend, wsa881x_runtime_resume, NULL) }; static const struct sdw_device_id wsa881x_slave_id[] = { @@ -1222,7 +1222,7 @@ static struct sdw_driver wsa881x_codec_driver = { .id_table = wsa881x_slave_id, .driver = { .name = "wsa881x-codec", - .pm = &wsa881x_pm_ops, + .pm = pm_ptr(&wsa881x_pm_ops), } }; module_sdw_driver(wsa881x_codec_driver); From d09125c2c68cc95c300e2a63a04b9a3d37ba64ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:18 +0100 Subject: [PATCH 1021/1090] ASoC: wsa883x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Srinivas Kandagatla Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-57-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wsa883x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index a5a6cb90bb43..d259e1d4d83d 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -1636,7 +1636,7 @@ err: } -static int __maybe_unused wsa883x_runtime_suspend(struct device *dev) +static int wsa883x_runtime_suspend(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -1646,7 +1646,7 @@ static int __maybe_unused wsa883x_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wsa883x_runtime_resume(struct device *dev) +static int wsa883x_runtime_resume(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -1657,7 +1657,7 @@ static int __maybe_unused wsa883x_runtime_resume(struct device *dev) } static const struct dev_pm_ops wsa883x_pm_ops = { - SET_RUNTIME_PM_OPS(wsa883x_runtime_suspend, wsa883x_runtime_resume, NULL) + RUNTIME_PM_OPS(wsa883x_runtime_suspend, wsa883x_runtime_resume, NULL) }; static const struct sdw_device_id wsa883x_swr_id[] = { @@ -1670,7 +1670,7 @@ MODULE_DEVICE_TABLE(sdw, wsa883x_swr_id); static struct sdw_driver wsa883x_codec_driver = { .driver = { .name = "wsa883x-codec", - .pm = &wsa883x_pm_ops, + .pm = pm_ptr(&wsa883x_pm_ops), .suppress_bind_attrs = true, }, .probe = wsa883x_probe, From 60c1c181139e2ebe138faafa4f5e4e695236c1f0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:19 +0100 Subject: [PATCH 1022/1090] ASoC: wsa884x: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Srinivas Kandagatla Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-58-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/wsa884x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c index 560a2c04b695..8051483aa1ac 100644 --- a/sound/soc/codecs/wsa884x.c +++ b/sound/soc/codecs/wsa884x.c @@ -2136,7 +2136,7 @@ static int wsa884x_probe(struct sdw_slave *pdev, ARRAY_SIZE(wsa884x_dais)); } -static int __maybe_unused wsa884x_runtime_suspend(struct device *dev) +static int wsa884x_runtime_suspend(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -2146,7 +2146,7 @@ static int __maybe_unused wsa884x_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused wsa884x_runtime_resume(struct device *dev) +static int wsa884x_runtime_resume(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); @@ -2157,7 +2157,7 @@ static int __maybe_unused wsa884x_runtime_resume(struct device *dev) } static const struct dev_pm_ops wsa884x_pm_ops = { - SET_RUNTIME_PM_OPS(wsa884x_runtime_suspend, wsa884x_runtime_resume, NULL) + RUNTIME_PM_OPS(wsa884x_runtime_suspend, wsa884x_runtime_resume, NULL) }; static const struct sdw_device_id wsa884x_swr_id[] = { @@ -2169,7 +2169,7 @@ MODULE_DEVICE_TABLE(sdw, wsa884x_swr_id); static struct sdw_driver wsa884x_codec_driver = { .driver = { .name = "wsa884x-codec", - .pm = &wsa884x_pm_ops, + .pm = pm_ptr(&wsa884x_pm_ops), }, .probe = wsa884x_probe, .ops = &wsa884x_slave_ops, From fc12699cda764ea807db0b22db7f06d1acbabe8e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:20 +0100 Subject: [PATCH 1023/1090] ASoC: dwc: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-59-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 57b789d7fbed..4c4171bb3fbb 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -478,7 +478,6 @@ static const struct snd_soc_dai_ops dw_i2s_dai_ops = { .set_tdm_slot = dw_i2s_set_tdm_slot, }; -#ifdef CONFIG_PM static int dw_i2s_runtime_suspend(struct device *dev) { struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev); @@ -501,6 +500,7 @@ static int dw_i2s_runtime_resume(struct device *dev) return 0; } +#ifdef CONFIG_PM static int dw_i2s_suspend(struct snd_soc_component *component) { struct dw_i2s_dev *dev = snd_soc_component_get_drvdata(component); @@ -1084,7 +1084,7 @@ MODULE_DEVICE_TABLE(of, dw_i2s_of_match); #endif static const struct dev_pm_ops dwc_pm_ops = { - SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL) + RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL) }; static struct platform_driver dw_i2s_driver = { @@ -1093,7 +1093,7 @@ static struct platform_driver dw_i2s_driver = { .driver = { .name = "designware-i2s", .of_match_table = of_match_ptr(dw_i2s_of_match), - .pm = &dwc_pm_ops, + .pm = pm_ptr(&dwc_pm_ops), }, }; From d1baa8193fd8cb8d0088851b468c9b0c5874ff42 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:21 +0100 Subject: [PATCH 1024/1090] ASoC: fsl: Convert to RUNTIME_PM_OPS() and co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr() This optimizes slightly when CONFIG_PM is disabled, too. Cc: Shengjiu Wang Cc: Xiubo Li Cc: Fabio Estevam Cc: Nicolin Chen Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-60-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_aud2htx.c | 3 +-- sound/soc/fsl/fsl_esai.c | 9 +++------ sound/soc/fsl/fsl_micfil.c | 9 +++------ sound/soc/fsl/fsl_sai.c | 8 +++----- sound/soc/fsl/fsl_xcvr.c | 3 +-- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index bde642318835..da401561e2de 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -290,8 +290,7 @@ static int fsl_aud2htx_runtime_resume(struct device *dev) static const struct dev_pm_ops fsl_aud2htx_pm_ops = { RUNTIME_PM_OPS(fsl_aud2htx_runtime_suspend, fsl_aud2htx_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_aud2htx_driver = { diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 0b247f16a163..cde0b0c6c1ef 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -1189,11 +1189,8 @@ static int fsl_esai_runtime_suspend(struct device *dev) } static const struct dev_pm_ops fsl_esai_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend, - fsl_esai_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_esai_runtime_suspend, fsl_esai_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_esai_driver = { @@ -1201,7 +1198,7 @@ static struct platform_driver fsl_esai_driver = { .remove = fsl_esai_remove, .driver = { .name = "fsl-esai-dai", - .pm = &fsl_esai_pm_ops, + .pm = pm_ptr(&fsl_esai_pm_ops), .of_match_table = fsl_esai_dt_ids, }, }; diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 73d8910a6188..aabd90a8b3ec 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -1512,11 +1512,8 @@ static int fsl_micfil_runtime_resume(struct device *dev) } static const struct dev_pm_ops fsl_micfil_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_micfil_runtime_suspend, - fsl_micfil_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_micfil_runtime_suspend, fsl_micfil_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_micfil_driver = { @@ -1524,7 +1521,7 @@ static struct platform_driver fsl_micfil_driver = { .remove = fsl_micfil_remove, .driver = { .name = "fsl-micfil-dai", - .pm = &fsl_micfil_pm_ops, + .pm = pm_ptr(&fsl_micfil_pm_ops), .of_match_table = fsl_micfil_dt_ids, }, }; diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 9f33dd11d47f..ed2b4780c470 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1817,10 +1817,8 @@ disable_bus_clk: } static const struct dev_pm_ops fsl_sai_pm_ops = { - SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend, - fsl_sai_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(fsl_sai_runtime_suspend, fsl_sai_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_sai_driver = { @@ -1828,7 +1826,7 @@ static struct platform_driver fsl_sai_driver = { .remove = fsl_sai_remove, .driver = { .name = "fsl-sai", - .pm = &fsl_sai_pm_ops, + .pm = pm_ptr(&fsl_sai_pm_ops), .of_match_table = fsl_sai_ids, }, }; diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index c59c1af5a98a..83aea341c1b6 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1821,8 +1821,7 @@ stop_ipg_clk: static const struct dev_pm_ops fsl_xcvr_pm_ops = { RUNTIME_PM_OPS(fsl_xcvr_runtime_suspend, fsl_xcvr_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver fsl_xcvr_driver = { From 5580e82d222668dd0a484af5612f1d9ae938f075 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:22 +0100 Subject: [PATCH 1025/1090] ASoC: img: Convert to RUNTIME_PM_OPS() and co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-61-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 9 +++------ sound/soc/img/img-i2s-out.c | 9 +++------ sound/soc/img/img-parallel-out.c | 5 ++--- sound/soc/img/img-spdif-in.c | 9 +++------ sound/soc/img/img-spdif-out.c | 10 ++++------ sound/soc/img/pistachio-internal-dac.c | 8 +++----- 6 files changed, 18 insertions(+), 32 deletions(-) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 6a988976fb0d..98d2ab68883a 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -539,7 +539,6 @@ static void img_i2s_in_dev_remove(struct platform_device *pdev) img_i2s_in_runtime_suspend(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int img_i2s_in_suspend(struct device *dev) { struct img_i2s_in *i2s = dev_get_drvdata(dev); @@ -586,7 +585,6 @@ static int img_i2s_in_resume(struct device *dev) return 0; } -#endif static const struct of_device_id img_i2s_in_of_match[] = { { .compatible = "img,i2s-in" }, @@ -595,16 +593,15 @@ static const struct of_device_id img_i2s_in_of_match[] = { MODULE_DEVICE_TABLE(of, img_i2s_in_of_match); static const struct dev_pm_ops img_i2s_in_pm_ops = { - SET_RUNTIME_PM_OPS(img_i2s_in_runtime_suspend, - img_i2s_in_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(img_i2s_in_suspend, img_i2s_in_resume) + RUNTIME_PM_OPS(img_i2s_in_runtime_suspend, img_i2s_in_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(img_i2s_in_suspend, img_i2s_in_resume) }; static struct platform_driver img_i2s_in_driver = { .driver = { .name = "img-i2s-in", .of_match_table = img_i2s_in_of_match, - .pm = &img_i2s_in_pm_ops + .pm = pm_ptr(&img_i2s_in_pm_ops) }, .probe = img_i2s_in_probe, .remove = img_i2s_in_dev_remove diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index 1211e6184d97..aedcf56a5359 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -539,7 +539,6 @@ static void img_i2s_out_dev_remove(struct platform_device *pdev) img_i2s_out_runtime_suspend(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int img_i2s_out_suspend(struct device *dev) { struct img_i2s_out *i2s = dev_get_drvdata(dev); @@ -586,7 +585,6 @@ static int img_i2s_out_resume(struct device *dev) return 0; } -#endif static const struct of_device_id img_i2s_out_of_match[] = { { .compatible = "img,i2s-out" }, @@ -595,16 +593,15 @@ static const struct of_device_id img_i2s_out_of_match[] = { MODULE_DEVICE_TABLE(of, img_i2s_out_of_match); static const struct dev_pm_ops img_i2s_out_pm_ops = { - SET_RUNTIME_PM_OPS(img_i2s_out_runtime_suspend, - img_i2s_out_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(img_i2s_out_suspend, img_i2s_out_resume) + RUNTIME_PM_OPS(img_i2s_out_runtime_suspend, img_i2s_out_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(img_i2s_out_suspend, img_i2s_out_resume) }; static struct platform_driver img_i2s_out_driver = { .driver = { .name = "img-i2s-out", .of_match_table = img_i2s_out_of_match, - .pm = &img_i2s_out_pm_ops + .pm = pm_ptr(&img_i2s_out_pm_ops) }, .probe = img_i2s_out_probe, .remove = img_i2s_out_dev_remove diff --git a/sound/soc/img/img-parallel-out.c b/sound/soc/img/img-parallel-out.c index 4ec63119d67c..86b60e6dab38 100644 --- a/sound/soc/img/img-parallel-out.c +++ b/sound/soc/img/img-parallel-out.c @@ -300,15 +300,14 @@ static const struct of_device_id img_prl_out_of_match[] = { MODULE_DEVICE_TABLE(of, img_prl_out_of_match); static const struct dev_pm_ops img_prl_out_pm_ops = { - SET_RUNTIME_PM_OPS(img_prl_out_suspend, - img_prl_out_resume, NULL) + RUNTIME_PM_OPS(img_prl_out_suspend, img_prl_out_resume, NULL) }; static struct platform_driver img_prl_out_driver = { .driver = { .name = "img-parallel-out", .of_match_table = img_prl_out_of_match, - .pm = &img_prl_out_pm_ops + .pm = pm_ptr(&img_prl_out_pm_ops) }, .probe = img_prl_out_probe, .remove = img_prl_out_dev_remove diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c index 3c513f5b8c54..82295e2508fa 100644 --- a/sound/soc/img/img-spdif-in.c +++ b/sound/soc/img/img-spdif-in.c @@ -817,7 +817,6 @@ static void img_spdif_in_dev_remove(struct platform_device *pdev) img_spdif_in_runtime_suspend(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int img_spdif_in_suspend(struct device *dev) { struct img_spdif_in *spdif = dev_get_drvdata(dev); @@ -857,7 +856,6 @@ static int img_spdif_in_resume(struct device *dev) return 0; } -#endif static const struct of_device_id img_spdif_in_of_match[] = { { .compatible = "img,spdif-in" }, @@ -866,16 +864,15 @@ static const struct of_device_id img_spdif_in_of_match[] = { MODULE_DEVICE_TABLE(of, img_spdif_in_of_match); static const struct dev_pm_ops img_spdif_in_pm_ops = { - SET_RUNTIME_PM_OPS(img_spdif_in_runtime_suspend, - img_spdif_in_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend, img_spdif_in_resume) + RUNTIME_PM_OPS(img_spdif_in_runtime_suspend, img_spdif_in_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend, img_spdif_in_resume) }; static struct platform_driver img_spdif_in_driver = { .driver = { .name = "img-spdif-in", .of_match_table = img_spdif_in_of_match, - .pm = &img_spdif_in_pm_ops + .pm = pm_ptr(&img_spdif_in_pm_ops) }, .probe = img_spdif_in_probe, .remove = img_spdif_in_dev_remove diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c index 402695b5fc41..52f696219ef4 100644 --- a/sound/soc/img/img-spdif-out.c +++ b/sound/soc/img/img-spdif-out.c @@ -409,7 +409,6 @@ static void img_spdif_out_dev_remove(struct platform_device *pdev) img_spdif_out_runtime_suspend(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int img_spdif_out_suspend(struct device *dev) { struct img_spdif_out *spdif = dev_get_drvdata(dev); @@ -448,7 +447,7 @@ static int img_spdif_out_resume(struct device *dev) return 0; } -#endif + static const struct of_device_id img_spdif_out_of_match[] = { { .compatible = "img,spdif-out" }, {} @@ -456,16 +455,15 @@ static const struct of_device_id img_spdif_out_of_match[] = { MODULE_DEVICE_TABLE(of, img_spdif_out_of_match); static const struct dev_pm_ops img_spdif_out_pm_ops = { - SET_RUNTIME_PM_OPS(img_spdif_out_runtime_suspend, - img_spdif_out_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(img_spdif_out_suspend, img_spdif_out_resume) + RUNTIME_PM_OPS(img_spdif_out_runtime_suspend, img_spdif_out_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(img_spdif_out_suspend, img_spdif_out_resume) }; static struct platform_driver img_spdif_out_driver = { .driver = { .name = "img-spdif-out", .of_match_table = img_spdif_out_of_match, - .pm = &img_spdif_out_pm_ops + .pm = pm_ptr(&img_spdif_out_pm_ops) }, .probe = img_spdif_out_probe, .remove = img_spdif_out_dev_remove diff --git a/sound/soc/img/pistachio-internal-dac.c b/sound/soc/img/pistachio-internal-dac.c index fdeceb271e7f..ec4f891295c9 100644 --- a/sound/soc/img/pistachio-internal-dac.c +++ b/sound/soc/img/pistachio-internal-dac.c @@ -224,7 +224,6 @@ static void pistachio_internal_dac_remove(struct platform_device *pdev) regulator_disable(dac->supply); } -#ifdef CONFIG_PM static int pistachio_internal_dac_rt_resume(struct device *dev) { struct pistachio_internal_dac *dac = dev_get_drvdata(dev); @@ -251,11 +250,10 @@ static int pistachio_internal_dac_rt_suspend(struct device *dev) return 0; } -#endif static const struct dev_pm_ops pistachio_internal_dac_pm_ops = { - SET_RUNTIME_PM_OPS(pistachio_internal_dac_rt_suspend, - pistachio_internal_dac_rt_resume, NULL) + RUNTIME_PM_OPS(pistachio_internal_dac_rt_suspend, + pistachio_internal_dac_rt_resume, NULL) }; static const struct of_device_id pistachio_internal_dac_of_match[] = { @@ -268,7 +266,7 @@ static struct platform_driver pistachio_internal_dac_plat_driver = { .driver = { .name = "img-pistachio-internal-dac", .of_match_table = pistachio_internal_dac_of_match, - .pm = &pistachio_internal_dac_pm_ops + .pm = pm_ptr(&pistachio_internal_dac_pm_ops) }, .probe = pistachio_internal_dac_probe, .remove = pistachio_internal_dac_remove From 72954863350eff04a4961acb49bfce11416f7856 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:23 +0100 Subject: [PATCH 1026/1090] ASoC: intel: avs: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Cezary Rojewski Signed-off-by: Takashi Iwai Reviewed-by: Cezary Rojewski Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-62-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/intel/avs/core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 0e750e9e01d9..8fbf33e30dfc 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -612,7 +612,7 @@ static int avs_suspend_standby(struct avs_dev *adev) return 0; } -static int __maybe_unused avs_suspend_common(struct avs_dev *adev, bool low_power) +static int avs_suspend_common(struct avs_dev *adev, bool low_power) { struct hdac_bus *bus = &adev->base.core; int ret; @@ -673,7 +673,7 @@ static int avs_resume_standby(struct avs_dev *adev) return 0; } -static int __maybe_unused avs_resume_common(struct avs_dev *adev, bool low_power, bool purge) +static int avs_resume_common(struct avs_dev *adev, bool low_power, bool purge) { struct hdac_bus *bus = &adev->base.core; int ret; @@ -696,41 +696,41 @@ static int __maybe_unused avs_resume_common(struct avs_dev *adev, bool low_power return 0; } -static int __maybe_unused avs_suspend(struct device *dev) +static int avs_suspend(struct device *dev) { return avs_suspend_common(to_avs_dev(dev), true); } -static int __maybe_unused avs_resume(struct device *dev) +static int avs_resume(struct device *dev) { return avs_resume_common(to_avs_dev(dev), true, true); } -static int __maybe_unused avs_runtime_suspend(struct device *dev) +static int avs_runtime_suspend(struct device *dev) { return avs_suspend_common(to_avs_dev(dev), true); } -static int __maybe_unused avs_runtime_resume(struct device *dev) +static int avs_runtime_resume(struct device *dev) { return avs_resume_common(to_avs_dev(dev), true, false); } -static int __maybe_unused avs_freeze(struct device *dev) +static int avs_freeze(struct device *dev) { return avs_suspend_common(to_avs_dev(dev), false); } -static int __maybe_unused avs_thaw(struct device *dev) +static int avs_thaw(struct device *dev) { return avs_resume_common(to_avs_dev(dev), false, true); } -static int __maybe_unused avs_poweroff(struct device *dev) +static int avs_poweroff(struct device *dev) { return avs_suspend_common(to_avs_dev(dev), false); } -static int __maybe_unused avs_restore(struct device *dev) +static int avs_restore(struct device *dev) { return avs_resume_common(to_avs_dev(dev), false, true); } @@ -742,7 +742,7 @@ static const struct dev_pm_ops avs_dev_pm = { .thaw = avs_thaw, .poweroff = avs_poweroff, .restore = avs_restore, - SET_RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL) + RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL) }; static const struct avs_sram_spec skl_sram_spec = { @@ -893,7 +893,7 @@ static struct pci_driver avs_pci_driver = { .shutdown = avs_pci_shutdown, .dev_groups = avs_attr_groups, .driver = { - .pm = &avs_dev_pm, + .pm = pm_ptr(&avs_dev_pm), }, }; module_pci_driver(avs_pci_driver); From 2c498d9a3a5ad28d2cfbdffde8496626f1b89c82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:24 +0100 Subject: [PATCH 1027/1090] ASoC: intel: catpt: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Cezary Rojewski Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-63-tiwai@suse.de Reviewed-by: Cezary Rojewski Signed-off-by: Mark Brown --- sound/soc/intel/catpt/device.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c index 2aa637124bec..faa916f40069 100644 --- a/sound/soc/intel/catpt/device.c +++ b/sound/soc/intel/catpt/device.c @@ -28,7 +28,7 @@ #define CREATE_TRACE_POINTS #include "trace.h" -static int __maybe_unused catpt_suspend(struct device *dev) +static int catpt_suspend(struct device *dev) { struct catpt_dev *cdev = dev_get_drvdata(dev); struct dma_chan *chan; @@ -72,7 +72,7 @@ release_dma_chan: return catpt_dsp_power_down(cdev); } -static int __maybe_unused catpt_resume(struct device *dev) +static int catpt_resume(struct device *dev) { struct catpt_dev *cdev = dev_get_drvdata(dev); int ret, i; @@ -106,7 +106,7 @@ static int __maybe_unused catpt_resume(struct device *dev) return 0; } -static int __maybe_unused catpt_runtime_suspend(struct device *dev) +static int catpt_runtime_suspend(struct device *dev) { if (!try_module_get(dev->driver->owner)) { dev_info(dev, "module unloading, skipping suspend\n"); @@ -117,14 +117,14 @@ static int __maybe_unused catpt_runtime_suspend(struct device *dev) return catpt_suspend(dev); } -static int __maybe_unused catpt_runtime_resume(struct device *dev) +static int catpt_runtime_resume(struct device *dev) { return catpt_resume(dev); } static const struct dev_pm_ops catpt_dev_pm = { - SET_SYSTEM_SLEEP_PM_OPS(catpt_suspend, catpt_resume) - SET_RUNTIME_PM_OPS(catpt_runtime_suspend, catpt_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(catpt_suspend, catpt_resume) + RUNTIME_PM_OPS(catpt_runtime_suspend, catpt_runtime_resume, NULL) }; /* machine board owned by CATPT is removed with this hook */ @@ -378,7 +378,7 @@ static struct platform_driver catpt_acpi_driver = { .driver = { .name = "intel_catpt", .acpi_match_table = catpt_ids, - .pm = &catpt_dev_pm, + .pm = pm_ptr(&catpt_dev_pm), .dev_groups = catpt_attr_groups, }, }; From 50ffa9e4d22db71ce370a8cde3bd2d706138df8b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:25 +0100 Subject: [PATCH 1028/1090] ASoC: mediatek: mt2701: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-64-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 5f11bc5438bd..fcae38135d93 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -1462,15 +1462,15 @@ static const struct of_device_id mt2701_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match); static const struct dev_pm_ops mt2701_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt2701_afe_runtime_suspend, - mt2701_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt2701_afe_runtime_suspend, + mt2701_afe_runtime_resume, NULL) }; static struct platform_driver mt2701_afe_pcm_driver = { .driver = { .name = "mt2701-audio", .of_match_table = mt2701_afe_pcm_dt_match, - .pm = &mt2701_afe_pm_ops, + .pm = pm_ptr(&mt2701_afe_pm_ops), }, .probe = mt2701_afe_pcm_dev_probe, .remove = mt2701_afe_pcm_dev_remove, From 6afabcdad370f117588dfd7203a803f050503c91 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:26 +0100 Subject: [PATCH 1029/1090] ASoC: mediatek: mt6797: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-65-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index 9159b42adf6a..f62a32f2f2b6 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -879,15 +879,15 @@ static const struct of_device_id mt6797_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt6797_afe_pcm_dt_match); static const struct dev_pm_ops mt6797_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt6797_afe_runtime_suspend, - mt6797_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt6797_afe_runtime_suspend, + mt6797_afe_runtime_resume, NULL) }; static struct platform_driver mt6797_afe_pcm_driver = { .driver = { .name = "mt6797-audio", .of_match_table = mt6797_afe_pcm_dt_match, - .pm = &mt6797_afe_pm_ops, + .pm = pm_ptr(&mt6797_afe_pm_ops), }, .probe = mt6797_afe_pcm_dev_probe, .remove = mt6797_afe_pcm_dev_remove, From 0d7c63bc74a8fdcfc37e093efaeb8657b0e21022 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:27 +0100 Subject: [PATCH 1030/1090] ASoC: mediatek: mt7986: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-66-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c index 7db090414d59..7a6ad9116e55 100644 --- a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c +++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c @@ -589,15 +589,15 @@ static const struct of_device_id mt7986_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt7986_afe_pcm_dt_match); static const struct dev_pm_ops mt7986_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt7986_afe_runtime_suspend, - mt7986_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt7986_afe_runtime_suspend, + mt7986_afe_runtime_resume, NULL) }; static struct platform_driver mt7986_afe_pcm_driver = { .driver = { .name = "mt7986-audio", .of_match_table = mt7986_afe_pcm_dt_match, - .pm = &mt7986_afe_pm_ops, + .pm = pm_ptr(&mt7986_afe_pm_ops), }, .probe = mt7986_afe_pcm_dev_probe, .remove = mt7986_afe_pcm_dev_remove, From 09b926f215df0206f1f3d8f4a2b4f4e28c68168e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:28 +0100 Subject: [PATCH 1031/1090] ASoC: mediatek: mt8173: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-67-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 03250273ea9c..04ed0cfec174 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -1212,15 +1212,15 @@ static const struct of_device_id mt8173_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8173_afe_pcm_dt_match); static const struct dev_pm_ops mt8173_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8173_afe_runtime_suspend, - mt8173_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8173_afe_runtime_suspend, + mt8173_afe_runtime_resume, NULL) }; static struct platform_driver mt8173_afe_pcm_driver = { .driver = { .name = "mt8173-afe-pcm", .of_match_table = mt8173_afe_pcm_dt_match, - .pm = &mt8173_afe_pm_ops, + .pm = pm_ptr(&mt8173_afe_pm_ops), }, .probe = mt8173_afe_pcm_dev_probe, .remove = mt8173_afe_pcm_dev_remove, From 564cb5ebb488a11708e63eb7cd8037accea7120d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:29 +0100 Subject: [PATCH 1032/1090] ASoC: mediatek: mt8183: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-68-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 3f377ba4ad53..d083b4bf0f95 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1257,15 +1257,15 @@ static const struct of_device_id mt8183_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8183_afe_pcm_dt_match); static const struct dev_pm_ops mt8183_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8183_afe_runtime_suspend, - mt8183_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8183_afe_runtime_suspend, + mt8183_afe_runtime_resume, NULL) }; static struct platform_driver mt8183_afe_pcm_driver = { .driver = { .name = "mt8183-audio", .of_match_table = mt8183_afe_pcm_dt_match, - .pm = &mt8183_afe_pm_ops, + .pm = pm_ptr(&mt8183_afe_pm_ops), }, .probe = mt8183_afe_pcm_dev_probe, .remove = mt8183_afe_pcm_dev_remove, From 26d342b04f5e9190487cd2e6fdce75c52cee4a86 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:30 +0100 Subject: [PATCH 1033/1090] ASoC: mediatek: mt8186: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-69-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c index bafbef96a42d..db7c93401bee 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c @@ -2978,15 +2978,15 @@ static const struct of_device_id mt8186_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8186_afe_pcm_dt_match); static const struct dev_pm_ops mt8186_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8186_afe_runtime_suspend, - mt8186_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8186_afe_runtime_suspend, + mt8186_afe_runtime_resume, NULL) }; static struct platform_driver mt8186_afe_pcm_driver = { .driver = { .name = "mt8186-audio", .of_match_table = mt8186_afe_pcm_dt_match, - .pm = &mt8186_afe_pm_ops, + .pm = pm_ptr(&mt8186_afe_pm_ops), }, .probe = mt8186_afe_pcm_dev_probe, }; From 49a70f2ed0a2a65aaf099dc45d73ba6b4f0c9c94 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:31 +0100 Subject: [PATCH 1034/1090] ASoC: mediatek: mt8188: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-70-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index a2b57e00ff4e..ac4fdf8ba78f 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -3381,15 +3381,15 @@ static const struct of_device_id mt8188_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8188_afe_pcm_dt_match); static const struct dev_pm_ops mt8188_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8188_afe_runtime_suspend, - mt8188_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8188_afe_runtime_suspend, + mt8188_afe_runtime_resume, NULL) }; static struct platform_driver mt8188_afe_pcm_driver = { .driver = { .name = "mt8188-audio", .of_match_table = mt8188_afe_pcm_dt_match, - .pm = &mt8188_afe_pm_ops, + .pm = pm_ptr(&mt8188_afe_pm_ops), }, .probe = mt8188_afe_pcm_dev_probe, }; From ecd140a2063d618e1239351d3ae146cfdaa9a13f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:32 +0100 Subject: [PATCH 1035/1090] ASoC: mediatek: mt8192: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-71-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 80cda7bf5ccc..fd6af74d7995 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2313,15 +2313,15 @@ static const struct of_device_id mt8192_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8192_afe_pcm_dt_match); static const struct dev_pm_ops mt8192_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8192_afe_runtime_suspend, - mt8192_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8192_afe_runtime_suspend, + mt8192_afe_runtime_resume, NULL) }; static struct platform_driver mt8192_afe_pcm_driver = { .driver = { .name = "mt8192-audio", .of_match_table = mt8192_afe_pcm_dt_match, - .pm = &mt8192_afe_pm_ops, + .pm = pm_ptr(&mt8192_afe_pm_ops), }, .probe = mt8192_afe_pcm_dev_probe, .remove = mt8192_afe_pcm_dev_remove, From 951f082eb09b50d68b8271257777f206ee3001a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:33 +0100 Subject: [PATCH 1036/1090] ASoC: mediatek: mt8195: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-72-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c index 8016bfb35015..5d025ad72263 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -3188,15 +3188,15 @@ static const struct of_device_id mt8195_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8195_afe_pcm_dt_match); static const struct dev_pm_ops mt8195_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8195_afe_runtime_suspend, - mt8195_afe_runtime_resume, NULL) + RUNTIME_PM_OPS(mt8195_afe_runtime_suspend, + mt8195_afe_runtime_resume, NULL) }; static struct platform_driver mt8195_afe_pcm_driver = { .driver = { .name = "mt8195-audio", .of_match_table = mt8195_afe_pcm_dt_match, - .pm = &mt8195_afe_pm_ops, + .pm = pm_ptr(&mt8195_afe_pm_ops), }, .probe = mt8195_afe_pcm_dev_probe, .remove = mt8195_afe_pcm_dev_remove, From bd8540105e88581bdf27a9a92231907a9168d0b6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:34 +0100 Subject: [PATCH 1037/1090] ASoC: mediatek: mt8365: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us to drop ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-73-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c index 743b46572144..10793bbe9275 100644 --- a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c +++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c @@ -1957,7 +1957,7 @@ err_irq: return IRQ_HANDLED; } -static int __maybe_unused mt8365_afe_runtime_suspend(struct device *dev) +static int mt8365_afe_runtime_suspend(struct device *dev) { return 0; } @@ -1967,7 +1967,7 @@ static int mt8365_afe_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused mt8365_afe_suspend(struct device *dev) +static int mt8365_afe_suspend(struct device *dev) { struct mtk_base_afe *afe = dev_get_drvdata(dev); struct regmap *regmap = afe->regmap; @@ -1989,7 +1989,7 @@ static int __maybe_unused mt8365_afe_suspend(struct device *dev) return 0; } -static int __maybe_unused mt8365_afe_resume(struct device *dev) +static int mt8365_afe_resume(struct device *dev) { struct mtk_base_afe *afe = dev_get_drvdata(dev); struct regmap *regmap = afe->regmap; @@ -2009,7 +2009,7 @@ static int __maybe_unused mt8365_afe_resume(struct device *dev) return 0; } -static int __maybe_unused mt8365_afe_dev_runtime_suspend(struct device *dev) +static int mt8365_afe_dev_runtime_suspend(struct device *dev) { struct mtk_base_afe *afe = dev_get_drvdata(dev); @@ -2021,7 +2021,7 @@ static int __maybe_unused mt8365_afe_dev_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused mt8365_afe_dev_runtime_resume(struct device *dev) +static int mt8365_afe_dev_runtime_resume(struct device *dev) { struct mtk_base_afe *afe = dev_get_drvdata(dev); @@ -2250,17 +2250,16 @@ static const struct of_device_id mt8365_afe_pcm_dt_match[] = { MODULE_DEVICE_TABLE(of, mt8365_afe_pcm_dt_match); static const struct dev_pm_ops mt8365_afe_pm_ops = { - SET_RUNTIME_PM_OPS(mt8365_afe_dev_runtime_suspend, - mt8365_afe_dev_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(mt8365_afe_suspend, - mt8365_afe_resume) + RUNTIME_PM_OPS(mt8365_afe_dev_runtime_suspend, + mt8365_afe_dev_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(mt8365_afe_suspend, mt8365_afe_resume) }; static struct platform_driver mt8365_afe_pcm_driver = { .driver = { .name = "mt8365-afe-pcm", .of_match_table = mt8365_afe_pcm_dt_match, - .pm = &mt8365_afe_pm_ops, + .pm = pm_ptr(&mt8365_afe_pm_ops), }, .probe = mt8365_afe_pcm_dev_probe, .remove = mt8365_afe_pcm_dev_remove, From 23a6b07ceff59eabb45543091416951711f0963e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:35 +0100 Subject: [PATCH 1038/1090] ASoC: qcom: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us to drop ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Srinivas Kandagatla Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-74-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-sc7180.c | 8 ++++---- sound/soc/qcom/lpass-sc7280.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c index fbead6af3d95..7c6a9b0fda89 100644 --- a/sound/soc/qcom/lpass-sc7180.c +++ b/sound/soc/qcom/lpass-sc7180.c @@ -160,14 +160,14 @@ static int sc7180_lpass_exit(struct platform_device *pdev) return 0; } -static int __maybe_unused sc7180_lpass_dev_resume(struct device *dev) +static int sc7180_lpass_dev_resume(struct device *dev) { struct lpass_data *drvdata = dev_get_drvdata(dev); return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); } -static int __maybe_unused sc7180_lpass_dev_suspend(struct device *dev) +static int sc7180_lpass_dev_suspend(struct device *dev) { struct lpass_data *drvdata = dev_get_drvdata(dev); @@ -176,7 +176,7 @@ static int __maybe_unused sc7180_lpass_dev_suspend(struct device *dev) } static const struct dev_pm_ops sc7180_lpass_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(sc7180_lpass_dev_suspend, sc7180_lpass_dev_resume) + SYSTEM_SLEEP_PM_OPS(sc7180_lpass_dev_suspend, sc7180_lpass_dev_resume) }; static const struct lpass_variant sc7180_data = { @@ -312,7 +312,7 @@ static struct platform_driver sc7180_lpass_cpu_platform_driver = { .driver = { .name = "sc7180-lpass-cpu", .of_match_table = of_match_ptr(sc7180_lpass_cpu_device_id), - .pm = &sc7180_lpass_pm_ops, + .pm = pm_ptr(&sc7180_lpass_pm_ops), }, .probe = asoc_qcom_lpass_cpu_platform_probe, .remove = asoc_qcom_lpass_cpu_platform_remove, diff --git a/sound/soc/qcom/lpass-sc7280.c b/sound/soc/qcom/lpass-sc7280.c index 7cd3e291382a..817c824f9179 100644 --- a/sound/soc/qcom/lpass-sc7280.c +++ b/sound/soc/qcom/lpass-sc7280.c @@ -233,14 +233,14 @@ static int sc7280_lpass_exit(struct platform_device *pdev) return 0; } -static int __maybe_unused sc7280_lpass_dev_resume(struct device *dev) +static int sc7280_lpass_dev_resume(struct device *dev) { struct lpass_data *drvdata = dev_get_drvdata(dev); return clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); } -static int __maybe_unused sc7280_lpass_dev_suspend(struct device *dev) +static int sc7280_lpass_dev_suspend(struct device *dev) { struct lpass_data *drvdata = dev_get_drvdata(dev); @@ -249,7 +249,7 @@ static int __maybe_unused sc7280_lpass_dev_suspend(struct device *dev) } static const struct dev_pm_ops sc7280_lpass_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(sc7280_lpass_dev_suspend, sc7280_lpass_dev_resume) + SYSTEM_SLEEP_PM_OPS(sc7280_lpass_dev_suspend, sc7280_lpass_dev_resume) }; static const struct lpass_variant sc7280_data = { @@ -442,7 +442,7 @@ static struct platform_driver sc7280_lpass_cpu_platform_driver = { .driver = { .name = "sc7280-lpass-cpu", .of_match_table = of_match_ptr(sc7280_lpass_cpu_device_id), - .pm = &sc7280_lpass_pm_ops, + .pm = pm_ptr(&sc7280_lpass_pm_ops), }, .probe = asoc_qcom_lpass_cpu_platform_probe, .remove = asoc_qcom_lpass_cpu_platform_remove, From 4330d33f04ea71c9cfb193a0ae60fb40f6080a19 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:36 +0100 Subject: [PATCH 1039/1090] ASoC: rcar: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead of SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us to drop ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Acked-by: Kuninori Morimoto Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-75-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/renesas/rcar/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c index f3f0c3f0bb9f..30afc942d381 100644 --- a/sound/soc/renesas/rcar/core.c +++ b/sound/soc/renesas/rcar/core.c @@ -2059,7 +2059,7 @@ static void rsnd_remove(struct platform_device *pdev) remove_func[i](priv); } -static int __maybe_unused rsnd_suspend(struct device *dev) +static int rsnd_suspend(struct device *dev) { struct rsnd_priv *priv = dev_get_drvdata(dev); @@ -2068,7 +2068,7 @@ static int __maybe_unused rsnd_suspend(struct device *dev) return 0; } -static int __maybe_unused rsnd_resume(struct device *dev) +static int rsnd_resume(struct device *dev) { struct rsnd_priv *priv = dev_get_drvdata(dev); @@ -2076,13 +2076,13 @@ static int __maybe_unused rsnd_resume(struct device *dev) } static const struct dev_pm_ops rsnd_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(rsnd_suspend, rsnd_resume) + SYSTEM_SLEEP_PM_OPS(rsnd_suspend, rsnd_resume) }; static struct platform_driver rsnd_driver = { .driver = { .name = "rcar_sound", - .pm = &rsnd_pm_ops, + .pm = pm_ptr(&rsnd_pm_ops), .of_match_table = rsnd_of_match, }, .probe = rsnd_probe, From 43a2930348040b3a7ad3b809e211dea233267f28 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:37 +0100 Subject: [PATCH 1040/1090] ASoC: rockchip: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us to drop ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-76-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 5 ++--- sound/soc/rockchip/rockchip_i2s_tdm.c | 16 +++++++--------- sound/soc/rockchip/rockchip_pdm.c | 10 ++++------ sound/soc/rockchip/rockchip_spdif.c | 9 ++++----- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 4315da4a47c1..0a0a95b4f520 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -860,8 +860,7 @@ static void rockchip_i2s_remove(struct platform_device *pdev) } static const struct dev_pm_ops rockchip_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, - NULL) + RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, NULL) }; static struct platform_driver rockchip_i2s_driver = { @@ -870,7 +869,7 @@ static struct platform_driver rockchip_i2s_driver = { .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rockchip_i2s_match), - .pm = &rockchip_i2s_pm_ops, + .pm = pm_ptr(&rockchip_i2s_pm_ops), }, }; module_platform_driver(rockchip_i2s_driver); diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 78ab88843f86..d9a1fab7f403 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -122,7 +122,7 @@ err_mclk_tx: return ret; } -static int __maybe_unused i2s_tdm_runtime_suspend(struct device *dev) +static int i2s_tdm_runtime_suspend(struct device *dev) { struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); @@ -134,7 +134,7 @@ static int __maybe_unused i2s_tdm_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused i2s_tdm_runtime_resume(struct device *dev) +static int i2s_tdm_runtime_resume(struct device *dev) { struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); int ret; @@ -1390,7 +1390,7 @@ static void rockchip_i2s_tdm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused rockchip_i2s_tdm_suspend(struct device *dev) +static int rockchip_i2s_tdm_suspend(struct device *dev) { struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); @@ -1399,7 +1399,7 @@ static int __maybe_unused rockchip_i2s_tdm_suspend(struct device *dev) return 0; } -static int __maybe_unused rockchip_i2s_tdm_resume(struct device *dev) +static int rockchip_i2s_tdm_resume(struct device *dev) { struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev); int ret; @@ -1414,10 +1414,8 @@ static int __maybe_unused rockchip_i2s_tdm_resume(struct device *dev) } static const struct dev_pm_ops rockchip_i2s_tdm_pm_ops = { - SET_RUNTIME_PM_OPS(i2s_tdm_runtime_suspend, i2s_tdm_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(rockchip_i2s_tdm_suspend, - rockchip_i2s_tdm_resume) + RUNTIME_PM_OPS(i2s_tdm_runtime_suspend, i2s_tdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rockchip_i2s_tdm_suspend, rockchip_i2s_tdm_resume) }; static struct platform_driver rockchip_i2s_tdm_driver = { @@ -1426,7 +1424,7 @@ static struct platform_driver rockchip_i2s_tdm_driver = { .driver = { .name = DRV_NAME, .of_match_table = rockchip_i2s_tdm_match, - .pm = &rockchip_i2s_tdm_pm_ops, + .pm = pm_ptr(&rockchip_i2s_tdm_pm_ops), }, }; module_platform_driver(rockchip_i2s_tdm_driver); diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index cae91108f7a8..c1ee470ec607 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -668,7 +668,6 @@ static void rockchip_pdm_remove(struct platform_device *pdev) clk_disable_unprepare(pdm->hclk); } -#ifdef CONFIG_PM_SLEEP static int rockchip_pdm_suspend(struct device *dev) { struct rk_pdm_dev *pdm = dev_get_drvdata(dev); @@ -693,12 +692,11 @@ static int rockchip_pdm_resume(struct device *dev) return ret; } -#endif static const struct dev_pm_ops rockchip_pdm_pm_ops = { - SET_RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend, - rockchip_pdm_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume) + RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend, + rockchip_pdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume) }; static struct platform_driver rockchip_pdm_driver = { @@ -707,7 +705,7 @@ static struct platform_driver rockchip_pdm_driver = { .driver = { .name = "rockchip-pdm", .of_match_table = of_match_ptr(rockchip_pdm_match), - .pm = &rockchip_pdm_pm_ops, + .pm = pm_ptr(&rockchip_pdm_pm_ops), }, }; diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index d87c0e4f6f91..d365168934dc 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -63,7 +63,7 @@ static const struct of_device_id rk_spdif_match[] __maybe_unused = { }; MODULE_DEVICE_TABLE(of, rk_spdif_match); -static int __maybe_unused rk_spdif_runtime_suspend(struct device *dev) +static int rk_spdif_runtime_suspend(struct device *dev) { struct rk_spdif_dev *spdif = dev_get_drvdata(dev); @@ -74,7 +74,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused rk_spdif_runtime_resume(struct device *dev) +static int rk_spdif_runtime_resume(struct device *dev) { struct rk_spdif_dev *spdif = dev_get_drvdata(dev); int ret; @@ -374,8 +374,7 @@ static void rk_spdif_remove(struct platform_device *pdev) } static const struct dev_pm_ops rk_spdif_pm_ops = { - SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume, - NULL) + RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume, NULL) }; static struct platform_driver rk_spdif_driver = { @@ -384,7 +383,7 @@ static struct platform_driver rk_spdif_driver = { .driver = { .name = "rockchip-spdif", .of_match_table = of_match_ptr(rk_spdif_match), - .pm = &rk_spdif_pm_ops, + .pm = pm_ptr(&rk_spdif_pm_ops), }, }; module_platform_driver(rk_spdif_driver); From 692fc8ac774adb9ac86b607b9c8a59b4ddc53484 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:38 +0100 Subject: [PATCH 1041/1090] ASoC: samsung: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us to drop superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Sylwester Nawrocki Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-77-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 8f6deb06e234..e9964f0e010a 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1216,7 +1216,6 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, return 0; } -#ifdef CONFIG_PM static int i2s_runtime_suspend(struct device *dev) { struct samsung_i2s_priv *priv = dev_get_drvdata(dev); @@ -1254,7 +1253,6 @@ static int i2s_runtime_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM */ static void i2s_unregister_clocks(struct samsung_i2s_priv *priv) { @@ -1733,10 +1731,8 @@ MODULE_DEVICE_TABLE(of, exynos_i2s_match); #endif static const struct dev_pm_ops samsung_i2s_pm = { - SET_RUNTIME_PM_OPS(i2s_runtime_suspend, - i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver samsung_i2s_driver = { @@ -1746,7 +1742,7 @@ static struct platform_driver samsung_i2s_driver = { .driver = { .name = "samsung-i2s", .of_match_table = of_match_ptr(exynos_i2s_match), - .pm = &samsung_i2s_pm, + .pm = pm_ptr(&samsung_i2s_pm), }, }; From 40456c8e7b9401d76363aebaae71763072b2e281 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:39 +0100 Subject: [PATCH 1042/1090] ASoC: SOF: acpi: Convert to EXPORT_NS_DEV_PM_OPS() Use the newer EXPORT_NS_DEV_PM_OPS() macro together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Cc: sound-open-firmware@alsa-project.org Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-78-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/sof-acpi-dev.c | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 79374dcde89f..f1287d509835 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -686,7 +686,7 @@ static struct platform_driver snd_sof_acpi_intel_bdw_driver = { .remove = sof_acpi_remove, .driver = { .name = "sof-audio-acpi-intel-bdw", - .pm = &sof_acpi_pm, + .pm = pm_ptr(&sof_acpi_pm), .acpi_match_table = sof_broadwell_match, }, }; diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 900cc10a3b7f..18208f77b84d 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -467,7 +467,7 @@ static struct platform_driver snd_sof_acpi_intel_byt_driver = { .remove = sof_acpi_remove, .driver = { .name = "sof-audio-acpi-intel-byt", - .pm = &sof_acpi_pm, + .pm = pm_ptr(&sof_acpi_pm), .acpi_match_table = sof_baytrail_match, }, }; diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 58fd5f7c7905..68bf1b57093e 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -36,12 +36,11 @@ MODULE_PARM_DESC(sof_acpi_debug, "SOF ACPI debug options (0x0 all off)"); #define SOF_ACPI_DISABLE_PM_RUNTIME BIT(0) -const struct dev_pm_ops sof_acpi_pm = { - SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) - SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, - snd_sof_runtime_idle) +EXPORT_NS_DEV_PM_OPS(sof_acpi_pm, SND_SOC_SOF_ACPI_DEV) = { + SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) + RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, + snd_sof_runtime_idle) }; -EXPORT_SYMBOL_NS(sof_acpi_pm, "SND_SOC_SOF_ACPI_DEV"); static void sof_acpi_probe_complete(struct device *dev) { From 24df03e2b43c8a66c0f235320177f7199dca47a9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:40 +0100 Subject: [PATCH 1043/1090] ASoC: SOF: pci: Convert to EXPORT_NS_DEV_PM_OPS() Use the newer EXPORT_NS_DEV_PM_OPS() macro together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Cc: sound-open-firmware@alsa-project.org Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20250317095603.20073-79-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/amd/pci-acp63.c | 2 +- sound/soc/sof/amd/pci-acp70.c | 2 +- sound/soc/sof/amd/pci-rn.c | 2 +- sound/soc/sof/amd/pci-vangogh.c | 2 +- sound/soc/sof/intel/pci-apl.c | 2 +- sound/soc/sof/intel/pci-cnl.c | 2 +- sound/soc/sof/intel/pci-icl.c | 2 +- sound/soc/sof/intel/pci-lnl.c | 2 +- sound/soc/sof/intel/pci-mtl.c | 2 +- sound/soc/sof/intel/pci-ptl.c | 2 +- sound/soc/sof/intel/pci-skl.c | 2 +- sound/soc/sof/intel/pci-tgl.c | 2 +- sound/soc/sof/intel/pci-tng.c | 2 +- sound/soc/sof/sof-pci-dev.c | 9 ++++----- 14 files changed, 17 insertions(+), 18 deletions(-) diff --git a/sound/soc/sof/amd/pci-acp63.c b/sound/soc/sof/amd/pci-acp63.c index 13aa87cdeeac..21ffdfdcf03d 100644 --- a/sound/soc/sof/amd/pci-acp63.c +++ b/sound/soc/sof/amd/pci-acp63.c @@ -104,7 +104,7 @@ static struct pci_driver snd_sof_pci_amd_acp63_driver = { .probe = acp63_pci_probe, .remove = acp63_pci_remove, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_amd_acp63_driver); diff --git a/sound/soc/sof/amd/pci-acp70.c b/sound/soc/sof/amd/pci-acp70.c index d886bdf3a112..8fa1170a2161 100644 --- a/sound/soc/sof/amd/pci-acp70.c +++ b/sound/soc/sof/amd/pci-acp70.c @@ -100,7 +100,7 @@ static struct pci_driver snd_sof_pci_amd_acp70_driver = { .probe = acp70_pci_probe, .remove = acp70_pci_remove, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_amd_acp70_driver); diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index 4a36029a00de..2b7fbcf11b55 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -97,7 +97,7 @@ static struct pci_driver snd_sof_pci_amd_rn_driver = { .probe = acp_pci_rn_probe, .remove = acp_pci_rn_remove, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_amd_rn_driver); diff --git a/sound/soc/sof/amd/pci-vangogh.c b/sound/soc/sof/amd/pci-vangogh.c index caf9e2b2e463..6ef692becfb9 100644 --- a/sound/soc/sof/amd/pci-vangogh.c +++ b/sound/soc/sof/amd/pci-vangogh.c @@ -90,7 +90,7 @@ static struct pci_driver snd_sof_pci_amd_vgh_driver = { .probe = acp_pci_vgh_probe, .remove = acp_pci_vgh_remove, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_amd_vgh_driver); diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index 94ab3c61e3f7..0bf7ee753bc3 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -99,7 +99,7 @@ static struct pci_driver snd_sof_pci_intel_apl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_apl_driver); diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 739c352c3860..de48640024e4 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -137,7 +137,7 @@ static struct pci_driver snd_sof_pci_intel_cnl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_cnl_driver); diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index 8545ab95eac8..fd219e654844 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -102,7 +102,7 @@ static struct pci_driver snd_sof_pci_intel_icl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_icl_driver); diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index 91b9cff8c4ca..ae379c23f008 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -72,7 +72,7 @@ static struct pci_driver snd_sof_pci_intel_lnl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_lnl_driver); diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index c5048a4a56be..7b2533999195 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -135,7 +135,7 @@ static struct pci_driver snd_sof_pci_intel_mtl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_mtl_driver); diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c index 3812ab6d99c0..7d4c46f56931 100644 --- a/sound/soc/sof/intel/pci-ptl.c +++ b/sound/soc/sof/intel/pci-ptl.c @@ -71,7 +71,7 @@ static struct pci_driver snd_sof_pci_intel_ptl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_ptl_driver); diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index bd9daae51e4c..a16945dc35f7 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -83,7 +83,7 @@ static struct pci_driver snd_sof_pci_intel_skl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_skl_driver); diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index f76a7197f6ca..437c43819825 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -311,7 +311,7 @@ static struct pci_driver snd_sof_pci_intel_tgl_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_tgl_driver); diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index 3eb7400942dd..0c11cc1fd820 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -238,7 +238,7 @@ static struct pci_driver snd_sof_pci_intel_tng_driver = { .remove = sof_pci_remove, .shutdown = sof_pci_shutdown, .driver = { - .pm = &sof_pci_pm, + .pm = pm_ptr(&sof_pci_pm), }, }; module_pci_driver(snd_sof_pci_intel_tng_driver); diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 103377e2caaf..2fc14b9a33d4 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -155,14 +155,13 @@ static const struct dmi_system_id community_key_platforms[] = { {}, }; -const struct dev_pm_ops sof_pci_pm = { +EXPORT_NS_DEV_PM_OPS(sof_pci_pm, SND_SOC_SOF_PCI_DEV) = { .prepare = snd_sof_prepare, .complete = snd_sof_complete, - SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) - SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, - snd_sof_runtime_idle) + SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) + RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, + snd_sof_runtime_idle) }; -EXPORT_SYMBOL_NS(sof_pci_pm, "SND_SOC_SOF_PCI_DEV"); static void sof_pci_probe_complete(struct device *dev) { From f8d952c5f77fb8c2791d0978a2f4d6c72965cbe0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:41 +0100 Subject: [PATCH 1044/1090] ASoC: SOF: of: Convert to EXPORT_DEV_PM_OPS() Use the newer EXPORT_DEV_PM_OPS() macro together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Cc: sound-open-firmware@alsa-project.org Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-80-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 2 +- sound/soc/sof/imx/imx9.c | 2 +- sound/soc/sof/mediatek/mt8186/mt8186.c | 2 +- sound/soc/sof/mediatek/mt8195/mt8195.c | 2 +- sound/soc/sof/sof-of-dev.c | 8 +++----- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 4be4c569b583..ab07512e511d 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -456,7 +456,7 @@ static struct platform_driver snd_sof_of_imx8_driver = { .remove = sof_of_remove, .driver = { .name = "sof-audio-of-imx8", - .pm = &sof_of_pm, + .pm = pm_ptr(&sof_of_pm), .of_match_table = sof_of_imx8_ids, }, }; diff --git a/sound/soc/sof/imx/imx9.c b/sound/soc/sof/imx/imx9.c index 598675d4350a..853155d5990a 100644 --- a/sound/soc/sof/imx/imx9.c +++ b/sound/soc/sof/imx/imx9.c @@ -126,7 +126,7 @@ static struct platform_driver snd_sof_of_imx9_driver = { .remove = sof_of_remove, .driver = { .name = "sof-audio-of-imx9", - .pm = &sof_of_pm, + .pm = pm_ptr(&sof_of_pm), .of_match_table = sof_of_imx9_ids, }, }; diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c index 31437fdd4e92..18144d9504e1 100644 --- a/sound/soc/sof/mediatek/mt8186/mt8186.c +++ b/sound/soc/sof/mediatek/mt8186/mt8186.c @@ -660,7 +660,7 @@ static struct platform_driver snd_sof_of_mt8186_driver = { .shutdown = sof_of_shutdown, .driver = { .name = "sof-audio-of-mt8186", - .pm = &sof_of_pm, + .pm = pm_ptr(&sof_of_pm), .of_match_table = sof_of_mt8186_ids, }, }; diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 371563d7ce79..821f43a3974a 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -616,7 +616,7 @@ static struct platform_driver snd_sof_of_mt8195_driver = { .shutdown = sof_of_shutdown, .driver = { .name = "sof-audio-of-mt8195", - .pm = &sof_of_pm, + .pm = pm_ptr(&sof_of_pm), .of_match_table = sof_of_mt8195_ids, }, }; diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index fb8c8a14d885..3ccfcfb142b7 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -30,14 +30,12 @@ static char *tplg_filename; module_param(tplg_filename, charp, 0444); MODULE_PARM_DESC(tplg_filename, "deprecated - moved to snd-sof module."); -const struct dev_pm_ops sof_of_pm = { +EXPORT_DEV_PM_OPS(sof_of_pm) = { .prepare = snd_sof_prepare, .complete = snd_sof_complete, - SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) - SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, - NULL) + SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume) + RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume, NULL) }; -EXPORT_SYMBOL(sof_of_pm); static void sof_of_probe_complete(struct device *dev) { From 7369a2d95878f427959980539549d0eb9ec4958c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:42 +0100 Subject: [PATCH 1045/1090] ASoC: stm: Convert to SYSTEM_SLEEP_PM_OPS() Use the newer SYSTEM_SLEEP_PM_OPS() macro instead SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping superfluous CONFIG_PM_SLEEP ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Olivier Moysan Cc: Arnaud Pouliquen Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-81-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 6 ++---- sound/soc/stm/stm32_sai.c | 6 ++---- sound/soc/stm/stm32_sai_sub.c | 6 ++---- sound/soc/stm/stm32_spdifrx.c | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 19dc61008a75..6037b7a9c97b 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1352,7 +1352,6 @@ error: MODULE_DEVICE_TABLE(of, stm32_i2s_ids); -#ifdef CONFIG_PM_SLEEP static int stm32_i2s_suspend(struct device *dev) { struct stm32_i2s_data *i2s = dev_get_drvdata(dev); @@ -1370,17 +1369,16 @@ static int stm32_i2s_resume(struct device *dev) regcache_cache_only(i2s->regmap, false); return regcache_sync(i2s->regmap); } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops stm32_i2s_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_i2s_suspend, stm32_i2s_resume) + SYSTEM_SLEEP_PM_OPS(stm32_i2s_suspend, stm32_i2s_resume) }; static struct platform_driver stm32_i2s_driver = { .driver = { .name = "st,stm32-i2s", .of_match_table = stm32_i2s_ids, - .pm = &stm32_i2s_pm_ops, + .pm = pm_ptr(&stm32_i2s_pm_ops), }, .probe = stm32_i2s_probe, .remove = stm32_i2s_remove, diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index bc8180fc8462..504a14584765 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -270,7 +270,6 @@ static int stm32_sai_probe(struct platform_device *pdev) return devm_of_platform_populate(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP /* * When pins are shared by two sai sub instances, pins have to be defined * in sai parent node. In this case, pins state is not managed by alsa fw. @@ -305,10 +304,9 @@ static int stm32_sai_resume(struct device *dev) return pinctrl_pm_select_default_state(dev); } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops stm32_sai_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_sai_suspend, stm32_sai_resume) + SYSTEM_SLEEP_PM_OPS(stm32_sai_suspend, stm32_sai_resume) }; MODULE_DEVICE_TABLE(of, stm32_sai_ids); @@ -317,7 +315,7 @@ static struct platform_driver stm32_sai_driver = { .driver = { .name = "st,stm32-sai", .of_match_table = stm32_sai_ids, - .pm = &stm32_sai_pm_ops, + .pm = pm_ptr(&stm32_sai_pm_ops), }, .probe = stm32_sai_probe, }; diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 3efbf4aaf965..e8c1abf1ae0a 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1704,7 +1704,6 @@ static void stm32_sai_sub_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP static int stm32_sai_sub_suspend(struct device *dev) { struct stm32_sai_sub_data *sai = dev_get_drvdata(dev); @@ -1738,17 +1737,16 @@ static int stm32_sai_sub_resume(struct device *dev) return ret; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops stm32_sai_sub_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_sai_sub_suspend, stm32_sai_sub_resume) + SYSTEM_SLEEP_PM_OPS(stm32_sai_sub_suspend, stm32_sai_sub_resume) }; static struct platform_driver stm32_sai_sub_driver = { .driver = { .name = "st,stm32-sai-sub", .of_match_table = stm32_sai_sub_ids, - .pm = &stm32_sai_sub_pm_ops, + .pm = pm_ptr(&stm32_sai_sub_pm_ops), }, .probe = stm32_sai_sub_probe, .remove = stm32_sai_sub_remove, diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 9e30852de93c..57b711c44278 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -1040,7 +1040,6 @@ error: MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); -#ifdef CONFIG_PM_SLEEP static int stm32_spdifrx_suspend(struct device *dev) { struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(dev); @@ -1059,17 +1058,16 @@ static int stm32_spdifrx_resume(struct device *dev) return regcache_sync(spdifrx->regmap); } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops stm32_spdifrx_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_spdifrx_suspend, stm32_spdifrx_resume) + SYSTEM_SLEEP_PM_OPS(stm32_spdifrx_suspend, stm32_spdifrx_resume) }; static struct platform_driver stm32_spdifrx_driver = { .driver = { .name = "st,stm32-spdifrx", .of_match_table = stm32_spdifrx_ids, - .pm = &stm32_spdifrx_pm_ops, + .pm = pm_ptr(&stm32_spdifrx_pm_ops), }, .probe = stm32_spdifrx_probe, .remove = stm32_spdifrx_remove, From 723b690723287c39b386dbf8dad8834c4acbc0ef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:43 +0100 Subject: [PATCH 1046/1090] ASoC: sunxi: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-82-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-spdif.c | 6 +++--- sound/soc/sunxi/sun50i-dmic.c | 6 +++--- sound/soc/sunxi/sun8i-codec.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 41caf1795d09..34e5bd94e9af 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -727,15 +727,15 @@ static void sun4i_spdif_remove(struct platform_device *pdev) } static const struct dev_pm_ops sun4i_spdif_pm = { - SET_RUNTIME_PM_OPS(sun4i_spdif_runtime_suspend, - sun4i_spdif_runtime_resume, NULL) + RUNTIME_PM_OPS(sun4i_spdif_runtime_suspend, + sun4i_spdif_runtime_resume, NULL) }; static struct platform_driver sun4i_spdif_driver = { .driver = { .name = "sun4i-spdif", .of_match_table = sun4i_spdif_of_match, - .pm = &sun4i_spdif_pm, + .pm = pm_ptr(&sun4i_spdif_pm), }, .probe = sun4i_spdif_probe, .remove = sun4i_spdif_remove, diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index 3e751b5694fe..bab1e29c9988 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -415,15 +415,15 @@ static void sun50i_dmic_remove(struct platform_device *pdev) } static const struct dev_pm_ops sun50i_dmic_pm = { - SET_RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend, - sun50i_dmic_runtime_resume, NULL) + RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend, + sun50i_dmic_runtime_resume, NULL) }; static struct platform_driver sun50i_dmic_driver = { .driver = { .name = "sun50i-dmic", .of_match_table = sun50i_dmic_of_match, - .pm = &sun50i_dmic_pm, + .pm = pm_ptr(&sun50i_dmic_pm), }, .probe = sun50i_dmic_probe, .remove = sun50i_dmic_remove, diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 8c645e04d571..8b9eb1a202f7 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -1702,15 +1702,15 @@ static const struct of_device_id sun8i_codec_of_match[] = { MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); static const struct dev_pm_ops sun8i_codec_pm_ops = { - SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, - sun8i_codec_runtime_resume, NULL) + RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, + sun8i_codec_runtime_resume, NULL) }; static struct platform_driver sun8i_codec_driver = { .driver = { .name = "sun8i-codec", .of_match_table = sun8i_codec_of_match, - .pm = &sun8i_codec_pm_ops, + .pm = pm_ptr(&sun8i_codec_pm_ops), }, .probe = sun8i_codec_probe, .remove = sun8i_codec_remove, From 5f6e34c575b86becafbee0051b2eb47145b5af57 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:44 +0100 Subject: [PATCH 1047/1090] ASoC: tegra186: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: linux-tegra@vger.kernel.org Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-83-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra186_asrc.c | 13 ++++++------- sound/soc/tegra/tegra186_dspk.c | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sound/soc/tegra/tegra186_asrc.c b/sound/soc/tegra/tegra186_asrc.c index d914dba56013..5c67e1f01d9b 100644 --- a/sound/soc/tegra/tegra186_asrc.c +++ b/sound/soc/tegra/tegra186_asrc.c @@ -76,7 +76,7 @@ static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc, 1); } -static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev) +static int tegra186_asrc_runtime_suspend(struct device *dev) { struct tegra186_asrc *asrc = dev_get_drvdata(dev); @@ -86,7 +86,7 @@ static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev) +static int tegra186_asrc_runtime_resume(struct device *dev) { struct tegra186_asrc *asrc = dev_get_drvdata(dev); int id; @@ -1021,17 +1021,16 @@ static void tegra186_asrc_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra186_asrc_pm_ops = { - SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend, - tegra186_asrc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend, + tegra186_asrc_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra186_asrc_driver = { .driver = { .name = "tegra186-asrc", .of_match_table = tegra186_asrc_of_match, - .pm = &tegra186_asrc_pm_ops, + .pm = pm_ptr(&tegra186_asrc_pm_ops), }, .probe = tegra186_asrc_platform_probe, .remove = tegra186_asrc_platform_remove, diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index 1be6c09cbe1a..21fdab2a1977 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -181,7 +181,7 @@ static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol, return 1; } -static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) +static int tegra186_dspk_runtime_suspend(struct device *dev) { struct tegra186_dspk *dspk = dev_get_drvdata(dev); @@ -193,7 +193,7 @@ static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev) +static int tegra186_dspk_runtime_resume(struct device *dev) { struct tegra186_dspk *dspk = dev_get_drvdata(dev); int err; @@ -532,17 +532,16 @@ static void tegra186_dspk_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra186_dspk_pm_ops = { - SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, - tegra186_dspk_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend, + tegra186_dspk_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra186_dspk_driver = { .driver = { .name = "tegra186-dspk", .of_match_table = tegra186_dspk_of_match, - .pm = &tegra186_dspk_pm_ops, + .pm = pm_ptr(&tegra186_dspk_pm_ops), }, .probe = tegra186_dspk_platform_probe, .remove = tegra186_dspk_platform_remove, From 083c6a6f79e724ff89394d6ab900028a2e99ff7b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:45 +0100 Subject: [PATCH 1048/1090] ASoC: tegra210: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: linux-tegra@vger.kernel.org Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-84-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_admaif.c | 13 ++++++------- sound/soc/tegra/tegra210_adx.c | 13 ++++++------- sound/soc/tegra/tegra210_ahub.c | 13 ++++++------- sound/soc/tegra/tegra210_amx.c | 13 ++++++------- sound/soc/tegra/tegra210_dmic.c | 13 ++++++------- sound/soc/tegra/tegra210_i2s.c | 13 ++++++------- sound/soc/tegra/tegra210_mixer.c | 13 ++++++------- sound/soc/tegra/tegra210_mvc.c | 13 ++++++------- sound/soc/tegra/tegra210_ope.c | 13 ++++++------- sound/soc/tegra/tegra210_sfc.c | 13 ++++++------- 10 files changed, 60 insertions(+), 70 deletions(-) diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index f56d1e03239d..76ff4fe40f65 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -220,7 +220,7 @@ static const struct regmap_config tegra186_admaif_regmap_config = { .cache_type = REGCACHE_FLAT, }; -static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev) +static int tegra_admaif_runtime_suspend(struct device *dev) { struct tegra_admaif *admaif = dev_get_drvdata(dev); @@ -230,7 +230,7 @@ static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev) +static int tegra_admaif_runtime_resume(struct device *dev) { struct tegra_admaif *admaif = dev_get_drvdata(dev); @@ -877,10 +877,9 @@ static void tegra_admaif_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra_admaif_pm_ops = { - SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend, - tegra_admaif_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra_admaif_runtime_suspend, + tegra_admaif_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra_admaif_driver = { @@ -889,7 +888,7 @@ static struct platform_driver tegra_admaif_driver = { .driver = { .name = "tegra210-admaif", .of_match_table = tegra_admaif_of_match, - .pm = &tegra_admaif_pm_ops, + .pm = pm_ptr(&tegra_admaif_pm_ops), }, }; module_platform_driver(tegra_admaif_driver); diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 0aa93b948378..ff34682ebb15 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -84,7 +84,7 @@ static int tegra210_adx_startup(struct snd_pcm_substream *substream, return 0; } -static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev) +static int tegra210_adx_runtime_suspend(struct device *dev) { struct tegra210_adx *adx = dev_get_drvdata(dev); @@ -94,7 +94,7 @@ static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev) +static int tegra210_adx_runtime_resume(struct device *dev) { struct tegra210_adx *adx = dev_get_drvdata(dev); @@ -524,17 +524,16 @@ static void tegra210_adx_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_adx_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, - tegra210_adx_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, + tegra210_adx_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra210_adx_driver = { .driver = { .name = "tegra210-adx", .of_match_table = tegra210_adx_of_match, - .pm = &tegra210_adx_pm_ops, + .pm = pm_ptr(&tegra210_adx_pm_ops), }, .probe = tegra210_adx_platform_probe, .remove = tegra210_adx_platform_remove, diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index 1920b996e9aa..99683f292b5d 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -1319,7 +1319,7 @@ static const struct of_device_id tegra_ahub_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_ahub_of_match); -static int __maybe_unused tegra_ahub_runtime_suspend(struct device *dev) +static int tegra_ahub_runtime_suspend(struct device *dev) { struct tegra_ahub *ahub = dev_get_drvdata(dev); @@ -1331,7 +1331,7 @@ static int __maybe_unused tegra_ahub_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra_ahub_runtime_resume(struct device *dev) +static int tegra_ahub_runtime_resume(struct device *dev) { struct tegra_ahub *ahub = dev_get_drvdata(dev); int err; @@ -1408,10 +1408,9 @@ static void tegra_ahub_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra_ahub_pm_ops = { - SET_RUNTIME_PM_OPS(tegra_ahub_runtime_suspend, - tegra_ahub_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra_ahub_runtime_suspend, + tegra_ahub_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra_ahub_driver = { @@ -1420,7 +1419,7 @@ static struct platform_driver tegra_ahub_driver = { .driver = { .name = "tegra210-ahub", .of_match_table = tegra_ahub_of_match, - .pm = &tegra_ahub_pm_ops, + .pm = pm_ptr(&tegra_ahub_pm_ops), }, }; module_platform_driver(tegra_ahub_driver); diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index a9ef22c19e81..1981b94009cf 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -98,7 +98,7 @@ static int tegra210_amx_startup(struct snd_pcm_substream *substream, return 0; } -static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev) +static int tegra210_amx_runtime_suspend(struct device *dev) { struct tegra210_amx *amx = dev_get_drvdata(dev); @@ -108,7 +108,7 @@ static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_amx_runtime_resume(struct device *dev) +static int tegra210_amx_runtime_resume(struct device *dev) { struct tegra210_amx *amx = dev_get_drvdata(dev); @@ -581,17 +581,16 @@ static void tegra210_amx_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_amx_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend, - tegra210_amx_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_amx_runtime_suspend, + tegra210_amx_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra210_amx_driver = { .driver = { .name = "tegra210-amx", .of_match_table = tegra210_amx_of_match, - .pm = &tegra210_amx_pm_ops, + .pm = pm_ptr(&tegra210_amx_pm_ops), }, .probe = tegra210_amx_platform_probe, .remove = tegra210_amx_platform_remove, diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index 7986be71f43d..e4a144571265 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -40,7 +40,7 @@ static const struct reg_default tegra210_dmic_reg_defaults[] = { { TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 }, }; -static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev) +static int tegra210_dmic_runtime_suspend(struct device *dev) { struct tegra210_dmic *dmic = dev_get_drvdata(dev); @@ -52,7 +52,7 @@ static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_dmic_runtime_resume(struct device *dev) +static int tegra210_dmic_runtime_resume(struct device *dev) { struct tegra210_dmic *dmic = dev_get_drvdata(dev); int err; @@ -543,10 +543,9 @@ static void tegra210_dmic_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_dmic_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, - tegra210_dmic_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, + tegra210_dmic_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct of_device_id tegra210_dmic_of_match[] = { @@ -559,7 +558,7 @@ static struct platform_driver tegra210_dmic_driver = { .driver = { .name = "tegra210-dmic", .of_match_table = tegra210_dmic_of_match, - .pm = &tegra210_dmic_pm_ops, + .pm = pm_ptr(&tegra210_dmic_pm_ops), }, .probe = tegra210_dmic_probe, .remove = tegra210_dmic_remove, diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 07ce2dbe6c00..766cddebd5f6 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -166,7 +166,7 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, return tegra210_i2s_sw_reset(compnt, stream); } -static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev) +static int tegra210_i2s_runtime_suspend(struct device *dev) { struct tegra210_i2s *i2s = dev_get_drvdata(dev); @@ -178,7 +178,7 @@ static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_i2s_runtime_resume(struct device *dev) +static int tegra210_i2s_runtime_resume(struct device *dev) { struct tegra210_i2s *i2s = dev_get_drvdata(dev); int err; @@ -1010,10 +1010,9 @@ static void tegra210_i2s_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, - tegra210_i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, + tegra210_i2s_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct of_device_id tegra210_i2s_of_match[] = { @@ -1026,7 +1025,7 @@ static struct platform_driver tegra210_i2s_driver = { .driver = { .name = "tegra210-i2s", .of_match_table = tegra210_i2s_of_match, - .pm = &tegra210_i2s_pm_ops, + .pm = pm_ptr(&tegra210_i2s_pm_ops), }, .probe = tegra210_i2s_probe, .remove = tegra210_i2s_remove, diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index 410259d98dfb..95d69a7e027f 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -73,7 +73,7 @@ static const struct tegra210_mixer_gain_params gain_params = { { 0, 0, 0x400, 0x8000000 }, }; -static int __maybe_unused tegra210_mixer_runtime_suspend(struct device *dev) +static int tegra210_mixer_runtime_suspend(struct device *dev) { struct tegra210_mixer *mixer = dev_get_drvdata(dev); @@ -83,7 +83,7 @@ static int __maybe_unused tegra210_mixer_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_mixer_runtime_resume(struct device *dev) +static int tegra210_mixer_runtime_resume(struct device *dev) { struct tegra210_mixer *mixer = dev_get_drvdata(dev); @@ -666,17 +666,16 @@ static void tegra210_mixer_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_mixer_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend, - tegra210_mixer_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend, + tegra210_mixer_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra210_mixer_driver = { .driver = { .name = "tegra210_mixer", .of_match_table = tegra210_mixer_of_match, - .pm = &tegra210_mixer_pm_ops, + .pm = pm_ptr(&tegra210_mixer_pm_ops), }, .probe = tegra210_mixer_platform_probe, .remove = tegra210_mixer_platform_remove, diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index 119f17501478..35b14c8396f4 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -47,7 +47,7 @@ static const struct tegra210_mvc_gain_params gain_params = { .duration_inv = 14316558, }; -static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev) +static int tegra210_mvc_runtime_suspend(struct device *dev) { struct tegra210_mvc *mvc = dev_get_drvdata(dev); @@ -59,7 +59,7 @@ static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_mvc_runtime_resume(struct device *dev) +static int tegra210_mvc_runtime_resume(struct device *dev) { struct tegra210_mvc *mvc = dev_get_drvdata(dev); @@ -758,17 +758,16 @@ static void tegra210_mvc_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_mvc_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend, - tegra210_mvc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend, + tegra210_mvc_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra210_mvc_driver = { .driver = { .name = "tegra210-mvc", .of_match_table = tegra210_mvc_of_match, - .pm = &tegra210_mvc_pm_ops, + .pm = pm_ptr(&tegra210_mvc_pm_ops), }, .probe = tegra210_mvc_platform_probe, .remove = tegra210_mvc_platform_remove, diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c index c595cec9baab..5036bcfe0828 100644 --- a/sound/soc/tegra/tegra210_ope.c +++ b/sound/soc/tegra/tegra210_ope.c @@ -356,7 +356,7 @@ static void tegra210_ope_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev) +static int tegra210_ope_runtime_suspend(struct device *dev) { struct tegra210_ope *ope = dev_get_drvdata(dev); @@ -374,7 +374,7 @@ static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_ope_runtime_resume(struct device *dev) +static int tegra210_ope_runtime_resume(struct device *dev) { struct tegra210_ope *ope = dev_get_drvdata(dev); @@ -393,10 +393,9 @@ static int __maybe_unused tegra210_ope_runtime_resume(struct device *dev) } static const struct dev_pm_ops tegra210_ope_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_ope_runtime_suspend, - tegra210_ope_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_ope_runtime_suspend, + tegra210_ope_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct of_device_id tegra210_ope_of_match[] = { @@ -409,7 +408,7 @@ static struct platform_driver tegra210_ope_driver = { .driver = { .name = "tegra210-ope", .of_match_table = tegra210_ope_of_match, - .pm = &tegra210_ope_pm_ops, + .pm = pm_ptr(&tegra210_ope_pm_ops), }, .probe = tegra210_ope_probe, .remove = tegra210_ope_remove, diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c index df88708c733c..a0bd36f12c68 100644 --- a/sound/soc/tegra/tegra210_sfc.c +++ b/sound/soc/tegra/tegra210_sfc.c @@ -3056,7 +3056,7 @@ static s32 *coef_addr_table[TEGRA210_SFC_NUM_RATES][TEGRA210_SFC_NUM_RATES] = { }, }; -static int __maybe_unused tegra210_sfc_runtime_suspend(struct device *dev) +static int tegra210_sfc_runtime_suspend(struct device *dev) { struct tegra210_sfc *sfc = dev_get_drvdata(dev); @@ -3066,7 +3066,7 @@ static int __maybe_unused tegra210_sfc_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused tegra210_sfc_runtime_resume(struct device *dev) +static int tegra210_sfc_runtime_resume(struct device *dev) { struct tegra210_sfc *sfc = dev_get_drvdata(dev); @@ -3623,17 +3623,16 @@ static void tegra210_sfc_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra210_sfc_pm_ops = { - SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend, - tegra210_sfc_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend, + tegra210_sfc_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra210_sfc_driver = { .driver = { .name = "tegra210-sfc", .of_match_table = tegra210_sfc_of_match, - .pm = &tegra210_sfc_pm_ops, + .pm = pm_ptr(&tegra210_sfc_pm_ops), }, .probe = tegra210_sfc_platform_probe, .remove = tegra210_sfc_platform_remove, From b7055fc11dc66f5dda6ffc0d88d7ede09970b244 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:46 +0100 Subject: [PATCH 1049/1090] ASoC: tegra20: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: linux-tegra@vger.kernel.org Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-85-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 13 ++++++------- sound/soc/tegra/tegra20_spdif.c | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 3b9823d1a87a..51df0835ce3e 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -34,7 +34,7 @@ #define DRV_NAME "tegra20-i2s" -static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev) +static int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); @@ -45,7 +45,7 @@ static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev) return 0; } -static __maybe_unused int tegra20_i2s_runtime_resume(struct device *dev) +static int tegra20_i2s_runtime_resume(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); int ret; @@ -487,17 +487,16 @@ static const struct of_device_id tegra20_i2s_of_match[] = { }; static const struct dev_pm_ops tegra20_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, - tegra20_i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, + tegra20_i2s_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra20_i2s_driver = { .driver = { .name = DRV_NAME, .of_match_table = tegra20_i2s_of_match, - .pm = &tegra20_i2s_pm_ops, + .pm = pm_ptr(&tegra20_i2s_pm_ops), }, .probe = tegra20_i2s_platform_probe, .remove = tegra20_i2s_platform_remove, diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 380011233eb1..38661d9b4a7c 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -25,7 +25,7 @@ #include "tegra20_spdif.h" -static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev) +static int tegra20_spdif_runtime_suspend(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); @@ -36,7 +36,7 @@ static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev) return 0; } -static __maybe_unused int tegra20_spdif_runtime_resume(struct device *dev) +static int tegra20_spdif_runtime_resume(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); int ret; @@ -403,10 +403,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) } static const struct dev_pm_ops tegra20_spdif_pm_ops = { - SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend, - tegra20_spdif_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend, + tegra20_spdif_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static const struct of_device_id tegra20_spdif_of_match[] = { @@ -418,7 +417,7 @@ MODULE_DEVICE_TABLE(of, tegra20_spdif_of_match); static struct platform_driver tegra20_spdif_driver = { .driver = { .name = "tegra20-spdif", - .pm = &tegra20_spdif_pm_ops, + .pm = pm_ptr(&tegra20_spdif_pm_ops), .of_match_table = tegra20_spdif_of_match, }, .probe = tegra20_spdif_platform_probe, From 212f5c4f1d45ffe43e52edc175f294426aba8ee7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:47 +0100 Subject: [PATCH 1050/1090] ASoC: tegra30: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Cc: linux-tegra@vger.kernel.org Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-86-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 13 ++++++------- sound/soc/tegra/tegra30_i2s.c | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index c9b52f54cea8..51e5ab6c276b 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -40,7 +40,7 @@ static inline void tegra30_audio_write(u32 reg, u32 val) regmap_write(ahub->regmap_ahub, reg, val); } -static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev) +static int tegra30_ahub_runtime_suspend(struct device *dev) { regcache_cache_only(ahub->regmap_apbif, true); regcache_cache_only(ahub->regmap_ahub, true); @@ -61,7 +61,7 @@ static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev) * stopping streams should dynamically adjust the clock as required. However, * this is not yet implemented. */ -static __maybe_unused int tegra30_ahub_runtime_resume(struct device *dev) +static int tegra30_ahub_runtime_resume(struct device *dev) { int ret; @@ -600,10 +600,9 @@ static void tegra30_ahub_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra30_ahub_pm_ops = { - SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, - tegra30_ahub_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, + tegra30_ahub_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra30_ahub_driver = { @@ -612,7 +611,7 @@ static struct platform_driver tegra30_ahub_driver = { .driver = { .name = DRV_NAME, .of_match_table = tegra30_ahub_of_match, - .pm = &tegra30_ahub_pm_ops, + .pm = pm_ptr(&tegra30_ahub_pm_ops), }, }; module_platform_driver(tegra30_ahub_driver); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 0d3badfbe143..b121af9ef8ed 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -35,7 +35,7 @@ #define DRV_NAME "tegra30-i2s" -static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev) +static int tegra30_i2s_runtime_suspend(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); @@ -46,7 +46,7 @@ static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev) return 0; } -static __maybe_unused int tegra30_i2s_runtime_resume(struct device *dev) +static int tegra30_i2s_runtime_resume(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); int ret; @@ -547,17 +547,16 @@ static void tegra30_i2s_platform_remove(struct platform_device *pdev) } static const struct dev_pm_ops tegra30_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, - tegra30_i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, + tegra30_i2s_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver tegra30_i2s_driver = { .driver = { .name = DRV_NAME, .of_match_table = tegra30_i2s_of_match, - .pm = &tegra30_i2s_pm_ops, + .pm = pm_ptr(&tegra30_i2s_pm_ops), }, .probe = tegra30_i2s_platform_probe, .remove = tegra30_i2s_platform_remove, From c7ef05c0061acf505523133986adc47086265d99 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:48 +0100 Subject: [PATCH 1051/1090] ASoC: xtensa: Convert to RUNTIME_PM_OPS() Use the newer RUNTIME_PM_OPS() macro instead of SET_RUNTIME_PM_OPS() together with pm_ptr(). This optimizes slightly when CONFIG_PM is disabled, too. Reviewed-by: Max Filippov Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-87-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 4eaa9011405f..678ded059b95 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -629,8 +629,8 @@ MODULE_DEVICE_TABLE(of, xtfpga_i2s_of_match); #endif static const struct dev_pm_ops xtfpga_i2s_pm_ops = { - SET_RUNTIME_PM_OPS(xtfpga_i2s_runtime_suspend, - xtfpga_i2s_runtime_resume, NULL) + RUNTIME_PM_OPS(xtfpga_i2s_runtime_suspend, + xtfpga_i2s_runtime_resume, NULL) }; static struct platform_driver xtfpga_i2s_driver = { @@ -639,7 +639,7 @@ static struct platform_driver xtfpga_i2s_driver = { .driver = { .name = "xtfpga-i2s", .of_match_table = of_match_ptr(xtfpga_i2s_of_match), - .pm = &xtfpga_i2s_pm_ops, + .pm = pm_ptr(&xtfpga_i2s_pm_ops), }, }; From 5f86b16c49a9d156a459c7e9e3ebcbbe9439953c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:49 +0100 Subject: [PATCH 1052/1090] ASoC: amd: Convert to RUNTIME_PM_OPS() & co Use the newer RUNTIME_PM_OPS() and SYSTEM_SLEEP_PM_OPS() macros instead of SET_RUNTIME_PM_OPS() and SET_SYSTEM_SLEEP_PM_OPS() together with pm_ptr(), which allows us dropping ugly __maybe_unused attributes. This optimizes slightly when CONFIG_PM is disabled, too. Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-88-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pci.c | 10 +++++----- sound/soc/amd/acp/acp-rembrandt.c | 6 +++--- sound/soc/amd/acp/acp-renoir.c | 6 +++--- sound/soc/amd/acp/acp63.c | 6 +++--- sound/soc/amd/acp/acp70.c | 6 +++--- sound/soc/amd/ps/pci-ps.c | 12 ++++++------ sound/soc/amd/ps/ps-pdm-dma.c | 12 ++++++------ sound/soc/amd/ps/ps-sdw-dma.c | 6 +++--- sound/soc/amd/rpl/rpl-pci-acp6x.c | 10 +++++----- sound/soc/amd/vangogh/acp5x-pcm-dma.c | 11 +++++------ sound/soc/amd/yc/acp6x-pdm-dma.c | 12 ++++++------ sound/soc/amd/yc/pci-acp6x.c | 10 +++++----- 12 files changed, 53 insertions(+), 54 deletions(-) diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 9322379cb36f..de1cdca5ade7 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -221,7 +221,7 @@ disable_pci: return ret; }; -static int __maybe_unused snd_acp_suspend(struct device *dev) +static int snd_acp_suspend(struct device *dev) { struct acp_chip_info *chip; int ret; @@ -233,7 +233,7 @@ static int __maybe_unused snd_acp_suspend(struct device *dev) return ret; } -static int __maybe_unused snd_acp_resume(struct device *dev) +static int snd_acp_resume(struct device *dev) { struct acp_chip_info *chip; int ret; @@ -251,8 +251,8 @@ static int __maybe_unused snd_acp_resume(struct device *dev) } static const struct dev_pm_ops acp_pm_ops = { - SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) + RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) }; static void acp_pci_remove(struct pci_dev *pci) @@ -289,7 +289,7 @@ static struct pci_driver snd_amd_acp_pci_driver = { .probe = acp_pci_probe, .remove = acp_pci_remove, .driver = { - .pm = &acp_pm_ops, + .pm = pm_ptr(&acp_pm_ops), }, }; module_pci_driver(snd_amd_acp_pci_driver); diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 21614e2e1b6c..746b6ed72029 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -197,7 +197,7 @@ static void rembrandt_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused rmb_pcm_resume(struct device *dev) +static int rmb_pcm_resume(struct device *dev) { struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; @@ -227,7 +227,7 @@ static int __maybe_unused rmb_pcm_resume(struct device *dev) } static const struct dev_pm_ops rmb_dma_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume) + SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume) }; static struct platform_driver rembrandt_driver = { @@ -235,7 +235,7 @@ static struct platform_driver rembrandt_driver = { .remove = rembrandt_audio_remove, .driver = { .name = "acp_asoc_rembrandt", - .pm = &rmb_dma_pm_ops, + .pm = pm_ptr(&rmb_dma_pm_ops), }, }; diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index b8ded929d52e..ebf0106fc737 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -144,7 +144,7 @@ static void renoir_audio_remove(struct platform_device *pdev) acp_platform_unregister(dev); } -static int __maybe_unused rn_pcm_resume(struct device *dev) +static int rn_pcm_resume(struct device *dev) { struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; @@ -171,7 +171,7 @@ static int __maybe_unused rn_pcm_resume(struct device *dev) } static const struct dev_pm_ops rn_dma_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume) + SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume) }; static struct platform_driver renoir_driver = { @@ -179,7 +179,7 @@ static struct platform_driver renoir_driver = { .remove = renoir_audio_remove, .driver = { .name = "acp_asoc_renoir", - .pm = &rn_dma_pm_ops, + .pm = pm_ptr(&rn_dma_pm_ops), }, }; diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 53c013a64854..52d895e624c7 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -248,7 +248,7 @@ static void acp63_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused acp63_pcm_resume(struct device *dev) +static int acp63_pcm_resume(struct device *dev) { struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; @@ -278,7 +278,7 @@ static int __maybe_unused acp63_pcm_resume(struct device *dev) } static const struct dev_pm_ops acp63_dma_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume) + SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume) }; static struct platform_driver acp63_driver = { @@ -286,7 +286,7 @@ static struct platform_driver acp63_driver = { .remove = acp63_audio_remove, .driver = { .name = "acp_asoc_acp63", - .pm = &acp63_dma_pm_ops, + .pm = pm_ptr(&acp63_dma_pm_ops), }, }; diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 1a89f8a3724f..6d5f5ade075c 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -180,7 +180,7 @@ static void acp_acp70_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused acp70_pcm_resume(struct device *dev) +static int acp70_pcm_resume(struct device *dev) { struct acp_chip_info *chip = dev_get_platdata(dev); struct acp_stream *stream; @@ -207,7 +207,7 @@ static int __maybe_unused acp70_pcm_resume(struct device *dev) } static const struct dev_pm_ops acp70_dma_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume) + SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume) }; static struct platform_driver acp70_driver = { @@ -215,7 +215,7 @@ static struct platform_driver acp70_driver = { .remove = acp_acp70_audio_remove, .driver = { .name = "acp_asoc_acp70", - .pm = &acp70_dma_pm_ops, + .pm = pm_ptr(&acp70_dma_pm_ops), }, }; diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 221c65ff03c9..8e57f31ef7f7 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -668,24 +668,24 @@ disable_pci: return ret; } -static int __maybe_unused snd_acp_suspend(struct device *dev) +static int snd_acp_suspend(struct device *dev) { return acp_hw_suspend(dev); } -static int __maybe_unused snd_acp_runtime_resume(struct device *dev) +static int snd_acp_runtime_resume(struct device *dev) { return acp_hw_runtime_resume(dev); } -static int __maybe_unused snd_acp_resume(struct device *dev) +static int snd_acp_resume(struct device *dev) { return acp_hw_resume(dev); } static const struct dev_pm_ops acp63_pm_ops = { - SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) + RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) }; static void snd_acp63_remove(struct pci_dev *pci) @@ -727,7 +727,7 @@ static struct pci_driver ps_acp63_driver = { .probe = snd_acp63_probe, .remove = snd_acp63_remove, .driver = { - .pm = &acp63_pm_ops, + .pm = pm_ptr(&acp63_pm_ops), } }; diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index 7cdeb34e8f73..9cfbe05ad996 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -402,7 +402,7 @@ static void acp63_pdm_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused acp63_pdm_resume(struct device *dev) +static int acp63_pdm_resume(struct device *dev) { struct pdm_dev_data *adata; struct snd_pcm_runtime *runtime; @@ -423,7 +423,7 @@ static int __maybe_unused acp63_pdm_resume(struct device *dev) return 0; } -static int __maybe_unused acp63_pdm_suspend(struct device *dev) +static int acp63_pdm_suspend(struct device *dev) { struct pdm_dev_data *adata; @@ -432,7 +432,7 @@ static int __maybe_unused acp63_pdm_suspend(struct device *dev) return 0; } -static int __maybe_unused acp63_pdm_runtime_resume(struct device *dev) +static int acp63_pdm_runtime_resume(struct device *dev) { struct pdm_dev_data *adata; @@ -442,8 +442,8 @@ static int __maybe_unused acp63_pdm_runtime_resume(struct device *dev) } static const struct dev_pm_ops acp63_pdm_pm_ops = { - SET_RUNTIME_PM_OPS(acp63_pdm_suspend, acp63_pdm_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(acp63_pdm_suspend, acp63_pdm_resume) + RUNTIME_PM_OPS(acp63_pdm_suspend, acp63_pdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp63_pdm_suspend, acp63_pdm_resume) }; static struct platform_driver acp63_pdm_dma_driver = { @@ -451,7 +451,7 @@ static struct platform_driver acp63_pdm_dma_driver = { .remove = acp63_pdm_audio_remove, .driver = { .name = "acp_ps_pdm_dma", - .pm = &acp63_pdm_pm_ops, + .pm = pm_ptr(&acp63_pdm_pm_ops), }, }; diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 21b336109c99..1b933a017c06 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -767,7 +767,7 @@ static int acp70_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) return 0; } -static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev) +static int acp63_sdw_pcm_resume(struct device *dev) { struct sdw_dma_dev_data *sdw_data; @@ -779,7 +779,7 @@ static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev) } static const struct dev_pm_ops acp63_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume) + SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume) }; static struct platform_driver acp63_sdw_dma_driver = { @@ -787,7 +787,7 @@ static struct platform_driver acp63_sdw_dma_driver = { .remove = acp63_sdw_platform_remove, .driver = { .name = "amd_ps_sdw_dma", - .pm = &acp63_pm_ops, + .pm = pm_ptr(&acp63_pm_ops), }, }; diff --git a/sound/soc/amd/rpl/rpl-pci-acp6x.c b/sound/soc/amd/rpl/rpl-pci-acp6x.c index a8e548ed991b..e3afe9172bdf 100644 --- a/sound/soc/amd/rpl/rpl-pci-acp6x.c +++ b/sound/soc/amd/rpl/rpl-pci-acp6x.c @@ -159,7 +159,7 @@ disable_pci: return ret; } -static int __maybe_unused snd_rpl_suspend(struct device *dev) +static int snd_rpl_suspend(struct device *dev) { struct rpl_dev_data *adata; int ret; @@ -171,7 +171,7 @@ static int __maybe_unused snd_rpl_suspend(struct device *dev) return ret; } -static int __maybe_unused snd_rpl_resume(struct device *dev) +static int snd_rpl_resume(struct device *dev) { struct rpl_dev_data *adata; int ret; @@ -184,8 +184,8 @@ static int __maybe_unused snd_rpl_resume(struct device *dev) } static const struct dev_pm_ops rpl_pm = { - SET_RUNTIME_PM_OPS(snd_rpl_suspend, snd_rpl_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_rpl_suspend, snd_rpl_resume) + RUNTIME_PM_OPS(snd_rpl_suspend, snd_rpl_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_rpl_suspend, snd_rpl_resume) }; static void snd_rpl_remove(struct pci_dev *pci) @@ -217,7 +217,7 @@ static struct pci_driver rpl_acp6x_driver = { .probe = snd_rpl_probe, .remove = snd_rpl_remove, .driver = { - .pm = &rpl_pm, + .pm = pm_ptr(&rpl_pm), } }; diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c index d5965f2b09bc..aa4726899434 100644 --- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -420,7 +420,7 @@ static void acp5x_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused acp5x_pcm_resume(struct device *dev) +static int acp5x_pcm_resume(struct device *dev) { struct i2s_dev_data *adata; struct i2s_stream_instance *rtd; @@ -473,7 +473,7 @@ static int __maybe_unused acp5x_pcm_resume(struct device *dev) return 0; } -static int __maybe_unused acp5x_pcm_suspend(struct device *dev) +static int acp5x_pcm_suspend(struct device *dev) { struct i2s_dev_data *adata; @@ -482,7 +482,7 @@ static int __maybe_unused acp5x_pcm_suspend(struct device *dev) return 0; } -static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev) +static int acp5x_pcm_runtime_resume(struct device *dev) { struct i2s_dev_data *adata; @@ -492,9 +492,8 @@ static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev) } static const struct dev_pm_ops acp5x_pm_ops = { - SET_RUNTIME_PM_OPS(acp5x_pcm_suspend, - acp5x_pcm_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume) + RUNTIME_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume) }; static struct platform_driver acp5x_dma_driver = { diff --git a/sound/soc/amd/yc/acp6x-pdm-dma.c b/sound/soc/amd/yc/acp6x-pdm-dma.c index 3eb3e82efb10..ac758b90f441 100644 --- a/sound/soc/amd/yc/acp6x-pdm-dma.c +++ b/sound/soc/amd/yc/acp6x-pdm-dma.c @@ -394,7 +394,7 @@ static void acp6x_pdm_audio_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } -static int __maybe_unused acp6x_pdm_resume(struct device *dev) +static int acp6x_pdm_resume(struct device *dev) { struct pdm_dev_data *adata; struct snd_pcm_runtime *runtime; @@ -415,7 +415,7 @@ static int __maybe_unused acp6x_pdm_resume(struct device *dev) return 0; } -static int __maybe_unused acp6x_pdm_suspend(struct device *dev) +static int acp6x_pdm_suspend(struct device *dev) { struct pdm_dev_data *adata; @@ -424,7 +424,7 @@ static int __maybe_unused acp6x_pdm_suspend(struct device *dev) return 0; } -static int __maybe_unused acp6x_pdm_runtime_resume(struct device *dev) +static int acp6x_pdm_runtime_resume(struct device *dev) { struct pdm_dev_data *adata; @@ -434,8 +434,8 @@ static int __maybe_unused acp6x_pdm_runtime_resume(struct device *dev) } static const struct dev_pm_ops acp6x_pdm_pm_ops = { - SET_RUNTIME_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_resume) + RUNTIME_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(acp6x_pdm_suspend, acp6x_pdm_resume) }; static struct platform_driver acp6x_pdm_dma_driver = { @@ -443,7 +443,7 @@ static struct platform_driver acp6x_pdm_dma_driver = { .remove = acp6x_pdm_audio_remove, .driver = { .name = "acp_yc_pdm_dma", - .pm = &acp6x_pdm_pm_ops, + .pm = pm_ptr(&acp6x_pdm_pm_ops), }, }; diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c index 7af6a349b1d4..1140ed1cbb3d 100644 --- a/sound/soc/amd/yc/pci-acp6x.c +++ b/sound/soc/amd/yc/pci-acp6x.c @@ -277,7 +277,7 @@ disable_pci: return ret; } -static int __maybe_unused snd_acp6x_suspend(struct device *dev) +static int snd_acp6x_suspend(struct device *dev) { struct acp6x_dev_data *adata; int ret; @@ -289,7 +289,7 @@ static int __maybe_unused snd_acp6x_suspend(struct device *dev) return ret; } -static int __maybe_unused snd_acp6x_resume(struct device *dev) +static int snd_acp6x_resume(struct device *dev) { struct acp6x_dev_data *adata; int ret; @@ -302,8 +302,8 @@ static int __maybe_unused snd_acp6x_resume(struct device *dev) } static const struct dev_pm_ops acp6x_pm = { - SET_RUNTIME_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume) + RUNTIME_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume, NULL) + SYSTEM_SLEEP_PM_OPS(snd_acp6x_suspend, snd_acp6x_resume) }; static void snd_acp6x_remove(struct pci_dev *pci) @@ -339,7 +339,7 @@ static struct pci_driver yc_acp6x_driver = { .probe = snd_acp6x_probe, .remove = snd_acp6x_remove, .driver = { - .pm = &acp6x_pm, + .pm = pm_ptr(&acp6x_pm), } }; From 15559cdeb9be5a0fe528cdc3f8b759a27ea8f943 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 17 Mar 2025 10:55:50 +0100 Subject: [PATCH 1053/1090] ASoC: pcm3168a: Convert to EXPORT_GPL_DEV_PM_OPS() Use the newer EXPORT_GPL_DEV_PM_OPS() macro together with pm_ptr(), which allows us to drop superfluous CONFIG_PM ifdefs. This optimizes slightly when CONFIG_PM is disabled, too. Cc: Shenghao Ding Cc: Kevin Lu Cc: Baojun Xu Signed-off-by: Takashi Iwai Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250317095603.20073-89-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a-i2c.c | 2 +- sound/soc/codecs/pcm3168a-spi.c | 2 +- sound/soc/codecs/pcm3168a.c | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c index 4da608ba514d..ff18c74b616c 100644 --- a/sound/soc/codecs/pcm3168a-i2c.c +++ b/sound/soc/codecs/pcm3168a-i2c.c @@ -59,7 +59,7 @@ static struct i2c_driver pcm3168a_i2c_driver = { .name = "pcm3168a", .acpi_match_table = pcm3168a_acpi_match, .of_match_table = pcm3168a_of_match, - .pm = &pcm3168a_pm_ops, + .pm = pm_ptr(&pcm3168a_pm_ops), }, }; module_i2c_driver(pcm3168a_i2c_driver); diff --git a/sound/soc/codecs/pcm3168a-spi.c b/sound/soc/codecs/pcm3168a-spi.c index b5b08046f545..0871338eacba 100644 --- a/sound/soc/codecs/pcm3168a-spi.c +++ b/sound/soc/codecs/pcm3168a-spi.c @@ -50,7 +50,7 @@ static struct spi_driver pcm3168a_spi_driver = { .driver = { .name = "pcm3168a", .of_match_table = pcm3168a_of_match, - .pm = &pcm3168a_pm_ops, + .pm = pm_ptr(&pcm3168a_pm_ops), }, }; module_spi_driver(pcm3168a_spi_driver); diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index df6836a652ef..c8617a488b11 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -849,7 +849,6 @@ void pcm3168a_remove(struct device *dev) } EXPORT_SYMBOL_GPL(pcm3168a_remove); -#ifdef CONFIG_PM static int pcm3168a_rt_resume(struct device *dev) { struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); @@ -905,12 +904,10 @@ static int pcm3168a_rt_suspend(struct device *dev) return 0; } -#endif -const struct dev_pm_ops pcm3168a_pm_ops = { - SET_RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL) +EXPORT_GPL_DEV_PM_OPS(pcm3168a_pm_ops) = { + RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL) }; -EXPORT_SYMBOL_GPL(pcm3168a_pm_ops); MODULE_DESCRIPTION("PCM3168A codec driver"); MODULE_AUTHOR("Damien Horsley "); From 9c2c0ef6400980f09b377be250f5dff14dbbf3b6 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Mon, 17 Mar 2025 12:54:07 +0530 Subject: [PATCH 1054/1090] ASoC: amd: acp: Fix snd_soc_acpi_mach id's duplicate symbol error Move snd_soc_acpi_mach id's of all acp platforms form header file to amd-acpi-mach.c file to avoid below errors. ld.lld: error: duplicate symbol: amp_rt1019 ld.lld: error: duplicate symbol: amp_max ld.lld: error: duplicate symbol: snd_soc_acpi_amd_acp63_acp_machines ld.lld: error: duplicate symbol: snd_soc_acpi_amd_acp70_acp_machines ld.lld: error: duplicate symbol: snd_soc_acpi_amd_rmb_acp_machines ld.lld: error: duplicate symbol: snd_soc_acpi_amd_acp_machines Fixes: 6e60db74b69c ("ASoC: amd: acp: Refactor acp machine select") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202503160801.yExt0K2E-lkp@intel.com/ Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250317072413.88971-1-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/Kconfig | 8 +++ sound/soc/amd/acp/Makefile | 2 + sound/soc/amd/acp/acp-pci.c | 8 +-- sound/soc/amd/acp/amd-acpi-mach.c | 93 +++++++++++++++++++++++++++++++ sound/soc/amd/acp/amd.h | 79 ++------------------------ 5 files changed, 111 insertions(+), 79 deletions(-) create mode 100644 sound/soc/amd/acp/amd-acpi-mach.c diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 157c124570c8..b9432052c638 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -28,6 +28,9 @@ config SND_SOC_AMD_ACP_LEGACY_COMMON config SND_SOC_AMD_ACP_I2S tristate +config SND_SOC_AMD_ACPI_MACH + tristate + config SND_SOC_AMD_ACP_PCM tristate select SND_SOC_ACPI if ACPI @@ -37,6 +40,7 @@ config SND_SOC_AMD_ACP_PCI depends on X86 && PCI depends on ACPI select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH help This options enables generic PCI driver for ACP device. @@ -47,6 +51,7 @@ config SND_AMD_ASOC_RENOIR select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH depends on X86 && PCI help This option enables Renoir I2S support on AMD platform. @@ -58,6 +63,7 @@ config SND_AMD_ASOC_REMBRANDT select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH depends on AMD_NODE depends on X86 && PCI help @@ -74,6 +80,7 @@ config SND_AMD_ASOC_ACP63 select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH help This option enables Acp6.3 I2S support on AMD platform. Say Y if you want to enable AUDIO on ACP6.3 @@ -88,6 +95,7 @@ config SND_AMD_ASOC_ACP70 select SND_SOC_AMD_ACP_I2S select SND_SOC_AMD_ACP_PDM select SND_SOC_AMD_ACP_LEGACY_COMMON + select SND_SOC_AMD_ACPI_MACH help This option enables Acp7.0 PDM support on AMD platform. Say Y if you want to enable AUDIO on ACP7.0 diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 7c75892e678b..08220b9a3802 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -11,6 +11,7 @@ snd-acp-pdm-y := acp-pdm.o snd-acp-legacy-common-y := acp-legacy-common.o snd-acp-pci-y := acp-pci.o snd-amd-sdw-acpi-y := amd-sdw-acpi.o +snd-amd-acpi-mach-y := amd-acpi-mach.o #platform specific driver snd-acp-renoir-y := acp-renoir.o @@ -32,6 +33,7 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o obj-$(CONFIG_SND_SOC_AMD_ACP_LEGACY_COMMON) += snd-acp-legacy-common.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o +obj-$(CONFIG_SND_SOC_AMD_ACPI_MACH) += snd-amd-acpi-mach.o obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index 123524f90d6c..1892fbdfc780 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -137,26 +137,26 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->name = "acp_asoc_renoir"; chip->rsrc = &rn_rsrc; chip->acp_hw_ops_init = acp31_hw_ops_init; - chip->machines = snd_soc_acpi_amd_acp_machines; + chip->machines = &snd_soc_acpi_amd_acp_machines; break; case 0x6f: chip->name = "acp_asoc_rembrandt"; chip->rsrc = &rmb_rsrc; chip->acp_hw_ops_init = acp6x_hw_ops_init; - chip->machines = snd_soc_acpi_amd_rmb_acp_machines; + chip->machines = &snd_soc_acpi_amd_rmb_acp_machines; break; case 0x63: chip->name = "acp_asoc_acp63"; chip->rsrc = &acp63_rsrc; chip->acp_hw_ops_init = acp63_hw_ops_init; - chip->machines = snd_soc_acpi_amd_acp63_acp_machines; + chip->machines = &snd_soc_acpi_amd_acp63_acp_machines; break; case 0x70: case 0x71: chip->name = "acp_asoc_acp70"; chip->rsrc = &acp70_rsrc; chip->acp_hw_ops_init = acp70_hw_ops_init; - chip->machines = snd_soc_acpi_amd_acp70_acp_machines; + chip->machines = &snd_soc_acpi_amd_acp70_acp_machines; break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); diff --git a/sound/soc/amd/acp/amd-acpi-mach.c b/sound/soc/amd/acp/amd-acpi-mach.c new file mode 100644 index 000000000000..d95047d2ee94 --- /dev/null +++ b/sound/soc/amd/acp/amd-acpi-mach.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acpi-match.c - tables and support for ACP platforms + * ACPI enumeration. + * + * Copyright 2025 Advanced Micro Devices, Inc. + */ + +#include + +struct snd_soc_acpi_codecs amp_rt1019 = { + .num_codecs = 1, + .codecs = {"10EC1019"} +}; + +struct snd_soc_acpi_codecs amp_max = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { + { + .id = "10EC5682", + .drv_name = "acp3xalc56821019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682sm98360", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "RTL5682", + .drv_name = "acp3xalc5682s1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + { + .id = "AMDI1019", + .drv_name = "renoir-acp", + }, + { + .id = "ESSX8336", + .drv_name = "acp3x-es83xx", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { + { + .id = "10508825", + .drv_name = "rmb-nau8825-max", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + }, + { + .id = "AMDI0007", + .drv_name = "rembrandt-acp", + }, + { + .id = "RTL5682", + .drv_name = "rmb-rt5682s-rt1019", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_rmb_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { + { + .id = "AMDI0052", + .drv_name = "acp63-acp", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp63_acp_machines, "SND_SOC_ACP_COMMON"); + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { + { + .id = "AMDI0029", + .drv_name = "acp70-acp", + }, + {}, +}; +EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp70_acp_machines, "SND_SOC_ACP_COMMON"); + +MODULE_DESCRIPTION("AMD ACP tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Venkataprasad.potturu@amd.com"); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 796f8efd395c..928aa60ab386 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -277,81 +277,10 @@ struct acp_resource acp70_rsrc = { .sram_pte_offset = 0x03800000, }; -struct snd_soc_acpi_codecs amp_rt1019 = { - .num_codecs = 1, - .codecs = {"10EC1019"} -}; - -struct snd_soc_acpi_codecs amp_max = { - .num_codecs = 1, - .codecs = {"MX98360A"} -}; - -struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { - { - .id = "10EC5682", - .drv_name = "acp3xalc56821019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - { - .id = "RTL5682", - .drv_name = "acp3xalc5682sm98360", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_max, - }, - { - .id = "RTL5682", - .drv_name = "acp3xalc5682s1019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - { - .id = "AMDI1019", - .drv_name = "renoir-acp", - }, - { - .id = "ESSX8336", - .drv_name = "acp3x-es83xx", - }, - {}, -}; - -struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { - { - .id = "10508825", - .drv_name = "rmb-nau8825-max", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_max, - }, - { - .id = "AMDI0007", - .drv_name = "rembrandt-acp", - }, - { - .id = "RTL5682", - .drv_name = "rmb-rt5682s-rt1019", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &_rt1019, - }, - {}, -}; - -struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { - { - .id = "AMDI0052", - .drv_name = "acp63-acp", - }, - {}, -}; - -struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { - { - .id = "AMDI0029", - .drv_name = "acp70-acp", - }, - {}, -}; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines; extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; extern const struct snd_soc_dai_ops acp_dmic_dai_ops; From 09dc8031f4a84103f4ba8f704ec21f1926b04366 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Mon, 17 Mar 2025 12:54:08 +0530 Subject: [PATCH 1055/1090] ASoC: amd: acp: Fix acp_resource duplicate symbol error Fix acp_resource structure duplicate defination error by adding export symbol and extern keyword in header file. ld.lld: error: duplicate symbol: acp63_rsrc ld.lld: error: duplicate symbol: acp70_rsrc Fixes: f8b4f3f525e8 ("ASoC: amd: acp: Refactor acp70 platform resource structure") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202503160801.yExt0K2E-lkp@intel.com/ Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250317072413.88971-2-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 43 +++++++++++++++++++++++++++ sound/soc/amd/acp/amd.h | 42 +++----------------------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 255f90ca956a..5fad6c4a8d86 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -24,6 +24,49 @@ #define ACP63_PDM_ADDR 0x02 #define ACP70_PDM_ADDR 0x02 +struct acp_resource rn_rsrc = { + .offset = 20, + .no_of_ctrls = 1, + .irqp_used = 0, + .irq_reg_offset = 0x1800, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x02052800, +}; +EXPORT_SYMBOL_NS_GPL(rn_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource rmb_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; +EXPORT_SYMBOL_NS_GPL(rmb_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource acp63_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x12800, + .sram_pte_offset = 0x03802800, +}; +EXPORT_SYMBOL_NS_GPL(acp63_rsrc, "SND_SOC_ACP_COMMON"); + +struct acp_resource acp70_rsrc = { + .offset = 0, + .no_of_ctrls = 2, + .irqp_used = 1, + .soc_mclk = true, + .irq_reg_offset = 0x1a00, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, +}; +EXPORT_SYMBOL_NS_GPL(acp70_rsrc, "SND_SOC_ACP_COMMON"); + const struct snd_acp_hw_ops acp_common_hw_ops = { /* ACP hardware initilizations */ .acp_init = acp_init, diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 928aa60ab386..863e74fcee43 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -238,44 +238,10 @@ enum acp_config { ACP_CONFIG_20, }; -struct acp_resource rn_rsrc = { - .offset = 20, - .no_of_ctrls = 1, - .irqp_used = 0, - .irq_reg_offset = 0x1800, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x02052800, -}; - -struct acp_resource rmb_rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, -}; - -struct acp_resource acp63_rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, -}; - -struct acp_resource acp70_rsrc = { - .offset = 0, - .no_of_ctrls = 2, - .irqp_used = 1, - .soc_mclk = true, - .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x10000, - .sram_pte_offset = 0x03800000, -}; +extern struct acp_resource rn_rsrc; +extern struct acp_resource rmb_rsrc; +extern struct acp_resource acp63_rsrc; +extern struct acp_resource acp70_rsrc; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines; From 77ad261ecc4aa1b09bc98b32cdbfadb5e92197b7 Mon Sep 17 00:00:00 2001 From: Venkata Prasad Potturu Date: Mon, 17 Mar 2025 12:54:09 +0530 Subject: [PATCH 1056/1090] ASoC: amd: acp: Fix acp_common_hw_ops declaration error Fix acp_common_hw_ops declaration error by adding static and remove export symbol. sparse: symbol 'acp_common_hw_ops' was not declared. Should it be static? Fixes: 8ae746fe5104 ("ASoC: amd: acp: Implement acp_common_hw_ops support for acp platforms") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202503141442.iT0LHEMx-lkp@intel.com/ Signed-off-by: Venkata Prasad Potturu Link: https://patch.msgid.link/20250317072413.88971-3-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-legacy-common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 5fad6c4a8d86..b4d68484e06d 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -67,7 +67,7 @@ struct acp_resource acp70_rsrc = { }; EXPORT_SYMBOL_NS_GPL(acp70_rsrc, "SND_SOC_ACP_COMMON"); -const struct snd_acp_hw_ops acp_common_hw_ops = { +static const struct snd_acp_hw_ops acp_common_hw_ops = { /* ACP hardware initilizations */ .acp_init = acp_init, .acp_deinit = acp_deinit, @@ -77,7 +77,6 @@ const struct snd_acp_hw_ops acp_common_hw_ops = { .en_interrupts = acp_enable_interrupts, .dis_interrupts = acp_disable_interrupts, }; -EXPORT_SYMBOL_NS_GPL(acp_common_hw_ops, "SND_SOC_ACP_COMMON"); irqreturn_t acp_irq_handler(int irq, void *data) { From 6d9d66626c58bcd9b949574aca7d47149b8ad9e1 Mon Sep 17 00:00:00 2001 From: Ethan Carter Edwards Date: Mon, 17 Mar 2025 08:21:56 -0400 Subject: [PATCH 1057/1090] ASoC: Intel: avs: Replace devm_kzalloc() with devm_kcalloc() Open coded arithmetic in allocator arguments is discouraged [1]. Helper functions like kcalloc or, in this case, devm_kcalloc are preferred. [1]: https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Ethan Carter Edwards Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20250317-sound-avs-kcalloc-v2-1-20e2a132b18f@ethancedwards.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 4bfbcb5a5ae8..dac463390da1 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1380,7 +1380,7 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l for_each_set_bit(i, &port_mask, ssp_count) cpu_count += hweight_long(tdms[i]); - cpus = devm_kzalloc(adev->dev, sizeof(*cpus) * cpu_count, GFP_KERNEL); + cpus = devm_kcalloc(adev->dev, cpu_count, sizeof(*cpus), GFP_KERNEL); if (!cpus) return -ENOMEM; From 61b1a1bddf7d166946d7ca7054b6cbced29b72f5 Mon Sep 17 00:00:00 2001 From: Ethan Carter Edwards Date: Mon, 17 Mar 2025 08:21:57 -0400 Subject: [PATCH 1058/1090] ASoC: Intel: avs: ssm4567: Replace devm_kzalloc() with devm_kcalloc() Open coded arithmetic in allocator arguments is discouraged [1]. Helper functions like kcalloc or, in this case, devm_kcalloc are preferred. [1]: https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Ethan Carter Edwards Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20250317-sound-avs-kcalloc-v2-2-20e2a132b18f@ethancedwards.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/ssm4567.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index c9d89bfe7178..7667790d5273 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -97,7 +97,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); - dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + dl->codecs = devm_kcalloc(dev, 2, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; From bde479694a7da7c127bb5bba98e2e4773f1d7951 Mon Sep 17 00:00:00 2001 From: Ethan Carter Edwards Date: Mon, 17 Mar 2025 08:21:58 -0400 Subject: [PATCH 1059/1090] ASoC: Intel: avs: max98373: Replace devm_kzalloc() with devm_kcalloc() Open coded arithmetic in allocator arguments is discouraged [1]. Helper functions like kcalloc or, in this case, devm_kcalloc are preferred. [1]: https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Ethan Carter Edwards Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20250317-sound-avs-kcalloc-v2-3-20e2a132b18f@ethancedwards.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/max98373.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index 6f25e66344b7..970f82bf4ce8 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -111,7 +111,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); - dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + dl->codecs = devm_kcalloc(dev, 2, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; From 3602571baf9a6864bde89422d179e422a3ea4d8d Mon Sep 17 00:00:00 2001 From: Ethan Carter Edwards Date: Mon, 17 Mar 2025 08:21:59 -0400 Subject: [PATCH 1060/1090] ASoC: Intel: avs: max98927: Replace devm_kzalloc() with devm_kcalloc() Open coded arithmetic in allocator arguments is discouraged [1]. Helper functions like kcalloc or, in this case, devm_kcalloc are preferred. [1]: https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Ethan Carter Edwards Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20250317-sound-avs-kcalloc-v2-4-20e2a132b18f@ethancedwards.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/max98927.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index e8e5d1c717cd..e4ce553bf1d6 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -108,7 +108,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in dl->name = devm_kasprintf(dev, GFP_KERNEL, AVS_STRING_FMT("SSP", "-Codec", ssp_port, tdm_slot)); dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); - dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + dl->codecs = devm_kcalloc(dev, 2, sizeof(*dl->codecs), GFP_KERNEL); if (!dl->name || !dl->cpus || !dl->codecs) return -ENOMEM; From 811944a790451169876947a89338d2b86ff9fe5b Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 11 Mar 2025 12:32:53 -0400 Subject: [PATCH 1061/1090] ASoC: dt-bindings: support imx95's CM7 core Add binding for imx95's CM7 core, used for audio processing. Additionally, introduce a common binding for NXP audio processors with Sound Open Firmware (SOF) support. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Krzysztof Kozlowski Reviewed-by: Iuliana Prodan Link: https://patch.msgid.link/20250311163255.2664-2-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/fsl,imx95-cm7-sof.yaml | 64 +++++++++++++++++++ .../bindings/sound/fsl,sof-cpu.yaml | 27 ++++++++ 2 files changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml create mode 100644 Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml b/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml new file mode 100644 index 000000000000..f00ae3219e15 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,imx95-cm7-sof.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,imx95-cm7-sof.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP imx95 CM7 core + +maintainers: + - Daniel Baluta + +description: NXP imx95 CM7 core used for audio processing + +properties: + compatible: + const: fsl,imx95-cm7-sof + + reg: + maxItems: 1 + + reg-names: + const: sram + + memory-region: + maxItems: 1 + + memory-region-names: + const: dma + + port: + description: SAI3 port + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - reg-names + - memory-region + - memory-region-names + - port + +allOf: + - $ref: fsl,sof-cpu.yaml# + +unevaluatedProperties: false + +examples: + - | + cm7-cpu@80000000 { + compatible = "fsl,imx95-cm7-sof"; + reg = <0x80000000 0x6100000>; + reg-names = "sram"; + mboxes = <&mu7 2 0>, <&mu7 2 1>, <&mu7 3 0>, <&mu7 3 1>; + mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1"; + memory-region = <&adma_res>; + memory-region-names = "dma"; + port { + /* SAI3-WM8962 link */ + endpoint { + remote-endpoint = <&wm8962_ep>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml b/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml new file mode 100644 index 000000000000..31863932dbc3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,sof-cpu.yaml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,sof-cpu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP audio processor common properties + +maintainers: + - Daniel Baluta + +properties: + mboxes: + maxItems: 4 + + mbox-names: + items: + - const: txdb0 + - const: txdb1 + - const: rxdb0 + - const: rxdb1 + +required: + - mboxes + - mbox-names + +additionalProperties: true From ed92f40eccc801bd0e5dfd78b1058072638471f1 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 11 Mar 2025 12:32:54 -0400 Subject: [PATCH 1062/1090] ASoC: dt-bindings: audio-graph-card2: add widgets and hp-det-gpios support Introduce the 'widgets' property, allowing the creation of widgets from 4 template widgets: Microphone, Line, Headphone, and Speaker. Also introduce the 'hp-det-gpios' property, which allows using headphone detection using the specified GPIO. Signed-off-by: Laurentiu Mihalcea Acked-by: Krzysztof Kozlowski Reviewed-by: Iuliana Prodan Reviewed-by: Daniel Baluta Link: https://patch.msgid.link/20250311163255.2664-3-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/audio-graph-card2.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml b/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml index f943f90d8b15..94588353f852 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-card2.yaml @@ -37,6 +37,10 @@ properties: codec2codec: type: object description: Codec to Codec node + hp-det-gpios: + $ref: audio-graph.yaml#/properties/hp-det-gpios + widgets: + $ref: audio-graph.yaml#/properties/widgets required: - compatible From 18abb3797f1ceca97a705aa1c14cbec5c6fcab79 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 17 Mar 2025 10:13:18 +0000 Subject: [PATCH 1063/1090] ASoC: soc-utils: Transition to the faux device interface The ASoC soc-utils driver does not require the creation of a platform device. Originally, this approach was chosen for simplicity when the driver was first implemented. With the introduction of the lightweight faux device interface, we now have a more appropriate alternative. Migrate the driver to utilize the faux bus, given that the platform device it previously created was not a real one anyway. This will simplify the code, reducing its footprint while maintaining functionality. Cc: Mark Brown Cc: Takashi Iwai Cc: linux-sound@vger.kernel.org Signed-off-by: Sudeep Holla Link: https://patch.msgid.link/20250317-plat2faux_dev-v1-6-5fe67c085ad5@arm.com Signed-off-by: Mark Brown --- sound/soc/soc-utils.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 318b141c00b3..5e3e4f14c392 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -7,7 +7,7 @@ // Author: Mark Brown // Liam Girdwood -#include +#include #include #include #include @@ -262,48 +262,38 @@ struct snd_soc_dai_link_component snd_soc_dummy_dlc = { }; EXPORT_SYMBOL_GPL(snd_soc_dummy_dlc); -static int snd_soc_dummy_probe(struct platform_device *pdev) +static int snd_soc_dummy_probe(struct faux_device *fdev) { int ret; - ret = devm_snd_soc_register_component(&pdev->dev, + ret = devm_snd_soc_register_component(&fdev->dev, &dummy_codec, &dummy_dai, 1); if (ret < 0) return ret; - ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform, + ret = devm_snd_soc_register_component(&fdev->dev, &dummy_platform, NULL, 0); return ret; } -static struct platform_driver soc_dummy_driver = { - .driver = { - .name = "snd-soc-dummy", - }, +static struct faux_device_ops soc_dummy_ops = { .probe = snd_soc_dummy_probe, }; -static struct platform_device *soc_dummy_dev; +static struct faux_device *soc_dummy_dev; int __init snd_soc_util_init(void) { - int ret; + soc_dummy_dev = faux_device_create("snd-soc-dummy", NULL, + &soc_dummy_ops); + if (!soc_dummy_dev) + return -ENODEV; - soc_dummy_dev = - platform_device_register_simple("snd-soc-dummy", -1, NULL, 0); - if (IS_ERR(soc_dummy_dev)) - return PTR_ERR(soc_dummy_dev); - - ret = platform_driver_register(&soc_dummy_driver); - if (ret != 0) - platform_device_unregister(soc_dummy_dev); - - return ret; + return 0; } void snd_soc_util_exit(void) { - platform_driver_unregister(&soc_dummy_driver); - platform_device_unregister(soc_dummy_dev); + faux_device_destroy(soc_dummy_dev); } From 340abded86def0ab8ad8ef9ba73d8ac2fb6fe991 Mon Sep 17 00:00:00 2001 From: Jayesh Choudhary Date: Tue, 18 Mar 2025 16:17:15 +0530 Subject: [PATCH 1064/1090] ASoC: ti: j721e-evm: Reduce log level for EPROBE_DEFER Drop the log level for deferral probe to avoid flooding in kernel logs. Signed-off-by: Jayesh Choudhary Link: https://patch.msgid.link/20250318104715.43267-1-j-choudhary@ti.com Signed-off-by: Mark Brown --- sound/soc/ti/j721e-evm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c index c0fa72e626ff..2057d46ad884 100644 --- a/sound/soc/ti/j721e-evm.c +++ b/sound/soc/ti/j721e-evm.c @@ -913,8 +913,9 @@ static int j721e_soc_probe(struct platform_device *pdev) mutex_init(&priv->mutex); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) - dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", - ret); + dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card() failed: %d\n", + ret); return ret; } From 1822c4484efeb8056de53bf4edfca377d2939418 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 18 Mar 2025 16:10:43 +0800 Subject: [PATCH 1065/1090] ASoC: codecs: ntp8918: Remove duplicate clk.h header Remove duplicate header which is included twice. Signed-off-by: Chen Ni Link: https://patch.msgid.link/20250318081043.2870229-1-nichen@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/ntp8918.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/ntp8918.c b/sound/soc/codecs/ntp8918.c index a332893fc51d..5593d48ef696 100644 --- a/sound/soc/codecs/ntp8918.c +++ b/sound/soc/codecs/ntp8918.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include From 7a24b876ad8cdd56457e881d384a038922b508c3 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:45 +0000 Subject: [PATCH 1066/1090] ASoC: ops-test: Add some basic kunit tests for soc-ops Add some basic kunit tests for some of the ASoC control put and get helpers. This will assist in doing some refactoring. Note that presently some tests fail, but the rest of the series will fix these up. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/Kconfig | 7 + sound/soc/Makefile | 4 + sound/soc/soc-ops-test.c | 541 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 552 insertions(+) create mode 100644 sound/soc/soc-ops-test.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 5efba76abb31..8b7d51266f81 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -81,6 +81,13 @@ config SND_SOC_UTILS_KUNIT_TEST help If you want to perform tests on ALSA SoC utils library say Y here. +config SND_SOC_OPS_KUNIT_TEST + tristate "KUnit tests for SoC ops" + depends on KUNIT + default KUNIT_ALL_TESTS + help + If you want to perform tests on ALSA SoC ops library say Y here. + config SND_SOC_ACPI tristate diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 08baaa11d813..358e227c5ab6 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -21,6 +21,10 @@ ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),) obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o endif +ifneq ($(CONFIG_SND_SOC_OPS_KUNIT_TEST),) +obj-$(CONFIG_SND_SOC_OPS_KUNIT_TEST) += soc-ops-test.o +endif + ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) snd-soc-core-y += soc-generic-dmaengine-pcm.o endif diff --git a/sound/soc/soc-ops-test.c b/sound/soc/soc-ops-test.c new file mode 100644 index 000000000000..dc1e482bba6a --- /dev/null +++ b/sound/soc/soc-ops-test.c @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2025 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum soc_ops_test_control_layout { + SOC_OPS_TEST_SINGLE, + SOC_OPS_TEST_DOUBLE, + SOC_OPS_TEST_DOUBLE_R, +}; + +#define TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert) \ + .mc = { \ + .min = xmin, .max = xmax, .platform_max = xpmax, \ + .reg = 0, .shift = 0, .sign_bit = xsign, .invert = xinvert, \ + .rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? 1 : 0, \ + .rshift = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? 16 : 0, \ + } + +#define TEST_UINFO(clayout, ctype, cmin, cmax) \ + .uinfo = { \ + .type = SNDRV_CTL_ELEM_TYPE_##ctype, \ + .count = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_SINGLE ? 1 : 2, \ + .value.integer.min = cmin, \ + .value.integer.max = cmax, \ + } + +#define ITEST(cname, clayout, ctype, cfunc, cmin, cmax, \ + xmin, xmax, xpmax, xsign, xinvert) \ + { \ + .name = cname, \ + .func_name = #cfunc, \ + .layout = SOC_OPS_TEST_##clayout, \ + .info = snd_soc_info_##cfunc, \ + TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \ + TEST_UINFO(clayout, ctype, cmin, cmax), \ + } + +#define ATEST(clayout, cfunc, cctl, cret, cinit, \ + xmask, xreg, xmin, xmax, xpmax, xsign, xinvert) \ + { \ + .func_name = #cfunc, \ + .layout = SOC_OPS_TEST_##clayout, \ + .put = snd_soc_put_##cfunc, \ + .get = snd_soc_get_##cfunc, \ + TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \ + .lctl = cctl, .rctl = cctl, \ + .lmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \ + (xmask) | (xmask) << 16 : (xmask), \ + .rmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xmask) : 0, \ + .init = cinit ? 0xFFFFFFFF : 0x00000000, \ + .lreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \ + (xreg) | (xreg) << 16 : (xreg), \ + .rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xreg) : 0, \ + .ret = cret, \ + } + +struct soc_ops_test_priv { + struct kunit *test; + + struct snd_soc_component component; +}; + +struct info_test_param { + const char * const name; + const char * const func_name; + enum soc_ops_test_control_layout layout; + struct soc_mixer_control mc; + int (*info)(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info); + + struct snd_ctl_elem_info uinfo; +}; + +struct access_test_param { + const char * const func_name; + enum soc_ops_test_control_layout layout; + struct soc_mixer_control mc; + int (*put)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value); + int (*get)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value); + + unsigned int init; + unsigned int lmask; + unsigned int rmask; + unsigned int lreg; + unsigned int rreg; + long lctl; + long rctl; + int ret; +}; + +static const struct info_test_param all_info_test_params[] = { + // Handling of volume control name for types + ITEST("Test Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Control", DOUBLE_R, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume", DOUBLE_R, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume Control", DOUBLE_R, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume", DOUBLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Volume Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0), + ITEST("Test Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Volume", DOUBLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Volume Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1), + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0), + ITEST("Test Volume Control", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0), + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0), + ITEST("Test Volume Control", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0), + // Negative minimums + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 20, -10, 10, 0, 4, 0), + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 15, -10, 10, 15, 4, 0), + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 20, -10, 10, 0, 4, 1), + ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 15, -10, 10, 15, 4, 1), + // SX control volume control naming + ITEST("Test Control", SINGLE, BOOLEAN, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0), + ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0), + ITEST("Test Control", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0), + ITEST("Test Volume Control", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0), + ITEST("Test Control", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0), + ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0), + ITEST("Test Volume Control", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0), +}; + +static const struct access_test_param all_access_test_params[] = { + // Single positive value controls + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0), + ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0), + ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0), + // Inverted single positive value controls + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 1), + ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 1), + ATEST(SINGLE, volsw, 20, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 1), + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 1), + ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 1), + ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x05, 0, 20, 15, 0, 1), + ATEST(SINGLE, volsw, 10, 1, true, 0x1F, 0x0A, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 0, 1, true, 0x1F, 0x00, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 20, 1, true, 0x1F, 0x14, 0, 20, 0, 0, 0), + ATEST(SINGLE, volsw, 10, 1, true, 0x1F, 0x0A, 0, 20, 15, 0, 0), + ATEST(SINGLE, volsw, 25, -22, true, 0x1F, 0x00, 0, 20, 15, 0, 0), + ATEST(SINGLE, volsw, 15, 1, true, 0x1F, 0x0F, 0, 20, 15, 0, 0), + // Single negative value controls + ATEST(SINGLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0), + ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0), + ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0), + ATEST(SINGLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0), + // Single non-zero minimum positive value controls + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0), + ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0), + ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0), + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0), + ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0), + ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0), + // Inverted single non-zero minimum positive value controls + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 1), + ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 1), + ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 1), + ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 1), + ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 1), + ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x0F, 10, 30, 15, 0, 1), + // Double register positive value controls + ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0), + ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0), + ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0), + // Double register negative value controls + ATEST(DOUBLE_R, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0), + ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 0, 1, true, 0x1F, 0x16, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 20, 1, true, 0x1F, 0x0A, -10, 10, 0, 4, 0), + ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE_R, volsw, 25, -22, true, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE_R, volsw, 15, 1, true, 0x1F, 0x05, -10, 10, 15, 4, 0), + // Inverted double register negative value controls + ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 0, 4, 1), + ATEST(DOUBLE_R, volsw, 0, 1, true, 0x1F, 0x0A, -10, 10, 0, 4, 1), + ATEST(DOUBLE_R, volsw, 20, 1, true, 0x1F, 0x16, -10, 10, 0, 4, 1), + ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 15, 4, 1), + ATEST(DOUBLE_R, volsw, 25, -22, true, 0x1F, 0x00, -10, 10, 15, 4, 1), + ATEST(DOUBLE_R, volsw, 15, 1, true, 0x1F, 0x1B, -10, 10, 15, 4, 1), + // Double register non-zero minimum positive value controls + ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0), + ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0), + ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0), + ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0), + // Double shift positive value controls + ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0), + ATEST(DOUBLE, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0), + ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0), + ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0), + ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0), + ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0), + // Double shift negative value controls + ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0), + ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0), + ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0), + ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0), + ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0), + // Inverted double shift negative value controls + ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 1), + ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 1), + ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 1), + ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 1), + ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 1), + ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x1B, -10, 10, 15, 4, 1), + // Double shift non-zero minimum positive value controls + ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0), + ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0), + ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0), + ATEST(DOUBLE, volsw, 10, 1, true, 0x1F, 0x14, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 0, 1, true, 0x1F, 0x0A, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 20, 1, true, 0x1F, 0x1E, 10, 30, 0, 0, 0), + ATEST(DOUBLE, volsw, 10, 1, true, 0x1F, 0x14, 10, 30, 15, 0, 0), + ATEST(DOUBLE, volsw, 25, -22, true, 0x1F, 0x00, 10, 30, 15, 0, 0), + ATEST(DOUBLE, volsw, 15, 1, true, 0x1F, 0x19, 10, 30, 15, 0, 0), + // Single SX all values + ATEST(SINGLE, volsw_sx, 0, 1, false, 0xF, 0x0F, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 1, 0, false, 0xF, 0x00, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 2, 1, false, 0xF, 0x01, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 3, 1, false, 0xF, 0x02, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 4, 1, false, 0xF, 0x03, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 5, -22, false, 0xF, 0x00, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 0, 0, true, 0xF, 0x0F, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 1, 1, true, 0xF, 0x00, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 2, 1, true, 0xF, 0x01, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 3, 1, true, 0xF, 0x02, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 4, 1, true, 0xF, 0x03, 0x0F, 4, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 5, -22, true, 0xF, 0x00, 0x0F, 4, 0, 0, 0), + // Inverted single SX all values + ATEST(SINGLE, volsw_sx, 0, 1, false, 0x1F, 0x03, 0x0F, 4, 0, 0, 1), + ATEST(SINGLE, volsw_sx, 1, 1, false, 0x1F, 0x02, 0x0F, 4, 0, 0, 1), + ATEST(SINGLE, volsw_sx, 2, 1, false, 0x1F, 0x01, 0x0F, 4, 0, 0, 1), + ATEST(SINGLE, volsw_sx, 3, 0, false, 0x1F, 0x00, 0x0F, 4, 0, 0, 1), + ATEST(SINGLE, volsw_sx, 4, 1, false, 0x1F, 0x0F, 0x0F, 4, 0, 0, 1), + ATEST(SINGLE, volsw_sx, 5, -22, false, 0x1F, 0x00, 0x0F, 4, 0, 0, 1), + // Single SX select values + ATEST(SINGLE, volsw_sx, 0, 1, false, 0xFF, 0x88, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 1, 1, false, 0xFF, 0x89, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 119, 1, false, 0xFF, 0xFF, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 120, 0, false, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 121, 1, false, 0xFF, 0x01, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 143, 1, false, 0xFF, 0x17, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 144, 1, false, 0xFF, 0x18, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 145, -22, false, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0), + ATEST(SINGLE, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + // Double shift SX select values + ATEST(DOUBLE, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + // Double register SX select values + ATEST(DOUBLE_R, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0), + ATEST(DOUBLE_R, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0), +}; + +static const char *control_type_str(const snd_ctl_elem_type_t type) +{ + switch (type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + return "bool"; + case SNDRV_CTL_ELEM_TYPE_INTEGER: + return "int"; + default: + return "unknown"; + } +} + +static const char *control_layout_str(const enum soc_ops_test_control_layout layout) +{ + switch (layout) { + case SOC_OPS_TEST_SINGLE: + return "single"; + case SOC_OPS_TEST_DOUBLE: + return "double"; + case SOC_OPS_TEST_DOUBLE_R: + return "double_r"; + default: + return "unknown"; + } +}; + +static int mock_regmap_read(void *context, const void *reg_buf, + const size_t reg_size, void *val_buf, + size_t val_size) +{ + struct soc_ops_test_priv *priv = context; + + KUNIT_FAIL(priv->test, "Unexpected bus read"); + + return -EIO; +} + +static int mock_regmap_gather_write(void *context, + const void *reg_buf, size_t reg_size, + const void *val_buf, size_t val_size) +{ + struct soc_ops_test_priv *priv = context; + + KUNIT_FAIL(priv->test, "Unexpected bus gather_write"); + + return -EIO; +} + +static int mock_regmap_write(void *context, const void *val_buf, + size_t val_size) +{ + struct soc_ops_test_priv *priv = context; + + KUNIT_FAIL(priv->test, "Unexpected bus write"); + + return -EIO; +} + +static const struct regmap_bus mock_regmap_bus = { + .read = mock_regmap_read, + .write = mock_regmap_write, + .gather_write = mock_regmap_gather_write, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +static const struct regmap_config mock_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_format_endian = REGMAP_ENDIAN_NATIVE, + .val_format_endian = REGMAP_ENDIAN_NATIVE, + .max_register = 0x1, + .cache_type = REGCACHE_FLAT, +}; + +static int soc_ops_test_init(struct kunit *test) +{ + struct soc_ops_test_priv *priv; + struct regmap *regmap; + struct device *dev; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->test = test; + + dev = kunit_device_register(test, "soc_ops_test_drv"); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + regmap = devm_regmap_init(dev, &mock_regmap_bus, priv, &mock_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* No actual hardware, we just use the cache */ + regcache_cache_only(regmap, true); + + priv->component.dev = dev; + priv->component.regmap = regmap; + mutex_init(&priv->component.io_mutex); + + test->priv = priv; + + return 0; +} + +static void soc_ops_test_exit(struct kunit *test) +{ + struct soc_ops_test_priv *priv = test->priv; + + kunit_device_unregister(test, priv->component.dev); +} + +static void info_test_desc(const struct info_test_param *param, char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "%s %s %s: ctl range: %ld->%ld, reg range: %d->%d(%d), sign: %d, inv: %d", + control_layout_str(param->layout), param->func_name, + control_type_str(param->uinfo.type), + param->uinfo.value.integer.min, param->uinfo.value.integer.max, + param->mc.min, param->mc.max, param->mc.platform_max, + param->mc.sign_bit, param->mc.invert); +} + +static void soc_ops_test_info(struct kunit *test) +{ + struct soc_ops_test_priv *priv = test->priv; + const struct info_test_param *param = test->param_value; + const struct snd_ctl_elem_info *target = ¶m->uinfo; + struct snd_ctl_elem_info result; + struct snd_kcontrol kctl = { + .private_data = &priv->component, + .private_value = (unsigned long)¶m->mc, + }; + int ret; + + strscpy(kctl.id.name, param->name, sizeof(kctl.id.name)); + + ret = param->info(&kctl, &result); + KUNIT_ASSERT_FALSE(test, ret); + + KUNIT_EXPECT_EQ(test, result.count, target->count); + KUNIT_EXPECT_EQ(test, result.type, target->type); + KUNIT_EXPECT_EQ(test, result.value.integer.min, target->value.integer.min); + KUNIT_EXPECT_EQ(test, result.value.integer.max, target->value.integer.max); +} + +static void access_test_desc(const struct access_test_param *param, char *desc) +{ + if (param->ret < 0) { + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> err: %d", + control_layout_str(param->layout), param->func_name, + param->lctl, param->rctl, + param->mc.min, param->mc.max, param->mc.platform_max, + param->mc.sign_bit, param->mc.invert, + param->ret); + } else { + snprintf(desc, KUNIT_PARAM_DESC_SIZE, + "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> %#x,%#x", + control_layout_str(param->layout), param->func_name, + param->lctl, param->rctl, + param->mc.min, param->mc.max, param->mc.platform_max, + param->mc.sign_bit, param->mc.invert, + param->lreg, param->rreg); + } +} + +static void soc_ops_test_access(struct kunit *test) +{ + struct soc_ops_test_priv *priv = test->priv; + const struct access_test_param *param = test->param_value; + struct snd_kcontrol kctl = { + .private_data = &priv->component, + .private_value = (unsigned long)¶m->mc, + }; + struct snd_ctl_elem_value result; + unsigned int val; + int ret; + + ret = regmap_write(priv->component.regmap, 0x0, param->init); + KUNIT_ASSERT_FALSE(test, ret); + ret = regmap_write(priv->component.regmap, 0x1, param->init); + KUNIT_ASSERT_FALSE(test, ret); + + result.value.integer.value[0] = param->lctl; + result.value.integer.value[1] = param->rctl; + + ret = param->put(&kctl, &result); + KUNIT_ASSERT_EQ(test, ret, param->ret); + if (ret < 0) + return; + + ret = regmap_read(priv->component.regmap, 0x0, &val); + KUNIT_ASSERT_FALSE(test, ret); + KUNIT_EXPECT_EQ(test, val, (param->init & ~param->lmask) | param->lreg); + + ret = regmap_read(priv->component.regmap, 0x1, &val); + KUNIT_ASSERT_FALSE(test, ret); + KUNIT_EXPECT_EQ(test, val, (param->init & ~param->rmask) | param->rreg); + + result.value.integer.value[0] = 0; + result.value.integer.value[1] = 0; + + ret = param->get(&kctl, &result); + KUNIT_ASSERT_GE(test, ret, 0); + + KUNIT_EXPECT_EQ(test, result.value.integer.value[0], param->lctl); + if (param->layout != SOC_OPS_TEST_SINGLE) + KUNIT_EXPECT_EQ(test, result.value.integer.value[1], param->rctl); + else + KUNIT_EXPECT_EQ(test, result.value.integer.value[1], 0); +} + +KUNIT_ARRAY_PARAM(all_info_tests, all_info_test_params, info_test_desc); +KUNIT_ARRAY_PARAM(all_access_tests, all_access_test_params, access_test_desc); + +static struct kunit_case soc_ops_test_cases[] = { + KUNIT_CASE_PARAM(soc_ops_test_info, all_info_tests_gen_params), + KUNIT_CASE_PARAM(soc_ops_test_access, all_access_tests_gen_params), + {} +}; + +static struct kunit_suite soc_ops_test_suite = { + .name = "soc-ops", + .init = soc_ops_test_init, + .exit = soc_ops_test_exit, + .test_cases = soc_ops_test_cases, +}; + +kunit_test_suites(&soc_ops_test_suite); + +MODULE_DESCRIPTION("ASoC soc-ops kunit test"); +MODULE_LICENSE("GPL"); From 534bfb330b2612199b2afaafc769ccb42bebb204 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:46 +0000 Subject: [PATCH 1067/1090] ASoC: ops: Minor formatting fixups No functional changes just tidying up some tabbing etc. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 106 ++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index cd5f927bcd4e..9039bf3b6fb4 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -37,7 +37,7 @@ * Returns 0 for success. */ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -56,7 +56,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); * Returns 0 for success. */ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); * Returns 0 for success. */ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -124,8 +124,9 @@ EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); * the given registervalue into a signed integer if sign_bit is non-zero. */ static void snd_soc_read_signed(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, unsigned int shift, - unsigned int sign_bit, int *signed_val) + unsigned int reg, unsigned int mask, + unsigned int shift, unsigned int sign_bit, + int *signed_val) { int ret; unsigned int val; @@ -168,7 +169,7 @@ static void snd_soc_read_signed(struct snd_soc_component *component, * Returns 0 for success. */ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; @@ -247,7 +248,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); * Returns 0 for success. */ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = @@ -300,7 +301,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); * Returns 0 for success. */ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = @@ -362,9 +363,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, err = snd_soc_component_update_bits(component, reg2, val_mask, val2); /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) { + if (ret == 0 || err < 0) ret = err; - } } return ret; @@ -382,11 +382,11 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); * Returns 0 for success. */ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; + (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; @@ -423,18 +423,17 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - + (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; + unsigned int val, val_mask; int max = mc->max; int min = mc->min; unsigned int mask = (1U << (fls(min + max) - 1)) - 1; int err = 0; int ret; - unsigned int val, val_mask; if (ucontrol->value.integer.value[0] < 0) return -EINVAL; @@ -465,13 +464,13 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, val2 = val2 << rshift; err = snd_soc_component_update_bits(component, reg2, val_mask, - val2); + val2); /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) { + if (ret == 0 || err < 0) ret = err; - } } + return ret; } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); @@ -487,7 +486,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); * returns 0 for success. */ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; @@ -516,7 +515,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); * Returns 0 for success. */ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; @@ -568,11 +567,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, val = val << shift; err = snd_soc_component_update_bits(component, rreg, val_mask, - val); + val); /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) { + if (ret == 0 || err < 0) ret = err; - } } return ret; @@ -589,7 +587,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); * Returns 0 for success. */ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = @@ -663,8 +661,7 @@ static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) * * Return 0 for success, else error. */ -int snd_soc_limit_volume(struct snd_soc_card *card, - const char *name, int max) +int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max) { struct snd_kcontrol *kctl; int ret = -EINVAL; @@ -675,12 +672,15 @@ int snd_soc_limit_volume(struct snd_soc_card *card, kctl = snd_soc_card_get_kcontrol(card, name); if (kctl) { - struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kctl->private_value; + if (max <= mc->max - mc->min) { mc->platform_max = max; ret = snd_soc_clip_to_platform_max(kctl); } } + return ret; } EXPORT_SYMBOL_GPL(snd_soc_limit_volume); @@ -740,8 +740,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_bytes *params = (void *)kcontrol->private_value; - int ret, len; unsigned int val, mask; + int ret, len; if (!component->regmap || !params->num_regs) return -EINVAL; @@ -772,15 +772,13 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, break; case 2: mask = ~params->mask; - ret = regmap_parse_val(component->regmap, - &mask, &mask); + ret = regmap_parse_val(component->regmap, &mask, &mask); if (ret != 0) return ret; ((u16 *)data)[0] &= mask; - ret = regmap_parse_val(component->regmap, - &val, &val); + ret = regmap_parse_val(component->regmap, &val, &val); if (ret != 0) return ret; @@ -788,15 +786,13 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, break; case 4: mask = ~params->mask; - ret = regmap_parse_val(component->regmap, - &mask, &mask); + ret = regmap_parse_val(component->regmap, &mask, &mask); if (ret != 0) return ret; ((u32 *)data)[0] &= mask; - ret = regmap_parse_val(component->regmap, - &val, &val); + ret = regmap_parse_val(component->regmap, &val, &val); if (ret != 0) return ret; @@ -812,7 +808,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_bytes_put); int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *ucontrol) + struct snd_ctl_elem_info *ucontrol) { struct soc_bytes_ext *params = (void *)kcontrol->private_value; @@ -824,7 +820,7 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) + unsigned int size, unsigned int __user *tlv) { struct soc_bytes_ext *params = (void *)kcontrol->private_value; unsigned int count = size < params->max ? size : params->max; @@ -840,6 +836,7 @@ int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, ret = params->put(kcontrol, tlv, count); break; } + return ret; } EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); @@ -856,10 +853,11 @@ EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); * Returns 0 for success. */ int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { struct soc_mreg_control *mc = (struct soc_mreg_control *)kcontrol->private_value; + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = mc->min; @@ -883,7 +881,7 @@ EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); * Returns 0 for success. */ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mreg_control *mc = @@ -891,17 +889,18 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1UL<invert; - unsigned long mask = (1UL<nbits)-1; + unsigned long mask = (1UL << mc->nbits) - 1; long min = mc->min; long max = mc->max; long val = 0; unsigned int i; for (i = 0; i < regcount; i++) { - unsigned int regval = snd_soc_component_read(component, regbase+i); - val |= (regval & regwmask) << (regwshift*(regcount-i-1)); + unsigned int regval = snd_soc_component_read(component, regbase + i); + + val |= (regval & regwmask) << (regwshift * (regcount - i - 1)); } val &= mask; if (min < 0 && val > max) @@ -928,7 +927,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); * Returns 0 for success. */ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mreg_control *mc = @@ -936,9 +935,9 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1UL<invert; - unsigned long mask = (1UL<nbits)-1; + unsigned long mask = (1UL << mc->nbits) - 1; long max = mc->max; long val = ucontrol->value.integer.value[0]; int ret = 0; @@ -950,10 +949,13 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, val = max - val; val &= mask; for (i = 0; i < regcount; i++) { - unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask; - unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; - int err = snd_soc_component_update_bits(component, regbase+i, + unsigned int regval = (val >> (regwshift * (regcount - i - 1))) & + regwmask; + unsigned int regmask = (mask >> (regwshift * (regcount - i - 1))) & + regwmask; + int err = snd_soc_component_update_bits(component, regbase + i, regmask, regval); + if (err < 0) return err; if (err > 0) @@ -974,7 +976,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); * Returns 0 for success. */ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = @@ -1007,7 +1009,7 @@ EXPORT_SYMBOL_GPL(snd_soc_get_strobe); * Returns 1 for success. */ int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = From 7f978180673b4f3b68fcc66fc1f1d74a1fc5a93a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:47 +0000 Subject: [PATCH 1068/1090] ASoC: ops: Update comments for xr_sx control helpers Update the comments for the xr_sx control helper functions to better clarify the difference between these and the normal sx helpers. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 9039bf3b6fb4..dac55138210d 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -846,9 +846,10 @@ EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); * @kcontrol: mreg control * @uinfo: control element information * - * Callback to provide information of a control that can - * span multiple codec registers which together - * forms a single signed value in a MSB/LSB manner. + * Callback to provide information of a control that can span multiple + * codec registers which together forms a single signed value. Note + * that unlike the non-xr variant of sx controls these may or may not + * include the sign bit, depending on nbits, and there is no shift. * * Returns 0 for success. */ @@ -872,11 +873,12 @@ EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); * @kcontrol: mreg control * @ucontrol: control element information * - * Callback to get the value of a control that can span - * multiple codec registers which together forms a single - * signed value in a MSB/LSB manner. The control supports - * specifying total no of bits used to allow for bitfields - * across the multiple codec registers. + * Callback to get the value of a control that can span multiple codec + * registers which together forms a single signed value. The control + * supports specifying total no of bits used to allow for bitfields + * across the multiple codec registers. Note that unlike the non-xr + * variant of sx controls these may or may not include the sign bit, + * depending on nbits, and there is no shift. * * Returns 0 for success. */ @@ -918,11 +920,12 @@ EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); * @kcontrol: mreg control * @ucontrol: control element information * - * Callback to set the value of a control that can span - * multiple codec registers which together forms a single - * signed value in a MSB/LSB manner. The control supports - * specifying total no of bits used to allow for bitfields - * across the multiple codec registers. + * Callback to set the value of a control that can span multiple codec + * registers which together forms a single signed value. The control + * supports specifying total no of bits used to allow for bitfields + * across the multiple codec registers. Note that unlike the non-xr + * variant of sx controls these may or may not include the sign bit, + * depending on nbits, and there is no shift. * * Returns 0 for success. */ From c6002c1177cafb4462b6c188d2a62eb67f15165f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:48 +0000 Subject: [PATCH 1069/1090] ASoC: ops: Update mask generation to use GENMASK Use GENMASK to make the masks for the various control helper functions. Also factor out a shared helper function for the volsw and volsw_range controls since the same code is appropriate for each. Note this does add support for sign_bit into the volsw_range callbacks. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 46 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index dac55138210d..54945017e1f1 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -158,6 +158,20 @@ static void snd_soc_read_signed(struct snd_soc_component *component, *signed_val = ret; } +static int soc_mixer_mask(struct soc_mixer_control *mc) +{ + if (mc->sign_bit) + return GENMASK(mc->sign_bit, 0); + else + return GENMASK(fls(mc->max) - 1, 0); +} + +static int soc_mixer_sx_mask(struct soc_mixer_control *mc) +{ + // min + max will take us 1-bit over the size of the mask + return GENMASK(fls(mc->min + mc->max) - 2, 0); +} + /** * snd_soc_info_volsw - single mixer info callback * @kcontrol: mixer control @@ -260,13 +274,10 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; int min = mc->min; int sign_bit = mc->sign_bit; - unsigned int mask = (1ULL << fls(max)) - 1; + unsigned int mask = soc_mixer_mask(mc); unsigned int invert = mc->invert; int val; - if (sign_bit) - mask = BIT(sign_bit + 1) - 1; - snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); ucontrol->value.integer.value[0] = val - min; @@ -312,17 +323,13 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int rshift = mc->rshift; int max = mc->max; int min = mc->min; - unsigned int sign_bit = mc->sign_bit; - unsigned int mask = (1 << fls(max)) - 1; + unsigned int mask = soc_mixer_mask(mc); unsigned int invert = mc->invert; int err, ret; bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; - if (sign_bit) - mask = BIT(sign_bit + 1) - 1; - if (ucontrol->value.integer.value[0] < 0) return -EINVAL; val = ucontrol->value.integer.value[0]; @@ -391,9 +398,8 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; - int max = mc->max; int min = mc->min; - unsigned int mask = (1U << (fls(min + max) - 1)) - 1; + unsigned int mask = soc_mixer_sx_mask(mc); unsigned int val; val = snd_soc_component_read(component, reg); @@ -431,7 +437,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int val, val_mask; int max = mc->max; int min = mc->min; - unsigned int mask = (1U << (fls(min + max) - 1)) - 1; + unsigned int mask = soc_mixer_sx_mask(mc); int err = 0; int ret; @@ -525,7 +531,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; + unsigned int mask = soc_mixer_mask(mc); unsigned int invert = mc->invert; unsigned int val, val_mask; int err, ret, tmp; @@ -597,7 +603,7 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; int min = mc->min; int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; + unsigned int mask = soc_mixer_mask(mc); unsigned int invert = mc->invert; unsigned int val; @@ -891,9 +897,9 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1UL << regwshift) - 1; + unsigned int regwmask = GENMASK(regwshift - 1, 0); + unsigned long mask = GENMASK(mc->nbits - 1, 0); unsigned int invert = mc->invert; - unsigned long mask = (1UL << mc->nbits) - 1; long min = mc->min; long max = mc->max; long val = 0; @@ -938,9 +944,9 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regbase = mc->regbase; unsigned int regcount = mc->regcount; unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; - unsigned int regwmask = (1UL << regwshift) - 1; + unsigned int regwmask = GENMASK(regwshift - 1, 0); + unsigned long mask = GENMASK(mc->nbits - 1, 0); unsigned int invert = mc->invert; - unsigned long mask = (1UL << mc->nbits) - 1; long max = mc->max; long val = ucontrol->value.integer.value[0]; int ret = 0; @@ -986,7 +992,7 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int shift = mc->shift; - unsigned int mask = 1 << shift; + unsigned int mask = BIT(shift); unsigned int invert = mc->invert != 0; unsigned int val; @@ -1019,7 +1025,7 @@ int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int shift = mc->shift; - unsigned int mask = 1 << shift; + unsigned int mask = BIT(shift); unsigned int invert = mc->invert != 0; unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; unsigned int val1 = (strobe ^ invert) ? mask : 0; From eeb76cb1fa0dcccf33091b04ba150076dfbeb6fd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:49 +0000 Subject: [PATCH 1070/1090] ASoC: ops: Factor out helper to check valid control values Most of the put handlers have identical code to verify the value passed in from user-space. Factor this out into a single helper function. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 82 ++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 54945017e1f1..53a141426a96 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -158,6 +158,20 @@ static void snd_soc_read_signed(struct snd_soc_component *component, *signed_val = ret; } +static int soc_mixer_valid_ctl(struct soc_mixer_control *mc, long val, int max) +{ + if (val < 0) + return -EINVAL; + + if (mc->platform_max && val > mc->platform_max) + return -EINVAL; + + if (val > max) + return -EINVAL; + + return 0; +} + static int soc_mixer_mask(struct soc_mixer_control *mc) { if (mc->sign_bit) @@ -330,26 +344,24 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val2 = 0; unsigned int val, val_mask; - if (ucontrol->value.integer.value[0] < 0) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], + mc->max - mc->min); + if (ret) + return ret; + val = ucontrol->value.integer.value[0]; - if (mc->platform_max && val > mc->platform_max) - return -EINVAL; - if (val > max - min) - return -EINVAL; val = (val + min) & mask; if (invert) val = max - val; val_mask = mask << shift; val = val << shift; if (snd_soc_volsw_is_stereo(mc)) { - if (ucontrol->value.integer.value[1] < 0) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], + mc->max - mc->min); + if (ret) + return ret; + val2 = ucontrol->value.integer.value[1]; - if (mc->platform_max && val2 > mc->platform_max) - return -EINVAL; - if (val2 > max - min) - return -EINVAL; val2 = (val2 + min) & mask; if (invert) val2 = max - val2; @@ -435,19 +447,16 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; unsigned int val, val_mask; - int max = mc->max; int min = mc->min; unsigned int mask = soc_mixer_sx_mask(mc); int err = 0; int ret; - if (ucontrol->value.integer.value[0] < 0) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], mc->max); + if (ret) + return ret; + val = ucontrol->value.integer.value[0]; - if (mc->platform_max && val > mc->platform_max) - return -EINVAL; - if (val > max) - return -EINVAL; val_mask = mask << shift; val = (val + min) & mask; val = val << shift; @@ -458,13 +467,14 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, ret = err; if (snd_soc_volsw_is_stereo(mc)) { - unsigned int val2 = ucontrol->value.integer.value[1]; + unsigned int val2; - if (mc->platform_max && val2 > mc->platform_max) - return -EINVAL; - if (val2 > max) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], + mc->max); + if (ret) + return ret; + val2 = ucontrol->value.integer.value[1]; val_mask = mask << rshift; val2 = (val2 + min) & mask; val2 = val2 << rshift; @@ -534,15 +544,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, unsigned int mask = soc_mixer_mask(mc); unsigned int invert = mc->invert; unsigned int val, val_mask; - int err, ret, tmp; + int err, ret; - tmp = ucontrol->value.integer.value[0]; - if (tmp < 0) - return -EINVAL; - if (mc->platform_max && tmp > mc->platform_max) - return -EINVAL; - if (tmp > mc->max - mc->min) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], + mc->max - mc->min); + if (ret) + return ret; if (invert) val = (max - ucontrol->value.integer.value[0]) & mask; @@ -557,13 +564,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, ret = err; if (snd_soc_volsw_is_stereo(mc)) { - tmp = ucontrol->value.integer.value[1]; - if (tmp < 0) - return -EINVAL; - if (mc->platform_max && tmp > mc->platform_max) - return -EINVAL; - if (tmp > mc->max - mc->min) - return -EINVAL; + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], + mc->max - mc->min); + if (ret) + return ret; if (invert) val = (max - ucontrol->value.integer.value[1]) & mask; From 1522aacd0114069b7f01f047b9e5b159399af295 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:50 +0000 Subject: [PATCH 1071/1090] ASoC: ops: Replace snd_soc_read_signed() with new helper The current snd_soc_read_signed() helper is only used from snd_soc_get_volsw() and can be implemented more simply with sign_extend. Remove snd_soc_read_signed() and add a new soc_mixer_reg_to_ctl() helper. This new helper does not include the reading of the register, but does include min and max handling. This allows the helper to replace more of the duplicated code and makes it easier to process the differences between single, double register and double shift style controls. It is worth noting this adds support for sign_bit into the _range and sx callbacks and the invert option to sx callbacks. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 134 ++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 93 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 53a141426a96..af4e67817317 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -110,52 +110,20 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); -/** - * snd_soc_read_signed - Read a codec register and interpret as signed value - * @component: component - * @reg: Register to read - * @mask: Mask to use after shifting the register value - * @shift: Right shift of register value - * @sign_bit: Bit that describes if a number is negative or not. - * @signed_val: Pointer to where the read value should be stored - * - * This functions reads a codec register. The register value is shifted right - * by 'shift' bits and masked with the given 'mask'. Afterwards it translates - * the given registervalue into a signed integer if sign_bit is non-zero. - */ -static void snd_soc_read_signed(struct snd_soc_component *component, - unsigned int reg, unsigned int mask, - unsigned int shift, unsigned int sign_bit, - int *signed_val) +static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val, + unsigned int mask, unsigned int shift, int max) { - int ret; - unsigned int val; + int val = (reg_val >> shift) & mask; - val = snd_soc_component_read(component, reg); - val = (val >> shift) & mask; + if (mc->sign_bit) + val = sign_extend32(val, mc->sign_bit); - if (!sign_bit) { - *signed_val = val; - return; - } + val -= mc->min; - /* non-negative number */ - if (!(val & BIT(sign_bit))) { - *signed_val = val; - return; - } + if (mc->invert) + val = max - val; - ret = val; - - /* - * The register most probably does not contain a full-sized int. - * Instead we have an arbitrary number of bits in a signed - * representation which has to be translated into a full-sized int. - * This is done by filling up all bits above the sign-bit. - */ - ret |= ~((int)(BIT(sign_bit) - 1)); - - *signed_val = ret; + return val & mask; } static int soc_mixer_valid_ctl(struct soc_mixer_control *mc, long val, int max) @@ -281,34 +249,25 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; - int max = mc->max; - int min = mc->min; - int sign_bit = mc->sign_bit; + int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - unsigned int invert = mc->invert; + unsigned int reg_val; int val; - snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); + reg_val = snd_soc_component_read(component, mc->reg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); - ucontrol->value.integer.value[0] = val - min; - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; + ucontrol->value.integer.value[0] = val; if (snd_soc_volsw_is_stereo(mc)) { - if (reg == reg2) - snd_soc_read_signed(component, reg, mask, rshift, sign_bit, &val); - else - snd_soc_read_signed(component, reg2, mask, shift, sign_bit, &val); + if (mc->reg == mc->rreg) { + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max); + } else { + reg_val = snd_soc_component_read(component, mc->rreg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + } - ucontrol->value.integer.value[1] = val - min; - if (invert) - ucontrol->value.integer.value[1] = - max - ucontrol->value.integer.value[1]; + ucontrol->value.integer.value[1] = val; } return 0; @@ -408,18 +367,19 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; - int min = mc->min; unsigned int mask = soc_mixer_sx_mask(mc); - unsigned int val; + unsigned int reg_val; + int val; - val = snd_soc_component_read(component, reg); - ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; + reg_val = snd_soc_component_read(component, reg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, mc->max); + + ucontrol->value.integer.value[0] = val; if (snd_soc_volsw_is_stereo(mc)) { - val = snd_soc_component_read(component, reg2); - val = ((val >> rshift) - min) & mask; + reg_val = snd_soc_component_read(component, reg2); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, mc->max); + ucontrol->value.integer.value[1] = val; } @@ -602,33 +562,21 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int rreg = mc->rreg; - unsigned int shift = mc->shift; - int min = mc->min; - int max = mc->max; + int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - unsigned int invert = mc->invert; - unsigned int val; + unsigned int reg_val; + int val; - val = snd_soc_component_read(component, reg); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - else - ucontrol->value.integer.value[0] = - ucontrol->value.integer.value[0] - min; + reg_val = snd_soc_component_read(component, mc->reg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + + ucontrol->value.integer.value[0] = val; if (snd_soc_volsw_is_stereo(mc)) { - val = snd_soc_component_read(component, rreg); - ucontrol->value.integer.value[1] = (val >> shift) & mask; - if (invert) - ucontrol->value.integer.value[1] = - max - ucontrol->value.integer.value[1]; - else - ucontrol->value.integer.value[1] = - ucontrol->value.integer.value[1] - min; + reg_val = snd_soc_component_read(component, mc->rreg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + + ucontrol->value.integer.value[1] = val; } return 0; From ed336066202c02f0b0e47d0cf08fd8f40a42351f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:51 +0000 Subject: [PATCH 1072/1090] ASoC: ops: Add control to register value helper Add a helper function to convert from control values to register values that can replace a lot of the duplicated code in the various put handlers. This also fixes a small issue in snd_soc_put_volsw where the value is converted to a control value before doing the invert, but the invert is done against the register max which will result in incorrect values for inverted controls with a non-zero minimum. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-8-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 97 ++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 54 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index af4e67817317..888afdd23f84 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -126,6 +126,20 @@ static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_v return val & mask; } +static unsigned int soc_mixer_ctl_to_reg(struct soc_mixer_control *mc, int val, + unsigned int mask, unsigned int shift, + int max) +{ + unsigned int reg_val; + + if (mc->invert) + val = max - val; + + reg_val = val + mc->min; + + return (reg_val & mask) << shift; +} + static int soc_mixer_valid_ctl(struct soc_mixer_control *mc, long val, int max) { if (val < 0) @@ -292,43 +306,35 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; - int max = mc->max; - int min = mc->min; + int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - unsigned int invert = mc->invert; int err, ret; bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], - mc->max - mc->min); + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max); if (ret) return ret; - val = ucontrol->value.integer.value[0]; - val = (val + min) & mask; - if (invert) - val = max - val; - val_mask = mask << shift; - val = val << shift; + val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], + mask, mc->shift, max); + val_mask = mask << mc->shift; + if (snd_soc_volsw_is_stereo(mc)) { - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], - mc->max - mc->min); + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], max); if (ret) return ret; - val2 = ucontrol->value.integer.value[1]; - val2 = (val2 + min) & mask; - if (invert) - val2 = max - val2; if (reg == reg2) { - val_mask |= mask << rshift; - val |= val2 << rshift; + val |= soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->rshift, max); + val_mask |= mask << mc->rshift; } else { - val2 = val2 << shift; + val2 = soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->shift, max); type_2r = true; } } @@ -404,10 +410,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; unsigned int val, val_mask; - int min = mc->min; unsigned int mask = soc_mixer_sx_mask(mc); int err = 0; int ret; @@ -416,10 +419,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, if (ret) return ret; - val = ucontrol->value.integer.value[0]; - val_mask = mask << shift; - val = (val + min) & mask; - val = val << shift; + val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], + mask, mc->shift, mc->max); + val_mask = mask << mc->shift; err = snd_soc_component_update_bits(component, reg, val_mask, val); if (err < 0) @@ -427,20 +429,17 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, ret = err; if (snd_soc_volsw_is_stereo(mc)) { - unsigned int val2; - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], mc->max); if (ret) return ret; - val2 = ucontrol->value.integer.value[1]; - val_mask = mask << rshift; - val2 = (val2 + min) & mask; - val2 = val2 << rshift; + val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[1], + mask, mc->rshift, mc->max); + val_mask = mask << mc->rshift; err = snd_soc_component_update_bits(component, reg2, val_mask, - val2); + val); /* Don't discard any error code or drop change flag */ if (ret == 0 || err < 0) @@ -498,12 +497,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; unsigned int rreg = mc->rreg; - unsigned int shift = mc->shift; - int min = mc->min; - int max = mc->max; + int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - unsigned int invert = mc->invert; - unsigned int val, val_mask; + unsigned int val_mask = mask << mc->shift; + unsigned int val; int err, ret; ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], @@ -511,12 +508,8 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, if (ret) return ret; - if (invert) - val = (max - ucontrol->value.integer.value[0]) & mask; - else - val = ((ucontrol->value.integer.value[0] + min) & mask); - val_mask = mask << shift; - val = val << shift; + val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], + mask, mc->shift, max); err = snd_soc_component_update_bits(component, reg, val_mask, val); if (err < 0) @@ -525,16 +518,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], - mc->max - mc->min); + max); if (ret) return ret; - if (invert) - val = (max - ucontrol->value.integer.value[1]) & mask; - else - val = ((ucontrol->value.integer.value[1] + min) & mask); - val_mask = mask << shift; - val = val << shift; + val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[1], + mask, mc->shift, max); err = snd_soc_component_update_bits(component, rreg, val_mask, val); From 894a37c9de4b8a447ffa609d552e91ccb447c0a9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:52 +0000 Subject: [PATCH 1073/1090] ASoC: ops: Remove snd_soc_info_volsw_range() The only difference between snd_soc_info_volsw() and snd_soc_info_volsw_range() is that the later will not force a 2 value control to be of type integer if the name ends in "Volume". The kernel currently contains no users of snd_soc_info_volsw_range() that would return a boolean control with this code, so the risk is quite low and it seems appropriate that it should contain volume control detection. So remove snd_soc_info_volsw_range() and point its users at snd_soc_info_volsw(). Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-9-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 12 +++++------ sound/pci/hda/tas2781_hda_i2c.c | 2 +- sound/pci/hda/tas2781_hda_spi.c | 2 +- sound/soc/soc-ops.c | 36 +++------------------------------ sound/soc/soc-topology.c | 2 +- 5 files changed, 11 insertions(+), 43 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index d73fe26de166..b310f2c599f8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -65,7 +65,7 @@ struct platform_device; .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ + .info = snd_soc_info_volsw, .get = snd_soc_get_volsw_range, \ .put = snd_soc_put_volsw_range, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ @@ -90,7 +90,7 @@ struct platform_device; .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ @@ -116,7 +116,7 @@ struct platform_device; #define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } @@ -164,7 +164,7 @@ struct platform_device; .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } @@ -266,7 +266,7 @@ struct platform_device; .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ @@ -569,8 +569,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c index be9a90f643eb..50c5e5f26589 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -45,7 +45,7 @@ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = xshift, \ diff --git a/sound/pci/hda/tas2781_hda_spi.c b/sound/pci/hda/tas2781_hda_spi.c index 00676cbb2c8e..399f2e4c3b62 100644 --- a/sound/pci/hda/tas2781_hda_spi.c +++ b/sound/pci/hda/tas2781_hda_spi.c @@ -52,7 +52,7 @@ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_READWRITE, \ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = (unsigned long)&(struct soc_mixer_control) { \ .reg = xreg, .rreg = xreg, \ diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 888afdd23f84..1b52ba12df8d 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -169,12 +169,12 @@ static int soc_mixer_sx_mask(struct soc_mixer_control *mc) } /** - * snd_soc_info_volsw - single mixer info callback + * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control * @uinfo: control element information * - * Callback to provide information about a single mixer control, or a double - * mixer control that spans 2 registers. + * Callback to provide information, with a range, about a single mixer control, + * or a double mixer control that spans 2 registers. * * Returns 0 for success. */ @@ -450,36 +450,6 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); -/** - * snd_soc_info_volsw_range - single mixer info callback with range. - * @kcontrol: mixer control - * @uinfo: control element information - * - * Callback to provide information, within a range, about a single - * mixer control. - * - * returns 0 for success. - */ -int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int max; - - max = mc->max - mc->min; - if (mc->platform_max && mc->platform_max < max) - max = mc->platform_max; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = max; - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); - /** * snd_soc_put_volsw_range - single mixer put value callback with range. * @kcontrol: mixer control diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 2b86cc3311f7..9cbddfbbc556 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -132,7 +132,7 @@ static const struct snd_soc_tplg_kcontrol_ops io_ops[] = { {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get, snd_soc_bytes_put, snd_soc_bytes_info}, {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range, - snd_soc_put_volsw_range, snd_soc_info_volsw_range}, + snd_soc_put_volsw_range, snd_soc_info_volsw}, {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx, snd_soc_put_xr_sx, snd_soc_info_xr_sx}, {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe, From fd7442561cfe9516b37cdb1d229dc1f811dc86cc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:53 +0000 Subject: [PATCH 1074/1090] ASoC: ops: Remove snd_soc_get_volsw_range() With the addition of the soc_mixer_reg_to_ctl() helper it is now very clear that the only difference between snd_soc_get_volsw() and snd_soc_get_volsw_range() is that the former supports double controls with both values in the same register. As such we can combine both functions. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-10-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 10 ++++------ sound/soc/codecs/wm5110.c | 2 +- sound/soc/soc-ops.c | 42 +++------------------------------------ sound/soc/soc-topology.c | 2 +- 4 files changed, 9 insertions(+), 47 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index b310f2c599f8..b11c6cdb0201 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -65,7 +65,7 @@ struct platform_device; .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw, .get = snd_soc_get_volsw_range, \ + .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw_range, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ @@ -91,7 +91,7 @@ struct platform_device; SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -117,7 +117,7 @@ struct platform_device; xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ @@ -165,7 +165,7 @@ struct platform_device; SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ @@ -571,8 +571,6 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max); int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 64eee0d2347d..c24b42c37578 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -477,7 +477,7 @@ static int wm5110_in_pga_get(struct snd_kcontrol *kcontrol, */ snd_soc_dapm_mutex_lock(dapm); - ret = snd_soc_get_volsw_range(kcontrol, ucontrol); + ret = snd_soc_get_volsw(kcontrol, ucontrol); snd_soc_dapm_mutex_unlock(dapm); diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 1b52ba12df8d..fbda8e21c5a6 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -248,12 +248,12 @@ int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); /** - * snd_soc_get_volsw - single mixer get callback + * snd_soc_get_volsw - single mixer get callback with range * @kcontrol: mixer control * @ucontrol: control element information * - * Callback to get the value of a single mixer control, or a double mixer - * control that spans 2 registers. + * Callback to get the value, within a range, of a single mixer control, or a + * double mixer control that spans 2 registers. * * Returns 0 for success. */ @@ -506,42 +506,6 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); -/** - * snd_soc_get_volsw_range - single mixer get callback with range - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value, within a range, of a single mixer control. - * - * Returns 0 for success. - */ -int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int max = mc->max - mc->min; - unsigned int mask = soc_mixer_mask(mc); - unsigned int reg_val; - int val; - - reg_val = snd_soc_component_read(component, mc->reg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); - - ucontrol->value.integer.value[0] = val; - - if (snd_soc_volsw_is_stereo(mc)) { - reg_val = snd_soc_component_read(component, mc->rreg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); - - ucontrol->value.integer.value[1] = val; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); - static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 9cbddfbbc556..3c988925c512 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -131,7 +131,7 @@ static const struct snd_soc_tplg_kcontrol_ops io_ops[] = { snd_soc_put_enum_double, NULL}, {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get, snd_soc_bytes_put, snd_soc_bytes_info}, - {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range, + {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw, snd_soc_put_volsw_range, snd_soc_info_volsw}, {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx, snd_soc_put_xr_sx, snd_soc_info_xr_sx}, From 7d5df968f95cee274740d5fa42e0798ffb59bd38 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:54 +0000 Subject: [PATCH 1075/1090] ASoC: ops: Remove snd_soc_put_volsw_range() With the addition of the soc_mixer_ctl_to_reg() helper it is now very clear that the only difference between snd_soc_put_volsw() and snd_soc_put_volsw_range() is that the former supports double controls with both values in the same register. As such we can combine both functions. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-11-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc.h | 10 +++---- sound/soc/codecs/wm5110.c | 2 +- sound/soc/soc-ops.c | 62 ++------------------------------------- sound/soc/soc-topology.c | 2 +- 4 files changed, 9 insertions(+), 67 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index b11c6cdb0201..952ed77b8c87 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -66,7 +66,7 @@ struct platform_device; #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ - .put = snd_soc_put_volsw_range, \ + .put = snd_soc_put_volsw, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -91,7 +91,7 @@ struct platform_device; SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -117,7 +117,7 @@ struct platform_device; xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ @@ -165,7 +165,7 @@ struct platform_device; SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_range, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ @@ -569,8 +569,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max); int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index c24b42c37578..212eca675f27 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -497,7 +497,7 @@ static int wm5110_in_pga_put(struct snd_kcontrol *kcontrol, */ snd_soc_dapm_mutex_lock(dapm); - ret = snd_soc_put_volsw_range(kcontrol, ucontrol); + ret = snd_soc_put_volsw(kcontrol, ucontrol); snd_soc_dapm_mutex_unlock(dapm); diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index fbda8e21c5a6..d26d9e050af1 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -289,12 +289,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_get_volsw); /** - * snd_soc_put_volsw - single mixer put callback + * snd_soc_put_volsw - single mixer put callback with range * @kcontrol: mixer control * @ucontrol: control element information * - * Callback to set the value of a single mixer control, or a double mixer - * control that spans 2 registers. + * Callback to set the value , within a range, of a single mixer control, or + * a double mixer control that spans 2 registers. * * Returns 0 for success. */ @@ -450,62 +450,6 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); -/** - * snd_soc_put_volsw_range - single mixer put value callback with range. - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value, within a range, for a single mixer control. - * - * Returns 0 for success. - */ -int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int rreg = mc->rreg; - int max = mc->max - mc->min; - unsigned int mask = soc_mixer_mask(mc); - unsigned int val_mask = mask << mc->shift; - unsigned int val; - int err, ret; - - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], - mc->max - mc->min); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], - mask, mc->shift, max); - - err = snd_soc_component_update_bits(component, reg, val_mask, val); - if (err < 0) - return err; - ret = err; - - if (snd_soc_volsw_is_stereo(mc)) { - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], - max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[1], - mask, mc->shift, max); - - err = snd_soc_component_update_bits(component, rreg, val_mask, - val); - /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) - ret = err; - } - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); - static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 3c988925c512..7b0b8531bb32 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -132,7 +132,7 @@ static const struct snd_soc_tplg_kcontrol_ops io_ops[] = { {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get, snd_soc_bytes_put, snd_soc_bytes_info}, {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw, - snd_soc_put_volsw_range, snd_soc_info_volsw}, + snd_soc_put_volsw, snd_soc_info_volsw}, {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx, snd_soc_put_xr_sx, snd_soc_info_xr_sx}, {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe, From 9dfcafe2037acc14265cead8d8a937a8bc4e01d8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:55 +0000 Subject: [PATCH 1076/1090] ASoC: ops: Factor out common code from info callbacks snd_soc_info_volsw() and snd_soc_info_volsw_sx() do very similar things, and have a lot of code in common. Already this is causing some issues as the detection of volume controls has been fixed in the normal callback but not the sx callback. Factor out a new helper containing the common code and leave the function specific bits behind in each callback. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-12-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 64 ++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index d26d9e050af1..29537dd3a063 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -168,6 +168,30 @@ static int soc_mixer_sx_mask(struct soc_mixer_control *mc) return GENMASK(fls(mc->min + mc->max) - 2, 0); } +static int soc_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo, + struct soc_mixer_control *mc, int max) +{ + if (mc->platform_max && mc->platform_max < max) + max = mc->platform_max; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + + if (max == 1) { + /* Even two value controls ending in Volume should be integer */ + const char *vol_string = strstr(kcontrol->id.name, " Volume"); + + if (!vol_string || strcmp(vol_string, " Volume")) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + } + + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = max; + + return 0; +} + /** * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control @@ -183,29 +207,8 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - const char *vol_string = NULL; - int max; - max = uinfo->value.integer.max = mc->max - mc->min; - if (mc->platform_max && mc->platform_max < max) - max = mc->platform_max; - - if (max == 1) { - /* Even two value controls ending in Volume should always be integer */ - vol_string = strstr(kcontrol->id.name, " Volume"); - if (vol_string && !strcmp(vol_string, " Volume")) - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - } else { - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - } - - uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = max; - - return 0; + return soc_info_volsw(kcontrol, uinfo, mc, mc->max - mc->min); } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -227,23 +230,8 @@ int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int max; - if (mc->platform_max) - max = mc->platform_max; - else - max = mc->max; - - if (max == 1 && !strstr(kcontrol->id.name, " Volume")) - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - - uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = max; - - return 0; + return soc_info_volsw(kcontrol, uinfo, mc, mc->max); } EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); From 318e8794e05ca1879441a602e78c74f9d7e18309 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Mar 2025 17:14:56 +0000 Subject: [PATCH 1077/1090] ASoC: ops: Factor out common code from put callbacks There are only two differences between snd_soc_put_volsw() and snd_soc_put_volsw_sx(). The maximum field is handled differently, and snd_soc_put_volsw() supports double controls with both values in the same register. Factor out the common code into a new helper and pass in the appropriate max value such that it is handled correctly for each control. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250318171459.3203730-13-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 138 +++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 85 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 29537dd3a063..0b62ffb2e222 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -192,6 +192,57 @@ static int soc_info_volsw(struct snd_kcontrol *kcontrol, return 0; } +static int soc_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + struct soc_mixer_control *mc, int mask, int max) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + unsigned int val1, val_mask; + unsigned int val2 = 0; + bool double_r = false; + int ret; + + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max); + if (ret) + return ret; + + val1 = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], + mask, mc->shift, max); + val_mask = mask << mc->shift; + + if (snd_soc_volsw_is_stereo(mc)) { + ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], max); + if (ret) + return ret; + + if (mc->reg == mc->rreg) { + val1 |= soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->rshift, max); + val_mask |= mask << mc->rshift; + } else { + val2 = soc_mixer_ctl_to_reg(mc, + ucontrol->value.integer.value[1], + mask, mc->shift, max); + double_r = true; + } + } + + ret = snd_soc_component_update_bits(component, mc->reg, val_mask, val1); + if (ret < 0) + return ret; + + if (double_r) { + int err = snd_soc_component_update_bits(component, mc->rreg, + val_mask, val2); + /* Don't drop change flag */ + if (err) + return err; + } + + return ret; +} + /** * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control @@ -289,57 +340,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - int err, ret; - bool type_2r = false; - unsigned int val2 = 0; - unsigned int val, val_mask; - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], - mask, mc->shift, max); - val_mask = mask << mc->shift; - - if (snd_soc_volsw_is_stereo(mc)) { - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], max); - if (ret) - return ret; - - if (reg == reg2) { - val |= soc_mixer_ctl_to_reg(mc, - ucontrol->value.integer.value[1], - mask, mc->rshift, max); - val_mask |= mask << mc->rshift; - } else { - val2 = soc_mixer_ctl_to_reg(mc, - ucontrol->value.integer.value[1], - mask, mc->shift, max); - type_2r = true; - } - } - err = snd_soc_component_update_bits(component, reg, val_mask, val); - if (err < 0) - return err; - ret = err; - - if (type_2r) { - err = snd_soc_component_update_bits(component, reg2, val_mask, - val2); - /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) - ret = err; - } - - return ret; + return soc_put_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min); } EXPORT_SYMBOL_GPL(snd_soc_put_volsw); @@ -393,48 +398,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int val, val_mask; unsigned int mask = soc_mixer_sx_mask(mc); - int err = 0; - int ret; - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[0], mc->max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0], - mask, mc->shift, mc->max); - val_mask = mask << mc->shift; - - err = snd_soc_component_update_bits(component, reg, val_mask, val); - if (err < 0) - return err; - ret = err; - - if (snd_soc_volsw_is_stereo(mc)) { - ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], - mc->max); - if (ret) - return ret; - - val = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[1], - mask, mc->rshift, mc->max); - val_mask = mask << mc->rshift; - - err = snd_soc_component_update_bits(component, reg2, val_mask, - val); - - /* Don't discard any error code or drop change flag */ - if (ret == 0 || err < 0) - ret = err; - } - - return ret; + return soc_put_volsw(kcontrol, ucontrol, mc, mask, mc->max); } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); From 83eddf0116b09186f909bc643f2093f266f204ea Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Wed, 19 Mar 2025 10:29:28 +0100 Subject: [PATCH 1078/1090] irqdomain: sound: Switch to irq_domain_create_linear() irq_domain_add_linear() is going away as being obsolete now. Switch to the preferred irq_domain_create_linear(). That differs in the first parameter: It takes more generic struct fwnode_handle instead of struct device_node. Therefore, of_fwnode_handle() is added around the parameter. Note some of the users can likely use dev->fwnode directly instead of indirect of_fwnode_handle(dev->of_node). But dev->fwnode is not guaranteed to be set for all, so this has to be investigated on case to case basis (by people who can actually test with the HW). Signed-off-by: Jiri Slaby (SUSE) Cc: Liam Girdwood Cc: Mark Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Prasad Kumpatla Cc: linux-sound@vger.kernel.org Link: https://patch.msgid.link/20250319092951.37667-36-jirislaby@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd937x.c | 2 +- sound/soc/codecs/wcd938x.c | 2 +- sound/soc/codecs/wcd939x.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index ff8bb01edf42..dd2045a5d26d 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -2480,7 +2480,7 @@ static const struct irq_domain_ops wcd_domain_ops = { static int wcd937x_irq_init(struct wcd937x_priv *wcd, struct device *dev) { - wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); + wcd->virq = irq_domain_create_linear(NULL, 1, &wcd_domain_ops, NULL); if (!(wcd->virq)) { dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); return -EINVAL; diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index b536e8bdc5a7..1ae498c32391 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -3025,7 +3025,7 @@ static const struct irq_domain_ops wcd_domain_ops = { static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev) { - wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); + wcd->virq = irq_domain_create_linear(NULL, 1, &wcd_domain_ops, NULL); if (!(wcd->virq)) { dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); return -EINVAL; diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c index 4a417a92514d..0a87a79772da 100644 --- a/sound/soc/codecs/wcd939x.c +++ b/sound/soc/codecs/wcd939x.c @@ -2975,7 +2975,7 @@ static const struct irq_domain_ops wcd_domain_ops = { static int wcd939x_irq_init(struct wcd939x_priv *wcd, struct device *dev) { - wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); + wcd->virq = irq_domain_create_linear(NULL, 1, &wcd_domain_ops, NULL); if (!(wcd->virq)) { dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); return -EINVAL; From 1e3cd64a29baa874b89180ac0744178ecb00f3cd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 19 Mar 2025 17:51:21 +0000 Subject: [PATCH 1079/1090] ASoC: ops: Factor out common code from get callbacks There are only two differences between snd_soc_get_volsw() and snd_soc_get_volsw_sx(). The maximum field is handled differently, and snd_soc_get_volsw() supports double controls with both values in the same register. Factor out the common code into a new helper and pass in the appropriate max value such that it is handled correctly for each control. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250319175123.3835849-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 68 +++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 0b62ffb2e222..1d7c28993a63 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -243,6 +243,33 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol, return ret; } +static int soc_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + struct soc_mixer_control *mc, int mask, int max) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + unsigned int reg_val; + int val; + + reg_val = snd_soc_component_read(component, mc->reg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + + ucontrol->value.integer.value[0] = val; + + if (snd_soc_volsw_is_stereo(mc)) { + if (mc->reg == mc->rreg) { + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max); + } else { + reg_val = snd_soc_component_read(component, mc->rreg); + val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); + } + + ucontrol->value.integer.value[1] = val; + } + + return 0; +} + /** * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control @@ -299,31 +326,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int max = mc->max - mc->min; unsigned int mask = soc_mixer_mask(mc); - unsigned int reg_val; - int val; - reg_val = snd_soc_component_read(component, mc->reg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); - - ucontrol->value.integer.value[0] = val; - - if (snd_soc_volsw_is_stereo(mc)) { - if (mc->reg == mc->rreg) { - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max); - } else { - reg_val = snd_soc_component_read(component, mc->rreg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max); - } - - ucontrol->value.integer.value[1] = val; - } - - return 0; + return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min); } EXPORT_SYMBOL_GPL(snd_soc_get_volsw); @@ -361,28 +368,11 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; unsigned int mask = soc_mixer_sx_mask(mc); - unsigned int reg_val; - int val; - reg_val = snd_soc_component_read(component, reg); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, mc->max); - - ucontrol->value.integer.value[0] = val; - - if (snd_soc_volsw_is_stereo(mc)) { - reg_val = snd_soc_component_read(component, reg2); - val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, mc->max); - - ucontrol->value.integer.value[1] = val; - } - - return 0; + return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max); } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); From 94dfe71f0a4eb0d7df542560c22961dedf45141d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 19 Mar 2025 17:51:22 +0000 Subject: [PATCH 1080/1090] ASoC: ops: Remove some unnecessary local variables Remove some local variables that aren't adding much in terms of clarity or space saving. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250319175123.3835849-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 1d7c28993a63..3ac5b3a62c81 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -664,9 +664,6 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; unsigned int regwmask = GENMASK(regwshift - 1, 0); unsigned long mask = GENMASK(mc->nbits - 1, 0); - unsigned int invert = mc->invert; - long min = mc->min; - long max = mc->max; long val = 0; unsigned int i; @@ -676,10 +673,10 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, val |= (regval & regwmask) << (regwshift * (regcount - i - 1)); } val &= mask; - if (min < 0 && val > max) + if (mc->min < 0 && val > mc->max) val |= ~mask; - if (invert) - val = max - val; + if (mc->invert) + val = mc->max - val; ucontrol->value.integer.value[0] = val; return 0; @@ -711,16 +708,14 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; unsigned int regwmask = GENMASK(regwshift - 1, 0); unsigned long mask = GENMASK(mc->nbits - 1, 0); - unsigned int invert = mc->invert; - long max = mc->max; long val = ucontrol->value.integer.value[0]; int ret = 0; unsigned int i; if (val < mc->min || val > mc->max) return -EINVAL; - if (invert) - val = max - val; + if (mc->invert) + val = mc->max - val; val &= mask; for (i = 0; i < regcount; i++) { unsigned int regval = (val >> (regwshift * (regcount - i - 1))) & @@ -755,17 +750,16 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = BIT(shift); unsigned int invert = mc->invert != 0; + unsigned int mask = BIT(mc->shift); unsigned int val; - val = snd_soc_component_read(component, reg); + val = snd_soc_component_read(component, mc->reg); val &= mask; - if (shift != 0 && val != 0) - val = val >> shift; + if (mc->shift != 0 && val != 0) + val = val >> mc->shift; + ucontrol->value.enumerated.item[0] = val ^ invert; return 0; @@ -788,19 +782,17 @@ int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = BIT(shift); - unsigned int invert = mc->invert != 0; unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; + unsigned int invert = mc->invert != 0; + unsigned int mask = BIT(mc->shift); unsigned int val1 = (strobe ^ invert) ? mask : 0; unsigned int val2 = (strobe ^ invert) ? 0 : mask; - int err; + int ret; - err = snd_soc_component_update_bits(component, reg, mask, val1); - if (err < 0) - return err; + ret = snd_soc_component_update_bits(component, mc->reg, mask, val1); + if (ret < 0) + return ret; - return snd_soc_component_update_bits(component, reg, mask, val2); + return snd_soc_component_update_bits(component, mc->reg, mask, val2); } EXPORT_SYMBOL_GPL(snd_soc_put_strobe); From 502a668fad12b6ca10bcbb615d62e61d3b669c99 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 19 Mar 2025 17:51:23 +0000 Subject: [PATCH 1081/1090] ASoC: ops: Apply platform_max after deciding control type It doesn't really make sense for the type of a control to change based on the platform_max field. platform_max allows a specific system to limit values of a control for safety but it seems reasonable the control type should remain the same between different systems, even if it is restricted down to just two values. Move the application of platform_max to after control type determination in soc_info_volsw(). Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250319175123.3835849-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 3ac5b3a62c81..8d4dd11c9aef 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -172,9 +172,6 @@ static int soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo, struct soc_mixer_control *mc, int max) { - if (mc->platform_max && mc->platform_max < max) - max = mc->platform_max; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; if (max == 1) { @@ -185,6 +182,9 @@ static int soc_info_volsw(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; } + if (mc->platform_max && mc->platform_max < max) + max = mc->platform_max; + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = max; From fd9582998b9a82ef53a34756de8a1fb86abac972 Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 19 Mar 2025 15:20:55 +0100 Subject: [PATCH 1082/1090] of: Add of_property_read_u16_index There is an of_property_read_u32_index and of_property_read_u64_index. This patch adds a similar helper for u16. Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Rob Herring (Arm) Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250319142059.46692-2-francesco@dolcini.it Signed-off-by: Mark Brown --- drivers/of/property.c | 33 +++++++++++++++++++++++++++++++++ include/linux/of.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/of/property.c b/drivers/of/property.c index 208d922cc24c..c1feb631e383 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np, return prop->value; } +/** + * of_property_read_u16_index - Find and read a u16 from a multi-value property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the u16 in the list of values + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 16-bit value from + * it. + * + * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u16 value can be decoded. + */ +int of_property_read_u16_index(const struct device_node *np, + const char *propname, + u32 index, u16 *out_value) +{ + const u16 *val = of_find_property_value_of_size(np, propname, + ((index + 1) * sizeof(*out_value)), + 0, NULL); + + if (IS_ERR(val)) + return PTR_ERR(val); + + *out_value = be16_to_cpup(((__be16 *)val) + index); + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u16_index); + /** * of_property_read_u32_index - Find and read a u32 from a multi-value property. * diff --git a/include/linux/of.h b/include/linux/of.h index eaf0e2a2b75c..5e52d90f6408 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -314,6 +314,9 @@ extern struct property *of_find_property(const struct device_node *np, extern bool of_property_read_bool(const struct device_node *np, const char *propname); extern int of_property_count_elems_of_size(const struct device_node *np, const char *propname, int elem_size); +extern int of_property_read_u16_index(const struct device_node *np, + const char *propname, + u32 index, u16 *out_value); extern int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value); @@ -627,6 +630,12 @@ static inline int of_property_count_elems_of_size(const struct device_node *np, return -ENOSYS; } +static inline int of_property_read_u16_index(const struct device_node *np, + const char *propname, u32 index, u16 *out_value) +{ + return -ENOSYS; +} + static inline int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value) { From 2aa853248b6b6c76b9dd82353e45a4283f9c53ec Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 19 Mar 2025 15:20:56 +0100 Subject: [PATCH 1083/1090] ASoC: wm8904: Don't touch GPIO configs set to 0xFFFF When updating the GPIO registers, do nothing for all fields of gpio_cfg that are "0xFFFF". This "do nothing" flag used to be 0 to easily check whether the gpio_cfg field was actually set inside pdata or left empty (default). However, 0 is a valid configuration for these registers, while 0xFFFF is not. With this change, users can explicitly set them to 0. Not setting gpio_cfg in the platform data will now lead to setting all GPIO registers to 0 instead of leaving them unset. No one is using this platform data with this codec. The change gets the driver ready to properly set gpio_cfg from the DT. Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250319142059.46692-3-francesco@dolcini.it Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index aef82532f8cf..2082ff12d336 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2270,7 +2270,8 @@ static int wm8904_i2c_probe(struct i2c_client *i2c) /* Apply configuration from the platform data. */ if (wm8904->pdata) { for (i = 0; i < WM8904_GPIO_REGS; i++) { - if (!wm8904->pdata->gpio_cfg[i]) + /* 0xFFFF in this config means "don't touch" */ + if (wm8904->pdata->gpio_cfg[i] == 0xffff) continue; regmap_update_bits(wm8904->regmap, From bd552e937fc80faa70007f7a4cbbf7edd5a6629a Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 19 Mar 2025 15:20:57 +0100 Subject: [PATCH 1084/1090] ASoC: dt-bindings: wm8904: Add DMIC, GPIO, MIC and EQ support Add two properties to select the IN1L/DMICDAT1 and IN2R/DMICDAT2 functionality: - wlf,in1l-as-dmicdat1 - wlf,in1r-as-dmicdat2 Add a property to describe the GPIO configuration registers, that can be used to set the four multifunction pins: - wlf,gpio-cfg Add a property to describe the mic bias control registers: - wlf,micbias-cfg Add two properties to describe the Dynamic Range Controller (DRC), allowing multiple named configurations where each config sets the 4 DRC registers (R40-R43): - wlf,drc-cfg-regs - wlf,drc-cfg-names Add three properties to describe the equalizer (ReTune Mobile), allowing multiple named configurations (associated with a samplerate) that set the 24 (R134-R157) EQ registers: - wlf,retune-mobile-cfg-regs - wlf,retune-mobile-cfg-hz - wlf,retune-mobile-cfg-rates The set of names and configurations for DRC and ReTune Mobile are specified by system integrators. The names are exposed directly to userspace as options that can be selected at runtime. Adding the DRC and ReTune Mobile data to the DT eases the transition from pdata, which has handled them this way for over a decade. The parameters filled in here are almost certainly specific tuning for the hardware so it makes sense to ship them with the hardware description. Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20250319142059.46692-4-francesco@dolcini.it Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8904.yaml | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml index 329260cf0fa0..3029a868e5e1 100644 --- a/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml +++ b/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml @@ -38,6 +38,82 @@ properties: DCVDD-supply: true MICVDD-supply: true + wlf,in1l-as-dmicdat1: + type: boolean + description: + Use IN1L/DMICDAT1 as DMICDAT1, enabling the DMIC input path. + Can be used separately or together with wlf,in1r-as-dmicdat2. + + wlf,in1r-as-dmicdat2: + type: boolean + description: + Use IN1R/DMICDAT2 as DMICDAT2, enabling the DMIC input path. + Can be used separately or together with wlf,in1l-as-dmicdat1. + + wlf,gpio-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 4 + maxItems: 4 + description: + Default register values for R121/122/123/124 (GPIO Control). + If any entry has the value 0xFFFF, the related register won't be set. + default: [0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF] + + wlf,micbias-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + description: + Default register values for R6/R7 (Mic Bias Control). + default: [0, 0] + + wlf,drc-cfg-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + List of strings for the available DRC modes. + If absent, DRC is disabled. + + wlf,drc-cfg-regs: + $ref: /schemas/types.yaml#/definitions/uint16-matrix + description: + Sets of default register values for R40/41/42/43 (DRC). + Each set corresponds to a DRC mode, so the number of sets should equal + the length of wlf,drc-cfg-names. + If absent, DRC is disabled. + items: + minItems: 4 + maxItems: 4 + + wlf,retune-mobile-cfg-names: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + List of strings for the available retune modes. + If absent, retune is disabled. + + wlf,retune-mobile-cfg-hz: + description: + The list must be the same length as wlf,retune-mobile-cfg-names. + If absent, retune is disabled. + + wlf,retune-mobile-cfg-regs: + $ref: /schemas/types.yaml#/definitions/uint16-matrix + description: + Sets of default register values for R134/.../157 (EQ). + Each set corresponds to a retune mode, so the number of sets should equal + the length of wlf,retune-mobile-cfg-names. + If absent, retune is disabled. + items: + minItems: 24 + maxItems: 24 + +dependencies: + wlf,drc-cfg-names: [ 'wlf,drc-cfg-regs' ] + wlf,drc-cfg-regs: [ 'wlf,drc-cfg-names' ] + + wlf,retune-mobile-cfg-names: [ 'wlf,retune-mobile-cfg-hz', 'wlf,retune-mobile-cfg-regs' ] + wlf,retune-mobile-cfg-regs: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-hz' ] + wlf,retune-mobile-cfg-hz: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-regs' ] + required: - compatible - reg @@ -70,5 +146,58 @@ examples: DBVDD-supply = <®_1p8v>; DCVDD-supply = <®_1p8v>; MICVDD-supply = <®_1p8v>; + + wlf,drc-cfg-names = "default", "peaklimiter", "tradition", "soft", + "music"; + /* + * Config registers per name, respectively: + * KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1 + * KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1 + * KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1 + * KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1 + * KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1 + */ + wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>, + /bits/ 16 <0x04af 0x324b 0x0010 0x0408>, + /bits/ 16 <0x04af 0x324b 0x0028 0x0704>, + /bits/ 16 <0x04af 0x324b 0x0018 0x078c>, + /bits/ 16 <0x04af 0x324b 0x0010 0x050e>; + + /* GPIO1 = DMIC_CLK, don't touch others */ + wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>; + + /* Use IN1R as DMICDAT2, leave IN1L as an analog input path */ + wlf,in1r-as-dmicdat2; + + wlf,retune-mobile-cfg-names = "bassboost", "bassboost", "treble"; + wlf,retune-mobile-cfg-hz = <48000>, <44100>, <48000>; + /* + * Config registers per name, respectively: + * EQ_ENA, 100 Hz, 300 Hz, 875 Hz, 2400 Hz, 6900 Hz + * 1, +6 dB, +3 dB, 0 dB, 0 dB, 0 dB + * 1, +6 dB, +3 dB, 0 dB, 0 dB, 0 dB + * 1, -2 dB, -2 dB, 0 dB, 0 dB, +3 dB + * Each one uses the defaults for ReTune Mobile registers 140-157 + */ + wlf,retune-mobile-cfg-regs = /bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc + 0x0fca 0x0400 0x00d8 0x1eb5 + 0xf145 0x0bd5 0x0075 0x1c58 + 0xf3d3 0x0a54 0x0568 0x168e + 0xf829 0x07ad 0x1103 0x0564 + 0x0559 0x4000>, + + /bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc + 0x0fca 0x0400 0x00d8 0x1eb5 + 0xf145 0x0bd5 0x0075 0x1c58 + 0xf3d3 0x0a54 0x0568 0x168e + 0xf829 0x07ad 0x1103 0x0564 + 0x0559 0x4000>, + + /bits/ 16 <0x1 0xa 0xa 0xc 0xc 0xf + 0x0fca 0x0400 0x00d8 0x1eb5 + 0xf145 0x0bd5 0x0075 0x1c58 + 0xf3d3 0x0a54 0x0568 0x168e + 0xf829 0x07ad 0x1103 0x0564 + 0x0559 0x4000>; }; }; From afe66ef965317381fd2894c2eba144b38b791910 Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 19 Mar 2025 15:20:58 +0100 Subject: [PATCH 1085/1090] ASoC: wm8904: get platform data from DT Read in optional codec-specific properties from the device tree. The platform_data structure is not populated when using device trees. This change parses optional dts properties to populate it. - wlf,in1l-as-dmicdat1 - wlf,in1r-as-dmicdat2 - wlf,gpio-cfg - wlf,micbias-cfg - wlf,drc-cfg-regs - wlf,drc-cfg-names - wlf,retune-mobile-cfg-regs - wlf,retune-mobile-cfg-names - wlf,retune-mobile-cfg-hz Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250319142059.46692-5-francesco@dolcini.it Signed-off-by: Mark Brown --- include/sound/wm8904.h | 3 + sound/soc/codecs/wm8904.c | 189 +++++++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h index 88ac1870510e..8b2c16b524f7 100644 --- a/include/sound/wm8904.h +++ b/include/sound/wm8904.h @@ -151,6 +151,9 @@ struct wm8904_pdata { int num_retune_mobile_cfgs; struct wm8904_retune_mobile_cfg *retune_mobile_cfgs; + bool in1l_as_dmicdat1; + bool in1r_as_dmicdat2; + u32 gpio_cfg[WM8904_GPIO_REGS]; u32 mic_cfg[WM8904_MIC_REGS]; }; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 2082ff12d336..bac54c8e45a9 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2168,6 +2168,184 @@ static const struct of_device_id wm8904_of_match[] = { MODULE_DEVICE_TABLE(of, wm8904_of_match); #endif +/** + * wm8904_read_cfg_reg_arr() - Reads a subarray from a DT u16 array + * + * @np: pointer to the device_node struct + * @regs_property: DT property of interest + * @size: size of subarrays within the array + * @idx: index of the subarray of interest + * @out: output + * + * Helper to read a subarray from a DT uint16-array, + * divided into equally sized arrays of size `size` + * + * Subset starts at `idx * size` and is of size `size` + * + * Return: 0 on success, negative error code otherwise + */ +static int wm8904_read_cfg_reg_arr(const struct device_node *np, + const char * const regs_property, + int size, int idx, + u16 * const out) +{ + int i, offset, ret; + + offset = idx * size; + + for (i = 0; i < size; i++) { + ret = of_property_read_u16_index(np, regs_property, i + offset, &out[i]); + if (ret) + return ret; + } + return 0; +} + +static int wm8904_parse_retune_cfg_regs(const struct device_node *np, + struct wm8904_pdata *pdata, int cfg_idx) +{ + return wm8904_read_cfg_reg_arr(np, "wlf,retune-mobile-cfg-regs", + WM8904_EQ_REGS, cfg_idx, + &pdata->retune_mobile_cfgs[cfg_idx].regs[0]); +} + +static int wm8904_parse_drc_cfg_regs(const struct device_node *np, + struct wm8904_pdata *pdata, int cfg_idx) +{ + return wm8904_read_cfg_reg_arr(np, "wlf,drc-cfg-regs", + WM8904_DRC_REGS, cfg_idx, + &pdata->drc_cfgs[cfg_idx].regs[0]); +} + +static int wm8904_parse_drc_cfg_from_of(struct i2c_client *i2c, + struct wm8904_pdata *pdata) +{ + const struct device_node *np = i2c->dev.of_node; + int i, n_cfgs; + + n_cfgs = of_property_count_strings(np, "wlf,drc-cfg-names"); + if (n_cfgs == -EINVAL) + return 0; + + if (n_cfgs <= 0) { + dev_err(&i2c->dev, "Could not get wlf,drc-cfg-names length: %d", + n_cfgs); + return n_cfgs; + } + + pdata->drc_cfgs = devm_kzalloc(&i2c->dev, + n_cfgs * sizeof(struct wm8904_drc_cfg), + GFP_KERNEL); + if (!pdata->drc_cfgs) + return -ENOMEM; + + for (i = 0; i < n_cfgs; i++) { + if (wm8904_parse_drc_cfg_regs(np, pdata, i)) { + dev_err(&i2c->dev, + "Invalid 'wlf,drc-cfg-regs[%i,:]'\n", i); + return -EINVAL; + } + + if (of_property_read_string_index(np, "wlf,drc-cfg-names", i, + &pdata->drc_cfgs[i].name)) { + dev_err(&i2c->dev, + "Invalid 'wlf,drc-cfg-names[%i]'\n", i); + return -EINVAL; + } + } + + pdata->num_drc_cfgs = n_cfgs; + return 0; +} + +static int wm8904_parse_retune_cfg_from_of(struct i2c_client *i2c, + struct wm8904_pdata *pdata) +{ + const struct device_node *np = i2c->dev.of_node; + int i, n_cfgs; + + n_cfgs = of_property_count_strings(np, "wlf,retune-mobile-cfg-names"); + if (n_cfgs == -EINVAL) + return 0; + + if (n_cfgs <= 0) { + dev_err(&i2c->dev, + "Could not get wlf,retune-mobile-cfg-names length: %d", + n_cfgs); + return n_cfgs; + } + + pdata->retune_mobile_cfgs = devm_kzalloc(&i2c->dev, + n_cfgs * sizeof(struct wm8904_retune_mobile_cfg), + GFP_KERNEL); + if (!pdata->retune_mobile_cfgs) + return -ENOMEM; + + for (i = 0; i < n_cfgs; i++) { + if (wm8904_parse_retune_cfg_regs(np, pdata, i)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-regs[%i,:]'\n", i); + return -EINVAL; + } + + if (of_property_read_u32_index(np, "wlf,retune-mobile-cfg-hz", i, + &pdata->retune_mobile_cfgs[i].rate)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-hz[%i]'\n", i); + return -EINVAL; + } + + if (of_property_read_string_index(np, "wlf,retune-mobile-cfg-names", i, + &pdata->retune_mobile_cfgs[i].name)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-names[%i]'\n", i); + return -EINVAL; + } + } + + pdata->num_retune_mobile_cfgs = n_cfgs; + return 0; +} + +static int wm8904_set_pdata_from_of(struct i2c_client *i2c, + struct wm8904_priv *wm8904) +{ + const struct device_node *np = i2c->dev.of_node; + struct wm8904_pdata *pdata; + int ret, i; + + pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->in1l_as_dmicdat1 = + of_property_read_bool(np, "wlf,in1l-as-dmicdat1"); + + pdata->in1r_as_dmicdat2 = + of_property_read_bool(np, "wlf,in1r-as-dmicdat2"); + + /* If absent, default to 0xFFFF for GPIO config (i.e.: don't set) */ + for (i = 0; i < WM8904_GPIO_REGS; i++) + pdata->gpio_cfg[i] = 0xFFFF; + + of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg, + ARRAY_SIZE(pdata->gpio_cfg)); + + of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->mic_cfg, + ARRAY_SIZE(pdata->mic_cfg)); + + ret = wm8904_parse_drc_cfg_from_of(i2c, pdata); + if (ret) + return ret; + + ret = wm8904_parse_retune_cfg_from_of(i2c, pdata); + if (ret) + return ret; + + wm8904->pdata = pdata; + return 0; +} + static const struct i2c_device_id wm8904_i2c_id[]; static int wm8904_i2c_probe(struct i2c_client *i2c) @@ -2199,7 +2377,16 @@ static int wm8904_i2c_probe(struct i2c_client *i2c) wm8904->devtype = (uintptr_t)i2c_get_match_data(i2c); i2c_set_clientdata(i2c, wm8904); - wm8904->pdata = i2c->dev.platform_data; + + if (i2c->dev.of_node) { + ret = wm8904_set_pdata_from_of(i2c, wm8904); + if (ret) { + dev_err(&i2c->dev, "Failed to set platform data from of: %d\n", ret); + return ret; + } + } else { + wm8904->pdata = i2c->dev.platform_data; + } for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) wm8904->supplies[i].supply = wm8904_supply_names[i]; From b6612c8fc3a2c279196050ecc13c77a7863d83eb Mon Sep 17 00:00:00 2001 From: Ernest Van Hoecke Date: Wed, 19 Mar 2025 15:20:59 +0100 Subject: [PATCH 1086/1090] ASoC: wm8904: add DMIC support The WM8904 codec supports both ADC and DMIC inputs. Get input pin functionality from the platform data and add the necessary controls depending on the possible additional routing. The ADC and DMIC share the IN1L/DMICDAT1 and IN1R/DMICDAT2 pins. This leads to a few scenarios requiring different DAPM routing: - When both are connected to an analog input, only the ADC is used. - When one line is a DMIC and the other an analog input, the DMIC source is set from the platform data and a mux is added to select whether to use the ADC or DMIC. - When both are connected to a DMIC, another mux is added to this to select the DMIC source. Note that we still need to be able to select the ADC system for use with the IN2L, IN2R, IN3L and IN3R pins. Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250319142059.46692-6-francesco@dolcini.it Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 125 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index bac54c8e45a9..1c49e600eb6f 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -844,6 +844,26 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, return 0; } +static const char * const dmic_text[] = { + "DMIC1", "DMIC2" +}; + +static SOC_ENUM_SINGLE_DECL(dmic_enum, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_SRC_SHIFT, dmic_text); + +static const struct snd_kcontrol_new dmic_mux = + SOC_DAPM_ENUM("DMIC Mux", dmic_enum); + +static const char * const cin_text[] = { + "ADC", "DMIC" +}; + +static SOC_ENUM_SINGLE_DECL(cin_enum, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_ENA_SHIFT, cin_text); + +static const struct snd_kcontrol_new cin_mux = + SOC_DAPM_ENUM("Capture Input", cin_enum); + static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; @@ -963,6 +983,15 @@ SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), }; +static const struct snd_soc_dapm_widget wm8904_dmic_dapm_widgets[] = { +SND_SOC_DAPM_MUX("DMIC Mux", SND_SOC_NOPM, 0, 0, &dmic_mux), +}; + +static const struct snd_soc_dapm_widget wm8904_cin_dapm_widgets[] = { +SND_SOC_DAPM_MUX("Left Capture Input", SND_SOC_NOPM, 0, 0, &cin_mux), +SND_SOC_DAPM_MUX("Right Capture Input", SND_SOC_NOPM, 0, 0, &cin_mux), +}; + static const struct snd_soc_dapm_widget wm8904_dac_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), @@ -1101,12 +1130,45 @@ static const struct snd_soc_dapm_route adc_intercon[] = { { "AIFOUTR", NULL, "AIFOUTR Mux" }, { "ADCL", NULL, "CLK_DSP" }, - { "ADCL", NULL, "Left Capture PGA" }, - { "ADCR", NULL, "CLK_DSP" }, +}; + +/* No DMICs, always connect PGAs */ +static const struct snd_soc_dapm_route cin_nodmic_con[] = { + { "ADCL", NULL, "Left Capture PGA" }, { "ADCR", NULL, "Right Capture PGA" }, }; +/* DMIC system in use: mux between ADC and DMICDAT1, 2 or both */ +static const struct snd_soc_dapm_route cin_adc_dmic_con[] = { + { "Left Capture Input", "ADC", "Left Capture PGA" }, + { "Right Capture Input", "ADC", "Right Capture PGA" }, + + { "ADCL", NULL, "Left Capture Input" }, + { "ADCR", NULL, "Right Capture Input" }, +}; + +/* IN1L as DMICDAT1 */ +static const struct snd_soc_dapm_route cin_dmic1_con[] = { + { "Left Capture Input", "DMIC", "IN1L" }, + { "Right Capture Input", "DMIC", "IN1L" }, +}; + +/* IN1R as DMICDAT2 */ +static const struct snd_soc_dapm_route cin_dmic2_con[] = { + { "Left Capture Input", "DMIC", "IN1R" }, + { "Right Capture Input", "DMIC", "IN1R" }, +}; + +/* DMICDAT1 and DMICDAT2: mux between them, ADC still used for IN2 and IN3 */ +static const struct snd_soc_dapm_route cin_2dmics_con[] = { + { "DMIC Mux", "DMIC1", "IN1L" }, + { "DMIC Mux", "DMIC2", "IN1R" }, + + { "Left Capture Input", "DMIC", "DMIC Mux" }, + { "Right Capture Input", "DMIC", "DMIC Mux" }, +}; + static const struct snd_soc_dapm_route dac_intercon[] = { { "DACL Mux", "Left", "AIFINL" }, { "DACL Mux", "Right", "AIFINR" }, @@ -2050,18 +2112,70 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_component *componen "Failed to add ReTune Mobile control: %d\n", ret); } +static void wm8904_handle_dmic_pdata(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component); + struct wm8904_pdata *pdata = wm8904->pdata; + unsigned int dmic_src; + + if (!pdata->in1l_as_dmicdat1 && !pdata->in1r_as_dmicdat2) { + snd_soc_dapm_add_routes(dapm, cin_nodmic_con, + ARRAY_SIZE(cin_nodmic_con)); + snd_soc_component_update_bits(component, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_ENA_MASK, 0); + return; + } + + /* Need a control and routing to switch between DMIC and ADC */ + snd_soc_dapm_new_controls(dapm, wm8904_cin_dapm_widgets, + ARRAY_SIZE(wm8904_cin_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cin_adc_dmic_con, + ARRAY_SIZE(cin_adc_dmic_con)); + + if (pdata->in1l_as_dmicdat1 && pdata->in1r_as_dmicdat2) { + /* Need a control and routing to mux between DMICDAT1 and 2 */ + dev_dbg(component->dev, "DMICDAT1 and DMICDAT2 in use\n"); + snd_soc_dapm_new_controls(dapm, wm8904_dmic_dapm_widgets, + ARRAY_SIZE(wm8904_dmic_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cin_2dmics_con, + ARRAY_SIZE(cin_2dmics_con)); + return; + } + + /* Either DMICDAT1 or DMICDAT2 is in use, not both */ + if (pdata->in1l_as_dmicdat1) { + dmic_src = 0; + snd_soc_dapm_add_routes(dapm, cin_dmic1_con, + ARRAY_SIZE(cin_dmic1_con)); + } else { + dmic_src = 1; + snd_soc_dapm_add_routes(dapm, cin_dmic2_con, + ARRAY_SIZE(cin_dmic2_con)); + } + dev_dbg(component->dev, "DMIC_SRC (0 or 1): %d\n", dmic_src); + snd_soc_component_update_bits(component, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_SRC_MASK, + dmic_src << WM8904_DMIC_SRC_SHIFT); +} + static void wm8904_handle_pdata(struct snd_soc_component *component) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component); struct wm8904_pdata *pdata = wm8904->pdata; int ret, i; if (!pdata) { + snd_soc_dapm_add_routes(dapm, cin_nodmic_con, + ARRAY_SIZE(cin_nodmic_con)); snd_soc_add_component_controls(component, wm8904_eq_controls, - ARRAY_SIZE(wm8904_eq_controls)); + ARRAY_SIZE(wm8904_eq_controls)); return; } + wm8904_handle_dmic_pdata(component); + dev_dbg(component->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); if (pdata->num_drc_cfgs) { @@ -2117,10 +2231,11 @@ static int wm8904_probe(struct snd_soc_component *component) return -EINVAL; } - wm8904_handle_pdata(component); - wm8904_add_widgets(component); + /* This can add dependent widgets, so it is done after add_widgets */ + wm8904_handle_pdata(component); + return 0; } From 6271b746e40ebaf24dc54be5f4248f5a61618871 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 19 Mar 2025 09:56:31 -0500 Subject: [PATCH 1087/1090] ASoC: dmic: Fix NULL pointer dereference Regulator support was introduced in commit d3321a20b5111 ("ASoC: dmic: add regulator support"). During probe `dmic->vref` is initialized with devm_regulator_get_optional() but in the error flow doesn't get cleared in the case that PTR_ERR(dmic->vref) is -ENODEV. This leads to the following NULL pointer deref. ``` Oops: Oops: 0000 [#1] SMP NOPTI CPU: 7 UID: 1000 PID: 1587 Comm: wireplumber Not tainted 6.14.0-rc7-next-20250318 #1 PREEMPT(voluntary) RIP: 0010:regulator_enable+0x17/0x70 RSP: 0018:ffffcc10c1fe7a38 EFLAGS: 00010282 RAX: ffff8bccc1c25010 RBX: ffffffffffffffed RCX: 0000000000000000 RDX: 0000000000000002 RSI: ffffcc10c1fe7a38 RDI: ffffffffffffffed RBP: ffffcc10c1fe7a68 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8bcccd51f800 R13: ffffffffc1086e88 R14: 0000000000000001 R15: 0000000000000001 FS: 00007f927bc35800(0000) GS:ffff8bd44f09f000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000065 CR3: 00000001332c6000 CR4: 0000000000750ef0 PKRU: 55555554 Call Trace: ? show_regs+0x6c/0x80 ? __die+0x24/0x80 ? page_fault_oops+0x154/0x570 ? hrtimer_start_range_ns+0x142/0x4e0 ? timerqueue_del+0x31/0x50 ? do_user_addr_fault+0x4ac/0x880 ? exc_page_fault+0x82/0x1d0 ? asm_exc_page_fault+0x27/0x30 ? regulator_enable+0x17/0x70 ? __schedule+0x491/0x16b0 dmic_aif_event+0x82/0xa0 [snd_soc_dmic] ``` Adjust the error flow to explicitly set it back to NULL to avoid calling regulator_enable() with garbage data. Reported-by: Akshata V Unkal Fixes: d3321a20b5111 ("ASoC: dmic: add regulator support") Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250319145636.2401680-1-superm1@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/dmic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index 5d3c3f17c6d8..61e1bf1b3c9e 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c @@ -114,8 +114,12 @@ static int dmic_component_probe(struct snd_soc_component *component) return -ENOMEM; dmic->vref = devm_regulator_get_optional(component->dev, "vref"); - if (IS_ERR(dmic->vref) && PTR_ERR(dmic->vref) != -ENODEV) - return dev_err_probe(component->dev, PTR_ERR(dmic->vref), "Failed to get vref\n"); + if (IS_ERR(dmic->vref)) { + if (PTR_ERR(dmic->vref) != -ENODEV) + return dev_err_probe(component->dev, PTR_ERR(dmic->vref), + "Failed to get vref\n"); + dmic->vref = NULL; + } dmic->gpio_en = devm_gpiod_get_optional(component->dev, "dmicen", GPIOD_OUT_LOW); From 24489150c5d9afea54c6909ba05c4dbdd8846dc0 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 20 Mar 2025 12:53:00 +0100 Subject: [PATCH 1088/1090] ASoC: SOF: mediatek: Commonize duplicated functions In order to reduce duplication, move the ADSP mailbox callbacks handle_reply(), handle_request(), and other common SOF callbacks send_msg(), get_bar_index(), pcm_hw_params() and pcm_pointer() to the mtk-adsp-common.c file. This cleanup brings no functional differences. Signed-off-by: AngeloGioacchino Del Regno Link: https://patch.msgid.link/20250320115300.137410-1-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8186/mt8186.c | 105 ++---------------- sound/soc/sof/mediatek/mt8195/mt8195.c | 105 ++---------------- sound/soc/sof/mediatek/mtk-adsp-common.c | 130 +++++++++++++++++++++++ sound/soc/sof/mediatek/mtk-adsp-common.h | 10 ++ 4 files changed, 152 insertions(+), 198 deletions(-) diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c index 18144d9504e1..7ff080452cbe 100644 --- a/sound/soc/sof/mediatek/mt8186/mt8186.c +++ b/sound/soc/sof/mediatek/mt8186/mt8186.c @@ -22,7 +22,6 @@ #include #include "../../ops.h" #include "../../sof-of-dev.h" -#include "../../sof-audio.h" #include "../adsp_helper.h" #include "../mtk-adsp-common.h" #include "mt8186.h" @@ -38,53 +37,9 @@ static int mt8186_get_window_offset(struct snd_sof_dev *sdev, u32 id) return MBOX_OFFSET; } -static int mt8186_send_msg(struct snd_sof_dev *sdev, - struct snd_sof_ipc_msg *msg) -{ - struct adsp_priv *priv = sdev->pdata->hw_pdata; - - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - - return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ); -} - -static void mt8186_dsp_handle_reply(struct mtk_adsp_ipc *ipc) -{ - struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); - unsigned long flags; - - spin_lock_irqsave(&priv->sdev->ipc_lock, flags); - snd_sof_ipc_process_reply(priv->sdev, 0); - spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); -} - -static void mt8186_dsp_handle_request(struct mtk_adsp_ipc *ipc) -{ - struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); - u32 p; /* panic code */ - int ret; - - /* Read the message from the debug box. */ - sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, - &p, sizeof(p)); - - /* Check to see if the message is a panic code 0x0dead*** */ - if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { - snd_sof_dsp_panic(priv->sdev, p, true); - } else { - snd_sof_ipc_msgs_rx(priv->sdev); - - /* tell DSP cmd is done */ - ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP); - if (ret) - dev_err(priv->dev, "request send ipc failed"); - } -} - static const struct mtk_adsp_ipc_ops dsp_ops = { - .handle_reply = mt8186_dsp_handle_reply, - .handle_request = mt8186_dsp_handle_request, + .handle_reply = mtk_adsp_handle_reply, + .handle_request = mtk_adsp_handle_request, }; static int platform_parse_resource(struct platform_device *pdev, void *data) @@ -381,54 +336,6 @@ static int mt8186_dsp_resume(struct snd_sof_dev *sdev) return ret; } -/* on mt8186 there is 1 to 1 match between type and BAR idx */ -static int mt8186_get_bar_index(struct snd_sof_dev *sdev, u32 type) -{ - return type; -} - -static int mt8186_pcm_hw_params(struct snd_sof_dev *sdev, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_sof_platform_stream_params *platform_params) -{ - platform_params->cont_update_posn = 1; - - return 0; -} - -static snd_pcm_uframes_t mt8186_pcm_pointer(struct snd_sof_dev *sdev, - struct snd_pcm_substream *substream) -{ - int ret; - snd_pcm_uframes_t pos; - struct snd_sof_pcm *spcm; - struct sof_ipc_stream_posn posn; - struct snd_sof_pcm_stream *stream; - struct snd_soc_component *scomp = sdev->component; - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - - spcm = snd_sof_find_spcm_dai(scomp, rtd); - if (!spcm) { - dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", - rtd->dai_link->id); - return 0; - } - - stream = &spcm->stream[substream->stream]; - ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); - if (ret < 0) { - dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); - return 0; - } - - memcpy(&stream->posn, &posn, sizeof(posn)); - pos = spcm->stream[substream->stream].posn.host_posn; - pos = bytes_to_frames(substream->runtime, pos); - - return pos; -} - static void mt8186_adsp_dump(struct snd_sof_dev *sdev, u32 flags) { u32 dbg_pc, dbg_data, dbg_inst, dbg_ls0stat, dbg_status, faultinfo; @@ -505,19 +412,19 @@ static const struct snd_sof_dsp_ops sof_mt8186_ops = { .read64 = sof_io_read64, /* ipc */ - .send_msg = mt8186_send_msg, + .send_msg = mtk_adsp_send_msg, .get_mailbox_offset = mt8186_get_mailbox_offset, .get_window_offset = mt8186_get_window_offset, .ipc_msg_data = sof_ipc_msg_data, .set_stream_data_offset = sof_set_stream_data_offset, /* misc */ - .get_bar_index = mt8186_get_bar_index, + .get_bar_index = mtk_adsp_get_bar_index, /* stream callbacks */ .pcm_open = sof_stream_pcm_open, - .pcm_hw_params = mt8186_pcm_hw_params, - .pcm_pointer = mt8186_pcm_pointer, + .pcm_hw_params = mtk_adsp_stream_pcm_hw_params, + .pcm_pointer = mtk_adsp_stream_pcm_pointer, .pcm_close = sof_stream_pcm_close, /* firmware loading */ diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 821f43a3974a..3b3582d74510 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -22,7 +22,6 @@ #include #include "../../ops.h" #include "../../sof-of-dev.h" -#include "../../sof-audio.h" #include "../adsp_helper.h" #include "../mtk-adsp-common.h" #include "mt8195.h" @@ -38,53 +37,9 @@ static int mt8195_get_window_offset(struct snd_sof_dev *sdev, u32 id) return MBOX_OFFSET; } -static int mt8195_send_msg(struct snd_sof_dev *sdev, - struct snd_sof_ipc_msg *msg) -{ - struct adsp_priv *priv = sdev->pdata->hw_pdata; - - sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, - msg->msg_size); - - return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ); -} - -static void mt8195_dsp_handle_reply(struct mtk_adsp_ipc *ipc) -{ - struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); - unsigned long flags; - - spin_lock_irqsave(&priv->sdev->ipc_lock, flags); - snd_sof_ipc_process_reply(priv->sdev, 0); - spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); -} - -static void mt8195_dsp_handle_request(struct mtk_adsp_ipc *ipc) -{ - struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); - u32 p; /* panic code */ - int ret; - - /* Read the message from the debug box. */ - sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, - &p, sizeof(p)); - - /* Check to see if the message is a panic code 0x0dead*** */ - if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { - snd_sof_dsp_panic(priv->sdev, p, true); - } else { - snd_sof_ipc_msgs_rx(priv->sdev); - - /* tell DSP cmd is done */ - ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP); - if (ret) - dev_err(priv->dev, "request send ipc failed"); - } -} - static const struct mtk_adsp_ipc_ops dsp_ops = { - .handle_reply = mt8195_dsp_handle_reply, - .handle_request = mt8195_dsp_handle_request, + .handle_reply = mtk_adsp_handle_reply, + .handle_request = mtk_adsp_handle_request, }; static int platform_parse_resource(struct platform_device *pdev, void *data) @@ -400,54 +355,6 @@ static int mt8195_dsp_resume(struct snd_sof_dev *sdev) return ret; } -/* on mt8195 there is 1 to 1 match between type and BAR idx */ -static int mt8195_get_bar_index(struct snd_sof_dev *sdev, u32 type) -{ - return type; -} - -static int mt8195_pcm_hw_params(struct snd_sof_dev *sdev, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_sof_platform_stream_params *platform_params) -{ - platform_params->cont_update_posn = 1; - - return 0; -} - -static snd_pcm_uframes_t mt8195_pcm_pointer(struct snd_sof_dev *sdev, - struct snd_pcm_substream *substream) -{ - int ret; - snd_pcm_uframes_t pos; - struct snd_sof_pcm *spcm; - struct sof_ipc_stream_posn posn; - struct snd_sof_pcm_stream *stream; - struct snd_soc_component *scomp = sdev->component; - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - - spcm = snd_sof_find_spcm_dai(scomp, rtd); - if (!spcm) { - dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", - rtd->dai_link->id); - return 0; - } - - stream = &spcm->stream[substream->stream]; - ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); - if (ret < 0) { - dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); - return 0; - } - - memcpy(&stream->posn, &posn, sizeof(posn)); - pos = spcm->stream[substream->stream].posn.host_posn; - pos = bytes_to_frames(substream->runtime, pos); - - return pos; -} - static void mt8195_adsp_dump(struct snd_sof_dev *sdev, u32 flags) { u32 dbg_pc, dbg_data, dbg_bus0, dbg_bus1, dbg_inst; @@ -529,19 +436,19 @@ static const struct snd_sof_dsp_ops sof_mt8195_ops = { .read64 = sof_io_read64, /* ipc */ - .send_msg = mt8195_send_msg, + .send_msg = mtk_adsp_send_msg, .get_mailbox_offset = mt8195_get_mailbox_offset, .get_window_offset = mt8195_get_window_offset, .ipc_msg_data = sof_ipc_msg_data, .set_stream_data_offset = sof_set_stream_data_offset, /* misc */ - .get_bar_index = mt8195_get_bar_index, + .get_bar_index = mtk_adsp_get_bar_index, /* stream callbacks */ .pcm_open = sof_stream_pcm_open, - .pcm_hw_params = mt8195_pcm_hw_params, - .pcm_pointer = mt8195_pcm_pointer, + .pcm_hw_params = mtk_adsp_stream_pcm_hw_params, + .pcm_pointer = mtk_adsp_stream_pcm_pointer, .pcm_close = sof_stream_pcm_close, /* firmware loading */ diff --git a/sound/soc/sof/mediatek/mtk-adsp-common.c b/sound/soc/sof/mediatek/mtk-adsp-common.c index 20bcf5590eb8..01bbadb160ff 100644 --- a/sound/soc/sof/mediatek/mtk-adsp-common.c +++ b/sound/soc/sof/mediatek/mtk-adsp-common.c @@ -12,8 +12,11 @@ */ #include +#include #include #include "../ops.h" +#include "../sof-audio.h" +#include "adsp_helper.h" #include "mtk-adsp-common.h" /** @@ -81,5 +84,132 @@ void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags) } EXPORT_SYMBOL(mtk_adsp_dump); +/** + * mtk_adsp_send_msg - Send message to Audio DSP + * @sdev: SOF device + * @msg: SOF IPC Message to send + */ +int mtk_adsp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) +{ + struct adsp_priv *priv = sdev->pdata->hw_pdata; + + sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, + msg->msg_size); + + return mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_REQ, MTK_ADSP_IPC_OP_REQ); +} +EXPORT_SYMBOL(mtk_adsp_send_msg); + +/** + * mtk_adsp_handle_reply - Handle reply from the Audio DSP through Mailbox + * @ipc: ADSP IPC handle + */ +void mtk_adsp_handle_reply(struct mtk_adsp_ipc *ipc) +{ + struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); + unsigned long flags; + + spin_lock_irqsave(&priv->sdev->ipc_lock, flags); + snd_sof_ipc_process_reply(priv->sdev, 0); + spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags); +} +EXPORT_SYMBOL(mtk_adsp_handle_reply); + +/** + * mtk_adsp_handle_request - Handle request from the Audio DSP through Mailbox + * @ipc: ADSP IPC handle + */ +void mtk_adsp_handle_request(struct mtk_adsp_ipc *ipc) +{ + struct adsp_priv *priv = mtk_adsp_ipc_get_data(ipc); + u32 panic_code; + int ret; + + /* Read the message from the debug box. */ + sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, + &panic_code, sizeof(panic_code)); + + /* Check to see if the message is a panic code 0x0dead*** */ + if ((panic_code & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { + snd_sof_dsp_panic(priv->sdev, panic_code, true); + } else { + snd_sof_ipc_msgs_rx(priv->sdev); + + /* Tell DSP cmd is done */ + ret = mtk_adsp_ipc_send(priv->dsp_ipc, MTK_ADSP_IPC_RSP, MTK_ADSP_IPC_OP_RSP); + if (ret) + dev_err(priv->dev, "request send ipc failed"); + } +} +EXPORT_SYMBOL(mtk_adsp_handle_request); + +/** + * mtk_adsp_get_bar_index - Map section type with BAR idx + * @sdev: SOF device + * @type: Section type as described by snd_sof_fw_blk_type + * + * MediaTek Audio DSPs have a 1:1 match between type and BAR idx + */ +int mtk_adsp_get_bar_index(struct snd_sof_dev *sdev, u32 type) +{ + return type; +} +EXPORT_SYMBOL(mtk_adsp_get_bar_index); + +/** + * mtk_adsp_stream_pcm_hw_params - Platform specific host stream hw params + * @sdev: SOF device + * @substream: PCM Substream + * @params: hw params + * @platform_params: Platform specific SOF stream parameters + */ +int mtk_adsp_stream_pcm_hw_params(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_sof_platform_stream_params *platform_params) +{ + platform_params->cont_update_posn = 1; + return 0; +} +EXPORT_SYMBOL(mtk_adsp_stream_pcm_hw_params); + +/** + * mtk_adsp_stream_pcm_pointer - Get host stream pointer + * @sdev: SOF device + * @substream: PCM substream + */ +snd_pcm_uframes_t mtk_adsp_stream_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_component *scomp = sdev->component; + struct snd_sof_pcm_stream *stream; + struct sof_ipc_stream_posn posn; + struct snd_sof_pcm *spcm; + snd_pcm_uframes_t pos; + int ret; + + spcm = snd_sof_find_spcm_dai(scomp, rtd); + if (!spcm) { + dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", + rtd->dai_link->id); + return 0; + } + + stream = &spcm->stream[substream->stream]; + ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); + if (ret < 0) { + dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); + return 0; + } + + memcpy(&stream->posn, &posn, sizeof(posn)); + pos = spcm->stream[substream->stream].posn.host_posn; + pos = bytes_to_frames(substream->runtime, pos); + + return pos; +} +EXPORT_SYMBOL(mtk_adsp_stream_pcm_pointer); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("SOF helpers for MTK ADSP platforms"); diff --git a/sound/soc/sof/mediatek/mtk-adsp-common.h b/sound/soc/sof/mediatek/mtk-adsp-common.h index 612cff1f38f7..dc36b91d6779 100644 --- a/sound/soc/sof/mediatek/mtk-adsp-common.h +++ b/sound/soc/sof/mediatek/mtk-adsp-common.h @@ -7,4 +7,14 @@ #define MTK_ADSP_STACK_DUMP_SIZE 32 void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags); +int mtk_adsp_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg); +void mtk_adsp_handle_reply(struct mtk_adsp_ipc *ipc); +void mtk_adsp_handle_request(struct mtk_adsp_ipc *ipc); +int mtk_adsp_get_bar_index(struct snd_sof_dev *sdev, u32 type); +int mtk_adsp_stream_pcm_hw_params(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_sof_platform_stream_params *platform_params); +snd_pcm_uframes_t mtk_adsp_stream_pcm_pointer(struct snd_sof_dev *sdev, + struct snd_pcm_substream *substream); #endif From 5a4dd520ef8a94ecf81ac77b90d6a03e91c100a9 Mon Sep 17 00:00:00 2001 From: Syed Saba kareem Date: Fri, 21 Mar 2025 17:55:03 +0530 Subject: [PATCH 1089/1090] ASoC: amd: yc: update quirk data for new Lenovo model Update Quirk data for new Lenovo model 83J2 for YC platform. Signed-off-by: Syed Saba kareem Link: https://patch.msgid.link/20250321122507.190193-1-syed.sabakareem@amd.com Reported-by: Reiner Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219887 Tested-by: Reiner Reviewed-by: Mario Limonciello Signed-off-by: Mark Brown --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index a7637056972a..eded178f0b13 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -339,6 +339,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83J2"), + } + }, { .driver_data = &acp6x_card, .matches = { From 9ef52d529bb75071e03cf85078f724d69c4abe89 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 21 Mar 2025 13:53:24 +0000 Subject: [PATCH 1090/1090] ASoC: SDCA: Correct handling of selected mode DisCo property mipi-sdca-ge-selectedmode-controls-affected is actually required by the specification so the code should return an error if it is missing. Reported-by: Maciej Strozek Fixes: 13fe7497af19 ("ASoC: SDCA: Add support for GE Entity properties") Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250321135324.380237-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index c8efdc5301b5..493f390f087a 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -1159,7 +1159,7 @@ static int find_sdca_entity_ge(struct device *dev, num_affected = fwnode_property_count_u8(entity_node, "mipi-sdca-ge-selectedmode-controls-affected"); - if (!num_affected || num_affected == -EINVAL) { + if (!num_affected) { return 0; } else if (num_affected < 0) { dev_err(dev, "%s: failed to read affected controls: %d\n",