From: Sasha Levin Date: Sat, 24 Feb 2024 14:50:10 +0000 (-0500) Subject: Fixes for 5.10 X-Git-Tag: v4.19.308~76 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6176dc7f54ed8517ed661c24c94687fc5fc661aa;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/arm-dts-bcm53573-drop-nonexistent-default-off-led-tr.patch b/queue-5.10/arm-dts-bcm53573-drop-nonexistent-default-off-led-tr.patch new file mode 100644 index 00000000000..0ce4d8bbc51 --- /dev/null +++ b/queue-5.10/arm-dts-bcm53573-drop-nonexistent-default-off-led-tr.patch @@ -0,0 +1,68 @@ +From a031bc3b497d2da47277eaf425fa9d9369a9dab2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jul 2023 13:40:01 +0200 +Subject: ARM: dts: BCM53573: Drop nonexistent "default-off" LED trigger +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rafał Miłecki + +[ Upstream commit be7e1e5b0f67c58ec4be0a54db23b6a4fa6e2116 ] + +There is no such trigger documented or implemented in Linux. It was a +copy & paste mistake. + +This fixes: +arch/arm/boot/dts/broadcom/bcm47189-luxul-xap-1440.dtb: leds: led-wlan:linux,default-trigger: 'oneOf' conditional failed, one must be fixed: + 'default-off' is not one of ['backlight', 'default-on', 'heartbeat', 'disk-activity', 'disk-read', 'disk-write', 'timer', 'pattern', 'audio-micmute', 'audio-mute', 'bluetooth-power', 'flash', 'kbd-capslock', 'mtd', 'nand-disk', 'none', 'torch', 'usb-gadget', 'usb-host', 'usbport'] + 'default-off' does not match '^cpu[0-9]*$' + 'default-off' does not match '^hci[0-9]+-power$' + 'default-off' does not match '^mmc[0-9]+$' + 'default-off' does not match '^phy[0-9]+tx$' + From schema: Documentation/devicetree/bindings/leds/leds-gpio.yaml + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20230707114004.2740-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts | 1 - + arch/arm/boot/dts/bcm47189-luxul-xap-810.dts | 2 -- + 2 files changed, 3 deletions(-) + +diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +index 00e688b45d981..5901160919dcd 100644 +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -26,7 +26,6 @@ leds { + wlan { + label = "bcm53xx:blue:wlan"; + gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "default-off"; + }; + + system { +diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +index 78c80a5d3f4fa..8e7483272d47d 100644 +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -26,7 +26,6 @@ leds { + 5ghz { + label = "bcm53xx:blue:5ghz"; + gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; +- linux,default-trigger = "default-off"; + }; + + system { +@@ -42,7 +41,6 @@ pcie0_leds { + 2ghz { + label = "bcm53xx:blue:2ghz"; + gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>; +- linux,default-trigger = "default-off"; + }; + }; + +-- +2.43.0 + diff --git a/queue-5.10/arm-dts-imx-set-default-tuning-step-for-imx6sx-usdhc.patch b/queue-5.10/arm-dts-imx-set-default-tuning-step-for-imx6sx-usdhc.patch new file mode 100644 index 00000000000..9567a6ad020 --- /dev/null +++ b/queue-5.10/arm-dts-imx-set-default-tuning-step-for-imx6sx-usdhc.patch @@ -0,0 +1,63 @@ +From 0f8f019e9f3988f4270ae0d397f173c564961037 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Jul 2023 15:57:47 +0800 +Subject: ARM: dts: imx: Set default tuning step for imx6sx usdhc + +From: Xiaolei Wang + +[ Upstream commit 0a2b96e42a0284c4fc03022236f656a085ca714a ] + +If the tuning step is not set, the tuning step is set to 1. +For some sd cards, the following Tuning timeout will occur. + +Tuning failed, falling back to fixed sampling clock + +So set the default tuning step. This refers to the NXP vendor's +commit below: + +https://github.com/nxp-imx/linux-imx/blob/lf-6.1.y/ +arch/arm/boot/dts/imx6sx.dtsi#L1108-L1109 + +Fixes: 1e336aa0c025 ("mmc: sdhci-esdhc-imx: correct the tuning start tap and step setting") +Signed-off-by: Xiaolei Wang +Reviewed-by: Fabio Estevam +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sx.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi +index 08332f70a8dc2..51491b7418e40 100644 +--- a/arch/arm/boot/dts/imx6sx.dtsi ++++ b/arch/arm/boot/dts/imx6sx.dtsi +@@ -981,6 +981,8 @@ usdhc1: mmc@2190000 { + <&clks IMX6SX_CLK_USDHC1>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; ++ fsl,tuning-start-tap = <20>; ++ fsl,tuning-step= <2>; + status = "disabled"; + }; + +@@ -993,6 +995,8 @@ usdhc2: mmc@2194000 { + <&clks IMX6SX_CLK_USDHC2>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; ++ fsl,tuning-start-tap = <20>; ++ fsl,tuning-step= <2>; + status = "disabled"; + }; + +@@ -1005,6 +1009,8 @@ usdhc3: mmc@2198000 { + <&clks IMX6SX_CLK_USDHC3>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; ++ fsl,tuning-start-tap = <20>; ++ fsl,tuning-step= <2>; + status = "disabled"; + }; + +-- +2.43.0 + diff --git a/queue-5.10/asoc-fsl_micfil-register-platform-component-before-r.patch b/queue-5.10/asoc-fsl_micfil-register-platform-component-before-r.patch new file mode 100644 index 00000000000..70024d80ade --- /dev/null +++ b/queue-5.10/asoc-fsl_micfil-register-platform-component-before-r.patch @@ -0,0 +1,72 @@ +From 27d2db837f047f8e2a38ed810c8e83a4e755e12f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Sep 2021 18:30:04 +0800 +Subject: ASoC: fsl_micfil: register platform component before registering cpu + dai + +From: Shengjiu Wang + +[ Upstream commit 0adf292069dcca8bab76a603251fcaabf77468ca ] + +There is no defer probe when adding platform component to +snd_soc_pcm_runtime(rtd), the code is in snd_soc_add_pcm_runtime() + +snd_soc_register_card() + -> snd_soc_bind_card() + -> snd_soc_add_pcm_runtime() + -> adding cpu dai + -> adding codec dai + -> adding platform component. + +So if the platform component is not ready at that time, then the +sound card still registered successfully, but platform component +is empty, the sound card can't be used. + +As there is defer probe checking for cpu dai component, then register +platform component before cpu dai to avoid such issue. + +Fixes: 47a70e6fc9a8 ("ASoC: Add MICFIL SoC Digital Audio Interface driver.") +Signed-off-by: Shengjiu Wang +Link: https://lore.kernel.org/r/1630665006-31437-4-git-send-email-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/fsl_micfil.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c +index 97f83c63e7652..826829e3ff7a2 100644 +--- a/sound/soc/fsl/fsl_micfil.c ++++ b/sound/soc/fsl/fsl_micfil.c +@@ -756,18 +756,23 @@ static int fsl_micfil_probe(struct platform_device *pdev) + + pm_runtime_enable(&pdev->dev); + ++ /* ++ * Register platform component before registering cpu dai for there ++ * is not defer probe for platform component in snd_soc_add_pcm_runtime(). ++ */ ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to pcm register\n"); ++ return ret; ++ } ++ + ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component, + &fsl_micfil_dai, 1); + if (ret) { + dev_err(&pdev->dev, "failed to register component %s\n", + fsl_micfil_component.name); +- return ret; + } + +- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); +- if (ret) +- dev_err(&pdev->dev, "failed to pcm register\n"); +- + return ret; + } + +-- +2.43.0 + diff --git a/queue-5.10/asoc-intel-boards-get-codec-device-with-acpi-instead.patch b/queue-5.10/asoc-intel-boards-get-codec-device-with-acpi-instead.patch new file mode 100644 index 00000000000..ce178522d87 --- /dev/null +++ b/queue-5.10/asoc-intel-boards-get-codec-device-with-acpi-instead.patch @@ -0,0 +1,97 @@ +From 19d53b9cb499a7b6a94ebe015566b683d05d7962 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Aug 2021 10:11:11 -0500 +Subject: ASoC: Intel: boards: get codec device with ACPI instead of bus search + +From: Pierre-Louis Bossart + +[ Upstream commit d3409eb20d3ed7d9e021cd13243e9e63255a315f ] + +We have an existing 'adev' handle from which we can find the codec +device, no need for an I2C bus search. + +Suggested-by: Andy Shevchenko +Reviewed-by: Andy Shevchenko +Reviewed-by: Hans de Goede +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210813151116.23931-4-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Stable-dep-of: 721858823d7c ("ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after use") +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcht_es8316.c | 4 ++-- + sound/soc/intel/boards/bytcr_rt5640.c | 5 ++--- + sound/soc/intel/boards/bytcr_rt5651.c | 6 ++---- + 3 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c +index 91351b8536aa1..03b9cdbd3170f 100644 +--- a/sound/soc/intel/boards/bytcht_es8316.c ++++ b/sound/soc/intel/boards/bytcht_es8316.c +@@ -550,9 +550,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) + } + + /* get speaker enable GPIO */ +- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name); ++ codec_dev = acpi_get_first_physical_node(adev); + if (!codec_dev) + return -EPROBE_DEFER; ++ priv->codec_dev = get_device(codec_dev); + + if (quirk & BYT_CHT_ES8316_JD_INVERTED) + props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted"); +@@ -570,7 +571,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) + gpiod_get_index(codec_dev, "speaker-enable", 0, + /* see comment in byt_cht_es8316_resume */ + GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); +- priv->codec_dev = codec_dev; + + if (IS_ERR(priv->speaker_en_gpio)) { + ret = PTR_ERR(priv->speaker_en_gpio); +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index b531c348fb697..f5b1b3b876980 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -1425,11 +1425,10 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) + byt_rt5640_quirk = quirk_override; + } + +- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, byt_rt5640_codec_name); ++ codec_dev = acpi_get_first_physical_node(adev); + if (!codec_dev) + return -EPROBE_DEFER; +- +- priv->codec_dev = codec_dev; ++ priv->codec_dev = get_device(codec_dev); + + /* Must be called before register_card, also see declaration comment. */ + ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv); +diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c +index acea83e814acb..472f6e3327960 100644 +--- a/sound/soc/intel/boards/bytcr_rt5651.c ++++ b/sound/soc/intel/boards/bytcr_rt5651.c +@@ -926,10 +926,10 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + return -ENODEV; + } + +- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, +- byt_rt5651_codec_name); ++ codec_dev = acpi_get_first_physical_node(adev); + if (!codec_dev) + return -EPROBE_DEFER; ++ priv->codec_dev = get_device(codec_dev); + + /* + * swap SSP0 if bytcr is detected +@@ -996,8 +996,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + byt_rt5651_quirk = quirk_override; + } + +- priv->codec_dev = codec_dev; +- + /* Must be called before register_card, also see declaration comment. */ + ret_val = byt_rt5651_add_codec_device_props(codec_dev); + if (ret_val) +-- +2.43.0 + diff --git a/queue-5.10/asoc-intel-boards-harden-codec-property-handling.patch b/queue-5.10/asoc-intel-boards-harden-codec-property-handling.patch new file mode 100644 index 00000000000..92a199f894c --- /dev/null +++ b/queue-5.10/asoc-intel-boards-harden-codec-property-handling.patch @@ -0,0 +1,315 @@ +From ce2b0901f13d910f8b684e9b32044977ac085323 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Aug 2021 10:11:09 -0500 +Subject: ASoC: Intel: boards: harden codec property handling + +From: Pierre-Louis Bossart + +[ Upstream commit c50f126b3c9ebb77585838726a3a490ad33b92cd ] + +In current ACPI-based devices, the DSDT does not include any of the +properties required by the codec driver. This is not an ACPI +limitation proper since the _DSD method could be used, as done for +Camera and SoundWire in newer platforms. For legacy devices, there is +unfortunately no other option than using a work-around: we add +properties to the codec device from the machine driver. + +To avoid any issues with the codec driver being unbound, we need to +keep a reference to the codec device until the card is removed. + +Reviewed-by: Andy Shevchenko +Co-developed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20210813151116.23931-2-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Stable-dep-of: 721858823d7c ("ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after use") +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcht_es8316.c | 12 +++++-- + sound/soc/intel/boards/bytcr_rt5640.c | 47 +++++++++++++++++--------- + sound/soc/intel/boards/bytcr_rt5651.c | 37 +++++++++++++------- + 3 files changed, 64 insertions(+), 32 deletions(-) + +diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c +index 81269ed5a2aaa..91351b8536aa1 100644 +--- a/sound/soc/intel/boards/bytcht_es8316.c ++++ b/sound/soc/intel/boards/bytcht_es8316.c +@@ -37,6 +37,7 @@ struct byt_cht_es8316_private { + struct clk *mclk; + struct snd_soc_jack jack; + struct gpio_desc *speaker_en_gpio; ++ struct device *codec_dev; + bool speaker_en; + }; + +@@ -569,7 +570,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) + gpiod_get_index(codec_dev, "speaker-enable", 0, + /* see comment in byt_cht_es8316_resume */ + GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); +- put_device(codec_dev); ++ priv->codec_dev = codec_dev; + + if (IS_ERR(priv->speaker_en_gpio)) { + ret = PTR_ERR(priv->speaker_en_gpio); +@@ -581,7 +582,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) + dev_err(dev, "get speaker GPIO failed: %d\n", ret); + fallthrough; + case -EPROBE_DEFER: +- return ret; ++ goto err_put_codec; + } + } + +@@ -604,10 +605,14 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) + if (ret) { + gpiod_put(priv->speaker_en_gpio); + dev_err(dev, "snd_soc_register_card failed: %d\n", ret); +- return ret; ++ goto err_put_codec; + } + platform_set_drvdata(pdev, &byt_cht_es8316_card); + return 0; ++ ++err_put_codec: ++ put_device(priv->codec_dev); ++ return ret; + } + + static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) +@@ -616,6 +621,7 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) + struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); + + gpiod_put(priv->speaker_en_gpio); ++ put_device(priv->codec_dev); + return 0; + } + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 9a5ab96f917d3..b531c348fb697 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -86,6 +86,7 @@ enum { + struct byt_rt5640_private { + struct snd_soc_jack jack; + struct clk *mclk; ++ struct device *codec_dev; + }; + static bool is_bytcr; + +@@ -941,15 +942,11 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + * Note this MUST be called before snd_soc_register_card(), so that the props + * are in place before the codec component driver's probe function parses them. + */ +-static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) ++static int byt_rt5640_add_codec_device_props(struct device *i2c_dev, ++ struct byt_rt5640_private *priv) + { + struct property_entry props[MAX_NO_PROPS] = {}; +- struct device *i2c_dev; +- int ret, cnt = 0; +- +- i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name); +- if (!i2c_dev) +- return -EPROBE_DEFER; ++ int cnt = 0; + + switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { + case BYT_RT5640_DMIC1_MAP: +@@ -989,10 +986,7 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) + if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) + props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); + +- ret = device_add_properties(i2c_dev, props); +- put_device(i2c_dev); +- +- return ret; ++ return device_add_properties(i2c_dev, props); + } + + static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) +@@ -1324,6 +1318,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) + struct snd_soc_acpi_mach *mach; + const char *platform_name; + struct acpi_device *adev; ++ struct device *codec_dev; + int ret_val = 0; + int dai_index = 0; + int i, cfg_spk; +@@ -1430,10 +1425,16 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) + byt_rt5640_quirk = quirk_override; + } + ++ codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, byt_rt5640_codec_name); ++ if (!codec_dev) ++ return -EPROBE_DEFER; ++ ++ priv->codec_dev = codec_dev; ++ + /* Must be called before register_card, also see declaration comment. */ +- ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name); ++ ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv); + if (ret_val) +- return ret_val; ++ goto err; + + log_quirks(&pdev->dev); + +@@ -1460,7 +1461,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) + * for all other errors, including -EPROBE_DEFER + */ + if (ret_val != -ENOENT) +- return ret_val; ++ goto err; + byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; + } + } +@@ -1493,17 +1494,30 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) + ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, + platform_name); + if (ret_val) +- return ret_val; ++ goto err; + + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); + + if (ret_val) { + dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", + ret_val); +- return ret_val; ++ goto err; + } + platform_set_drvdata(pdev, &byt_rt5640_card); + return ret_val; ++ ++err: ++ put_device(priv->codec_dev); ++ return ret_val; ++} ++ ++static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); ++ ++ put_device(priv->codec_dev); ++ return 0; + } + + static struct platform_driver snd_byt_rt5640_mc_driver = { +@@ -1514,6 +1528,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = { + #endif + }, + .probe = snd_byt_rt5640_mc_probe, ++ .remove = snd_byt_rt5640_mc_remove, + }; + + module_platform_driver(snd_byt_rt5640_mc_driver); +diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c +index bf8b87d45cb0a..acea83e814acb 100644 +--- a/sound/soc/intel/boards/bytcr_rt5651.c ++++ b/sound/soc/intel/boards/bytcr_rt5651.c +@@ -85,6 +85,7 @@ struct byt_rt5651_private { + struct gpio_desc *ext_amp_gpio; + struct gpio_desc *hp_detect; + struct snd_soc_jack jack; ++ struct device *codec_dev; + }; + + static const struct acpi_gpio_mapping *byt_rt5651_gpios; +@@ -995,12 +996,12 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + byt_rt5651_quirk = quirk_override; + } + ++ priv->codec_dev = codec_dev; ++ + /* Must be called before register_card, also see declaration comment. */ + ret_val = byt_rt5651_add_codec_device_props(codec_dev); +- if (ret_val) { +- put_device(codec_dev); +- return ret_val; +- } ++ if (ret_val) ++ goto err; + + /* Cherry Trail devices use an external amplifier enable gpio */ + if (soc_intel_is_cht() && !byt_rt5651_gpios) +@@ -1024,8 +1025,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + ret_val); + fallthrough; + case -EPROBE_DEFER: +- put_device(codec_dev); +- return ret_val; ++ goto err; + } + } + priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev, +@@ -1044,14 +1044,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + ret_val); + fallthrough; + case -EPROBE_DEFER: +- put_device(codec_dev); +- return ret_val; ++ goto err; + } + } + } + +- put_device(codec_dev); +- + log_quirks(&pdev->dev); + + if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) || +@@ -1075,7 +1072,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + * for all other errors, including -EPROBE_DEFER + */ + if (ret_val != -ENOENT) +- return ret_val; ++ goto err; + byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN; + } + } +@@ -1104,17 +1101,30 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card, + platform_name); + if (ret_val) +- return ret_val; ++ goto err; + + ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card); + + if (ret_val) { + dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", + ret_val); +- return ret_val; ++ goto err; + } + platform_set_drvdata(pdev, &byt_rt5651_card); + return ret_val; ++ ++err: ++ put_device(priv->codec_dev); ++ return ret_val; ++} ++ ++static int snd_byt_rt5651_mc_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); ++ ++ put_device(priv->codec_dev); ++ return 0; + } + + static struct platform_driver snd_byt_rt5651_mc_driver = { +@@ -1125,6 +1135,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = { + #endif + }, + .probe = snd_byt_rt5651_mc_probe, ++ .remove = snd_byt_rt5651_mc_remove, + }; + + module_platform_driver(snd_byt_rt5651_mc_driver); +-- +2.43.0 + diff --git a/queue-5.10/asoc-intel-bytcr_rt5651-drop-reference-count-of-acpi.patch b/queue-5.10/asoc-intel-bytcr_rt5651-drop-reference-count-of-acpi.patch new file mode 100644 index 00000000000..6041c0916a3 --- /dev/null +++ b/queue-5.10/asoc-intel-bytcr_rt5651-drop-reference-count-of-acpi.patch @@ -0,0 +1,52 @@ +From 1496556315320f59ff3c3fa718cc28e4dbcde478 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Jan 2023 13:28:49 +0200 +Subject: ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after + use + +From: Andy Shevchenko + +[ Upstream commit 721858823d7cdc8f2a897579b040e935989f6f02 ] + +Theoretically the device might gone if its reference count drops to 0. +This might be the case when we try to find the first physical node of +the ACPI device. We need to keep reference to it until we get a result +of the above mentioned call. Refactor the code to drop the reference +count at the correct place. + +While at it, move to acpi_dev_put() as symmetrical call to the +acpi_dev_get_first_match_dev(). + +Fixes: 02c0a3b3047f ("ASoC: Intel: bytcr_rt5651: add MCLK, quirks and cleanups") +Signed-off-by: Andy Shevchenko +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20230112112852.67714-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5651.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c +index 472f6e3327960..a8289f74463e9 100644 +--- a/sound/soc/intel/boards/bytcr_rt5651.c ++++ b/sound/soc/intel/boards/bytcr_rt5651.c +@@ -919,7 +919,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + if (adev) { + snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), + "i2c-%s", acpi_dev_name(adev)); +- put_device(&adev->dev); + byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name; + } else { + dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); +@@ -927,6 +926,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) + } + + codec_dev = acpi_get_first_physical_node(adev); ++ acpi_dev_put(adev); + if (!codec_dev) + return -EPROBE_DEFER; + priv->codec_dev = get_device(codec_dev); +-- +2.43.0 + diff --git a/queue-5.10/block-ataflop-fix-breakage-introduced-at-blk-mq-refa.patch b/queue-5.10/block-ataflop-fix-breakage-introduced-at-blk-mq-refa.patch new file mode 100644 index 00000000000..6d2678e47e9 --- /dev/null +++ b/queue-5.10/block-ataflop-fix-breakage-introduced-at-blk-mq-refa.patch @@ -0,0 +1,118 @@ +From 4d9ab599060576628afbc9a33a6bfb026599b15e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Oct 2021 19:13:21 +1300 +Subject: block: ataflop: fix breakage introduced at blk-mq refactoring + +From: Michael Schmitz + +[ Upstream commit 86d46fdaa12ae5befc16b8d73fc85a3ca0399ea6 ] + +Refactoring of the Atari floppy driver when converting to blk-mq +has broken the state machine in not-so-subtle ways: + +finish_fdc() must be called when operations on the floppy device +have completed. This is crucial in order to relase the ST-DMA +lock, which protects against concurrent access to the ST-DMA +controller by other drivers (some DMA related, most just related +to device register access - broken beyond compare, I know). + +When rewriting the driver's old do_request() function, the fact +that finish_fdc() was called only when all queued requests had +completed appears to have been overlooked. Instead, the new +request function calls finish_fdc() immediately after the last +request has been queued. finish_fdc() executes a dummy seek after +most requests, and this overwrites the state machine's interrupt +hander that was set up to wait for completion of the read/write +request just prior. To make matters worse, finish_fdc() is called +before device interrupts are re-enabled, making certain that the +read/write interupt is missed. + +Shifting the finish_fdc() call into the read/write request +completion handler ensures the driver waits for the request to +actually complete. With a queue depth of 2, we won't see long +request sequences, so calling finish_fdc() unconditionally just +adds a little overhead for the dummy seeks, and keeps the code +simple. + +While we're at it, kill ataflop_commit_rqs() which does nothing +but run finish_fdc() unconditionally, again likely wiping out an +in-flight request. + +Signed-off-by: Michael Schmitz +Fixes: 6ec3938cff95 ("ataflop: convert to blk-mq") +CC: linux-block@vger.kernel.org +CC: Tetsuo Handa +Link: https://lore.kernel.org/r/20211019061321.26425-1-schmitzmic@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/ataflop.c | 18 +++--------------- + 1 file changed, 3 insertions(+), 15 deletions(-) + +diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c +index 3e881fdb06e0a..cd612cd04767a 100644 +--- a/drivers/block/ataflop.c ++++ b/drivers/block/ataflop.c +@@ -653,9 +653,6 @@ static inline void copy_buffer(void *from, void *to) + *p2++ = *p1++; + } + +- +- +- + /* General Interrupt Handling */ + + static void (*FloppyIRQHandler)( int status ) = NULL; +@@ -1225,6 +1222,7 @@ static void fd_rwsec_done1(int status) + } + else { + /* all sectors finished */ ++ finish_fdc(); + fd_end_request_cur(BLK_STS_OK); + } + return; +@@ -1472,15 +1470,6 @@ static void setup_req_params( int drive ) + ReqTrack, ReqSector, (unsigned long)ReqData )); + } + +-static void ataflop_commit_rqs(struct blk_mq_hw_ctx *hctx) +-{ +- spin_lock_irq(&ataflop_lock); +- atari_disable_irq(IRQ_MFP_FDC); +- finish_fdc(); +- atari_enable_irq(IRQ_MFP_FDC); +- spin_unlock_irq(&ataflop_lock); +-} +- + static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) + { +@@ -1488,6 +1477,8 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + int drive = floppy - unit; + int type = floppy->type; + ++ DPRINT(("Queue request: drive %d type %d last %d\n", drive, type, bd->last)); ++ + spin_lock_irq(&ataflop_lock); + if (fd_request) { + spin_unlock_irq(&ataflop_lock); +@@ -1547,8 +1538,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + setup_req_params( drive ); + do_fd_action( drive ); + +- if (bd->last) +- finish_fdc(); + atari_enable_irq( IRQ_MFP_FDC ); + + out: +@@ -1959,7 +1948,6 @@ static const struct block_device_operations floppy_fops = { + + static const struct blk_mq_ops ataflop_mq_ops = { + .queue_rq = ataflop_queue_rq, +- .commit_rqs = ataflop_commit_rqs, + }; + + static struct kobject *floppy_find(dev_t dev, int *part, void *data) +-- +2.43.0 + diff --git a/queue-5.10/btrfs-do-not-pin-logs-too-early-during-renames.patch b/queue-5.10/btrfs-do-not-pin-logs-too-early-during-renames.patch new file mode 100644 index 00000000000..3b2e865f100 --- /dev/null +++ b/queue-5.10/btrfs-do-not-pin-logs-too-early-during-renames.patch @@ -0,0 +1,244 @@ +From 79c2b66c9d8b013d9dc1c1a1f405603b143dc7fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jul 2021 11:24:45 +0100 +Subject: btrfs: do not pin logs too early during renames + +From: Filipe Manana + +[ Upstream commit bd54f381a12ac695593271a663d36d14220215b2 ] + +During renames we pin the logs of the roots a bit too early, before the +calls to btrfs_insert_inode_ref(). We can pin the logs after those calls, +since those will not change anything in a log tree. + +In a scenario where we have multiple and diverse filesystem operations +running in parallel, those calls can take a significant amount of time, +due to lock contention on extent buffers, and delay log commits from other +tasks for longer than necessary. + +So just pin logs after calls to btrfs_insert_inode_ref() and right before +the first operation that can update a log tree. + +The following script that uses dbench was used for testing: + + $ cat dbench-test.sh + #!/bin/bash + + DEV=/dev/nvme0n1 + MNT=/mnt/nvme0n1 + MOUNT_OPTIONS="-o ssd" + MKFS_OPTIONS="-m single -d single" + + echo "performance" | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor + + umount $DEV &> /dev/null + mkfs.btrfs -f $MKFS_OPTIONS $DEV + mount $MOUNT_OPTIONS $DEV $MNT + + dbench -D $MNT -t 120 16 + + umount $MNT + +The tests were run on a machine with 12 cores, 64G of RAN, a NVMe device +and using a non-debug kernel config (Debian's default config). + +The results compare a branch without this patch and without the previous +patch in the series, that has the subject: + + "btrfs: eliminate some false positives when checking if inode was logged" + +Versus the same branch with these two patches applied. + +dbench with 8 clients, results before: + + Operation Count AvgLat MaxLat + ---------------------------------------- + NTCreateX 4391359 0.009 249.745 + Close 3225882 0.001 3.243 + Rename 185953 0.065 240.643 + Unlink 886669 0.049 249.906 + Deltree 112 2.455 217.433 + Mkdir 56 0.002 0.004 + Qpathinfo 3980281 0.004 3.109 + Qfileinfo 697579 0.001 0.187 + Qfsinfo 729780 0.002 2.424 + Sfileinfo 357764 0.004 1.415 + Find 1538861 0.016 4.863 + WriteX 2189666 0.010 3.327 + ReadX 6883443 0.002 0.729 + LockX 14298 0.002 0.073 + UnlockX 14298 0.001 0.042 + Flush 307777 2.447 303.663 + +Throughput 1149.6 MB/sec 8 clients 8 procs max_latency=303.666 ms + +dbench with 8 clients, results after: + + Operation Count AvgLat MaxLat + ---------------------------------------- + NTCreateX 4269920 0.009 213.532 + Close 3136653 0.001 0.690 + Rename 180805 0.082 213.858 + Unlink 862189 0.050 172.893 + Deltree 112 2.998 218.328 + Mkdir 56 0.002 0.003 + Qpathinfo 3870158 0.004 5.072 + Qfileinfo 678375 0.001 0.194 + Qfsinfo 709604 0.002 0.485 + Sfileinfo 347850 0.004 1.304 + Find 1496310 0.017 5.504 + WriteX 2129613 0.010 2.882 + ReadX 6693066 0.002 1.517 + LockX 13902 0.002 0.075 + UnlockX 13902 0.001 0.055 + Flush 299276 2.511 220.189 + +Throughput 1187.33 MB/sec 8 clients 8 procs max_latency=220.194 ms + ++3.2% throughput, -31.8% max latency + +dbench with 16 clients, results before: + + Operation Count AvgLat MaxLat + ---------------------------------------- + NTCreateX 5978334 0.028 156.507 + Close 4391598 0.001 1.345 + Rename 253136 0.241 155.057 + Unlink 1207220 0.182 257.344 + Deltree 160 6.123 36.277 + Mkdir 80 0.003 0.005 + Qpathinfo 5418817 0.012 6.867 + Qfileinfo 949929 0.001 0.941 + Qfsinfo 993560 0.002 1.386 + Sfileinfo 486904 0.004 2.829 + Find 2095088 0.059 8.164 + WriteX 2982319 0.017 9.029 + ReadX 9371484 0.002 4.052 + LockX 19470 0.002 0.461 + UnlockX 19470 0.001 0.990 + Flush 418936 2.740 347.902 + +Throughput 1495.31 MB/sec 16 clients 16 procs max_latency=347.909 ms + +dbench with 16 clients, results after: + + Operation Count AvgLat MaxLat + ---------------------------------------- + NTCreateX 5711833 0.029 131.240 + Close 4195897 0.001 1.732 + Rename 241849 0.204 147.831 + Unlink 1153341 0.184 231.322 + Deltree 160 6.086 30.198 + Mkdir 80 0.003 0.021 + Qpathinfo 5177011 0.012 7.150 + Qfileinfo 907768 0.001 0.793 + Qfsinfo 949205 0.002 1.431 + Sfileinfo 465317 0.004 2.454 + Find 2001541 0.058 7.819 + WriteX 2850661 0.017 9.110 + ReadX 8952289 0.002 3.991 + LockX 18596 0.002 0.655 + UnlockX 18596 0.001 0.179 + Flush 400342 2.879 293.607 + +Throughput 1565.73 MB/sec 16 clients 16 procs max_latency=293.611 ms + ++4.6% throughput, -16.9% max latency + +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 6 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 250b6064876de..591caac2bf814 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8968,8 +8968,6 @@ static int btrfs_rename_exchange(struct inode *old_dir, + /* force full log commit if subvolume involved. */ + btrfs_set_log_full_commit(trans); + } else { +- btrfs_pin_log_trans(root); +- root_log_pinned = true; + ret = btrfs_insert_inode_ref(trans, dest, + new_dentry->d_name.name, + new_dentry->d_name.len, +@@ -8986,8 +8984,6 @@ static int btrfs_rename_exchange(struct inode *old_dir, + /* force full log commit if subvolume involved. */ + btrfs_set_log_full_commit(trans); + } else { +- btrfs_pin_log_trans(dest); +- dest_log_pinned = true; + ret = btrfs_insert_inode_ref(trans, root, + old_dentry->d_name.name, + old_dentry->d_name.len, +@@ -9018,6 +9014,29 @@ static int btrfs_rename_exchange(struct inode *old_dir, + BTRFS_I(new_inode), 1); + } + ++ /* ++ * Now pin the logs of the roots. We do it to ensure that no other task ++ * can sync the logs while we are in progress with the rename, because ++ * that could result in an inconsistency in case any of the inodes that ++ * are part of this rename operation were logged before. ++ * ++ * We pin the logs even if at this precise moment none of the inodes was ++ * logged before. This is because right after we checked for that, some ++ * other task fsyncing some other inode not involved with this rename ++ * operation could log that one of our inodes exists. ++ * ++ * We don't need to pin the logs before the above calls to ++ * btrfs_insert_inode_ref(), since those don't ever need to change a log. ++ */ ++ if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { ++ btrfs_pin_log_trans(root); ++ root_log_pinned = true; ++ } ++ if (new_ino != BTRFS_FIRST_FREE_OBJECTID) { ++ btrfs_pin_log_trans(dest); ++ dest_log_pinned = true; ++ } ++ + /* src is a subvolume */ + if (old_ino == BTRFS_FIRST_FREE_OBJECTID) { + ret = btrfs_unlink_subvol(trans, old_dir, old_dentry); +@@ -9267,8 +9286,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, + /* force full log commit if subvolume involved. */ + btrfs_set_log_full_commit(trans); + } else { +- btrfs_pin_log_trans(root); +- log_pinned = true; + ret = btrfs_insert_inode_ref(trans, dest, + new_dentry->d_name.name, + new_dentry->d_name.len, +@@ -9292,6 +9309,25 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, + if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) { + ret = btrfs_unlink_subvol(trans, old_dir, old_dentry); + } else { ++ /* ++ * Now pin the log. We do it to ensure that no other task can ++ * sync the log while we are in progress with the rename, as ++ * that could result in an inconsistency in case any of the ++ * inodes that are part of this rename operation were logged ++ * before. ++ * ++ * We pin the log even if at this precise moment none of the ++ * inodes was logged before. This is because right after we ++ * checked for that, some other task fsyncing some other inode ++ * not involved with this rename operation could log that one of ++ * our inodes exists. ++ * ++ * We don't need to pin the logs before the above call to ++ * btrfs_insert_inode_ref(), since that does not need to change ++ * a log. ++ */ ++ btrfs_pin_log_trans(root); ++ log_pinned = true; + ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir), + BTRFS_I(d_inode(old_dentry)), + old_dentry->d_name.name, +-- +2.43.0 + diff --git a/queue-5.10/btrfs-introduce-btrfs_lookup_match_dir.patch b/queue-5.10/btrfs-introduce-btrfs_lookup_match_dir.patch new file mode 100644 index 00000000000..9de62d5a47a --- /dev/null +++ b/queue-5.10/btrfs-introduce-btrfs_lookup_match_dir.patch @@ -0,0 +1,176 @@ +From cd669746950cf7389ef38fbf8e7916ccde0ba699 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Jul 2021 16:19:09 -0300 +Subject: btrfs: introduce btrfs_lookup_match_dir + +From: Marcos Paulo de Souza + +[ Upstream commit a7d1c5dc8632e9b370ad26478c468d4e4e29f263 ] + +btrfs_search_slot is called in multiple places in dir-item.c to search +for a dir entry, and then calling btrfs_match_dir_name to return a +btrfs_dir_item. + +In order to reduce the number of callers of btrfs_search_slot, create a +common function that looks for the dir key, and if found call +btrfs_match_dir_item_name. + +Signed-off-by: Marcos Paulo de Souza +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Stable-dep-of: 8dcbc26194eb ("btrfs: unify lookup return value when dir entry is missing") +Signed-off-by: Sasha Levin +--- + fs/btrfs/dir-item.c | 76 +++++++++++++++++++++++---------------------- + 1 file changed, 39 insertions(+), 37 deletions(-) + +diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c +index 863367c2c6205..1c0a7cd6b9b0a 100644 +--- a/fs/btrfs/dir-item.c ++++ b/fs/btrfs/dir-item.c +@@ -171,6 +171,25 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, const char *name, + return 0; + } + ++static struct btrfs_dir_item *btrfs_lookup_match_dir( ++ struct btrfs_trans_handle *trans, ++ struct btrfs_root *root, struct btrfs_path *path, ++ struct btrfs_key *key, const char *name, ++ int name_len, int mod) ++{ ++ const int ins_len = (mod < 0 ? -1 : 0); ++ const int cow = (mod != 0); ++ int ret; ++ ++ ret = btrfs_search_slot(trans, root, key, path, ins_len, cow); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ if (ret > 0) ++ return ERR_PTR(-ENOENT); ++ ++ return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); ++} ++ + /* + * lookup a directory item based on name. 'dir' is the objectid + * we're searching in, and 'mod' tells us if you plan on deleting the +@@ -182,23 +201,18 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, + const char *name, int name_len, + int mod) + { +- int ret; + struct btrfs_key key; +- int ins_len = mod < 0 ? -1 : 0; +- int cow = mod != 0; ++ struct btrfs_dir_item *di; + + key.objectid = dir; + key.type = BTRFS_DIR_ITEM_KEY; +- + key.offset = btrfs_name_hash(name, name_len); + +- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); +- if (ret < 0) +- return ERR_PTR(ret); +- if (ret > 0) ++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); ++ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT) + return NULL; + +- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); ++ return di; + } + + int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, +@@ -212,7 +226,6 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, + int slot; + struct btrfs_path *path; + +- + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +@@ -221,20 +234,20 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, + key.type = BTRFS_DIR_ITEM_KEY; + key.offset = btrfs_name_hash(name, name_len); + +- ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); +- +- /* return back any errors */ +- if (ret < 0) +- goto out; ++ di = btrfs_lookup_match_dir(NULL, root, path, &key, name, name_len, 0); ++ if (IS_ERR(di)) { ++ ret = PTR_ERR(di); ++ /* Nothing found, we're safe */ ++ if (ret == -ENOENT) { ++ ret = 0; ++ goto out; ++ } + +- /* nothing found, we're safe */ +- if (ret > 0) { +- ret = 0; +- goto out; ++ if (ret < 0) ++ goto out; + } + + /* we found an item, look for our name in the item */ +- di = btrfs_match_dir_item_name(root->fs_info, path, name, name_len); + if (di) { + /* our exact name was found */ + ret = -EEXIST; +@@ -275,21 +288,13 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, + u64 objectid, const char *name, int name_len, + int mod) + { +- int ret; + struct btrfs_key key; +- int ins_len = mod < 0 ? -1 : 0; +- int cow = mod != 0; + + key.objectid = dir; + key.type = BTRFS_DIR_INDEX_KEY; + key.offset = objectid; + +- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); +- if (ret < 0) +- return ERR_PTR(ret); +- if (ret > 0) +- return ERR_PTR(-ENOENT); +- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); ++ return btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); + } + + struct btrfs_dir_item * +@@ -346,21 +351,18 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + const char *name, u16 name_len, + int mod) + { +- int ret; + struct btrfs_key key; +- int ins_len = mod < 0 ? -1 : 0; +- int cow = mod != 0; ++ struct btrfs_dir_item *di; + + key.objectid = dir; + key.type = BTRFS_XATTR_ITEM_KEY; + key.offset = btrfs_name_hash(name, name_len); +- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); +- if (ret < 0) +- return ERR_PTR(ret); +- if (ret > 0) ++ ++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); ++ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT) + return NULL; + +- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); ++ return di; + } + + /* +-- +2.43.0 + diff --git a/queue-5.10/btrfs-tree-checker-check-for-overlapping-extent-item.patch b/queue-5.10/btrfs-tree-checker-check-for-overlapping-extent-item.patch new file mode 100644 index 00000000000..5202c754704 --- /dev/null +++ b/queue-5.10/btrfs-tree-checker-check-for-overlapping-extent-item.patch @@ -0,0 +1,77 @@ +From 0599d520506883b8e0763e2949d668c60aa7c8bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 14:28:47 -0400 +Subject: btrfs: tree-checker: check for overlapping extent items + +From: Josef Bacik + +[ Upstream commit 899b7f69f244e539ea5df1b4d756046337de44a5 ] + +We're seeing a weird problem in production where we have overlapping +extent items in the extent tree. It's unclear where these are coming +from, and in debugging we realized there's no check in the tree checker +for this sort of problem. Add a check to the tree-checker to make sure +that the extents do not overlap each other. + +Reviewed-by: Qu Wenruo +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/tree-checker.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index c0eda3816f685..5b952f69bc1f6 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -1189,7 +1189,8 @@ static void extent_err(const struct extent_buffer *eb, int slot, + } + + static int check_extent_item(struct extent_buffer *leaf, +- struct btrfs_key *key, int slot) ++ struct btrfs_key *key, int slot, ++ struct btrfs_key *prev_key) + { + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_extent_item *ei; +@@ -1400,6 +1401,26 @@ static int check_extent_item(struct extent_buffer *leaf, + total_refs, inline_refs); + return -EUCLEAN; + } ++ ++ if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) || ++ (prev_key->type == BTRFS_METADATA_ITEM_KEY)) { ++ u64 prev_end = prev_key->objectid; ++ ++ if (prev_key->type == BTRFS_METADATA_ITEM_KEY) ++ prev_end += fs_info->nodesize; ++ else ++ prev_end += prev_key->offset; ++ ++ if (unlikely(prev_end > key->objectid)) { ++ extent_err(leaf, slot, ++ "previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]", ++ prev_key->objectid, prev_key->type, ++ prev_key->offset, key->objectid, key->type, ++ key->offset); ++ return -EUCLEAN; ++ } ++ } ++ + return 0; + } + +@@ -1568,7 +1589,7 @@ static int check_leaf_item(struct extent_buffer *leaf, + break; + case BTRFS_EXTENT_ITEM_KEY: + case BTRFS_METADATA_ITEM_KEY: +- ret = check_extent_item(leaf, key, slot); ++ ret = check_extent_item(leaf, key, slot, prev_key); + break; + case BTRFS_TREE_BLOCK_REF_KEY: + case BTRFS_SHARED_DATA_REF_KEY: +-- +2.43.0 + diff --git a/queue-5.10/btrfs-unify-lookup-return-value-when-dir-entry-is-mi.patch b/queue-5.10/btrfs-unify-lookup-return-value-when-dir-entry-is-mi.patch new file mode 100644 index 00000000000..0fdd1cc556e --- /dev/null +++ b/queue-5.10/btrfs-unify-lookup-return-value-when-dir-entry-is-mi.patch @@ -0,0 +1,187 @@ +From a5dd6c29a25b5f8b2be106733df3d0b5e1c92e41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Oct 2021 13:52:33 +0100 +Subject: btrfs: unify lookup return value when dir entry is missing + +From: Filipe Manana + +[ Upstream commit 8dcbc26194eb872cc3430550fb70bb461424d267 ] + +btrfs_lookup_dir_index_item() and btrfs_lookup_dir_item() lookup for dir +entries and both are used during log replay or when updating a log tree +during an unlink. + +However when the dir item does not exists, btrfs_lookup_dir_item() returns +NULL while btrfs_lookup_dir_index_item() returns PTR_ERR(-ENOENT), and if +the dir item exists but there is no matching entry for a given name or +index, both return NULL. This makes the call sites during log replay to +be more verbose than necessary and it makes it easy to miss this slight +difference. Since we don't need to distinguish between those two cases, +make btrfs_lookup_dir_index_item() always return NULL when there is no +matching directory entry - either because there isn't any dir entry or +because there is one but it does not match the given name and index. + +Also rename the argument 'objectid' of btrfs_lookup_dir_index_item() to +'index' since it is supposed to match an index number, and the name +'objectid' is not very good because it can easily be confused with an +inode number (like the inode number a dir entry points to). + +CC: stable@vger.kernel.org # 4.14+ +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/ctree.h | 2 +- + fs/btrfs/dir-item.c | 48 ++++++++++++++++++++++++++++++++++----------- + fs/btrfs/tree-log.c | 14 ++++--------- + 3 files changed, 42 insertions(+), 22 deletions(-) + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 67831868ef0de..3ddb09f2b1685 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -2879,7 +2879,7 @@ struct btrfs_dir_item * + btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, +- u64 objectid, const char *name, int name_len, ++ u64 index, const char *name, int name_len, + int mod); + struct btrfs_dir_item * + btrfs_search_dir_index_item(struct btrfs_root *root, +diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c +index 1c0a7cd6b9b0a..98c6faa8ce15b 100644 +--- a/fs/btrfs/dir-item.c ++++ b/fs/btrfs/dir-item.c +@@ -191,9 +191,20 @@ static struct btrfs_dir_item *btrfs_lookup_match_dir( + } + + /* +- * lookup a directory item based on name. 'dir' is the objectid +- * we're searching in, and 'mod' tells us if you plan on deleting the +- * item (use mod < 0) or changing the options (use mod > 0) ++ * Lookup for a directory item by name. ++ * ++ * @trans: The transaction handle to use. Can be NULL if @mod is 0. ++ * @root: The root of the target tree. ++ * @path: Path to use for the search. ++ * @dir: The inode number (objectid) of the directory. ++ * @name: The name associated to the directory entry we are looking for. ++ * @name_len: The length of the name. ++ * @mod: Used to indicate if the tree search is meant for a read only ++ * lookup, for a modification lookup or for a deletion lookup, so ++ * its value should be 0, 1 or -1, respectively. ++ * ++ * Returns: NULL if the dir item does not exists, an error pointer if an error ++ * happened, or a pointer to a dir item if a dir item exists for the given name. + */ + struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, +@@ -274,27 +285,42 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, + } + + /* +- * lookup a directory item based on index. 'dir' is the objectid +- * we're searching in, and 'mod' tells us if you plan on deleting the +- * item (use mod < 0) or changing the options (use mod > 0) ++ * Lookup for a directory index item by name and index number. + * +- * The name is used to make sure the index really points to the name you were +- * looking for. ++ * @trans: The transaction handle to use. Can be NULL if @mod is 0. ++ * @root: The root of the target tree. ++ * @path: Path to use for the search. ++ * @dir: The inode number (objectid) of the directory. ++ * @index: The index number. ++ * @name: The name associated to the directory entry we are looking for. ++ * @name_len: The length of the name. ++ * @mod: Used to indicate if the tree search is meant for a read only ++ * lookup, for a modification lookup or for a deletion lookup, so ++ * its value should be 0, 1 or -1, respectively. ++ * ++ * Returns: NULL if the dir index item does not exists, an error pointer if an ++ * error happened, or a pointer to a dir item if the dir index item exists and ++ * matches the criteria (name and index number). + */ + struct btrfs_dir_item * + btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, +- u64 objectid, const char *name, int name_len, ++ u64 index, const char *name, int name_len, + int mod) + { ++ struct btrfs_dir_item *di; + struct btrfs_key key; + + key.objectid = dir; + key.type = BTRFS_DIR_INDEX_KEY; +- key.offset = objectid; ++ key.offset = index; + +- return btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); ++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod); ++ if (di == ERR_PTR(-ENOENT)) ++ return NULL; ++ ++ return di; + } + + struct btrfs_dir_item * +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 10a0913ffb492..34e9eb5010cda 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -912,8 +912,7 @@ static noinline int inode_in_dir(struct btrfs_root *root, + di = btrfs_lookup_dir_index_item(NULL, root, path, dirid, + index, name, name_len, 0); + if (IS_ERR(di)) { +- if (PTR_ERR(di) != -ENOENT) +- ret = PTR_ERR(di); ++ ret = PTR_ERR(di); + goto out; + } else if (di) { + btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location); +@@ -1149,8 +1148,7 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, + di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir), + ref_index, name, namelen, 0); + if (IS_ERR(di)) { +- if (PTR_ERR(di) != -ENOENT) +- return PTR_ERR(di); ++ return PTR_ERR(di); + } else if (di) { + ret = drop_one_dir_item(trans, root, path, dir, di); + if (ret) +@@ -1976,9 +1974,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, + goto out; + } + +- if (dst_di == ERR_PTR(-ENOENT)) +- dst_di = NULL; +- + if (IS_ERR(dst_di)) { + ret = PTR_ERR(dst_di); + goto out; +@@ -2286,7 +2281,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans, + dir_key->offset, + name, name_len, 0); + } +- if (!log_di || log_di == ERR_PTR(-ENOENT)) { ++ if (!log_di) { + btrfs_dir_item_key_to_cpu(eb, di, &location); + btrfs_release_path(path); + btrfs_release_path(log_path); +@@ -3495,8 +3490,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, + if (err == -ENOSPC) { + btrfs_set_log_full_commit(trans); + err = 0; +- } else if (err < 0 && err != -ENOENT) { +- /* ENOENT can be returned if the entry hasn't been fsynced yet */ ++ } else if (err < 0) { + btrfs_abort_transaction(trans, err); + } + +-- +2.43.0 + diff --git a/queue-5.10/cifs-add-a-warning-when-the-in-flight-count-goes-neg.patch b/queue-5.10/cifs-add-a-warning-when-the-in-flight-count-goes-neg.patch new file mode 100644 index 00000000000..357b7e3b6ff --- /dev/null +++ b/queue-5.10/cifs-add-a-warning-when-the-in-flight-count-goes-neg.patch @@ -0,0 +1,38 @@ +From 2f3e26abcc335b77e4bf8176b6351f462bd7ab12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Jun 2023 17:46:56 +0000 +Subject: cifs: add a warning when the in-flight count goes negative + +From: Shyam Prasad N + +[ Upstream commit e4645cc2f1e2d6f268bb8dcfac40997c52432aed ] + +We've seen the in-flight count go into negative with some +internal stress testing in Microsoft. + +Adding a WARN when this happens, in hope of understanding +why this happens when it happens. + +Signed-off-by: Shyam Prasad N +Reviewed-by: Bharath SM +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2ops.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index f83901c1c17a5..b2a7238a34221 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -82,6 +82,7 @@ smb2_add_credits(struct TCP_Server_Info *server, + *val = 65000; /* Don't get near 64K credits, avoid srv bugs */ + pr_warn_once("server overflowed SMB3 credits\n"); + } ++ WARN_ON_ONCE(server->in_flight == 0); + server->in_flight--; + if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP) + rc = change_conf(server); +-- +2.43.0 + diff --git a/queue-5.10/hsr-avoid-double-remove-of-a-node.patch b/queue-5.10/hsr-avoid-double-remove-of-a-node.patch new file mode 100644 index 00000000000..e59bddbe5d7 --- /dev/null +++ b/queue-5.10/hsr-avoid-double-remove-of-a-node.patch @@ -0,0 +1,85 @@ +From 04e6ec71cc692c92adc9cc18d1adb0c0abd1407b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:10 +0100 +Subject: hsr: Avoid double remove of a node. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 0c74d9f79ec4299365bbe803baa736ae0068179e ] + +Due to the hashed-MAC optimisation one problem become visible: +hsr_handle_sup_frame() walks over the list of available nodes and merges +two node entries into one if based on the information in the supervision +both MAC addresses belong to one node. The list-walk happens on a RCU +protected list and delete operation happens under a lock. + +If the supervision arrives on both slave interfaces at the same time +then this delete operation can occur simultaneously on two CPUs. The +result is the first-CPU deletes the from the list and the second CPUs +BUGs while attempting to dereference a poisoned list-entry. This happens +more likely with the optimisation because a new node for the mac_B entry +is created once a packet has been received and removed (merged) once the +supervision frame has been received. + +Avoid removing/ cleaning up a hsr_node twice by adding a `removed' field +which is set to true after the removal and checked before the removal. + +Fixes: f266a683a4804 ("net/hsr: Better frame dispatch") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_framereg.c | 16 +++++++++++----- + net/hsr/hsr_framereg.h | 1 + + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index afc97d65cf2d8..87fc86aade5c9 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -327,9 +327,12 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + node_real->addr_B_port = port_rcv->type; + + spin_lock_bh(&hsr->list_lock); +- list_del_rcu(&node_curr->mac_list); ++ if (!node_curr->removed) { ++ list_del_rcu(&node_curr->mac_list); ++ node_curr->removed = true; ++ kfree_rcu(node_curr, rcu_head); ++ } + spin_unlock_bh(&hsr->list_lock); +- kfree_rcu(node_curr, rcu_head); + + done: + /* PRP uses v0 header */ +@@ -506,9 +509,12 @@ void hsr_prune_nodes(struct timer_list *t) + if (time_is_before_jiffies(timestamp + + msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { + hsr_nl_nodedown(hsr, node->macaddress_A); +- list_del_rcu(&node->mac_list); +- /* Note that we need to free this entry later: */ +- kfree_rcu(node, rcu_head); ++ if (!node->removed) { ++ list_del_rcu(&node->mac_list); ++ node->removed = true; ++ /* Note that we need to free this entry later: */ ++ kfree_rcu(node, rcu_head); ++ } + } + } + spin_unlock_bh(&hsr->list_lock); +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index 5a771cb3f0325..48990166e4c4e 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -82,6 +82,7 @@ struct hsr_node { + bool san_a; + bool san_b; + u16 seq_out[HSR_PT_PORTS]; ++ bool removed; + struct rcu_head rcu_head; + }; + +-- +2.43.0 + diff --git a/queue-5.10/hvc-xen-prevent-concurrent-accesses-to-the-shared-ri.patch b/queue-5.10/hvc-xen-prevent-concurrent-accesses-to-the-shared-ri.patch new file mode 100644 index 00000000000..71d61686170 --- /dev/null +++ b/queue-5.10/hvc-xen-prevent-concurrent-accesses-to-the-shared-ri.patch @@ -0,0 +1,147 @@ +From 3c62db5430ed3b672d215d4106bc0732f6c479bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 16:09:11 +0100 +Subject: hvc/xen: prevent concurrent accesses to the shared ring +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +[ Upstream commit 6214894f49a967c749ee6c07cb00f9cede748df4 ] + +The hvc machinery registers both a console and a tty device based on +the hv ops provided by the specific implementation. Those two +interfaces however have different locks, and there's no single locks +that's shared between the tty and the console implementations, hence +the driver needs to protect itself against concurrent accesses. +Otherwise concurrent calls using the split interfaces are likely to +corrupt the ring indexes, leaving the console unusable. + +Introduce a lock to xencons_info to serialize accesses to the shared +ring. This is only required when using the shared memory console, +concurrent accesses to the hypercall based console implementation are +not an issue. + +Note the conditional logic in domU_read_console() is slightly modified +so the notify_daemon() call can be done outside of the locked region: +it's an hypercall and there's no need for it to be done with the lock +held. + +Fixes: b536b4b96230 ('xen: use the hvc console infrastructure for Xen console') +Signed-off-by: Roger Pau Monné +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/r/20221130150919.13935-1-roger.pau@citrix.com +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/tty/hvc/hvc_xen.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index cf0fb650a9247..4886cad0fde61 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -43,6 +43,7 @@ struct xencons_info { + int irq; + int vtermno; + grant_ref_t gntref; ++ spinlock_t ring_lock; + }; + + static LIST_HEAD(xenconsoles); +@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons, + XENCONS_RING_IDX cons, prod; + struct xencons_interface *intf = xencons->intf; + int sent = 0; ++ unsigned long flags; + ++ spin_lock_irqsave(&xencons->ring_lock, flags); + cons = intf->out_cons; + prod = intf->out_prod; + mb(); /* update queue values before going on */ + + if ((prod - cons) > sizeof(intf->out)) { ++ spin_unlock_irqrestore(&xencons->ring_lock, flags); + pr_err_once("xencons: Illegal ring page indices"); + return -EINVAL; + } +@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons, + + wmb(); /* write ring before updating pointer */ + intf->out_prod = prod; ++ spin_unlock_irqrestore(&xencons->ring_lock, flags); + + if (sent) + notify_daemon(xencons); +@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + int recv = 0; + struct xencons_info *xencons = vtermno_to_xencons(vtermno); + unsigned int eoiflag = 0; ++ unsigned long flags; + + if (xencons == NULL) + return -EINVAL; + intf = xencons->intf; + ++ spin_lock_irqsave(&xencons->ring_lock, flags); + cons = intf->in_cons; + prod = intf->in_prod; + mb(); /* get pointers before reading ring */ + + if ((prod - cons) > sizeof(intf->in)) { ++ spin_unlock_irqrestore(&xencons->ring_lock, flags); + pr_err_once("xencons: Illegal ring page indices"); + return -EINVAL; + } +@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + xencons->out_cons = intf->out_cons; + xencons->out_cons_same = 0; + } ++ if (!recv && xencons->out_cons_same++ > 1) { ++ eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ } ++ spin_unlock_irqrestore(&xencons->ring_lock, flags); ++ + if (recv) { + notify_daemon(xencons); +- } else if (xencons->out_cons_same++ > 1) { +- eoiflag = XEN_EOI_FLAG_SPURIOUS; + } + + xen_irq_lateeoi(xencons->irq, eoiflag); +@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void) + info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); + if (!info) + return -ENOMEM; ++ spin_lock_init(&info->ring_lock); + } else if (info->intf != NULL) { + /* already configured */ + return 0; +@@ -275,6 +287,7 @@ static int xen_hvm_console_init(void) + + static int xencons_info_pv_init(struct xencons_info *info, int vtermno) + { ++ spin_lock_init(&info->ring_lock); + info->evtchn = xen_start_info->console.domU.evtchn; + /* GFN == MFN for PV guest */ + info->intf = gfn_to_virt(xen_start_info->console.domU.mfn); +@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void) + info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); + if (!info) + return -ENOMEM; ++ spin_lock_init(&info->ring_lock); + } + + info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false); +@@ -485,6 +499,7 @@ static int xencons_probe(struct xenbus_device *dev, + info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); + if (!info) + return -ENOMEM; ++ spin_lock_init(&info->ring_lock); + dev_set_drvdata(&dev->dev, info); + info->xbdev = dev; + info->vtermno = xenbus_devid_to_vtermno(devid); +-- +2.43.0 + diff --git a/queue-5.10/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-inter.patch b/queue-5.10/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-inter.patch new file mode 100644 index 00000000000..6771271ec69 --- /dev/null +++ b/queue-5.10/irqchip-mips-gic-don-t-touch-vl_map-if-a-local-inter.patch @@ -0,0 +1,51 @@ +From ac8d057dd9d9bd6574fdcde88522ae9c81be174b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Apr 2023 11:31:55 +0100 +Subject: irqchip/mips-gic: Don't touch vl_map if a local interrupt is not + routable + +From: Jiaxun Yang + +[ Upstream commit 2c6c9c049510163090b979ea5f92a68ae8d93c45 ] + +When a GIC local interrupt is not routable, it's vl_map will be used +to control some internal states for core (providing IPTI, IPPCI, IPFDC +input signal for core). Overriding it will interfere core's intetrupt +controller. + +Do not touch vl_map if a local interrupt is not routable, we are not +going to remap it. + +Before dd098a0e0319 (" irqchip/mips-gic: Get rid of the reliance on +irq_cpu_online()"), if a local interrupt is not routable, then it won't +be requested from GIC Local domain, and thus gic_all_vpes_irq_cpu_online +won't be called for that particular interrupt. + +Fixes: dd098a0e0319 (" irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()") +Cc: stable@vger.kernel.org +Signed-off-by: Jiaxun Yang +Reviewed-by: Serge Semin +Tested-by: Serge Semin +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230424103156.66753-2-jiaxun.yang@flygoat.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-mips-gic.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c +index fc25b900cef71..7888e3c08df40 100644 +--- a/drivers/irqchip/irq-mips-gic.c ++++ b/drivers/irqchip/irq-mips-gic.c +@@ -398,6 +398,8 @@ static void gic_all_vpes_irq_cpu_online(void) + unsigned int intr = local_intrs[i]; + struct gic_all_vpes_chip_data *cd; + ++ if (!gic_local_irq_is_routable(intr)) ++ continue; + cd = &gic_all_vpes_chip_data[intr]; + write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); + if (cd->mask) +-- +2.43.0 + diff --git a/queue-5.10/iwlwifi-mvm-do-more-useful-queue-sync-accounting.patch b/queue-5.10/iwlwifi-mvm-do-more-useful-queue-sync-accounting.patch new file mode 100644 index 00000000000..a088f62d912 --- /dev/null +++ b/queue-5.10/iwlwifi-mvm-do-more-useful-queue-sync-accounting.patch @@ -0,0 +1,114 @@ +From 097431a2b270f8ecce1b799de76e1050293283e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Dec 2020 23:16:31 +0200 +Subject: iwlwifi: mvm: do more useful queue sync accounting + +From: Johannes Berg + +[ Upstream commit 2f7a04c7b03b7fd63b7618e29295fc25732faac1 ] + +We're currently doing accounting on the queue sync with an +atomic variable that counts down the number of remaining +notifications that we still need. + +As we've been hitting issues in this area, modify this to +track a bitmap of queues, not just the number of queues, +and print out the remaining bitmap in the warning. + +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20201209231352.0a3fa177cd6b.I7c69ff999419368266279ec27dd618eb450908b3@changeid +Signed-off-by: Luca Coelho +Stable-dep-of: 5f8a3561ea8b ("iwlwifi: mvm: write queue_sync_state only for sync") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 11 ++++++----- + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +- + drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 10 +++++++--- + 4 files changed, 15 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index d2c6fdb702732..f2096729ac5ac 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -5155,8 +5155,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, + + if (notif->sync) { + notif->cookie = mvm->queue_sync_cookie; +- atomic_set(&mvm->queue_sync_counter, +- mvm->trans->num_rx_queues); ++ mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1; + } + + ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, +@@ -5169,14 +5168,16 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, + if (notif->sync) { + lockdep_assert_held(&mvm->mutex); + ret = wait_event_timeout(mvm->rx_sync_waitq, +- atomic_read(&mvm->queue_sync_counter) == 0 || ++ READ_ONCE(mvm->queue_sync_state) == 0 || + iwl_mvm_is_radio_killed(mvm), + HZ); +- WARN_ON_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm)); ++ WARN_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm), ++ "queue sync: failed to sync, state is 0x%lx\n", ++ mvm->queue_sync_state); + } + + out: +- atomic_set(&mvm->queue_sync_counter, 0); ++ mvm->queue_sync_state = 0; + if (notif->sync) + mvm->queue_sync_cookie++; + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index 64f5a4cb3d3ac..8b779c3a92d43 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -842,7 +842,7 @@ struct iwl_mvm { + unsigned long status; + + u32 queue_sync_cookie; +- atomic_t queue_sync_counter; ++ unsigned long queue_sync_state; + /* + * for beacon filtering - + * currently only one interface can be supported +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +index 5b173f21e87bf..3548eb57f1f30 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -725,7 +725,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, + + init_waitqueue_head(&mvm->rx_sync_waitq); + +- atomic_set(&mvm->queue_sync_counter, 0); ++ mvm->queue_sync_state = 0; + + SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev); + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +index 86b3fb321dfdd..e2a39e8b98d07 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +@@ -853,9 +853,13 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, + WARN_ONCE(1, "Invalid identifier %d", internal_notif->type); + } + +- if (internal_notif->sync && +- !atomic_dec_return(&mvm->queue_sync_counter)) +- wake_up(&mvm->rx_sync_waitq); ++ if (internal_notif->sync) { ++ WARN_ONCE(!test_and_clear_bit(queue, &mvm->queue_sync_state), ++ "queue sync: queue %d responded a second time!\n", ++ queue); ++ if (READ_ONCE(mvm->queue_sync_state) == 0) ++ wake_up(&mvm->rx_sync_waitq); ++ } + } + + static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm, +-- +2.43.0 + diff --git a/queue-5.10/iwlwifi-mvm-write-queue_sync_state-only-for-sync.patch b/queue-5.10/iwlwifi-mvm-write-queue_sync_state-only-for-sync.patch new file mode 100644 index 00000000000..15d6bfe7fb0 --- /dev/null +++ b/queue-5.10/iwlwifi-mvm-write-queue_sync_state-only-for-sync.patch @@ -0,0 +1,44 @@ +From 5af83703fcbf21ff5d7e3c271e56b2eeaa04b972 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Mar 2021 12:14:41 +0300 +Subject: iwlwifi: mvm: write queue_sync_state only for sync + +From: Johannes Berg + +[ Upstream commit 5f8a3561ea8bf75ad52cb16dafe69dd550fa542e ] + +We use mvm->queue_sync_state to wait for synchronous queue sync +messages, but if an async one happens inbetween we shouldn't +clear mvm->queue_sync_state after sending the async one, that +can run concurrently (at least from the CPU POV) with another +synchronous queue sync. + +Signed-off-by: Johannes Berg +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20210331121101.d11c9bcdb4aa.I0772171dbaec87433a11513e9586d98b5d920b5f@changeid +Signed-off-by: Luca Coelho +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index f2096729ac5ac..08008b0c0637c 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -5177,9 +5177,10 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, + } + + out: +- mvm->queue_sync_state = 0; +- if (notif->sync) ++ if (notif->sync) { ++ mvm->queue_sync_state = 0; + mvm->queue_sync_cookie++; ++ } + } + + static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) +-- +2.43.0 + diff --git a/queue-5.10/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch b/queue-5.10/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch new file mode 100644 index 00000000000..1a2f7ae941e --- /dev/null +++ b/queue-5.10/jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch @@ -0,0 +1,106 @@ +From 22f2ba8418a0cc762b4ec67f8c0782abd491d4c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:26 +0800 +Subject: jbd2: Fix wrongly judgement for buffer head removing while doing + checkpoint + +From: Zhihao Cheng + +[ Upstream commit e34c8dd238d0c9368b746480f313055f5bab5040 ] + +Following process, + +jbd2_journal_commit_transaction +// there are several dirty buffer heads in transaction->t_checkpoint_list + P1 wb_workfn +jbd2_log_do_checkpoint + if (buffer_locked(bh)) // false + __block_write_full_page + trylock_buffer(bh) + test_clear_buffer_dirty(bh) + if (!buffer_dirty(bh)) + __jbd2_journal_remove_checkpoint(jh) + if (buffer_write_io_error(bh)) // false + >> bh IO error occurs << + jbd2_cleanup_journal_tail + __jbd2_update_log_tail + jbd2_write_superblock + // The bh won't be replayed in next mount. +, which could corrupt the ext4 image, fetch a reproducer in [Link]. + +Since writeback process clears buffer dirty after locking buffer head, +we can fix it by try locking buffer and check dirtiness while buffer is +locked, the buffer head can be removed if it is neither dirty nor locked. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217490 +Fixes: 470decc613ab ("[PATCH] jbd2: initial copy of files from jbd") +Signed-off-by: Zhihao Cheng +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-5-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index aac17c59b7ece..7898983c9fba0 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -228,20 +228,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + jh = transaction->t_checkpoint_list; + bh = jh2bh(jh); + +- /* +- * The buffer may be writing back, or flushing out in the +- * last couple of cycles, or re-adding into a new transaction, +- * need to check it again until it's unlocked. +- */ +- if (buffer_locked(bh)) { +- get_bh(bh); +- spin_unlock(&journal->j_list_lock); +- wait_on_buffer(bh); +- /* the journal_head may have gone by now */ +- BUFFER_TRACE(bh, "brelse"); +- __brelse(bh); +- goto retry; +- } + if (jh->b_transaction != NULL) { + transaction_t *t = jh->b_transaction; + tid_t tid = t->t_tid; +@@ -276,7 +262,22 @@ int jbd2_log_do_checkpoint(journal_t *journal) + spin_lock(&journal->j_list_lock); + goto restart; + } +- if (!buffer_dirty(bh)) { ++ if (!trylock_buffer(bh)) { ++ /* ++ * The buffer is locked, it may be writing back, or ++ * flushing out in the last couple of cycles, or ++ * re-adding into a new transaction, need to check ++ * it again until it's unlocked. ++ */ ++ get_bh(bh); ++ spin_unlock(&journal->j_list_lock); ++ wait_on_buffer(bh); ++ /* the journal_head may have gone by now */ ++ BUFFER_TRACE(bh, "brelse"); ++ __brelse(bh); ++ goto retry; ++ } else if (!buffer_dirty(bh)) { ++ unlock_buffer(bh); + BUFFER_TRACE(bh, "remove from checkpoint"); + /* + * If the transaction was released or the checkpoint +@@ -286,6 +287,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) + !transaction->t_checkpoint_list) + goto out; + } else { ++ unlock_buffer(bh); + /* + * We are about to write the buffer, it could be + * raced by some other transaction shrink or buffer +-- +2.43.0 + diff --git a/queue-5.10/jbd2-recheck-chechpointing-non-dirty-buffer.patch b/queue-5.10/jbd2-recheck-chechpointing-non-dirty-buffer.patch new file mode 100644 index 00000000000..f390ea9ae5d --- /dev/null +++ b/queue-5.10/jbd2-recheck-chechpointing-non-dirty-buffer.patch @@ -0,0 +1,197 @@ +From d2f8623acd10bbb54613815123ec600ef49667ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 21:59:23 +0800 +Subject: jbd2: recheck chechpointing non-dirty buffer + +From: Zhang Yi + +[ Upstream commit c2d6fd9d6f35079f1669f0100f05b46708c74b7f ] + +There is a long-standing metadata corruption issue that happens from +time to time, but it's very difficult to reproduce and analyse, benefit +from the JBD2_CYCLE_RECORD option, we found out that the problem is the +checkpointing process miss to write out some buffers which are raced by +another do_get_write_access(). Looks below for detail. + +jbd2_log_do_checkpoint() //transaction X + //buffer A is dirty and not belones to any transaction + __buffer_relink_io() //move it to the IO list + __flush_batch() + write_dirty_buffer() + do_get_write_access() + clear_buffer_dirty + __jbd2_journal_file_buffer() + //add buffer A to a new transaction Y + lock_buffer(bh) + //doesn't write out + __jbd2_journal_remove_checkpoint() + //finish checkpoint except buffer A + //filesystem corrupt if the new transaction Y isn't fully write out. + +Due to the t_checkpoint_list walking loop in jbd2_log_do_checkpoint() +have already handles waiting for buffers under IO and re-added new +transaction to complete commit, and it also removing cleaned buffers, +this makes sure the list will eventually get empty. So it's fine to +leave buffers on the t_checkpoint_list while flushing out and completely +stop using the t_checkpoint_io_list. + +Cc: stable@vger.kernel.org +Suggested-by: Jan Kara +Signed-off-by: Zhang Yi +Tested-by: Zhihao Cheng +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20230606135928.434610-2-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: e34c8dd238d0 ("jbd2: Fix wrongly judgement for buffer head removing while doing checkpoint") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 102 ++++++++++++------------------------------- + 1 file changed, 29 insertions(+), 73 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index ea08adcea84c3..aac17c59b7ece 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -57,28 +57,6 @@ static inline void __buffer_unlink(struct journal_head *jh) + } + } + +-/* +- * Move a buffer from the checkpoint list to the checkpoint io list +- * +- * Called with j_list_lock held +- */ +-static inline void __buffer_relink_io(struct journal_head *jh) +-{ +- transaction_t *transaction = jh->b_cp_transaction; +- +- __buffer_unlink_first(jh); +- +- if (!transaction->t_checkpoint_io_list) { +- jh->b_cpnext = jh->b_cpprev = jh; +- } else { +- jh->b_cpnext = transaction->t_checkpoint_io_list; +- jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev; +- jh->b_cpprev->b_cpnext = jh; +- jh->b_cpnext->b_cpprev = jh; +- } +- transaction->t_checkpoint_io_list = jh; +-} +- + /* + * Try to release a checkpointed buffer from its transaction. + * Returns 1 if we released it and 2 if we also released the +@@ -190,6 +168,7 @@ __flush_batch(journal_t *journal, int *batch_count) + struct buffer_head *bh = journal->j_chkpt_bhs[i]; + BUFFER_TRACE(bh, "brelse"); + __brelse(bh); ++ journal->j_chkpt_bhs[i] = NULL; + } + *batch_count = 0; + } +@@ -249,6 +228,11 @@ int jbd2_log_do_checkpoint(journal_t *journal) + jh = transaction->t_checkpoint_list; + bh = jh2bh(jh); + ++ /* ++ * The buffer may be writing back, or flushing out in the ++ * last couple of cycles, or re-adding into a new transaction, ++ * need to check it again until it's unlocked. ++ */ + if (buffer_locked(bh)) { + get_bh(bh); + spin_unlock(&journal->j_list_lock); +@@ -294,28 +278,32 @@ int jbd2_log_do_checkpoint(journal_t *journal) + } + if (!buffer_dirty(bh)) { + BUFFER_TRACE(bh, "remove from checkpoint"); +- if (__jbd2_journal_remove_checkpoint(jh)) +- /* The transaction was released; we're done */ ++ /* ++ * If the transaction was released or the checkpoint ++ * list was empty, we're done. ++ */ ++ if (__jbd2_journal_remove_checkpoint(jh) || ++ !transaction->t_checkpoint_list) + goto out; +- continue; ++ } else { ++ /* ++ * We are about to write the buffer, it could be ++ * raced by some other transaction shrink or buffer ++ * re-log logic once we release the j_list_lock, ++ * leave it on the checkpoint list and check status ++ * again to make sure it's clean. ++ */ ++ BUFFER_TRACE(bh, "queue"); ++ get_bh(bh); ++ J_ASSERT_BH(bh, !buffer_jwrite(bh)); ++ journal->j_chkpt_bhs[batch_count++] = bh; ++ transaction->t_chp_stats.cs_written++; ++ transaction->t_checkpoint_list = jh->b_cpnext; + } +- /* +- * Important: we are about to write the buffer, and +- * possibly block, while still holding the journal +- * lock. We cannot afford to let the transaction +- * logic start messing around with this buffer before +- * we write it to disk, as that would break +- * recoverability. +- */ +- BUFFER_TRACE(bh, "queue"); +- get_bh(bh); +- J_ASSERT_BH(bh, !buffer_jwrite(bh)); +- journal->j_chkpt_bhs[batch_count++] = bh; +- __buffer_relink_io(jh); +- transaction->t_chp_stats.cs_written++; ++ + if ((batch_count == JBD2_NR_BATCH) || +- need_resched() || +- spin_needbreak(&journal->j_list_lock)) ++ need_resched() || spin_needbreak(&journal->j_list_lock) || ++ jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0]) + goto unlock_and_flush; + } + +@@ -329,38 +317,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + goto restart; + } + +- /* +- * Now we issued all of the transaction's buffers, let's deal +- * with the buffers that are out for I/O. +- */ +-restart2: +- /* Did somebody clean up the transaction in the meanwhile? */ +- if (journal->j_checkpoint_transactions != transaction || +- transaction->t_tid != this_tid) +- goto out; +- +- while (transaction->t_checkpoint_io_list) { +- jh = transaction->t_checkpoint_io_list; +- bh = jh2bh(jh); +- if (buffer_locked(bh)) { +- get_bh(bh); +- spin_unlock(&journal->j_list_lock); +- wait_on_buffer(bh); +- /* the journal_head may have gone by now */ +- BUFFER_TRACE(bh, "brelse"); +- __brelse(bh); +- spin_lock(&journal->j_list_lock); +- goto restart2; +- } +- +- /* +- * Now in whatever state the buffer currently is, we +- * know that it has been written out and so we can +- * drop it from the list +- */ +- if (__jbd2_journal_remove_checkpoint(jh)) +- break; +- } + out: + spin_unlock(&journal->j_list_lock); + result = jbd2_cleanup_journal_tail(journal); +-- +2.43.0 + diff --git a/queue-5.10/jbd2-remove-redundant-buffer-io-error-checks.patch b/queue-5.10/jbd2-remove-redundant-buffer-io-error-checks.patch new file mode 100644 index 00000000000..0a0c01265c4 --- /dev/null +++ b/queue-5.10/jbd2-remove-redundant-buffer-io-error-checks.patch @@ -0,0 +1,79 @@ +From 5b9158f65a056fb8b4398665d84b2d785cc0aa67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Jun 2021 19:24:36 +0800 +Subject: jbd2: remove redundant buffer io error checks + +From: Zhang Yi + +[ Upstream commit 214eb5a4d8a2032fb9f0711d1b202eb88ee02920 ] + +Now that __jbd2_journal_remove_checkpoint() can detect buffer io error +and mark journal checkpoint error, then we abort the journal later +before updating log tail to ensure the filesystem works consistently. +So we could remove other redundant buffer io error checkes. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20210610112440.3438139-5-yi.zhang@huawei.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: e34c8dd238d0 ("jbd2: Fix wrongly judgement for buffer head removing while doing checkpoint") +Signed-off-by: Sasha Levin +--- + fs/jbd2/checkpoint.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 472932b9e6bca..ea08adcea84c3 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -91,8 +91,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) + int ret = 0; + struct buffer_head *bh = jh2bh(jh); + +- if (jh->b_transaction == NULL && !buffer_locked(bh) && +- !buffer_dirty(bh) && !buffer_write_io_error(bh)) { ++ if (!jh->b_transaction && !buffer_locked(bh) && !buffer_dirty(bh)) { + JBUFFER_TRACE(jh, "remove from checkpoint list"); + ret = __jbd2_journal_remove_checkpoint(jh) + 1; + } +@@ -228,7 +227,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + * OK, we need to start writing disk blocks. Take one transaction + * and write it. + */ +- result = 0; + spin_lock(&journal->j_list_lock); + if (!journal->j_checkpoint_transactions) + goto out; +@@ -295,8 +293,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + goto restart; + } + if (!buffer_dirty(bh)) { +- if (unlikely(buffer_write_io_error(bh)) && !result) +- result = -EIO; + BUFFER_TRACE(bh, "remove from checkpoint"); + if (__jbd2_journal_remove_checkpoint(jh)) + /* The transaction was released; we're done */ +@@ -356,8 +352,6 @@ int jbd2_log_do_checkpoint(journal_t *journal) + spin_lock(&journal->j_list_lock); + goto restart2; + } +- if (unlikely(buffer_write_io_error(bh)) && !result) +- result = -EIO; + + /* + * Now in whatever state the buffer currently is, we +@@ -369,10 +363,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) + } + out: + spin_unlock(&journal->j_list_lock); +- if (result < 0) +- jbd2_journal_abort(journal, result); +- else +- result = jbd2_cleanup_journal_tail(journal); ++ result = jbd2_cleanup_journal_tail(journal); + + return (result < 0) ? result : 0; + } +-- +2.43.0 + diff --git a/queue-5.10/lan743x-fix-for-potential-null-pointer-dereference-w.patch b/queue-5.10/lan743x-fix-for-potential-null-pointer-dereference-w.patch new file mode 100644 index 00000000000..992a19de934 --- /dev/null +++ b/queue-5.10/lan743x-fix-for-potential-null-pointer-dereference-w.patch @@ -0,0 +1,92 @@ +From 424ca6f0f8d94d59316320866b8e41b1ab614b1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Nov 2020 01:35:55 +0300 +Subject: lan743x: fix for potential NULL pointer dereference with bare card + +From: Sergej Bauer + +[ Upstream commit e9e13b6adc338be1eb88db87bcb392696144bd02 ] + +This is the 3rd revision of the patch fix for potential null pointer dereference +with lan743x card. + +The simpliest way to reproduce: boot with bare lan743x and issue "ethtool ethN" +commant where ethN is the interface with lan743x card. Example: + +$ sudo ethtool eth7 +dmesg: +[ 103.510336] BUG: kernel NULL pointer dereference, address: 0000000000000340 +... +[ 103.510836] RIP: 0010:phy_ethtool_get_wol+0x5/0x30 [libphy] +... +[ 103.511629] Call Trace: +[ 103.511666] lan743x_ethtool_get_wol+0x21/0x40 [lan743x] +[ 103.511724] dev_ethtool+0x1507/0x29d0 +[ 103.511769] ? avc_has_extended_perms+0x17f/0x440 +[ 103.511820] ? tomoyo_init_request_info+0x84/0x90 +[ 103.511870] ? tomoyo_path_number_perm+0x68/0x1e0 +[ 103.511919] ? tty_insert_flip_string_fixed_flag+0x82/0xe0 +[ 103.511973] ? inet_ioctl+0x187/0x1d0 +[ 103.512016] dev_ioctl+0xb5/0x560 +[ 103.512055] sock_do_ioctl+0xa0/0x140 +[ 103.512098] sock_ioctl+0x2cb/0x3c0 +[ 103.512139] __x64_sys_ioctl+0x84/0xc0 +[ 103.512183] do_syscall_64+0x33/0x80 +[ 103.512224] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +[ 103.512274] RIP: 0033:0x7f54a9cba427 +... + +Previous versions can be found at: +v1: +initial version + https://lkml.org/lkml/2020/10/28/921 + +v2: +do not return from lan743x_ethtool_set_wol if netdev->phydev == NULL, just skip +the call of phy_ethtool_set_wol() instead. + https://lkml.org/lkml/2020/10/31/380 + +v3: +in function lan743x_ethtool_set_wol: +use ternary operator instead of if-else sentence (review by Markus Elfring) +return -ENETDOWN insted of -EIO (review by Andrew Lunn) + +Signed-off-by: Sergej Bauer + +Link: https://lore.kernel.org/r/20201101223556.16116-1-sbauer@blackbox.su +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_ethtool.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c +index dcde496da7fb4..c5de8f46cdd35 100644 +--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c ++++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c +@@ -780,7 +780,9 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev, + + wol->supported = 0; + wol->wolopts = 0; +- phy_ethtool_get_wol(netdev->phydev, wol); ++ ++ if (netdev->phydev) ++ phy_ethtool_get_wol(netdev->phydev, wol); + + wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | + WAKE_MAGIC | WAKE_PHY | WAKE_ARP; +@@ -809,9 +811,8 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev, + + device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts); + +- phy_ethtool_set_wol(netdev->phydev, wol); +- +- return 0; ++ return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol) ++ : -ENETDOWN; + } + #endif /* CONFIG_PM */ + +-- +2.43.0 + diff --git a/queue-5.10/media-av7110-prevent-underflow-in-write_ts_to_decode.patch b/queue-5.10/media-av7110-prevent-underflow-in-write_ts_to_decode.patch new file mode 100644 index 00000000000..b722ddf6644 --- /dev/null +++ b/queue-5.10/media-av7110-prevent-underflow-in-write_ts_to_decode.patch @@ -0,0 +1,47 @@ +From be5fe86adde5088bf8b48eb9d14ac347c69c5714 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Mar 2023 11:00:23 +0100 +Subject: media: av7110: prevent underflow in write_ts_to_decoder() + +From: Dan Carpenter + +[ Upstream commit eed9496a0501357aa326ddd6b71408189ed872eb ] + +The buf[4] value comes from the user via ts_play(). It is a value in +the u8 range. The final length we pass to av7110_ipack_instant_repack() +is "len - (buf[4] + 1) - 4" so add a check to ensure that the length is +not negative. It's not clear that passing a negative len value does +anything bad necessarily, but it's not best practice. + +With the new bounds checking the "if (!len)" condition is no longer +possible or required so remove that. + +Fixes: fd46d16d602a ("V4L/DVB (11759): dvb-ttpci: Add TS replay capability") +Signed-off-by: Dan Carpenter +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/pci/ttpci/av7110_av.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c +index ea9f7d0058a21..e201d5a56bc65 100644 +--- a/drivers/media/pci/ttpci/av7110_av.c ++++ b/drivers/media/pci/ttpci/av7110_av.c +@@ -822,10 +822,10 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s + av7110_ipack_flush(ipack); + + if (buf[3] & ADAPT_FIELD) { ++ if (buf[4] > len - 1 - 4) ++ return 0; + len -= buf[4] + 1; + buf += buf[4] + 1; +- if (!len) +- return 0; + } + + av7110_ipack_instant_repack(buf + 4, len - 4, ipack); +-- +2.43.0 + diff --git a/queue-5.10/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch b/queue-5.10/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch new file mode 100644 index 00000000000..83b7581b704 --- /dev/null +++ b/queue-5.10/mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch @@ -0,0 +1,58 @@ +From 14e828b93fb1104ce9f4c90f7e5ff2d1bcbde356 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Nov 2020 15:23:40 +0800 +Subject: mtd: spinand: macronix: Add support for MX35LFxGE4AD + +From: YouChing Lin + +[ Upstream commit 5ece78de88739b4c68263e9f2582380c1fd8314f ] + +The Macronix MX35LF2GE4AD / MX35LF4GE4AD are 3V, 2G / 4Gbit serial +SLC NAND flash device (with on-die ECC). + +Validated by read, erase, read back, write, read back and nandtest +on Xilinx Zynq PicoZed FPGA board which included Macronix SPI Host +(drivers/spi/spi-mxic.c). + +Signed-off-by: YouChing Lin +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/1604561020-13499-1-git-send-email-ycllin@mxic.com.tw +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/spi/macronix.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c +index cd7a9cacc3fbf..8bd3f6bf9b103 100644 +--- a/drivers/mtd/nand/spi/macronix.c ++++ b/drivers/mtd/nand/spi/macronix.c +@@ -119,6 +119,26 @@ static const struct spinand_info macronix_spinand_table[] = { + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX35LF2GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35LF4GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37), ++ NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX31LF1GE4BC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), +-- +2.43.0 + diff --git a/queue-5.10/platform-x86-intel-vbtn-support-for-tablet-mode-on-h.patch b/queue-5.10/platform-x86-intel-vbtn-support-for-tablet-mode-on-h.patch new file mode 100644 index 00000000000..98aaf5708ce --- /dev/null +++ b/queue-5.10/platform-x86-intel-vbtn-support-for-tablet-mode-on-h.patch @@ -0,0 +1,42 @@ +From 522cb6e3e939db76edc8a79b247cb6fdca623c83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Nov 2020 15:16:52 +0200 +Subject: platform/x86: intel-vbtn: Support for tablet mode on HP Pavilion 13 + x360 PC + +From: Max Verevkin + +[ Upstream commit 07b211992d6c0d80b321403244d43bbd2d6cf48c ] + +The Pavilion 13 x360 PC has a chassis-type which does not indicate it is +a convertible, while it is actually a convertible. Add it to the +dmi_switches_allow_list. + +Signed-off-by: Max Verevkin +Link: https://lore.kernel.org/r/20201124131652.11165-1-me@maxverevkin.tk +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel-vbtn.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c +index a90c32d072da3..9c8a6722f115e 100644 +--- a/drivers/platform/x86/intel-vbtn.c ++++ b/drivers/platform/x86/intel-vbtn.c +@@ -230,6 +230,12 @@ static const struct dmi_system_id dmi_switches_allow_list[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"), + }, + }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"), ++ }, ++ }, + {} /* Array terminator */ + }; + +-- +2.43.0 + diff --git a/queue-5.10/powerpc-watchpoint-workaround-p10-dd1-issue-with-vsx.patch b/queue-5.10/powerpc-watchpoint-workaround-p10-dd1-issue-with-vsx.patch new file mode 100644 index 00000000000..3175844b614 --- /dev/null +++ b/queue-5.10/powerpc-watchpoint-workaround-p10-dd1-issue-with-vsx.patch @@ -0,0 +1,128 @@ +From af4b485cb28c3df3f0daeae34a22e879dda41be0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Nov 2020 10:26:50 +0530 +Subject: powerpc/watchpoint: Workaround P10 DD1 issue with VSX-32 byte + instructions + +From: Ravi Bangoria + +[ Upstream commit 3d2ffcdd2a982e8bbe65fa0f94fb21bf304c281e ] + +POWER10 DD1 has an issue where it generates watchpoint exceptions when +it shouldn't. The conditions where this occur are: + + - octword op + - ending address of DAWR range is less than starting address of op + - those addresses need to be in the same or in two consecutive 512B + blocks + - 'op address + 64B' generates an address that has a carry into bit + 52 (crosses 2K boundary) + +Handle such spurious exception by considering them as extraneous and +emulating/single-steeping instruction without generating an event. + +[ravi: Fixed build warning reported by lkp@intel.com] +Signed-off-by: Ravi Bangoria +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20201106045650.278987-1-ravi.bangoria@linux.ibm.com +Stable-dep-of: 27646b2e02b0 ("powerpc/watchpoints: Annotate atomic context in more places") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/hw_breakpoint.c | 67 ++++++++++++++++++++++++++++- + 1 file changed, 65 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c +index 6e5bed50c3578..49273f67c7498 100644 +--- a/arch/powerpc/kernel/hw_breakpoint.c ++++ b/arch/powerpc/kernel/hw_breakpoint.c +@@ -504,6 +504,11 @@ static bool is_larx_stcx_instr(int type) + return type == LARX || type == STCX; + } + ++static bool is_octword_vsx_instr(int type, int size) ++{ ++ return ((type == LOAD_VSX || type == STORE_VSX) && size == 32); ++} ++ + /* + * We've failed in reliably handling the hw-breakpoint. Unregister + * it and throw a warning message to let the user know about it. +@@ -554,6 +559,58 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event **bp, + return true; + } + ++static void handle_p10dd1_spurious_exception(struct arch_hw_breakpoint **info, ++ int *hit, unsigned long ea) ++{ ++ int i; ++ unsigned long hw_end_addr; ++ ++ /* ++ * Handle spurious exception only when any bp_per_reg is set. ++ * Otherwise this might be created by xmon and not actually a ++ * spurious exception. ++ */ ++ for (i = 0; i < nr_wp_slots(); i++) { ++ if (!info[i]) ++ continue; ++ ++ hw_end_addr = ALIGN(info[i]->address + info[i]->len, HW_BREAKPOINT_SIZE); ++ ++ /* ++ * Ending address of DAWR range is less than starting ++ * address of op. ++ */ ++ if ((hw_end_addr - 1) >= ea) ++ continue; ++ ++ /* ++ * Those addresses need to be in the same or in two ++ * consecutive 512B blocks; ++ */ ++ if (((hw_end_addr - 1) >> 10) != (ea >> 10)) ++ continue; ++ ++ /* ++ * 'op address + 64B' generates an address that has a ++ * carry into bit 52 (crosses 2K boundary). ++ */ ++ if ((ea & 0x800) == ((ea + 64) & 0x800)) ++ continue; ++ ++ break; ++ } ++ ++ if (i == nr_wp_slots()) ++ return; ++ ++ for (i = 0; i < nr_wp_slots(); i++) { ++ if (info[i]) { ++ hit[i] = 1; ++ info[i]->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ; ++ } ++ } ++} ++ + int hw_breakpoint_handler(struct die_args *args) + { + bool err = false; +@@ -612,8 +669,14 @@ int hw_breakpoint_handler(struct die_args *args) + goto reset; + + if (!nr_hit) { +- rc = NOTIFY_DONE; +- goto out; ++ /* Workaround for Power10 DD1 */ ++ if (!IS_ENABLED(CONFIG_PPC_8xx) && mfspr(SPRN_PVR) == 0x800100 && ++ is_octword_vsx_instr(type, size)) { ++ handle_p10dd1_spurious_exception(info, hit, ea); ++ } else { ++ rc = NOTIFY_DONE; ++ goto out; ++ } + } + + /* +-- +2.43.0 + diff --git a/queue-5.10/powerpc-watchpoints-annotate-atomic-context-in-more-.patch b/queue-5.10/powerpc-watchpoints-annotate-atomic-context-in-more-.patch new file mode 100644 index 00000000000..6abe686eb33 --- /dev/null +++ b/queue-5.10/powerpc-watchpoints-annotate-atomic-context-in-more-.patch @@ -0,0 +1,58 @@ +From 89d36f31280e1e585885ed9df519c4ffc110e9f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Aug 2023 16:34:57 +1000 +Subject: powerpc/watchpoints: Annotate atomic context in more places + +From: Benjamin Gray + +[ Upstream commit 27646b2e02b096a6936b3e3b6ba334ae20763eab ] + +It can be easy to miss that the notifier mechanism invokes the callbacks +in an atomic context, so add some comments to that effect on the two +handlers we register here. + +Signed-off-by: Benjamin Gray +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20230829063457.54157-4-bgray@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/hw_breakpoint.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c +index 49273f67c7498..ca3374c6f3749 100644 +--- a/arch/powerpc/kernel/hw_breakpoint.c ++++ b/arch/powerpc/kernel/hw_breakpoint.c +@@ -611,6 +611,11 @@ static void handle_p10dd1_spurious_exception(struct arch_hw_breakpoint **info, + } + } + ++/* ++ * Handle a DABR or DAWR exception. ++ * ++ * Called in atomic context. ++ */ + int hw_breakpoint_handler(struct die_args *args) + { + bool err = false; +@@ -737,6 +742,8 @@ NOKPROBE_SYMBOL(hw_breakpoint_handler); + + /* + * Handle single-step exceptions following a DABR hit. ++ * ++ * Called in atomic context. + */ + static int single_step_dabr_instruction(struct die_args *args) + { +@@ -794,6 +801,8 @@ NOKPROBE_SYMBOL(single_step_dabr_instruction); + + /* + * Handle debug exception notifications. ++ * ++ * Called in atomic context. + */ + int hw_breakpoint_exceptions_notify( + struct notifier_block *unused, unsigned long val, void *data) +-- +2.43.0 + diff --git a/queue-5.10/seccomp-invalidate-seccomp-mode-to-catch-death-failu.patch b/queue-5.10/seccomp-invalidate-seccomp-mode-to-catch-death-failu.patch new file mode 100644 index 00000000000..c64106b0aed --- /dev/null +++ b/queue-5.10/seccomp-invalidate-seccomp-mode-to-catch-death-failu.patch @@ -0,0 +1,69 @@ +From ecf30932cf59a59ff4a6e5a91cc7a3daf513bea7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Feb 2022 20:21:13 -0800 +Subject: seccomp: Invalidate seccomp mode to catch death failures + +From: Kees Cook + +[ Upstream commit 495ac3069a6235bfdf516812a2a9b256671bbdf9 ] + +If seccomp tries to kill a process, it should never see that process +again. To enforce this proactively, switch the mode to something +impossible. If encountered: WARN, reject all syscalls, and attempt to +kill the process again even harder. + +Cc: Andy Lutomirski +Cc: Will Drewry +Fixes: 8112c4f140fa ("seccomp: remove 2-phase API") +Cc: stable@vger.kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + kernel/seccomp.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 305f0eca163ed..0b0331346e4be 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -29,6 +29,9 @@ + #include + #include + ++/* Not exposed in headers: strictly internal use only. */ ++#define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1) ++ + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + #include + #endif +@@ -795,6 +798,7 @@ static void __secure_computing_strict(int this_syscall) + #ifdef SECCOMP_DEBUG + dump_stack(); + #endif ++ current->seccomp.mode = SECCOMP_MODE_DEAD; + seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true); + do_exit(SIGKILL); + } +@@ -1023,6 +1027,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, + case SECCOMP_RET_KILL_THREAD: + case SECCOMP_RET_KILL_PROCESS: + default: ++ current->seccomp.mode = SECCOMP_MODE_DEAD; + seccomp_log(this_syscall, SIGSYS, action, true); + /* Dump core only if this is the last remaining thread. */ + if (action != SECCOMP_RET_KILL_THREAD || +@@ -1075,6 +1080,11 @@ int __secure_computing(const struct seccomp_data *sd) + return 0; + case SECCOMP_MODE_FILTER: + return __seccomp_filter(this_syscall, sd, false); ++ /* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ ++ case SECCOMP_MODE_DEAD: ++ WARN_ON_ONCE(1); ++ do_exit(SIGKILL); ++ return -1; + default: + BUG(); + } +-- +2.43.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 518f60efa21..ba563dfaff1 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -40,3 +40,32 @@ scsi-lpfc-use-unsigned-type-for-num_sge.patch firewire-core-send-bus-reset-promptly-on-gap-count-e.patch virtio-blk-ensure-no-requests-in-virtqueues-before-d.patch pmdomain-renesas-r8a77980-sysc-cr7-must-be-always-on.patch +arm-dts-bcm53573-drop-nonexistent-default-off-led-tr.patch +irqchip-mips-gic-don-t-touch-vl_map-if-a-local-inter.patch +arm-dts-imx-set-default-tuning-step-for-imx6sx-usdhc.patch +asoc-fsl_micfil-register-platform-component-before-r.patch +media-av7110-prevent-underflow-in-write_ts_to_decode.patch +hvc-xen-prevent-concurrent-accesses-to-the-shared-ri.patch +hsr-avoid-double-remove-of-a-node.patch +x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch +seccomp-invalidate-seccomp-mode-to-catch-death-failu.patch +block-ataflop-fix-breakage-introduced-at-blk-mq-refa.patch +powerpc-watchpoint-workaround-p10-dd1-issue-with-vsx.patch +powerpc-watchpoints-annotate-atomic-context-in-more-.patch +cifs-add-a-warning-when-the-in-flight-count-goes-neg.patch +mtd-spinand-macronix-add-support-for-mx35lfxge4ad.patch +asoc-intel-boards-harden-codec-property-handling.patch +asoc-intel-boards-get-codec-device-with-acpi-instead.patch +asoc-intel-bytcr_rt5651-drop-reference-count-of-acpi.patch +task_stack-x86-cea-force-inline-stack-helpers.patch +btrfs-tree-checker-check-for-overlapping-extent-item.patch +btrfs-introduce-btrfs_lookup_match_dir.patch +btrfs-unify-lookup-return-value-when-dir-entry-is-mi.patch +btrfs-do-not-pin-logs-too-early-during-renames.patch +lan743x-fix-for-potential-null-pointer-dereference-w.patch +platform-x86-intel-vbtn-support-for-tablet-mode-on-h.patch +iwlwifi-mvm-do-more-useful-queue-sync-accounting.patch +iwlwifi-mvm-write-queue_sync_state-only-for-sync.patch +jbd2-remove-redundant-buffer-io-error-checks.patch +jbd2-recheck-chechpointing-non-dirty-buffer.patch +jbd2-fix-wrongly-judgement-for-buffer-head-removing-.patch diff --git a/queue-5.10/task_stack-x86-cea-force-inline-stack-helpers.patch b/queue-5.10/task_stack-x86-cea-force-inline-stack-helpers.patch new file mode 100644 index 00000000000..f1a77cefd0b --- /dev/null +++ b/queue-5.10/task_stack-x86-cea-force-inline-stack-helpers.patch @@ -0,0 +1,52 @@ +From 7486ddef1504b2dfc412194ab7fe03de0a6e78a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Mar 2022 20:02:41 +0100 +Subject: task_stack, x86/cea: Force-inline stack helpers + +From: Borislav Petkov + +[ Upstream commit e87f4152e542610d0b4c6c8548964a68a59d2040 ] + +Force-inline two stack helpers to fix the following objtool warnings: + + vmlinux.o: warning: objtool: in_task_stack()+0xc: call to task_stack_page() leaves .noinstr.text section + vmlinux.o: warning: objtool: in_entry_stack()+0x10: call to cpu_entry_stack() leaves .noinstr.text section + +Signed-off-by: Borislav Petkov +Acked-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20220324183607.31717-2-bp@alien8.de +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/cpu_entry_area.h | 2 +- + include/linux/sched/task_stack.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h +index dd5ea1bdf04c5..75efc4c6f0766 100644 +--- a/arch/x86/include/asm/cpu_entry_area.h ++++ b/arch/x86/include/asm/cpu_entry_area.h +@@ -143,7 +143,7 @@ extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags); + + extern struct cpu_entry_area *get_cpu_entry_area(int cpu); + +-static inline struct entry_stack *cpu_entry_stack(int cpu) ++static __always_inline struct entry_stack *cpu_entry_stack(int cpu) + { + return &get_cpu_entry_area(cpu)->entry_stack_page.stack; + } +diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h +index f24575942dabe..879a5c8f930b6 100644 +--- a/include/linux/sched/task_stack.h ++++ b/include/linux/sched/task_stack.h +@@ -16,7 +16,7 @@ + * try_get_task_stack() instead. task_stack_page will return a pointer + * that could get freed out from under you. + */ +-static inline void *task_stack_page(const struct task_struct *task) ++static __always_inline void *task_stack_page(const struct task_struct *task) + { + return task->stack; + } +-- +2.43.0 + diff --git a/queue-5.10/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch b/queue-5.10/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch new file mode 100644 index 00000000000..f83ec870eb5 --- /dev/null +++ b/queue-5.10/x86-uaccess-implement-macros-for-cmpxchg-on-user-add.patch @@ -0,0 +1,196 @@ +From 3ebd53663a48d6f20320150fba80da41e4614589 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Feb 2022 00:49:42 +0000 +Subject: x86/uaccess: Implement macros for CMPXCHG on user addresses + +From: Peter Zijlstra + +[ Upstream commit 989b5db215a2f22f89d730b607b071d964780f10 ] + +Add support for CMPXCHG loops on userspace addresses. Provide both an +"unsafe" version for tight loops that do their own uaccess begin/end, as +well as a "safe" version for use cases where the CMPXCHG is not buried in +a loop, e.g. KVM will resume the guest instead of looping when emulation +of a guest atomic accesses fails the CMPXCHG. + +Provide 8-byte versions for 32-bit kernels so that KVM can do CMPXCHG on +guest PAE PTEs, which are accessed via userspace addresses. + +Guard the asm_volatile_goto() variation with CC_HAS_ASM_GOTO_TIED_OUTPUT, +the "+m" constraint fails on some compilers that otherwise support +CC_HAS_ASM_GOTO_OUTPUT. + +Cc: stable@vger.kernel.org +Signed-off-by: Peter Zijlstra (Intel) +Co-developed-by: Sean Christopherson +Signed-off-by: Sean Christopherson +Message-Id: <20220202004945.2540433-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/uaccess.h | 142 +++++++++++++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index bf2561a5eb581..68b910f30b222 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -414,6 +414,103 @@ do { \ + + #endif // CONFIG_CC_ASM_GOTO_OUTPUT + ++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm_volatile_goto("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ _ASM_EXTABLE_UA(1b, %l[label]) \ ++ : CC_OUT(z) (success), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory" \ ++ : label); \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++#endif // CONFIG_X86_32 ++#else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \ ++ int __err = 0; \ ++ bool success; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ ++ CC_SET(z) \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \ ++ %[errout]) \ ++ : CC_OUT(z) (success), \ ++ [errout] "+r" (__err), \ ++ [ptr] "+m" (*_ptr), \ ++ [old] "+a" (__old) \ ++ : [new] ltype (__new) \ ++ : "memory", "cc"); \ ++ if (unlikely(__err)) \ ++ goto label; \ ++ if (unlikely(!success)) \ ++ *_old = __old; \ ++ likely(success); }) ++ ++#ifdef CONFIG_X86_32 ++/* ++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error. ++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are ++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI. If the compiler uses ++ * both ESI and EDI for the memory operand, compilation will fail if the error ++ * is an input+output as there will be no register available for input. ++ */ ++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \ ++ int __result; \ ++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ ++ __typeof__(*(_ptr)) __old = *_old; \ ++ __typeof__(*(_ptr)) __new = (_new); \ ++ asm volatile("\n" \ ++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ ++ "mov $0, %%ecx\n\t" \ ++ "setz %%cl\n" \ ++ "2:\n" \ ++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \ ++ : [result]"=c" (__result), \ ++ "+A" (__old), \ ++ [ptr] "+m" (*_ptr) \ ++ : "b" ((u32)__new), \ ++ "c" ((u32)((u64)__new >> 32)) \ ++ : "memory", "cc"); \ ++ if (unlikely(__result < 0)) \ ++ goto label; \ ++ if (unlikely(!__result)) \ ++ *_old = __old; \ ++ likely(__result); }) ++#endif // CONFIG_X86_32 ++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT ++ + /* FIXME: this hack is definitely wrong -AK */ + struct __large_struct { unsigned long buf[100]; }; + #define __m(x) (*(struct __large_struct __user *)(x)) +@@ -506,6 +603,51 @@ do { \ + } while (0) + #endif // CONFIG_CC_HAS_ASM_GOTO_OUTPUT + ++extern void __try_cmpxchg_user_wrong_size(void); ++ ++#ifndef CONFIG_X86_32 ++#define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label) \ ++ __try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label) ++#endif ++ ++/* ++ * Force the pointer to u to match the size expected by the asm helper. ++ * clang/LLVM compiles all cases and only discards the unused paths after ++ * processing errors, which breaks i386 if the pointer is an 8-byte value. ++ */ ++#define unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \ ++ bool __ret; \ ++ __chk_user_ptr(_ptr); \ ++ switch (sizeof(*(_ptr))) { \ ++ case 1: __ret = __try_cmpxchg_user_asm("b", "q", \ ++ (__force u8 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 2: __ret = __try_cmpxchg_user_asm("w", "r", \ ++ (__force u16 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 4: __ret = __try_cmpxchg_user_asm("l", "r", \ ++ (__force u32 *)(_ptr), (_oldp), \ ++ (_nval), _label); \ ++ break; \ ++ case 8: __ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\ ++ (_nval), _label); \ ++ break; \ ++ default: __try_cmpxchg_user_wrong_size(); \ ++ } \ ++ __ret; }) ++ ++/* "Returns" 0 on success, 1 on failure, -EFAULT if the access faults. */ ++#define __try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \ ++ int __ret = -EFAULT; \ ++ __uaccess_begin_nospec(); \ ++ __ret = !unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label); \ ++_label: \ ++ __uaccess_end(); \ ++ __ret; \ ++ }) ++ + /* + * We want the unsafe accessors to always be inlined and use + * the error labels - thus the macro games. +-- +2.43.0 +