From: Greg Kroah-Hartman Date: Thu, 20 Aug 2020 08:44:00 +0000 (+0200) Subject: 5.7-stable patches X-Git-Tag: v4.14.194~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=635001dae845f5d98c70761684863ba52720f609;p=thirdparty%2Fkernel%2Fstable-queue.git 5.7-stable patches added patches: asoc-tegra-add-audio-mclk-parent-configuration.patch asoc-tegra-enable-audio-mclk-during-tegra_asoc_utils_init.patch asoc-tegra-use-device-managed-resource-apis-to-get-the-clock.patch drm-added-orientation-quirk-for-asus-tablet-model-t103haf.patch drm-amd-display-dchubbub-p-state-warning-during-surface-planes-switch.patch drm-amd-display-fix-dmesg-warning-from-setting-abm-level.patch drm-amdgpu-fix-bug-where-dpm-is-not-enabled-after-hibernate-and-resume.patch drm-amdgpu-fix-ordering-of-psp-suspend.patch drm-dp_mst-fix-the-ddc-i2c-device-registration-of-an-mst-port.patch drm-fix-drm_dp_mst_port-refcount-leaks-in-drm_dp_mst_allocate_vcpi.patch drm-i915-gt-force-the-gt-reset-on-shutdown.patch drm-omap-force-runtime-pm-suspend-on-system-suspend.patch drm-panfrost-use-kvfree-to-free-bo-sgts.patch drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch drm-tidss-fix-modeset-init-for-dpi-panels.patch khugepaged-retract_page_tables-remember-to-test-exit.patch --- diff --git a/queue-5.7/asoc-tegra-add-audio-mclk-parent-configuration.patch b/queue-5.7/asoc-tegra-add-audio-mclk-parent-configuration.patch new file mode 100644 index 00000000000..9c2a40d0048 --- /dev/null +++ b/queue-5.7/asoc-tegra-add-audio-mclk-parent-configuration.patch @@ -0,0 +1,145 @@ +From 1e4e0bf136aa4b4aa59c1e6af19844bd6d807794 Mon Sep 17 00:00:00 2001 +From: Sowjanya Komatineni +Date: Mon, 13 Jan 2020 23:24:23 -0800 +Subject: ASoC: tegra: Add audio mclk parent configuration + +From: Sowjanya Komatineni + +commit 1e4e0bf136aa4b4aa59c1e6af19844bd6d807794 upstream. + +Tegra PMC clock clk_out_1 is dedicated for audio mclk from Tegra30 +through Tegra210 and currently Tegra clock driver does the initial +parent configuration for audio mclk and keeps it enabled by default. + +With the move of PMC clocks from clock driver into PMC driver, audio +clocks parent configuration can be specified through the device tree +using assigned-clock-parents property and audio mclk control should be +taken care of by the audio driver. + +This patch has implementation for parent configuration when default +parent configuration through assigned-clock-parents property is not +specified in the device tree. + +Tested-by: Dmitry Osipenko +Reviewed-by: Dmitry Osipenko +Reviewed-by: Sameer Pujar +Signed-off-by: Sowjanya Komatineni +Signed-off-by: Thierry Reding +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/tegra/tegra_asoc_utils.c | 68 +++++++++++++++++++++---------------- + 1 file changed, 40 insertions(+), 28 deletions(-) + +--- a/sound/soc/tegra/tegra_asoc_utils.c ++++ b/sound/soc/tegra/tegra_asoc_utils.c +@@ -60,8 +60,6 @@ int tegra_asoc_utils_set_rate(struct teg + data->set_mclk = 0; + + clk_disable_unprepare(data->clk_cdev1); +- clk_disable_unprepare(data->clk_pll_a_out0); +- clk_disable_unprepare(data->clk_pll_a); + + err = clk_set_rate(data->clk_pll_a, new_baseclock); + if (err) { +@@ -77,18 +75,6 @@ int tegra_asoc_utils_set_rate(struct teg + + /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ + +- err = clk_prepare_enable(data->clk_pll_a); +- if (err) { +- dev_err(data->dev, "Can't enable pll_a: %d\n", err); +- return err; +- } +- +- err = clk_prepare_enable(data->clk_pll_a_out0); +- if (err) { +- dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); +- return err; +- } +- + err = clk_prepare_enable(data->clk_cdev1); + if (err) { + dev_err(data->dev, "Can't enable cdev1: %d\n", err); +@@ -109,8 +95,6 @@ int tegra_asoc_utils_set_ac97_rate(struc + int err; + + clk_disable_unprepare(data->clk_cdev1); +- clk_disable_unprepare(data->clk_pll_a_out0); +- clk_disable_unprepare(data->clk_pll_a); + + /* + * AC97 rate is fixed at 24.576MHz and is used for both the host +@@ -130,18 +114,6 @@ int tegra_asoc_utils_set_ac97_rate(struc + + /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */ + +- err = clk_prepare_enable(data->clk_pll_a); +- if (err) { +- dev_err(data->dev, "Can't enable pll_a: %d\n", err); +- return err; +- } +- +- err = clk_prepare_enable(data->clk_pll_a_out0); +- if (err) { +- dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); +- return err; +- } +- + err = clk_prepare_enable(data->clk_cdev1); + if (err) { + dev_err(data->dev, "Can't enable cdev1: %d\n", err); +@@ -158,6 +130,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_a + int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, + struct device *dev) + { ++ struct clk *clk_out_1, *clk_extern1; + int ret; + + data->dev = dev; +@@ -193,6 +166,45 @@ int tegra_asoc_utils_init(struct tegra_a + return PTR_ERR(data->clk_cdev1); + } + ++ /* ++ * If clock parents are not set in DT, configure here to use clk_out_1 ++ * as mclk and extern1 as parent for Tegra30 and higher. ++ */ ++ if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) && ++ data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) { ++ dev_warn(data->dev, ++ "Configuring clocks for a legacy device-tree\n"); ++ dev_warn(data->dev, ++ "Please update DT to use assigned-clock-parents\n"); ++ clk_extern1 = devm_clk_get(dev, "extern1"); ++ if (IS_ERR(clk_extern1)) { ++ dev_err(data->dev, "Can't retrieve clk extern1\n"); ++ return PTR_ERR(clk_extern1); ++ } ++ ++ ret = clk_set_parent(clk_extern1, data->clk_pll_a_out0); ++ if (ret < 0) { ++ dev_err(data->dev, ++ "Set parent failed for clk extern1\n"); ++ return ret; ++ } ++ ++ clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1"); ++ if (IS_ERR(clk_out_1)) { ++ dev_err(data->dev, "Can't retrieve pmc_clk_out_1\n"); ++ return PTR_ERR(clk_out_1); ++ } ++ ++ ret = clk_set_parent(clk_out_1, clk_extern1); ++ if (ret < 0) { ++ dev_err(data->dev, ++ "Set parent failed for pmc_clk_out_1\n"); ++ return ret; ++ } ++ ++ data->clk_cdev1 = clk_out_1; ++ } ++ + ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); + if (ret) + return ret; diff --git a/queue-5.7/asoc-tegra-enable-audio-mclk-during-tegra_asoc_utils_init.patch b/queue-5.7/asoc-tegra-enable-audio-mclk-during-tegra_asoc_utils_init.patch new file mode 100644 index 00000000000..d4563521bc3 --- /dev/null +++ b/queue-5.7/asoc-tegra-enable-audio-mclk-during-tegra_asoc_utils_init.patch @@ -0,0 +1,55 @@ +From ff5d18cb04f4ecccbcf05b7f83ab6df2a0d95c16 Mon Sep 17 00:00:00 2001 +From: Sowjanya Komatineni +Date: Mon, 13 Jan 2020 23:24:24 -0800 +Subject: ASoC: tegra: Enable audio mclk during tegra_asoc_utils_init() + +From: Sowjanya Komatineni + +commit ff5d18cb04f4ecccbcf05b7f83ab6df2a0d95c16 upstream. + +Tegra PMC clock clk_out_1 is dedicated for audio mclk from Tegra30 +through Tegra210 and currently Tegra clock driver keeps the audio mclk +enabled. + +With the move of PMC clocks from clock driver into pmc driver, audio +mclk enable from clock driver is removed and this should be taken care +of by the audio driver. + +tegra_asoc_utils_init() calls tegra_asoc_utils_set_rate() and audio mclk +rate configuration is not needed during init and the rate is actually +set during the ->hw_params() callback. + +So, this patch removes tegra_asoc_utils_set_rate() call and just leaves +the audio mclk enabled. + +Signed-off-by: Sowjanya Komatineni +Tested-by: Dmitry Osipenko +Reviewed-by: Dmitry Osipenko +Signed-off-by: Thierry Reding +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/tegra/tegra_asoc_utils.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/sound/soc/tegra/tegra_asoc_utils.c ++++ b/sound/soc/tegra/tegra_asoc_utils.c +@@ -205,9 +205,16 @@ int tegra_asoc_utils_init(struct tegra_a + data->clk_cdev1 = clk_out_1; + } + +- ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); +- if (ret) ++ /* ++ * FIXME: There is some unknown dependency between audio mclk disable ++ * and suspend-resume functionality on Tegra30, although audio mclk is ++ * only needed for audio. ++ */ ++ ret = clk_prepare_enable(data->clk_cdev1); ++ if (ret) { ++ dev_err(data->dev, "Can't enable cdev1: %d\n", ret); + return ret; ++ } + + return 0; + } diff --git a/queue-5.7/asoc-tegra-use-device-managed-resource-apis-to-get-the-clock.patch b/queue-5.7/asoc-tegra-use-device-managed-resource-apis-to-get-the-clock.patch new file mode 100644 index 00000000000..e19ec3bacd8 --- /dev/null +++ b/queue-5.7/asoc-tegra-use-device-managed-resource-apis-to-get-the-clock.patch @@ -0,0 +1,565 @@ +From 0de6db30ef79b391cedd749801a49c485d2daf4b Mon Sep 17 00:00:00 2001 +From: Sowjanya Komatineni +Date: Mon, 13 Jan 2020 23:24:17 -0800 +Subject: ASoC: tegra: Use device managed resource APIs to get the clock + +From: Sowjanya Komatineni + +commit 0de6db30ef79b391cedd749801a49c485d2daf4b upstream. + +tegra_asoc_utils uses clk_get() to get the clock and clk_put() to free +them explicitly. + +This patch updates it to use device managed resource API devm_clk_get() +so the clock will be automatically released and freed when the device is +unbound and removes tegra_asoc_utils_fini() as its no longer needed. + +Tested-by: Dmitry Osipenko +Reviewed-by: Dmitry Osipenko +Reviewed-by: Sameer Pujar +Signed-off-by: Sowjanya Komatineni +Signed-off-by: Thierry Reding +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/tegra/tegra_alc5632.c | 7 +------ + sound/soc/tegra/tegra_asoc_utils.c | 34 +++++++--------------------------- + sound/soc/tegra/tegra_asoc_utils.h | 1 - + sound/soc/tegra/tegra_max98090.c | 22 ++++++---------------- + sound/soc/tegra/tegra_rt5640.c | 22 ++++++---------------- + sound/soc/tegra/tegra_rt5677.c | 7 +------ + sound/soc/tegra/tegra_sgtl5000.c | 7 +------ + sound/soc/tegra/tegra_wm8753.c | 22 ++++++---------------- + sound/soc/tegra/tegra_wm8903.c | 22 ++++++---------------- + sound/soc/tegra/tegra_wm9712.c | 8 ++------ + sound/soc/tegra/trimslice.c | 18 ++++-------------- + 11 files changed, 40 insertions(+), 130 deletions(-) + +--- a/sound/soc/tegra/tegra_alc5632.c ++++ b/sound/soc/tegra/tegra_alc5632.c +@@ -205,13 +205,11 @@ static int tegra_alc5632_probe(struct pl + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ goto err_put_cpu_of_node; + } + + return 0; + +-err_fini_utils: +- tegra_asoc_utils_fini(&alc5632->util_data); + err_put_cpu_of_node: + of_node_put(tegra_alc5632_dai.cpus->of_node); + tegra_alc5632_dai.cpus->of_node = NULL; +@@ -226,12 +224,9 @@ err: + static int tegra_alc5632_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + of_node_put(tegra_alc5632_dai.cpus->of_node); + tegra_alc5632_dai.cpus->of_node = NULL; + tegra_alc5632_dai.platforms->of_node = NULL; +--- a/sound/soc/tegra/tegra_asoc_utils.c ++++ b/sound/soc/tegra/tegra_asoc_utils.c +@@ -175,52 +175,32 @@ int tegra_asoc_utils_init(struct tegra_a + return -EINVAL; + } + +- data->clk_pll_a = clk_get(dev, "pll_a"); ++ data->clk_pll_a = devm_clk_get(dev, "pll_a"); + if (IS_ERR(data->clk_pll_a)) { + dev_err(data->dev, "Can't retrieve clk pll_a\n"); +- ret = PTR_ERR(data->clk_pll_a); +- goto err; ++ return PTR_ERR(data->clk_pll_a); + } + +- data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0"); ++ data->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0"); + if (IS_ERR(data->clk_pll_a_out0)) { + dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); +- ret = PTR_ERR(data->clk_pll_a_out0); +- goto err_put_pll_a; ++ return PTR_ERR(data->clk_pll_a_out0); + } + +- data->clk_cdev1 = clk_get(dev, "mclk"); ++ data->clk_cdev1 = devm_clk_get(dev, "mclk"); + if (IS_ERR(data->clk_cdev1)) { + dev_err(data->dev, "Can't retrieve clk cdev1\n"); +- ret = PTR_ERR(data->clk_cdev1); +- goto err_put_pll_a_out0; ++ return PTR_ERR(data->clk_cdev1); + } + + ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100); + if (ret) +- goto err_put_cdev1; ++ return ret; + + return 0; +- +-err_put_cdev1: +- clk_put(data->clk_cdev1); +-err_put_pll_a_out0: +- clk_put(data->clk_pll_a_out0); +-err_put_pll_a: +- clk_put(data->clk_pll_a); +-err: +- return ret; + } + EXPORT_SYMBOL_GPL(tegra_asoc_utils_init); + +-void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) +-{ +- clk_put(data->clk_cdev1); +- clk_put(data->clk_pll_a_out0); +- clk_put(data->clk_pll_a); +-} +-EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini); +- + MODULE_AUTHOR("Stephen Warren "); + MODULE_DESCRIPTION("Tegra ASoC utility code"); + MODULE_LICENSE("GPL"); +--- a/sound/soc/tegra/tegra_asoc_utils.h ++++ b/sound/soc/tegra/tegra_asoc_utils.h +@@ -34,6 +34,5 @@ int tegra_asoc_utils_set_rate(struct teg + int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data); + int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, + struct device *dev); +-void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); + + #endif +--- a/sound/soc/tegra/tegra_max98090.c ++++ b/sound/soc/tegra/tegra_max98090.c +@@ -218,19 +218,18 @@ static int tegra_max98090_probe(struct p + + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); + if (ret) +- goto err; ++ return ret; + + tegra_max98090_dai.codecs->of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); + if (!tegra_max98090_dai.codecs->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_max98090_dai.cpus->of_node = of_parse_phandle(np, +@@ -238,40 +237,31 @@ static int tegra_max98090_probe(struct p + if (!tegra_max98090_dai.cpus->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_max98090_dai.platforms->of_node = tegra_max98090_dai.cpus->of_node; + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ return ret; + } + + return 0; +- +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); +-err: +- return ret; + } + + static int tegra_max98090_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + return 0; + } + +--- a/sound/soc/tegra/tegra_rt5640.c ++++ b/sound/soc/tegra/tegra_rt5640.c +@@ -164,19 +164,18 @@ static int tegra_rt5640_probe(struct pla + + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); + if (ret) +- goto err; ++ return ret; + + tegra_rt5640_dai.codecs->of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); + if (!tegra_rt5640_dai.codecs->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_rt5640_dai.cpus->of_node = of_parse_phandle(np, +@@ -184,40 +183,31 @@ static int tegra_rt5640_probe(struct pla + if (!tegra_rt5640_dai.cpus->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_rt5640_dai.platforms->of_node = tegra_rt5640_dai.cpus->of_node; + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ return ret; + } + + return 0; +- +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); +-err: +- return ret; + } + + static int tegra_rt5640_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + return 0; + } + +--- a/sound/soc/tegra/tegra_rt5677.c ++++ b/sound/soc/tegra/tegra_rt5677.c +@@ -270,13 +270,11 @@ static int tegra_rt5677_probe(struct pla + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ goto err_put_cpu_of_node; + } + + return 0; + +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); + err_put_cpu_of_node: + of_node_put(tegra_rt5677_dai.cpus->of_node); + tegra_rt5677_dai.cpus->of_node = NULL; +@@ -291,12 +289,9 @@ err: + static int tegra_rt5677_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_rt5677 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + tegra_rt5677_dai.platforms->of_node = NULL; + of_node_put(tegra_rt5677_dai.codecs->of_node); + tegra_rt5677_dai.codecs->of_node = NULL; +--- a/sound/soc/tegra/tegra_sgtl5000.c ++++ b/sound/soc/tegra/tegra_sgtl5000.c +@@ -156,13 +156,11 @@ static int tegra_sgtl5000_driver_probe(s + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ goto err_put_cpu_of_node; + } + + return 0; + +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); + err_put_cpu_of_node: + of_node_put(tegra_sgtl5000_dai.cpus->of_node); + tegra_sgtl5000_dai.cpus->of_node = NULL; +@@ -177,13 +175,10 @@ err: + static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_sgtl5000 *machine = snd_soc_card_get_drvdata(card); + int ret; + + ret = snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + of_node_put(tegra_sgtl5000_dai.cpus->of_node); + tegra_sgtl5000_dai.cpus->of_node = NULL; + tegra_sgtl5000_dai.platforms->of_node = NULL; +--- a/sound/soc/tegra/tegra_wm8753.c ++++ b/sound/soc/tegra/tegra_wm8753.c +@@ -127,19 +127,18 @@ static int tegra_wm8753_driver_probe(str + + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); + if (ret) +- goto err; ++ return ret; + + tegra_wm8753_dai.codecs->of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); + if (!tegra_wm8753_dai.codecs->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_wm8753_dai.cpus->of_node = of_parse_phandle(np, +@@ -147,40 +146,31 @@ static int tegra_wm8753_driver_probe(str + if (!tegra_wm8753_dai.cpus->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_wm8753_dai.platforms->of_node = tegra_wm8753_dai.cpus->of_node; + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ return ret; + } + + return 0; +- +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); +-err: +- return ret; + } + + static int tegra_wm8753_driver_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + return 0; + } + +--- a/sound/soc/tegra/tegra_wm8903.c ++++ b/sound/soc/tegra/tegra_wm8903.c +@@ -323,19 +323,18 @@ static int tegra_wm8903_driver_probe(str + + ret = snd_soc_of_parse_card_name(card, "nvidia,model"); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing"); + if (ret) +- goto err; ++ return ret; + + tegra_wm8903_dai.codecs->of_node = of_parse_phandle(np, + "nvidia,audio-codec", 0); + if (!tegra_wm8903_dai.codecs->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_wm8903_dai.cpus->of_node = of_parse_phandle(np, +@@ -343,40 +342,31 @@ static int tegra_wm8903_driver_probe(str + if (!tegra_wm8903_dai.cpus->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + tegra_wm8903_dai.platforms->of_node = tegra_wm8903_dai.cpus->of_node; + + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ return ret; + } + + return 0; +- +-err_fini_utils: +- tegra_asoc_utils_fini(&machine->util_data); +-err: +- return ret; + } + + static int tegra_wm8903_driver_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + return 0; + } + +--- a/sound/soc/tegra/tegra_wm9712.c ++++ b/sound/soc/tegra/tegra_wm9712.c +@@ -113,19 +113,17 @@ static int tegra_wm9712_driver_probe(str + + ret = tegra_asoc_utils_set_ac97_rate(&machine->util_data); + if (ret) +- goto asoc_utils_fini; ++ goto codec_unregister; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto asoc_utils_fini; ++ goto codec_unregister; + } + + return 0; + +-asoc_utils_fini: +- tegra_asoc_utils_fini(&machine->util_data); + codec_unregister: + platform_device_del(machine->codec); + codec_put: +@@ -140,8 +138,6 @@ static int tegra_wm9712_driver_remove(st + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&machine->util_data); +- + platform_device_unregister(machine->codec); + + return 0; +--- a/sound/soc/tegra/trimslice.c ++++ b/sound/soc/tegra/trimslice.c +@@ -125,8 +125,7 @@ static int tegra_snd_trimslice_probe(str + if (!trimslice_tlv320aic23_dai.codecs->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,audio-codec' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + trimslice_tlv320aic23_dai.cpus->of_node = of_parse_phandle(np, +@@ -134,8 +133,7 @@ static int tegra_snd_trimslice_probe(str + if (!trimslice_tlv320aic23_dai.cpus->of_node) { + dev_err(&pdev->dev, + "Property 'nvidia,i2s-controller' missing or invalid\n"); +- ret = -EINVAL; +- goto err; ++ return -EINVAL; + } + + trimslice_tlv320aic23_dai.platforms->of_node = +@@ -143,32 +141,24 @@ static int tegra_snd_trimslice_probe(str + + ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); + if (ret) +- goto err; ++ return ret; + + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", + ret); +- goto err_fini_utils; ++ return ret; + } + + return 0; +- +-err_fini_utils: +- tegra_asoc_utils_fini(&trimslice->util_data); +-err: +- return ret; + } + + static int tegra_snd_trimslice_remove(struct platform_device *pdev) + { + struct snd_soc_card *card = platform_get_drvdata(pdev); +- struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); + + snd_soc_unregister_card(card); + +- tegra_asoc_utils_fini(&trimslice->util_data); +- + return 0; + } + diff --git a/queue-5.7/drm-added-orientation-quirk-for-asus-tablet-model-t103haf.patch b/queue-5.7/drm-added-orientation-quirk-for-asus-tablet-model-t103haf.patch new file mode 100644 index 00000000000..bcf70e66558 --- /dev/null +++ b/queue-5.7/drm-added-orientation-quirk-for-asus-tablet-model-t103haf.patch @@ -0,0 +1,34 @@ +From b5ac98cbb8e5e30c34ebc837d1e5a3982d2b5f5c Mon Sep 17 00:00:00 2001 +From: Marius Iacob +Date: Sat, 1 Aug 2020 15:34:46 +0300 +Subject: drm: Added orientation quirk for ASUS tablet model T103HAF + +From: Marius Iacob + +commit b5ac98cbb8e5e30c34ebc837d1e5a3982d2b5f5c upstream. + +Signed-off-by: Marius Iacob +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20200801123445.1514567-1-themariusus@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c ++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c +@@ -121,6 +121,12 @@ static const struct dmi_system_id orient + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T101HA"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, ++ }, { /* Asus T103HAF */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"), ++ }, ++ .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* GPD MicroPC (generic strings, also match on bios date) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"), diff --git a/queue-5.7/drm-amd-display-dchubbub-p-state-warning-during-surface-planes-switch.patch b/queue-5.7/drm-amd-display-dchubbub-p-state-warning-during-surface-planes-switch.patch new file mode 100644 index 00000000000..ebc0c62eb55 --- /dev/null +++ b/queue-5.7/drm-amd-display-dchubbub-p-state-warning-during-surface-planes-switch.patch @@ -0,0 +1,168 @@ +From 8b0379a85762b516c7b46aed7dbf2a4947c00564 Mon Sep 17 00:00:00 2001 +From: hersen wu +Date: Sun, 19 Jul 2020 17:21:59 -0400 +Subject: drm/amd/display: dchubbub p-state warning during surface planes switch + +From: hersen wu + +commit 8b0379a85762b516c7b46aed7dbf2a4947c00564 upstream. + +[Why] +ramp_up_dispclk_with_dpp is to change dispclk, dppclk and dprefclk +according to bandwidth requirement. call stack: rv1_update_clocks --> +update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth +--> prepare_bandwidth / optimize_bandwidth. before change dcn hw, +prepare_bandwidth will be called first to allow enough clock, +watermark for change, after end of dcn hw change, optimize_bandwidth +is executed to lower clock to save power for new dcn hw settings. + +below is sequence of commit_planes_for_stream: +step 1: prepare_bandwidth - raise clock to have enough bandwidth +step 2: lock_doublebuffer_enable +step 3: pipe_control_lock(true) - make dchubp register change will +not take effect right way +step 4: apply_ctx_for_surface - program dchubp +step 5: pipe_control_lock(false) - dchubp register change take effect +step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream +for full_date, optimize clock to save power + +at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be +changed for new dchubp configuration. but real dcn hub dchubps are +still running with old configuration until end of step 5. this need +clocks settings at step 1 should not less than that before step 1. +this is checked by two conditions: 1. if (should_set_clock(safe_to_lower +, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || +new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) +2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz + +the second condition is based on new dchubp configuration. dppclk +for new dchubp may be different from dppclk before step 1. +for example, before step 1, dchubps are as below: +pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) +pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) +for dppclk for pipe0 need dppclk = dispclk + +new dchubp pipe split configuration: +pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) +pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) +dppclk only needs dppclk = dispclk /2. + +dispclk, dppclk are not lock by otg master lock. they take effect +after step 1. during this transition, dispclk are the same, but +dppclk is changed to half of previous clock for old dchubp +configuration between step 1 and step 6. This may cause p-state +warning intermittently. + +[How] +for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we +need make sure dppclk are not changed to less between step 1 and 6. +for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, +new display clock is raised, but we do not know ratio of +new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, +new_clocks->dispclk_khz /2 does not guarantee equal or higher than +old dppclk. we could ignore power saving different between +dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. +as long as safe_to_lower = false, set dpclk = dispclk to simplify +condition check. + +CC: Stable +Signed-off-by: Hersen Wu +Reviewed-by: Aric Cyr +Acked-by: Eryk Brol +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c | 69 ++++++++++++- + 1 file changed, 67 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c +@@ -85,12 +85,77 @@ static int rv1_determine_dppclk_threshol + return disp_clk_threshold; + } + +-static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc *dc, struct dc_clocks *new_clocks) ++static void ramp_up_dispclk_with_dpp( ++ struct clk_mgr_internal *clk_mgr, ++ struct dc *dc, ++ struct dc_clocks *new_clocks, ++ bool safe_to_lower) + { + int i; + int dispclk_to_dpp_threshold = rv1_determine_dppclk_threshold(clk_mgr, new_clocks); + bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; + ++ /* this function is to change dispclk, dppclk and dprefclk according to ++ * bandwidth requirement. Its call stack is rv1_update_clocks --> ++ * update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth ++ * --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, ++ * prepare_bandwidth will be called first to allow enough clock, ++ * watermark for change, after end of dcn hw change, optimize_bandwidth ++ * is executed to lower clock to save power for new dcn hw settings. ++ * ++ * below is sequence of commit_planes_for_stream: ++ * ++ * step 1: prepare_bandwidth - raise clock to have enough bandwidth ++ * step 2: lock_doublebuffer_enable ++ * step 3: pipe_control_lock(true) - make dchubp register change will ++ * not take effect right way ++ * step 4: apply_ctx_for_surface - program dchubp ++ * step 5: pipe_control_lock(false) - dchubp register change take effect ++ * step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream ++ * for full_date, optimize clock to save power ++ * ++ * at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be ++ * changed for new dchubp configuration. but real dcn hub dchubps are ++ * still running with old configuration until end of step 5. this need ++ * clocks settings at step 1 should not less than that before step 1. ++ * this is checked by two conditions: 1. if (should_set_clock(safe_to_lower ++ * , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || ++ * new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) ++ * 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz ++ * ++ * the second condition is based on new dchubp configuration. dppclk ++ * for new dchubp may be different from dppclk before step 1. ++ * for example, before step 1, dchubps are as below: ++ * pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) ++ * pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) ++ * for dppclk for pipe0 need dppclk = dispclk ++ * ++ * new dchubp pipe split configuration: ++ * pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) ++ * pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) ++ * dppclk only needs dppclk = dispclk /2. ++ * ++ * dispclk, dppclk are not lock by otg master lock. they take effect ++ * after step 1. during this transition, dispclk are the same, but ++ * dppclk is changed to half of previous clock for old dchubp ++ * configuration between step 1 and step 6. This may cause p-state ++ * warning intermittently. ++ * ++ * for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we ++ * need make sure dppclk are not changed to less between step 1 and 6. ++ * for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, ++ * new display clock is raised, but we do not know ratio of ++ * new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, ++ * new_clocks->dispclk_khz /2 does not guarantee equal or higher than ++ * old dppclk. we could ignore power saving different between ++ * dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. ++ * as long as safe_to_lower = false, set dpclk = dispclk to simplify ++ * condition check. ++ * todo: review this change for other asic. ++ **/ ++ if (!safe_to_lower) ++ request_dpp_div = false; ++ + /* set disp clk to dpp clk threshold */ + + clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold); +@@ -209,7 +274,7 @@ static void rv1_update_clocks(struct clk + /* program dispclk on = as a w/a for sleep resume clock ramping issues */ + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) + || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) { +- ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks); ++ ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks, safe_to_lower); + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; + send_request_to_lower = true; + } diff --git a/queue-5.7/drm-amd-display-fix-dmesg-warning-from-setting-abm-level.patch b/queue-5.7/drm-amd-display-fix-dmesg-warning-from-setting-abm-level.patch new file mode 100644 index 00000000000..aced74dbf81 --- /dev/null +++ b/queue-5.7/drm-amd-display-fix-dmesg-warning-from-setting-abm-level.patch @@ -0,0 +1,59 @@ +From c5892a10218214d729699ab61bad6fc109baf0ce Mon Sep 17 00:00:00 2001 +From: Stylon Wang +Date: Tue, 30 Jun 2020 17:55:29 +0800 +Subject: drm/amd/display: Fix dmesg warning from setting abm level + +From: Stylon Wang + +commit c5892a10218214d729699ab61bad6fc109baf0ce upstream. + +[Why] +Setting abm level does not correctly update CRTC state. As a result +no surface update is added to dc stream state and triggers warning. + +[How] +Correctly update CRTC state when setting abm level property. + +CC: Stable +Signed-off-by: Stylon Wang +Reviewed-by: Nicholas Kazlauskas +Acked-by: Eryk Brol +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -8458,6 +8458,29 @@ static int amdgpu_dm_atomic_check(struct + if (ret) + goto fail; + ++ /* Check connector changes */ ++ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { ++ struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); ++ struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); ++ ++ /* Skip connectors that are disabled or part of modeset already. */ ++ if (!old_con_state->crtc && !new_con_state->crtc) ++ continue; ++ ++ if (!new_con_state->crtc) ++ continue; ++ ++ new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc); ++ if (IS_ERR(new_crtc_state)) { ++ ret = PTR_ERR(new_crtc_state); ++ goto fail; ++ } ++ ++ if (dm_old_con_state->abm_level != ++ dm_new_con_state->abm_level) ++ new_crtc_state->connectors_changed = true; ++ } ++ + #if defined(CONFIG_DRM_AMD_DC_DCN) + if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) + goto fail; diff --git a/queue-5.7/drm-amdgpu-fix-bug-where-dpm-is-not-enabled-after-hibernate-and-resume.patch b/queue-5.7/drm-amdgpu-fix-bug-where-dpm-is-not-enabled-after-hibernate-and-resume.patch new file mode 100644 index 00000000000..cc47905c1c9 --- /dev/null +++ b/queue-5.7/drm-amdgpu-fix-bug-where-dpm-is-not-enabled-after-hibernate-and-resume.patch @@ -0,0 +1,60 @@ +From f87812284172a9809820d10143b573d833cd3f75 Mon Sep 17 00:00:00 2001 +From: Sandeep Raghuraman +Date: Thu, 6 Aug 2020 22:52:20 +0530 +Subject: drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume + +From: Sandeep Raghuraman + +commit f87812284172a9809820d10143b573d833cd3f75 upstream. + +Reproducing bug report here: +After hibernating and resuming, DPM is not enabled. This remains the case +even if you test hibernate using the steps here: +https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html + +I debugged the problem, and figured out that in the file hardwaremanager.c, +in the function, phm_enable_dynamic_state_management(), the check +'if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev) && adev->in_suspend)' +returns true for the hibernate case, and false for the suspend case. + +This means that for the hibernate case, the AMDGPU driver doesn't enable DPM +(even though it should) and simply returns from that function. +In the suspend case, it goes ahead and enables DPM, even though it doesn't need to. + +I debugged further, and found out that in the case of suspend, for the +CIK/Hawaii GPUs, smum_is_dpm_running(hwmgr) returns false, while in the case of +hibernate, smum_is_dpm_running(hwmgr) returns true. + +For CIK, the ci_is_dpm_running() function calls the ci_is_smc_ram_running() function, +which is ultimately used to determine if DPM is currently enabled or not, +and this seems to provide the wrong answer. + +I've changed the ci_is_dpm_running() function to instead use the same method that +some other AMD GPU chips do (e.g Fiji), which seems to read the voltage controller. +I've tested on my R9 390 and it seems to work correctly for both suspend and +hibernate use cases, and has been stable so far. + +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=208839 +Signed-off-by: Sandeep Raghuraman +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +@@ -2725,7 +2725,10 @@ static int ci_initialize_mc_reg_table(st + + static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) + { +- return ci_is_smc_ram_running(hwmgr); ++ return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, ++ CGS_IND_REG__SMC, FEATURE_STATUS, ++ VOLTAGE_CONTROLLER_ON)) ++ ? true : false; + } + + static int ci_smu_init(struct pp_hwmgr *hwmgr) diff --git a/queue-5.7/drm-amdgpu-fix-ordering-of-psp-suspend.patch b/queue-5.7/drm-amdgpu-fix-ordering-of-psp-suspend.patch new file mode 100644 index 00000000000..bd1d2d4361b --- /dev/null +++ b/queue-5.7/drm-amdgpu-fix-ordering-of-psp-suspend.patch @@ -0,0 +1,50 @@ +From alexdeucher@gmail.com Thu Aug 20 10:36:01 2020 +From: Alex Deucher +Date: Thu, 6 Aug 2020 10:49:39 -0400 +Subject: drm/amdgpu: fix ordering of psp suspend +To: stable@vger.kernel.org +Cc: Alex Deucher , Huang Rui +Message-ID: <20200806144939.466297-1-alexander.deucher@amd.com> + +From: Alex Deucher + +The ordering of psp_tmr_terminate() and psp_asd_unload() +got reversed when the patches were applied to stable. + +This patch does not exist in Linus' tree because the ordering +is correct there. It got reversed when the patches were applied +to stable. This patch is for stable only. + +Fixes: 22ff658396b446 ("drm/amdgpu: asd function needs to be unloaded in suspend phase") +Fixes: 2c41c968c6f648 ("drm/amdgpu: add TMR destory function for psp") +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org # 5.7.x +Cc: Huang Rui +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -1679,15 +1679,15 @@ static int psp_suspend(void *handle) + } + } + +- ret = psp_tmr_terminate(psp); ++ ret = psp_asd_unload(psp); + if (ret) { +- DRM_ERROR("Falied to terminate tmr\n"); ++ DRM_ERROR("Failed to unload asd\n"); + return ret; + } + +- ret = psp_asd_unload(psp); ++ ret = psp_tmr_terminate(psp); + if (ret) { +- DRM_ERROR("Failed to unload asd\n"); ++ DRM_ERROR("Falied to terminate tmr\n"); + return ret; + } + diff --git a/queue-5.7/drm-dp_mst-fix-the-ddc-i2c-device-registration-of-an-mst-port.patch b/queue-5.7/drm-dp_mst-fix-the-ddc-i2c-device-registration-of-an-mst-port.patch new file mode 100644 index 00000000000..0986d28f3e2 --- /dev/null +++ b/queue-5.7/drm-dp_mst-fix-the-ddc-i2c-device-registration-of-an-mst-port.patch @@ -0,0 +1,112 @@ +From d8bd15b37d328a935a4fc695fed8b19157503950 Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Mon, 8 Jun 2020 00:25:21 +0300 +Subject: drm/dp_mst: Fix the DDC I2C device registration of an MST port + +From: Imre Deak + +commit d8bd15b37d328a935a4fc695fed8b19157503950 upstream. + +During the initial MST probing an MST port's I2C device will be +registered using the kdev of the DRM device as a parent. Later after MST +Connection Status Notifications this I2C device will be re-registered +with the kdev of the port's connector. This will also move +inconsistently the I2C device's sysfs entry from the DRM device's sysfs +dir to the connector's dir. + +Fix the above by keeping the DRM kdev as the parent of the I2C device. + +Ideally the connector's kdev would be used as a parent, similarly to +non-MST connectors, however that needs some more refactoring to ensure +the connector's kdev is already available early enough. So keep the +existing (initial) behavior for now. + +Cc: +Signed-off-by: Imre Deak +Reviewed-by: Stanislav Lisovskiy +Reviewed-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20200607212522.16935-2-imre.deak@intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -88,8 +88,8 @@ static int drm_dp_send_enum_path_resourc + static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, + u8 *guid); + +-static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux); +-static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux); ++static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port); ++static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port); + static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr); + + #define DBG_PREFIX "[dp_mst]" +@@ -1981,7 +1981,7 @@ drm_dp_port_set_pdt(struct drm_dp_mst_po + } + + /* remove i2c over sideband */ +- drm_dp_mst_unregister_i2c_bus(&port->aux); ++ drm_dp_mst_unregister_i2c_bus(port); + } else { + mutex_lock(&mgr->lock); + drm_dp_mst_topology_put_mstb(port->mstb); +@@ -1996,7 +1996,7 @@ drm_dp_port_set_pdt(struct drm_dp_mst_po + if (port->pdt != DP_PEER_DEVICE_NONE) { + if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) { + /* add i2c over sideband */ +- ret = drm_dp_mst_register_i2c_bus(&port->aux); ++ ret = drm_dp_mst_register_i2c_bus(port); + } else { + lct = drm_dp_calculate_rad(port, rad); + mstb = drm_dp_add_mst_branch_device(lct, rad); +@@ -5406,22 +5406,26 @@ static const struct i2c_algorithm drm_dp + + /** + * drm_dp_mst_register_i2c_bus() - register an I2C adapter for I2C-over-AUX +- * @aux: DisplayPort AUX channel ++ * @port: The port to add the I2C bus on + * + * Returns 0 on success or a negative error code on failure. + */ +-static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux) ++static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port) + { ++ struct drm_dp_aux *aux = &port->aux; ++ struct device *parent_dev = port->mgr->dev->dev; ++ + aux->ddc.algo = &drm_dp_mst_i2c_algo; + aux->ddc.algo_data = aux; + aux->ddc.retries = 3; + + aux->ddc.class = I2C_CLASS_DDC; + aux->ddc.owner = THIS_MODULE; +- aux->ddc.dev.parent = aux->dev; +- aux->ddc.dev.of_node = aux->dev->of_node; ++ /* FIXME: set the kdev of the port's connector as parent */ ++ aux->ddc.dev.parent = parent_dev; ++ aux->ddc.dev.of_node = parent_dev->of_node; + +- strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), ++ strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev), + sizeof(aux->ddc.name)); + + return i2c_add_adapter(&aux->ddc); +@@ -5429,11 +5433,11 @@ static int drm_dp_mst_register_i2c_bus(s + + /** + * drm_dp_mst_unregister_i2c_bus() - unregister an I2C-over-AUX adapter +- * @aux: DisplayPort AUX channel ++ * @port: The port to remove the I2C bus from + */ +-static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux) ++static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port) + { +- i2c_del_adapter(&aux->ddc); ++ i2c_del_adapter(&port->aux.ddc); + } + + /** diff --git a/queue-5.7/drm-fix-drm_dp_mst_port-refcount-leaks-in-drm_dp_mst_allocate_vcpi.patch b/queue-5.7/drm-fix-drm_dp_mst_port-refcount-leaks-in-drm_dp_mst_allocate_vcpi.patch new file mode 100644 index 00000000000..7cfe9600d98 --- /dev/null +++ b/queue-5.7/drm-fix-drm_dp_mst_port-refcount-leaks-in-drm_dp_mst_allocate_vcpi.patch @@ -0,0 +1,65 @@ +From a34a0a632dd991a371fec56431d73279f9c54029 Mon Sep 17 00:00:00 2001 +From: Xin Xiong +Date: Sun, 19 Jul 2020 23:45:45 +0800 +Subject: drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Xin Xiong + +commit a34a0a632dd991a371fec56431d73279f9c54029 upstream. + +drm_dp_mst_allocate_vcpi() invokes +drm_dp_mst_topology_get_port_validated(), which increases the refcount +of the "port". + +These reference counting issues take place in two exception handling +paths separately. Either when “slots” is less than 0 or when +drm_dp_init_vcpi() returns a negative value, the function forgets to +reduce the refcnt increased drm_dp_mst_topology_get_port_validated(), +which results in a refcount leak. + +Fix these issues by pulling up the error handling when "slots" is less +than 0, and calling drm_dp_mst_topology_put_port() before termination +when drm_dp_init_vcpi() returns a negative value. + +Fixes: 1e797f556c61 ("drm/dp: Split drm_dp_mst_allocate_vcpi") +Cc: # v4.12+ +Signed-off-by: Xiyu Yang +Signed-off-by: Xin Tan +Signed-off-by: Xin Xiong +Reviewed-by: Lyude Paul +Signed-off-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20200719154545.GA41231@xin-virtual-machine +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_dp_mst_topology.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/drm_dp_mst_topology.c +@@ -4319,11 +4319,11 @@ bool drm_dp_mst_allocate_vcpi(struct drm + { + int ret; + +- port = drm_dp_mst_topology_get_port_validated(mgr, port); +- if (!port) ++ if (slots < 0) + return false; + +- if (slots < 0) ++ port = drm_dp_mst_topology_get_port_validated(mgr, port); ++ if (!port) + return false; + + if (port->vcpi.vcpi > 0) { +@@ -4339,6 +4339,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm + if (ret) { + DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n", + DIV_ROUND_UP(pbn, mgr->pbn_div), ret); ++ drm_dp_mst_topology_put_port(port); + goto out; + } + DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", diff --git a/queue-5.7/drm-i915-gt-force-the-gt-reset-on-shutdown.patch b/queue-5.7/drm-i915-gt-force-the-gt-reset-on-shutdown.patch new file mode 100644 index 00000000000..193b66da041 --- /dev/null +++ b/queue-5.7/drm-i915-gt-force-the-gt-reset-on-shutdown.patch @@ -0,0 +1,41 @@ +From 7c4541a37bbbf83c0f16f779e85eb61d9348ed29 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 25 May 2020 16:14:59 +0100 +Subject: drm/i915/gt: Force the GT reset on shutdown + +From: Chris Wilson + +commit 7c4541a37bbbf83c0f16f779e85eb61d9348ed29 upstream. + +Before we return control to the system, and letting it reuse all the +pages being accessed by HW, we must disable the HW. At the moment, we +dare not reset the GPU if it will clobber the display, but once we know +the display has been disabled, we can proceed with the reset as we +shutdown the module. We know the next user must reinitialise the HW for +their purpose. + +Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/489 +Signed-off-by: Chris Wilson +Cc: stable@kernel.org +Reviewed-by: Mika Kuoppala +Link: https://patchwork.freedesktop.org/patch/msgid/20200525151459.12083-1-chris@chris-wilson.co.uk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/gt/intel_gt.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/i915/gt/intel_gt.c ++++ b/drivers/gpu/drm/i915/gt/intel_gt.c +@@ -656,6 +656,11 @@ void intel_gt_driver_unregister(struct i + void intel_gt_driver_release(struct intel_gt *gt) + { + struct i915_address_space *vm; ++ intel_wakeref_t wakeref; ++ ++ /* Scrub all HW state upon release */ ++ with_intel_runtime_pm(gt->uncore->rpm, wakeref) ++ __intel_gt_reset(gt, ALL_ENGINES); + + vm = fetch_and_zero(>->vm); + if (vm) /* FIXME being called twice on error paths :( */ diff --git a/queue-5.7/drm-omap-force-runtime-pm-suspend-on-system-suspend.patch b/queue-5.7/drm-omap-force-runtime-pm-suspend-on-system-suspend.patch new file mode 100644 index 00000000000..3e499d8eb2d --- /dev/null +++ b/queue-5.7/drm-omap-force-runtime-pm-suspend-on-system-suspend.patch @@ -0,0 +1,71 @@ +From ecfdedd7da5d54416db5ca0f851264dca8736f59 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 18 Jun 2020 12:51:52 +0300 +Subject: drm/omap: force runtime PM suspend on system suspend + +From: Tomi Valkeinen + +commit ecfdedd7da5d54416db5ca0f851264dca8736f59 upstream. + +Use SET_LATE_SYSTEM_SLEEP_PM_OPS in DSS submodules to force runtime PM +suspend and resume. + +We use suspend late version so that omapdrm's system suspend callback is +called first, as that will disable all the display outputs after which +it's safe to force DSS into suspend. + +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20200618095153.611071-1-tomi.valkeinen@ti.com +Acked-by: Tony Lindgren +Fixes: cef766300353 ("drm/omap: Prepare DSS for probing without legacy platform data") +Cc: stable@vger.kernel.org # v5.7+ +Tested-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/omapdrm/dss/dispc.c | 1 + + drivers/gpu/drm/omapdrm/dss/dsi.c | 1 + + drivers/gpu/drm/omapdrm/dss/dss.c | 1 + + drivers/gpu/drm/omapdrm/dss/venc.c | 1 + + 4 files changed, 4 insertions(+) + +--- a/drivers/gpu/drm/omapdrm/dss/dispc.c ++++ b/drivers/gpu/drm/omapdrm/dss/dispc.c +@@ -4936,6 +4936,7 @@ static int dispc_runtime_resume(struct d + static const struct dev_pm_ops dispc_pm_ops = { + .runtime_suspend = dispc_runtime_suspend, + .runtime_resume = dispc_runtime_resume, ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + }; + + struct platform_driver omap_dispchw_driver = { +--- a/drivers/gpu/drm/omapdrm/dss/dsi.c ++++ b/drivers/gpu/drm/omapdrm/dss/dsi.c +@@ -5467,6 +5467,7 @@ static int dsi_runtime_resume(struct dev + static const struct dev_pm_ops dsi_pm_ops = { + .runtime_suspend = dsi_runtime_suspend, + .runtime_resume = dsi_runtime_resume, ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + }; + + struct platform_driver omap_dsihw_driver = { +--- a/drivers/gpu/drm/omapdrm/dss/dss.c ++++ b/drivers/gpu/drm/omapdrm/dss/dss.c +@@ -1614,6 +1614,7 @@ static int dss_runtime_resume(struct dev + static const struct dev_pm_ops dss_pm_ops = { + .runtime_suspend = dss_runtime_suspend, + .runtime_resume = dss_runtime_resume, ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + }; + + struct platform_driver omap_dsshw_driver = { +--- a/drivers/gpu/drm/omapdrm/dss/venc.c ++++ b/drivers/gpu/drm/omapdrm/dss/venc.c +@@ -945,6 +945,7 @@ static int venc_runtime_resume(struct de + static const struct dev_pm_ops venc_pm_ops = { + .runtime_suspend = venc_runtime_suspend, + .runtime_resume = venc_runtime_resume, ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + }; + + static const struct of_device_id venc_of_match[] = { diff --git a/queue-5.7/drm-panfrost-use-kvfree-to-free-bo-sgts.patch b/queue-5.7/drm-panfrost-use-kvfree-to-free-bo-sgts.patch new file mode 100644 index 00000000000..f02d5af2d53 --- /dev/null +++ b/queue-5.7/drm-panfrost-use-kvfree-to-free-bo-sgts.patch @@ -0,0 +1,47 @@ +From 114427b8927a4def2942b2b886f7e4aeae289ccb Mon Sep 17 00:00:00 2001 +From: Denis Efremov +Date: Mon, 8 Jun 2020 18:17:28 +0300 +Subject: drm/panfrost: Use kvfree() to free bo->sgts + +From: Denis Efremov + +commit 114427b8927a4def2942b2b886f7e4aeae289ccb upstream. + +Use kvfree() to free bo->sgts, because the memory is allocated with +kvmalloc_array() in panfrost_mmu_map_fault_addr(). + +Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations") +Cc: stable@vger.kernel.org +Signed-off-by: Denis Efremov +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patchwork.freedesktop.org/patch/msgid/20200608151728.234026-1-efremov@linux.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/panfrost/panfrost_gem.c | 2 +- + drivers/gpu/drm/panfrost/panfrost_mmu.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/panfrost/panfrost_gem.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gem.c +@@ -46,7 +46,7 @@ static void panfrost_gem_free_object(str + sg_free_table(&bo->sgts[i]); + } + } +- kfree(bo->sgts); ++ kvfree(bo->sgts); + } + + drm_gem_shmem_free_object(obj); +--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c ++++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c +@@ -486,7 +486,7 @@ static int panfrost_mmu_map_fault_addr(s + pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT, + sizeof(struct page *), GFP_KERNEL | __GFP_ZERO); + if (!pages) { +- kfree(bo->sgts); ++ kvfree(bo->sgts); + bo->sgts = NULL; + mutex_unlock(&bo->base.pages_lock); + ret = -ENOMEM; diff --git a/queue-5.7/drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch b/queue-5.7/drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch new file mode 100644 index 00000000000..1f9fa7ab047 --- /dev/null +++ b/queue-5.7/drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch @@ -0,0 +1,33 @@ +From f29aa08852e1953e461f2d47ab13c34e14bc08b3 Mon Sep 17 00:00:00 2001 +From: Denis Efremov +Date: Mon, 22 Jun 2020 23:31:22 +0300 +Subject: drm/radeon: fix fb_div check in ni_init_smc_spll_table() + +From: Denis Efremov + +commit f29aa08852e1953e461f2d47ab13c34e14bc08b3 upstream. + +clk_s is checked twice in a row in ni_init_smc_spll_table(). +fb_div should be checked instead. + +Fixes: 69e0b57a91ad ("drm/radeon/kms: add dpm support for cayman (v5)") +Cc: stable@vger.kernel.org +Signed-off-by: Denis Efremov +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/ni_dpm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/ni_dpm.c ++++ b/drivers/gpu/drm/radeon/ni_dpm.c +@@ -2124,7 +2124,7 @@ static int ni_init_smc_spll_table(struct + if (p_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT)) + ret = -EINVAL; + +- if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) ++ if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) + ret = -EINVAL; + + if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) diff --git a/queue-5.7/drm-tidss-fix-modeset-init-for-dpi-panels.patch b/queue-5.7/drm-tidss-fix-modeset-init-for-dpi-panels.patch new file mode 100644 index 00000000000..19c0d30cf18 --- /dev/null +++ b/queue-5.7/drm-tidss-fix-modeset-init-for-dpi-panels.patch @@ -0,0 +1,37 @@ +From a72a6a16d51034045cb6355924b62221a8221ca3 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 4 Jun 2020 11:02:14 +0300 +Subject: drm/tidss: fix modeset init for DPI panels + +From: Tomi Valkeinen + +commit a72a6a16d51034045cb6355924b62221a8221ca3 upstream. + +The connector type for DISPC's DPI videoport was set the LVDS instead of +DPI. This causes any DPI panel setup to fail with tidss, making all DPI +panels unusable. + +Fix this by using correct connector type. + +Signed-off-by: Tomi Valkeinen +Fixes: 32a1795f57eecc39749017 ("drm/tidss: New driver for TI Keystone platform Display SubSystem") +Cc: stable@vger.kernel.org # v5.7+ +Link: https://patchwork.freedesktop.org/patch/msgid/20200604080214.107159-1-tomi.valkeinen@ti.com +Reviewed-by: Jyri Sarha +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/tidss/tidss_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/tidss/tidss_kms.c ++++ b/drivers/gpu/drm/tidss/tidss_kms.c +@@ -154,7 +154,7 @@ static int tidss_dispc_modeset_init(stru + break; + case DISPC_VP_DPI: + enc_type = DRM_MODE_ENCODER_DPI; +- conn_type = DRM_MODE_CONNECTOR_LVDS; ++ conn_type = DRM_MODE_CONNECTOR_DPI; + break; + default: + WARN_ON(1); diff --git a/queue-5.7/khugepaged-retract_page_tables-remember-to-test-exit.patch b/queue-5.7/khugepaged-retract_page_tables-remember-to-test-exit.patch new file mode 100644 index 00000000000..7c8c09f6f38 --- /dev/null +++ b/queue-5.7/khugepaged-retract_page_tables-remember-to-test-exit.patch @@ -0,0 +1,100 @@ +From 18e77600f7a1ed69f8ce46c9e11cad0985712dfa Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Thu, 6 Aug 2020 23:26:22 -0700 +Subject: khugepaged: retract_page_tables() remember to test exit + +From: Hugh Dickins + +commit 18e77600f7a1ed69f8ce46c9e11cad0985712dfa upstream. + +Only once have I seen this scenario (and forgot even to notice what forced +the eventual crash): a sequence of "BUG: Bad page map" alerts from +vm_normal_page(), from zap_pte_range() servicing exit_mmap(); +pmd:00000000, pte values corresponding to data in physical page 0. + +The pte mappings being zapped in this case were supposed to be from a huge +page of ext4 text (but could as well have been shmem): my belief is that +it was racing with collapse_file()'s retract_page_tables(), found *pmd +pointing to a page table, locked it, but *pmd had become 0 by the time +start_pte was decided. + +In most cases, that possibility is excluded by holding mmap lock; but +exit_mmap() proceeds without mmap lock. Most of what's run by khugepaged +checks khugepaged_test_exit() after acquiring mmap lock: +khugepaged_collapse_pte_mapped_thps() and hugepage_vma_revalidate() do so, +for example. But retract_page_tables() did not: fix that. + +The fix is for retract_page_tables() to check khugepaged_test_exit(), +after acquiring mmap lock, before doing anything to the page table. +Getting the mmap lock serializes with __mmput(), which briefly takes and +drops it in __khugepaged_exit(); then the khugepaged_test_exit() check on +mm_users makes sure we don't touch the page table once exit_mmap() might +reach it, since exit_mmap() will be proceeding without mmap lock, not +expecting anyone to be racing with it. + +Fixes: f3f0e1d2150b ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins +Signed-off-by: Andrew Morton +Acked-by: Kirill A. Shutemov +Cc: Andrea Arcangeli +Cc: Mike Kravetz +Cc: Song Liu +Cc: [4.8+] +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.2008021215400.27773@eggly.anvils +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + + +--- + mm/khugepaged.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1433,6 +1433,7 @@ out: + static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) + { + struct vm_area_struct *vma; ++ struct mm_struct *mm; + unsigned long addr; + pmd_t *pmd, _pmd; + +@@ -1461,7 +1462,8 @@ static void retract_page_tables(struct a + continue; + if (vma->vm_end < addr + HPAGE_PMD_SIZE) + continue; +- pmd = mm_find_pmd(vma->vm_mm, addr); ++ mm = vma->vm_mm; ++ pmd = mm_find_pmd(mm, addr); + if (!pmd) + continue; + /* +@@ -1471,17 +1473,19 @@ static void retract_page_tables(struct a + * mmap_sem while holding page lock. Fault path does it in + * reverse order. Trylock is a way to avoid deadlock. + */ +- if (down_write_trylock(&vma->vm_mm->mmap_sem)) { +- spinlock_t *ptl = pmd_lock(vma->vm_mm, pmd); +- /* assume page table is clear */ +- _pmd = pmdp_collapse_flush(vma, addr, pmd); +- spin_unlock(ptl); +- up_write(&vma->vm_mm->mmap_sem); +- mm_dec_nr_ptes(vma->vm_mm); +- pte_free(vma->vm_mm, pmd_pgtable(_pmd)); ++ if (down_write_trylock(&mm->mmap_sem)) { ++ if (!khugepaged_test_exit(mm)) { ++ spinlock_t *ptl = pmd_lock(mm, pmd); ++ /* assume page table is clear */ ++ _pmd = pmdp_collapse_flush(vma, addr, pmd); ++ spin_unlock(ptl); ++ mm_dec_nr_ptes(mm); ++ pte_free(mm, pmd_pgtable(_pmd)); ++ } ++ up_write(&mm->mmap_sem); + } else { + /* Try again later */ +- khugepaged_add_pte_mapped_thp(vma->vm_mm, addr); ++ khugepaged_add_pte_mapped_thp(mm, addr); + } + } + i_mmap_unlock_write(mapping); diff --git a/queue-5.7/series b/queue-5.7/series index 41d9f74e149..e3ced0e46dc 100644 --- a/queue-5.7/series +++ b/queue-5.7/series @@ -186,3 +186,19 @@ perf-bench-mem-always-memset-source-before-memcpy.patch tools-build-feature-quote-cc-and-cxx-for-their-argum.patch perf-x86-rapl-fix-missing-psys-sysfs-attributes.patch sh-landisk-add-missing-initialization-of-sh_io_port_.patch +khugepaged-retract_page_tables-remember-to-test-exit.patch +asoc-tegra-use-device-managed-resource-apis-to-get-the-clock.patch +asoc-tegra-add-audio-mclk-parent-configuration.patch +asoc-tegra-enable-audio-mclk-during-tegra_asoc_utils_init.patch +drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch +drm-i915-gt-force-the-gt-reset-on-shutdown.patch +drm-panfrost-use-kvfree-to-free-bo-sgts.patch +drm-dp_mst-fix-the-ddc-i2c-device-registration-of-an-mst-port.patch +drm-amdgpu-fix-ordering-of-psp-suspend.patch +drm-omap-force-runtime-pm-suspend-on-system-suspend.patch +drm-tidss-fix-modeset-init-for-dpi-panels.patch +drm-added-orientation-quirk-for-asus-tablet-model-t103haf.patch +drm-fix-drm_dp_mst_port-refcount-leaks-in-drm_dp_mst_allocate_vcpi.patch +drm-amdgpu-fix-bug-where-dpm-is-not-enabled-after-hibernate-and-resume.patch +drm-amd-display-fix-dmesg-warning-from-setting-abm-level.patch +drm-amd-display-dchubbub-p-state-warning-during-surface-planes-switch.patch