]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Fri, 27 Jun 2025 14:02:14 +0000 (10:02 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 27 Jun 2025 14:02:14 +0000 (10:02 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
59 files changed:
queue-5.15/alsa-hda-add-new-pci-id-for-amd-gpu-display-hd-audio.patch [new file with mode: 0644]
queue-5.15/alsa-hda-ignore-unsol-events-for-cards-being-shut-do.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-a-quirk-for-lenovo-thinkpad-thund.patch [new file with mode: 0644]
queue-5.15/asoc-codec-wcd9335-convert-to-gpio-descriptors.patch [new file with mode: 0644]
queue-5.15/asoc-codecs-wcd9335-fix-missing-free-of-regulator-su.patch [new file with mode: 0644]
queue-5.15/asoc-codecs-wcd9335-handle-nicer-probe-deferral-and-.patch [new file with mode: 0644]
queue-5.15/bcache-fix-null-pointer-in-cache_set_flush.patch [new file with mode: 0644]
queue-5.15/ceph-fix-possible-integer-overflow-in-ceph_zero_obje.patch [new file with mode: 0644]
queue-5.15/cifs-fix-cifs_query_path_info-for-windows-nt-servers.patch [new file with mode: 0644]
queue-5.15/clk-ti-am43xx-add-clkctrl-data-for-am43xx-adc1.patch [new file with mode: 0644]
queue-5.15/coresight-only-check-bottom-two-claim-bits.patch [new file with mode: 0644]
queue-5.15/dmaengine-xilinx_dma-set-dma_device-directions.patch [new file with mode: 0644]
queue-5.15/drivers-hv-rename-alloced-to-allocated.patch [new file with mode: 0644]
queue-5.15/drivers-hv-vmbus-add-utility-function-for-querying-r.patch [new file with mode: 0644]
queue-5.15/dummycon-trigger-redraw-when-switching-consoles-with.patch [new file with mode: 0644]
queue-5.15/f2fs-don-t-over-report-free-space-or-inodes-in-statv.patch [new file with mode: 0644]
queue-5.15/fbcon-delete-a-few-unneeded-forward-decl.patch [new file with mode: 0644]
queue-5.15/fbcon-extract-fbcon_open-release-helpers.patch [new file with mode: 0644]
queue-5.15/fbcon-move-console_lock-for-register-unlink-unregist.patch [new file with mode: 0644]
queue-5.15/fbcon-move-more-common-code-into-fb_open.patch [new file with mode: 0644]
queue-5.15/fbcon-use-delayed-work-for-cursor.patch [new file with mode: 0644]
queue-5.15/fbcon-use-lock_fb_info-in-fbcon_open-release.patch [new file with mode: 0644]
queue-5.15/fbdev-fix-do_register_framebuffer-to-prevent-null-pt.patch [new file with mode: 0644]
queue-5.15/fs-jfs-consolidate-sanity-checking-in-dbmount.patch [new file with mode: 0644]
queue-5.15/hwmon-pmbus-max34440-fix-support-for-max34451.patch [new file with mode: 0644]
queue-5.15/iio-pressure-zpa2326-use-aligned_s64-for-the-timesta.patch [new file with mode: 0644]
queue-5.15/jfs-validate-ag-parameters-in-dbmount-to-prevent-cra.patch [new file with mode: 0644]
queue-5.15/ksmbd-allow-a-filename-to-contain-special-characters.patch [new file with mode: 0644]
queue-5.15/leds-multicolor-fix-intensity-setting-while-sw-blink.patch [new file with mode: 0644]
queue-5.15/mailbox-not-protect-module_put-with-spin_lock_irqsav.patch [new file with mode: 0644]
queue-5.15/md-md-bitmap-fix-dm-raid-max_write_behind-setting.patch [new file with mode: 0644]
queue-5.15/media-davinci-vpif-fix-memory-leak-in-probe-error-pa.patch [new file with mode: 0644]
queue-5.15/media-imx-jpeg-drop-the-first-error-frames.patch [new file with mode: 0644]
queue-5.15/media-omap3isp-use-sgtable-based-scatterlist-wrapper.patch [new file with mode: 0644]
queue-5.15/mfd-max14577-fix-wakeup-source-leaks-on-device-unbin.patch [new file with mode: 0644]
queue-5.15/nfsv4-always-set-nlink-even-if-the-server-doesn-t-su.patch [new file with mode: 0644]
queue-5.15/nfsv4.2-fix-listxattr-to-return-selinux-security-lab.patch [new file with mode: 0644]
queue-5.15/ovl-check-for-null-d_inode-in-ovl_dentry_upper.patch [new file with mode: 0644]
queue-5.15/platform-x86-ideapad-laptop-use-usleep_range-for-ec-.patch [new file with mode: 0644]
queue-5.15/regulator-add-devm-helpers-for-get-and-enable.patch [new file with mode: 0644]
queue-5.15/regulator-core-allow-drivers-to-define-their-init-da.patch [new file with mode: 0644]
queue-5.15/revert-iommu-amd-prevent-binding-other-pci-drivers-t.patch [new file with mode: 0644]
queue-5.15/series [new file with mode: 0644]
queue-5.15/tty-serial-uartlite-register-uart-driver-in-init.patch [new file with mode: 0644]
queue-5.15/tty-vt-consolemap-rename-and-document-struct-uni_pag.patch [new file with mode: 0644]
queue-5.15/tty-vt-make-consw-con_switch-return-a-bool.patch [new file with mode: 0644]
queue-5.15/tty-vt-make-init-parameter-of-consw-con_init-a-bool.patch [new file with mode: 0644]
queue-5.15/tty-vt-sanitize-arguments-of-consw-con_clear.patch [new file with mode: 0644]
queue-5.15/uio_hv_generic-align-ring-size-to-system-page.patch [new file with mode: 0644]
queue-5.15/uio_hv_generic-query-the-ringbuffer-size-for-device.patch [new file with mode: 0644]
queue-5.15/um-add-cmpxchg8b_emu-and-checksum-functions-to-asm-p.patch [new file with mode: 0644]
queue-5.15/usb-add-checks-for-snprintf-calls-in-usb_alloc_dev.patch [new file with mode: 0644]
queue-5.15/usb-cdc-wdm-avoid-setting-wdm_read-for-zlp-s.patch [new file with mode: 0644]
queue-5.15/usb-common-usb-conn-gpio-use-a-unique-name-for-usb-c.patch [new file with mode: 0644]
queue-5.15/usb-dwc2-also-exit-clock_gating-when-stopping-udc-wh.patch [new file with mode: 0644]
queue-5.15/usb-potential-integer-overflow-in-usbg_make_tpg.patch [new file with mode: 0644]
queue-5.15/usb-typec-displayport-receive-dp-status-update-nak-r.patch [new file with mode: 0644]
queue-5.15/vgacon-remove-unneeded-forward-declarations.patch [new file with mode: 0644]
queue-5.15/vgacon-switch-vgacon_scrolldelta-and-vgacon_restore_.patch [new file with mode: 0644]

diff --git a/queue-5.15/alsa-hda-add-new-pci-id-for-amd-gpu-display-hd-audio.patch b/queue-5.15/alsa-hda-add-new-pci-id-for-amd-gpu-display-hd-audio.patch
new file mode 100644 (file)
index 0000000..fc7d7c4
--- /dev/null
@@ -0,0 +1,37 @@
+From c80ef7016d2f9c0dfe73582aad4f47b66e022d78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 May 2025 11:08:13 +0530
+Subject: ALSA: hda: Add new pci id for AMD GPU display HD audio controller
+
+From: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+
+[ Upstream commit ab72bfce7647522e01a181e3600c3d14ff5c143e ]
+
+Add new pci id for AMD GPU display HD audio controller(device id- 0xab40).
+
+Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Link: https://patch.msgid.link/20250529053838.2350071-1-Vijendar.Mukunda@amd.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/hda_intel.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index cc8c066327b6c..c69f4e5989d4f 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -2731,6 +2731,9 @@ static const struct pci_device_id azx_ids[] = {
+       { PCI_DEVICE(0x1002, 0xab38),
+         .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+         AZX_DCAPS_PM_RUNTIME },
++      { PCI_VDEVICE(ATI, 0xab40),
++        .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
++        AZX_DCAPS_PM_RUNTIME },
+       /* GLENFLY */
+       { PCI_DEVICE(PCI_VENDOR_ID_GLENFLY, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+-- 
+2.39.5
+
diff --git a/queue-5.15/alsa-hda-ignore-unsol-events-for-cards-being-shut-do.patch b/queue-5.15/alsa-hda-ignore-unsol-events-for-cards-being-shut-do.patch
new file mode 100644 (file)
index 0000000..0c5240f
--- /dev/null
@@ -0,0 +1,48 @@
+From d9b2e224ff65f4df6d1b67e49955a40ec286761b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 May 2025 16:13:09 +0200
+Subject: ALSA: hda: Ignore unsol events for cards being shut down
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 3f100f524e75586537e337b34d18c8d604b398e7 ]
+
+For the classic snd_hda_intel driver, codec->card and bus->card point to
+the exact same thing. When snd_card_diconnect() fires, bus->shutdown is
+set thanks to azx_dev_disconnect(). card->shutdown is already set when
+that happens but both provide basically the same functionality.
+
+For the DSP snd_soc_avs driver where multiple codecs are located on
+multiple cards, bus->shutdown 'shortcut' is not sufficient. One codec
+card may be unregistered while other codecs are still operational.
+Proper check in form of card->shutdown must be used to verify whether
+the codec's card is being shut down.
+
+Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Link: https://patch.msgid.link/20250530141309.2943404-1-cezary.rojewski@intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/hda_bind.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
+index 8e35009ec25cb..a22f723ab3ab6 100644
+--- a/sound/pci/hda/hda_bind.c
++++ b/sound/pci/hda/hda_bind.c
+@@ -45,7 +45,7 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
+       struct hda_codec *codec = container_of(dev, struct hda_codec, core);
+       /* ignore unsol events during shutdown */
+-      if (codec->bus->shutdown)
++      if (codec->card->shutdown || codec->bus->shutdown)
+               return;
+       /* ignore unsol events during system suspend/resume */
+-- 
+2.39.5
+
diff --git a/queue-5.15/alsa-usb-audio-add-a-quirk-for-lenovo-thinkpad-thund.patch b/queue-5.15/alsa-usb-audio-add-a-quirk-for-lenovo-thinkpad-thund.patch
new file mode 100644 (file)
index 0000000..95f5d9b
--- /dev/null
@@ -0,0 +1,39 @@
+From bc8119a5ff12e462555798b891adf01e99b6f316 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 May 2025 12:26:56 -0500
+Subject: ALSA: usb-audio: Add a quirk for Lenovo Thinkpad Thunderbolt 3 dock
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 4919353c7789b8047e06a9b2b943f775a8f72883 ]
+
+The audio controller in the Lenovo Thinkpad Thunderbolt 3 dock doesn't
+support reading the sampling rate.
+
+Add a quirk for it.
+
+Suggested-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://patch.msgid.link/20250527172657.1972565-1-superm1@kernel.org
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 488fcdbb6a2d4..f24a334316a29 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1877,6 +1877,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+       DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
++      DEVICE_FLG(0x17ef, 0x3083, /* Lenovo TBT3 dock */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x1852, 0x5062, /* Luxman D-08u */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */
+-- 
+2.39.5
+
diff --git a/queue-5.15/asoc-codec-wcd9335-convert-to-gpio-descriptors.patch b/queue-5.15/asoc-codec-wcd9335-convert-to-gpio-descriptors.patch
new file mode 100644 (file)
index 0000000..928daa4
--- /dev/null
@@ -0,0 +1,85 @@
+From 01d44ef331f5fa633cded81b14cb22b1574b1072 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 19:51:29 +0800
+Subject: ASoC: codec: wcd9335: Convert to GPIO descriptors
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit d5099bc1b56417733f4cccf10c61ee74dadd5562 ]
+
+of_gpio.h is deprecated, update the driver to use GPIO descriptors.
+- Use dev_gpiod_get to get GPIO descriptor.
+- Use gpiod_set_value to configure output value.
+
+With legacy of_gpio API, the driver set gpio value 0 to assert reset,
+and 1 to deassert reset. And the reset-gpios use GPIO_ACTIVE_LOW flag in
+DTS, so set GPIOD_OUT_LOW when get GPIO descriptors, and set value 1 means
+output low, set value 0 means output high with gpiod API.
+
+The in-tree DTS files have the right polarity set up already so we can
+expect this to "just work"
+
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Link: https://patch.msgid.link/20250324-wcd-gpiod-v2-3-773f67ce3b56@nxp.com
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index dc4ce2c3f2188..08b7ca26c3c97 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -16,7 +16,7 @@
+ #include <sound/soc.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc-dapm.h>
+-#include <linux/of_gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+ #include <sound/tlv.h>
+@@ -338,7 +338,7 @@ struct wcd9335_codec {
+       int comp_enabled[COMPANDER_MAX];
+       int intr1;
+-      int reset_gpio;
++      struct gpio_desc *reset_gpio;
+       struct regulator_bulk_data supplies[WCD9335_MAX_SUPPLY];
+       unsigned int rx_port_value;
+@@ -5024,12 +5024,11 @@ static const struct regmap_irq_chip wcd9335_regmap_irq1_chip = {
+ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+ {
+       struct device *dev = wcd->dev;
+-      struct device_node *np = dev->of_node;
+       int ret;
+-      wcd->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+-      if (wcd->reset_gpio < 0)
+-              return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n");
++      wcd->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
++      if (IS_ERR(wcd->reset_gpio))
++              return dev_err_probe(dev, PTR_ERR(wcd->reset_gpio), "Reset GPIO missing from DT\n");
+       wcd->mclk = devm_clk_get(dev, "mclk");
+       if (IS_ERR(wcd->mclk))
+@@ -5072,9 +5071,9 @@ static int wcd9335_power_on_reset(struct wcd9335_codec *wcd)
+        */
+       usleep_range(600, 650);
+-      gpio_direction_output(wcd->reset_gpio, 0);
++      gpiod_set_value(wcd->reset_gpio, 1);
+       msleep(20);
+-      gpio_set_value(wcd->reset_gpio, 1);
++      gpiod_set_value(wcd->reset_gpio, 0);
+       msleep(20);
+       return 0;
+-- 
+2.39.5
+
diff --git a/queue-5.15/asoc-codecs-wcd9335-fix-missing-free-of-regulator-su.patch b/queue-5.15/asoc-codecs-wcd9335-fix-missing-free-of-regulator-su.patch
new file mode 100644 (file)
index 0000000..a995d4b
--- /dev/null
@@ -0,0 +1,88 @@
+From f790b9c961884c7660fc8757b9b6655f869daf5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 May 2025 11:47:01 +0200
+Subject: ASoC: codecs: wcd9335: Fix missing free of regulator supplies
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 9079db287fc3e38e040b0edeb0a25770bb679c8e ]
+
+Driver gets and enables all regulator supplies in probe path
+(wcd9335_parse_dt() and wcd9335_power_on_reset()), but does not cleanup
+in final error paths and in unbind (missing remove() callback).  This
+leads to leaked memory and unbalanced regulator enable count during
+probe errors or unbind.
+
+Fix this by converting entire code into devm_regulator_bulk_get_enable()
+which also greatly simplifies the code.
+
+Fixes: 20aedafdf492 ("ASoC: wcd9335: add support to wcd9335 codec")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20250526-b4-b4-asoc-wcd9395-vdd-px-fixes-v1-1-0b8a2993b7d3@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 25 +++++++------------------
+ 1 file changed, 7 insertions(+), 18 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index 08b7ca26c3c97..f20d0c9e91e49 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -339,7 +339,6 @@ struct wcd9335_codec {
+       int intr1;
+       struct gpio_desc *reset_gpio;
+-      struct regulator_bulk_data supplies[WCD9335_MAX_SUPPLY];
+       unsigned int rx_port_value;
+       unsigned int tx_port_value;
+@@ -366,6 +365,10 @@ struct wcd9335_irq {
+       char *name;
+ };
++static const char * const wcd9335_supplies[] = {
++      "vdd-buck", "vdd-buck-sido", "vdd-tx", "vdd-rx", "vdd-io",
++};
++
+ static const struct wcd9335_slim_ch wcd9335_tx_chs[WCD9335_TX_MAX] = {
+       WCD9335_SLIM_TX_CH(0),
+       WCD9335_SLIM_TX_CH(1),
+@@ -5038,30 +5041,16 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+       if (IS_ERR(wcd->native_clk))
+               return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n");
+-      wcd->supplies[0].supply = "vdd-buck";
+-      wcd->supplies[1].supply = "vdd-buck-sido";
+-      wcd->supplies[2].supply = "vdd-tx";
+-      wcd->supplies[3].supply = "vdd-rx";
+-      wcd->supplies[4].supply = "vdd-io";
+-
+-      ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies);
++      ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(wcd9335_supplies),
++                                           wcd9335_supplies);
+       if (ret)
+-              return dev_err_probe(dev, ret, "Failed to get supplies\n");
++              return dev_err_probe(dev, ret, "Failed to get and enable supplies\n");
+       return 0;
+ }
+ static int wcd9335_power_on_reset(struct wcd9335_codec *wcd)
+ {
+-      struct device *dev = wcd->dev;
+-      int ret;
+-
+-      ret = regulator_bulk_enable(WCD9335_MAX_SUPPLY, wcd->supplies);
+-      if (ret) {
+-              dev_err(dev, "Failed to get supplies: err = %d\n", ret);
+-              return ret;
+-      }
+-
+       /*
+        * For WCD9335, it takes about 600us for the Vout_A and
+        * Vout_D to be ready after BUCK_SIDO is powered up.
+-- 
+2.39.5
+
diff --git a/queue-5.15/asoc-codecs-wcd9335-handle-nicer-probe-deferral-and-.patch b/queue-5.15/asoc-codecs-wcd9335-handle-nicer-probe-deferral-and-.patch
new file mode 100644 (file)
index 0000000..c7e3fe2
--- /dev/null
@@ -0,0 +1,85 @@
+From e2bc0e5dd72e5873642518be3eb38166b4daa53b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 18:15:17 +0200
+Subject: ASoC: codecs: wcd9335: Handle nicer probe deferral and simplify with
+ dev_err_probe()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 4a03b5dbad466c902d522f3405daa4e5d80578c5 ]
+
+wcd9335_parse_dt() function is called only from probe(), so printing
+errors on resource acquisition is discouraged, because it can pollute
+dmesg.  Use dev_err_probe() to fix this and also make the code a bit
+simpler.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://msgid.link/r/20240612-asoc-wcd9xxx-wide-cleanups-v1-4-0d15885b2a06@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 28 +++++++++-------------------
+ 1 file changed, 9 insertions(+), 19 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index 075ed20e9fad8..dc4ce2c3f2188 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -5028,22 +5028,16 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+       int ret;
+       wcd->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+-      if (wcd->reset_gpio < 0) {
+-              dev_err(dev, "Reset GPIO missing from DT\n");
+-              return wcd->reset_gpio;
+-      }
++      if (wcd->reset_gpio < 0)
++              return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n");
+       wcd->mclk = devm_clk_get(dev, "mclk");
+-      if (IS_ERR(wcd->mclk)) {
+-              dev_err(dev, "mclk not found\n");
+-              return PTR_ERR(wcd->mclk);
+-      }
++      if (IS_ERR(wcd->mclk))
++              return dev_err_probe(dev, PTR_ERR(wcd->mclk), "mclk not found\n");
+       wcd->native_clk = devm_clk_get(dev, "slimbus");
+-      if (IS_ERR(wcd->native_clk)) {
+-              dev_err(dev, "slimbus clock not found\n");
+-              return PTR_ERR(wcd->native_clk);
+-      }
++      if (IS_ERR(wcd->native_clk))
++              return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n");
+       wcd->supplies[0].supply = "vdd-buck";
+       wcd->supplies[1].supply = "vdd-buck-sido";
+@@ -5052,10 +5046,8 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+       wcd->supplies[4].supply = "vdd-io";
+       ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies);
+-      if (ret) {
+-              dev_err(dev, "Failed to get supplies: err = %d\n", ret);
+-              return ret;
+-      }
++      if (ret)
++              return dev_err_probe(dev, ret, "Failed to get supplies\n");
+       return 0;
+ }
+@@ -5158,10 +5150,8 @@ static int wcd9335_slim_probe(struct slim_device *slim)
+       wcd->dev = dev;
+       ret = wcd9335_parse_dt(wcd);
+-      if (ret) {
+-              dev_err(dev, "Error parsing DT: %d\n", ret);
++      if (ret)
+               return ret;
+-      }
+       ret = wcd9335_power_on_reset(wcd);
+       if (ret)
+-- 
+2.39.5
+
diff --git a/queue-5.15/bcache-fix-null-pointer-in-cache_set_flush.patch b/queue-5.15/bcache-fix-null-pointer-in-cache_set_flush.patch
new file mode 100644 (file)
index 0000000..b0d15be
--- /dev/null
@@ -0,0 +1,151 @@
+From 5d6df08cd7ac36160d55ef3fa01b1478a116c18a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 May 2025 13:15:59 +0800
+Subject: bcache: fix NULL pointer in cache_set_flush()
+
+From: Linggang Zeng <linggang.zeng@easystack.cn>
+
+[ Upstream commit 1e46ed947ec658f89f1a910d880cd05e42d3763e ]
+
+1. LINE#1794 - LINE#1887 is some codes about function of
+   bch_cache_set_alloc().
+2. LINE#2078 - LINE#2142 is some codes about function of
+   register_cache_set().
+3. register_cache_set() will call bch_cache_set_alloc() in LINE#2098.
+
+ 1794 struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
+ 1795 {
+ ...
+ 1860         if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) ||
+ 1861             mempool_init_slab_pool(&c->search, 32, bch_search_cache) ||
+ 1862             mempool_init_kmalloc_pool(&c->bio_meta, 2,
+ 1863                                 sizeof(struct bbio) + sizeof(struct bio_vec) *
+ 1864                                 bucket_pages(c)) ||
+ 1865             mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
+ 1866             bioset_init(&c->bio_split, 4, offsetof(struct bbio, bio),
+ 1867                         BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER) ||
+ 1868             !(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) ||
+ 1869             !(c->moving_gc_wq = alloc_workqueue("bcache_gc",
+ 1870                                                 WQ_MEM_RECLAIM, 0)) ||
+ 1871             bch_journal_alloc(c) ||
+ 1872             bch_btree_cache_alloc(c) ||
+ 1873             bch_open_buckets_alloc(c) ||
+ 1874             bch_bset_sort_state_init(&c->sort, ilog2(c->btree_pages)))
+ 1875                 goto err;
+                      ^^^^^^^^
+ 1876
+ ...
+ 1883         return c;
+ 1884 err:
+ 1885         bch_cache_set_unregister(c);
+              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 1886         return NULL;
+ 1887 }
+ ...
+ 2078 static const char *register_cache_set(struct cache *ca)
+ 2079 {
+ ...
+ 2098         c = bch_cache_set_alloc(&ca->sb);
+ 2099         if (!c)
+ 2100                 return err;
+                      ^^^^^^^^^^
+ ...
+ 2128         ca->set = c;
+ 2129         ca->set->cache[ca->sb.nr_this_dev] = ca;
+              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ ...
+ 2138         return NULL;
+ 2139 err:
+ 2140         bch_cache_set_unregister(c);
+ 2141         return err;
+ 2142 }
+
+(1) If LINE#1860 - LINE#1874 is true, then do 'goto err'(LINE#1875) and
+    call bch_cache_set_unregister()(LINE#1885).
+(2) As (1) return NULL(LINE#1886), LINE#2098 - LINE#2100 would return.
+(3) As (2) has returned, LINE#2128 - LINE#2129 would do *not* give the
+    value to c->cache[], it means that c->cache[] is NULL.
+
+LINE#1624 - LINE#1665 is some codes about function of cache_set_flush().
+As (1), in LINE#1885 call
+bch_cache_set_unregister()
+---> bch_cache_set_stop()
+     ---> closure_queue()
+          -.-> cache_set_flush() (as below LINE#1624)
+
+ 1624 static void cache_set_flush(struct closure *cl)
+ 1625 {
+ ...
+ 1654         for_each_cache(ca, c, i)
+ 1655                 if (ca->alloc_thread)
+                          ^^
+ 1656                         kthread_stop(ca->alloc_thread);
+ ...
+ 1665 }
+
+(4) In LINE#1655 ca is NULL(see (3)) in cache_set_flush() then the
+    kernel crash occurred as below:
+[  846.712887] bcache: register_cache() error drbd6: cannot allocate memory
+[  846.713242] bcache: register_bcache() error : failed to register device
+[  846.713336] bcache: cache_set_free() Cache set 2f84bdc1-498a-4f2f-98a7-01946bf54287 unregistered
+[  846.713768] BUG: unable to handle kernel NULL pointer dereference at 00000000000009f8
+[  846.714790] PGD 0 P4D 0
+[  846.715129] Oops: 0000 [#1] SMP PTI
+[  846.715472] CPU: 19 PID: 5057 Comm: kworker/19:16 Kdump: loaded Tainted: G           OE    --------- -  - 4.18.0-147.5.1.el8_1.5es.3.x86_64 #1
+[  846.716082] Hardware name: ESPAN GI-25212/X11DPL-i, BIOS 2.1 06/15/2018
+[  846.716451] Workqueue: events cache_set_flush [bcache]
+[  846.716808] RIP: 0010:cache_set_flush+0xc9/0x1b0 [bcache]
+[  846.717155] Code: 00 4c 89 a5 b0 03 00 00 48 8b 85 68 f6 ff ff a8 08 0f 84 88 00 00 00 31 db 66 83 bd 3c f7 ff ff 00 48 8b 85 48 ff ff ff 74 28 <48> 8b b8 f8 09 00 00 48 85 ff 74 05 e8 b6 58 a2 e1 0f b7 95 3c f7
+[  846.718026] RSP: 0018:ffffb56dcf85fe70 EFLAGS: 00010202
+[  846.718372] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
+[  846.718725] RDX: 0000000000000001 RSI: 0000000040000001 RDI: 0000000000000000
+[  846.719076] RBP: ffffa0ccc0f20df8 R08: ffffa0ce1fedb118 R09: 000073746e657665
+[  846.719428] R10: 8080808080808080 R11: 0000000000000000 R12: ffffa0ce1fee8700
+[  846.719779] R13: ffffa0ccc0f211a8 R14: ffffa0cd1b902840 R15: ffffa0ccc0f20e00
+[  846.720132] FS:  0000000000000000(0000) GS:ffffa0ce1fec0000(0000) knlGS:0000000000000000
+[  846.720726] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  846.721073] CR2: 00000000000009f8 CR3: 00000008ba00a005 CR4: 00000000007606e0
+[  846.721426] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[  846.721778] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[  846.722131] PKRU: 55555554
+[  846.722467] Call Trace:
+[  846.722814]  process_one_work+0x1a7/0x3b0
+[  846.723157]  worker_thread+0x30/0x390
+[  846.723501]  ? create_worker+0x1a0/0x1a0
+[  846.723844]  kthread+0x112/0x130
+[  846.724184]  ? kthread_flush_work_fn+0x10/0x10
+[  846.724535]  ret_from_fork+0x35/0x40
+
+Now, check whether that ca is NULL in LINE#1655 to fix the issue.
+
+Signed-off-by: Linggang Zeng <linggang.zeng@easystack.cn>
+Signed-off-by: Mingzhe Zou <mingzhe.zou@easystack.cn>
+Signed-off-by: Coly Li <colyli@kernel.org>
+Link: https://lore.kernel.org/r/20250527051601.74407-2-colyli@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/bcache/super.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
+index 4b79b793cb806..7e0176e43acec 100644
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1746,7 +1746,12 @@ static void cache_set_flush(struct closure *cl)
+                       mutex_unlock(&b->write_lock);
+               }
+-      if (ca->alloc_thread)
++      /*
++       * If the register_cache_set() call to bch_cache_set_alloc() failed,
++       * ca has not been assigned a value and return error.
++       * So we need check ca is not NULL during bch_cache_set_unregister().
++       */
++      if (ca && ca->alloc_thread)
+               kthread_stop(ca->alloc_thread);
+       if (c->journal.cur) {
+-- 
+2.39.5
+
diff --git a/queue-5.15/ceph-fix-possible-integer-overflow-in-ceph_zero_obje.patch b/queue-5.15/ceph-fix-possible-integer-overflow-in-ceph_zero_obje.patch
new file mode 100644 (file)
index 0000000..ab777db
--- /dev/null
@@ -0,0 +1,40 @@
+From ff240b7e5542ff362f35929420d1ccc5158ef241 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Apr 2025 12:32:04 +0300
+Subject: ceph: fix possible integer overflow in ceph_zero_objects()
+
+From: Dmitry Kandybka <d.kandybka@gmail.com>
+
+[ Upstream commit 0abd87942e0c93964e93224836944712feba1d91 ]
+
+In 'ceph_zero_objects', promote 'object_size' to 'u64' to avoid possible
+integer overflow.
+
+Compile tested only.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Dmitry Kandybka <d.kandybka@gmail.com>
+Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ceph/file.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/ceph/file.c b/fs/ceph/file.c
+index f3fba3d27efa6..e92a10ba58b3f 100644
+--- a/fs/ceph/file.c
++++ b/fs/ceph/file.c
+@@ -2032,7 +2032,7 @@ static int ceph_zero_objects(struct inode *inode, loff_t offset, loff_t length)
+       s32 stripe_unit = ci->i_layout.stripe_unit;
+       s32 stripe_count = ci->i_layout.stripe_count;
+       s32 object_size = ci->i_layout.object_size;
+-      u64 object_set_size = object_size * stripe_count;
++      u64 object_set_size = (u64) object_size * stripe_count;
+       u64 nearly, t;
+       /* round offset up to next period boundary */
+-- 
+2.39.5
+
diff --git a/queue-5.15/cifs-fix-cifs_query_path_info-for-windows-nt-servers.patch b/queue-5.15/cifs-fix-cifs_query_path_info-for-windows-nt-servers.patch
new file mode 100644 (file)
index 0000000..7d8bd9d
--- /dev/null
@@ -0,0 +1,55 @@
+From 6fb92aabaf285ae9e18d96eaa27e81f2ae8aa50d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Dec 2024 16:06:22 +0100
+Subject: cifs: Fix cifs_query_path_info() for Windows NT servers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit a3e771afbb3bce91c8296828304903e7348003fe ]
+
+For TRANS2 QUERY_PATH_INFO request when the path does not exist, the
+Windows NT SMB server returns error response STATUS_OBJECT_NAME_NOT_FOUND
+or ERRDOS/ERRbadfile without the SMBFLG_RESPONSE flag set. Similarly it
+returns STATUS_DELETE_PENDING when the file is being deleted. And looks
+like that any error response from TRANS2 QUERY_PATH_INFO does not have
+SMBFLG_RESPONSE flag set.
+
+So relax check in check_smb_hdr() for detecting if the packet is response
+for this special case.
+
+This change fixes stat() operation against Windows NT SMB servers and also
+all operations which depends on -ENOENT result from stat like creat() or
+mkdir().
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/misc.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
+index 33328eae03d7a..a3d37e7769e61 100644
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -297,6 +297,14 @@ check_smb_hdr(struct smb_hdr *smb)
+       if (smb->Command == SMB_COM_LOCKING_ANDX)
+               return 0;
++      /*
++       * Windows NT server returns error resposne (e.g. STATUS_DELETE_PENDING
++       * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other)
++       * for some TRANS2 requests without the RESPONSE flag set in header.
++       */
++      if (smb->Command == SMB_COM_TRANSACTION2 && smb->Status.CifsError != 0)
++              return 0;
++
+       cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
+                get_mid(smb));
+       return 1;
+-- 
+2.39.5
+
diff --git a/queue-5.15/clk-ti-am43xx-add-clkctrl-data-for-am43xx-adc1.patch b/queue-5.15/clk-ti-am43xx-add-clkctrl-data-for-am43xx-adc1.patch
new file mode 100644 (file)
index 0000000..a39ae39
--- /dev/null
@@ -0,0 +1,51 @@
+From 72e8a7415f56a3261af7a16be93a0d85cd93662c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Oct 2021 10:14:19 +0200
+Subject: clk: ti: am43xx: Add clkctrl data for am43xx ADC1
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 59139ada4a7eacd4db378ee40a3d6ffbf1d0d72f ]
+
+Declare ADC1 clkctrl which feeds the magnetic-reader/ADC1 hardware
+module.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Acked-by: Stephen Boyd <sboyd@kernel.org>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Link: https://lore.kernel.org/r/20211015081506.933180-2-miquel.raynal@bootlin.com
+Stable-dep-of: d52b9b7e2f10 ("media: imx-jpeg: Drop the first error frames")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/clk-43xx.c       | 1 +
+ include/dt-bindings/clock/am4.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c
+index 46c0add995700..6e97a541cfd36 100644
+--- a/drivers/clk/ti/clk-43xx.c
++++ b/drivers/clk/ti/clk-43xx.c
+@@ -116,6 +116,7 @@ static const struct omap_clkctrl_reg_data am4_l3s_clkctrl_regs[] __initconst = {
+       { AM4_L3S_VPFE0_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" },
+       { AM4_L3S_VPFE1_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk" },
+       { AM4_L3S_GPMC_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" },
++      { AM4_L3S_ADC1_CLKCTRL, NULL, CLKF_SW_SUP, "l3s_gclk" },
+       { AM4_L3S_MCASP0_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp0_fck" },
+       { AM4_L3S_MCASP1_CLKCTRL, NULL, CLKF_SW_SUP, "mcasp1_fck" },
+       { AM4_L3S_MMC3_CLKCTRL, NULL, CLKF_SW_SUP, "mmc_clk" },
+diff --git a/include/dt-bindings/clock/am4.h b/include/dt-bindings/clock/am4.h
+index d961e7cb36821..4be6c5961f342 100644
+--- a/include/dt-bindings/clock/am4.h
++++ b/include/dt-bindings/clock/am4.h
+@@ -158,6 +158,7 @@
+ #define AM4_L3S_VPFE0_CLKCTRL AM4_L3S_CLKCTRL_INDEX(0x68)
+ #define AM4_L3S_VPFE1_CLKCTRL AM4_L3S_CLKCTRL_INDEX(0x70)
+ #define AM4_L3S_GPMC_CLKCTRL  AM4_L3S_CLKCTRL_INDEX(0x220)
++#define AM4_L3S_ADC1_CLKCTRL  AM4_L3S_CLKCTRL_INDEX(0x230)
+ #define AM4_L3S_MCASP0_CLKCTRL        AM4_L3S_CLKCTRL_INDEX(0x238)
+ #define AM4_L3S_MCASP1_CLKCTRL        AM4_L3S_CLKCTRL_INDEX(0x240)
+ #define AM4_L3S_MMC3_CLKCTRL  AM4_L3S_CLKCTRL_INDEX(0x248)
+-- 
+2.39.5
+
diff --git a/queue-5.15/coresight-only-check-bottom-two-claim-bits.patch b/queue-5.15/coresight-only-check-bottom-two-claim-bits.patch
new file mode 100644 (file)
index 0000000..9bbe0c4
--- /dev/null
@@ -0,0 +1,55 @@
+From 5d5b765c53ef767940d974b0e7f72db81edd1b68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Mar 2025 11:58:47 +0000
+Subject: coresight: Only check bottom two claim bits
+
+From: James Clark <james.clark@linaro.org>
+
+[ Upstream commit a4e65842e1142aa18ef36113fbd81d614eaefe5a ]
+
+The use of the whole register and == could break the claim mechanism if
+any of the other bits are used in the future. The referenced doc "PSCI -
+ARM DEN 0022D" also says to only read and clear the bottom two bits.
+
+Use FIELD_GET() to extract only the relevant part.
+
+Reviewed-by: Leo Yan <leo.yan@arm.com>
+Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
+Signed-off-by: James Clark <james.clark@linaro.org>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/20250325-james-coresight-claim-tags-v4-2-dfbd3822b2e5@linaro.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/coresight/coresight-core.c | 3 ++-
+ drivers/hwtracing/coresight/coresight-priv.h | 1 +
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
+index 3ea6900542223..f6989a74fec94 100644
+--- a/drivers/hwtracing/coresight/coresight-core.c
++++ b/drivers/hwtracing/coresight/coresight-core.c
+@@ -161,7 +161,8 @@ static int coresight_find_link_outport(struct coresight_device *csdev,
+ static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
+ {
+-      return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
++      return FIELD_GET(CORESIGHT_CLAIM_MASK,
++                       csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
+ }
+ static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
+diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
+index ff1dd2092ac5b..b416edcdf797d 100644
+--- a/drivers/hwtracing/coresight/coresight-priv.h
++++ b/drivers/hwtracing/coresight/coresight-priv.h
+@@ -32,6 +32,7 @@
+  * Coresight device CLAIM protocol.
+  * See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
+  */
++#define CORESIGHT_CLAIM_MASK          GENMASK(1, 0)
+ #define CORESIGHT_CLAIM_SELF_HOSTED   BIT(1)
+ #define TIMEOUT_US            100
+-- 
+2.39.5
+
diff --git a/queue-5.15/dmaengine-xilinx_dma-set-dma_device-directions.patch b/queue-5.15/dmaengine-xilinx_dma-set-dma_device-directions.patch
new file mode 100644 (file)
index 0000000..8ece311
--- /dev/null
@@ -0,0 +1,40 @@
+From 13df1e437841c2c6bf453f8e70cc4244d51148e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 May 2025 20:21:01 +0200
+Subject: dmaengine: xilinx_dma: Set dma_device directions
+
+From: Thomas Gessler <thomas.gessler@brueckmann-gmbh.de>
+
+[ Upstream commit 7e01511443c30a55a5ae78d3debd46d4d872517e ]
+
+Coalesce the direction bits from the enabled TX and/or RX channels into
+the directions bit mask of dma_device. Without this mask set,
+dma_get_slave_caps() in the DMAEngine fails, which prevents the driver
+from being used with an IIO DMAEngine buffer.
+
+Signed-off-by: Thomas Gessler <thomas.gessler@brueckmann-gmbh.de>
+Reviewed-by: Suraj Gupta <suraj.gupta2@amd.com>
+Tested-by: Folker Schwesinger <dev@folker-schwesinger.de>
+Link: https://lore.kernel.org/r/20250507182101.909010-1-thomas.gessler@brueckmann-gmbh.de
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/xilinx/xilinx_dma.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
+index edc2bb8f0523c..48ac51447baee 100644
+--- a/drivers/dma/xilinx/xilinx_dma.c
++++ b/drivers/dma/xilinx/xilinx_dma.c
+@@ -2861,6 +2861,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
+               return -EINVAL;
+       }
++      xdev->common.directions |= chan->direction;
++
+       /* Request the interrupt */
+       chan->irq = irq_of_parse_and_map(node, chan->tdest);
+       err = request_irq(chan->irq, xdev->dma_config->irq_handler,
+-- 
+2.39.5
+
diff --git a/queue-5.15/drivers-hv-rename-alloced-to-allocated.patch b/queue-5.15/drivers-hv-rename-alloced-to-allocated.patch
new file mode 100644 (file)
index 0000000..affed25
--- /dev/null
@@ -0,0 +1,145 @@
+From a3138d972344773023f3090e232fa7954facabca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jan 2022 11:34:11 +0100
+Subject: Drivers: hv: Rename 'alloced' to 'allocated'
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+[ Upstream commit de96e8a09889b35dd8d1cb6d19ef2bb123b05be1 ]
+
+'Alloced' is not a real word and only saves us two letters, let's
+use 'allocated' instead.
+
+No functional change intended.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Reviewed-by: Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/20220128103412.3033736-2-vkuznets@redhat.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Stable-dep-of: 0315fef2aff9 ("uio_hv_generic: Align ring size to system page")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hv/channel_mgmt.c | 18 +++++++++---------
+ drivers/hv/hyperv_vmbus.h | 14 +++++++-------
+ drivers/hv/vmbus_drv.c    |  2 +-
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
+index 62c864f8d991b..029f8269ad15d 100644
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -459,7 +459,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel)
+        * init_vp_index() can (re-)use the CPU.
+        */
+       if (hv_is_perf_channel(channel))
+-              hv_clear_alloced_cpu(channel->target_cpu);
++              hv_clear_allocated_cpu(channel->target_cpu);
+       /*
+        * Upon suspend, an in-use hv_sock channel is marked as "rescinded" and
+@@ -733,7 +733,7 @@ static void init_vp_index(struct vmbus_channel *channel)
+       bool perf_chn = hv_is_perf_channel(channel);
+       u32 i, ncpu = num_online_cpus();
+       cpumask_var_t available_mask;
+-      struct cpumask *alloced_mask;
++      struct cpumask *allocated_mask;
+       u32 target_cpu;
+       int numa_node;
+@@ -750,7 +750,7 @@ static void init_vp_index(struct vmbus_channel *channel)
+                */
+               channel->target_cpu = VMBUS_CONNECT_CPU;
+               if (perf_chn)
+-                      hv_set_alloced_cpu(VMBUS_CONNECT_CPU);
++                      hv_set_allocated_cpu(VMBUS_CONNECT_CPU);
+               return;
+       }
+@@ -765,22 +765,22 @@ static void init_vp_index(struct vmbus_channel *channel)
+                               continue;
+                       break;
+               }
+-              alloced_mask = &hv_context.hv_numa_map[numa_node];
++              allocated_mask = &hv_context.hv_numa_map[numa_node];
+-              if (cpumask_weight(alloced_mask) ==
++              if (cpumask_weight(allocated_mask) ==
+                   cpumask_weight(cpumask_of_node(numa_node))) {
+                       /*
+                        * We have cycled through all the CPUs in the node;
+-                       * reset the alloced map.
++                       * reset the allocated map.
+                        */
+-                      cpumask_clear(alloced_mask);
++                      cpumask_clear(allocated_mask);
+               }
+-              cpumask_xor(available_mask, alloced_mask,
++              cpumask_xor(available_mask, allocated_mask,
+                           cpumask_of_node(numa_node));
+               target_cpu = cpumask_first(available_mask);
+-              cpumask_set_cpu(target_cpu, alloced_mask);
++              cpumask_set_cpu(target_cpu, allocated_mask);
+               if (channel->offermsg.offer.sub_channel_index >= ncpu ||
+                   i > ncpu || !hv_cpuself_used(target_cpu, channel))
+diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
+index 631f0a138c2b9..6a0ae815a198e 100644
+--- a/drivers/hv/hyperv_vmbus.h
++++ b/drivers/hv/hyperv_vmbus.h
+@@ -405,7 +405,7 @@ static inline bool hv_is_perf_channel(struct vmbus_channel *channel)
+       return vmbus_devs[channel->device_id].perf_device;
+ }
+-static inline bool hv_is_alloced_cpu(unsigned int cpu)
++static inline bool hv_is_allocated_cpu(unsigned int cpu)
+ {
+       struct vmbus_channel *channel, *sc;
+@@ -427,23 +427,23 @@ static inline bool hv_is_alloced_cpu(unsigned int cpu)
+       return false;
+ }
+-static inline void hv_set_alloced_cpu(unsigned int cpu)
++static inline void hv_set_allocated_cpu(unsigned int cpu)
+ {
+       cpumask_set_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]);
+ }
+-static inline void hv_clear_alloced_cpu(unsigned int cpu)
++static inline void hv_clear_allocated_cpu(unsigned int cpu)
+ {
+-      if (hv_is_alloced_cpu(cpu))
++      if (hv_is_allocated_cpu(cpu))
+               return;
+       cpumask_clear_cpu(cpu, &hv_context.hv_numa_map[cpu_to_node(cpu)]);
+ }
+-static inline void hv_update_alloced_cpus(unsigned int old_cpu,
++static inline void hv_update_allocated_cpus(unsigned int old_cpu,
+                                         unsigned int new_cpu)
+ {
+-      hv_set_alloced_cpu(new_cpu);
+-      hv_clear_alloced_cpu(old_cpu);
++      hv_set_allocated_cpu(new_cpu);
++      hv_clear_allocated_cpu(old_cpu);
+ }
+ #ifdef CONFIG_HYPERV_TESTING
+diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
+index cb3a5b13c3ec2..f42c3cb3cc0aa 100644
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -1878,7 +1878,7 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
+       /* See init_vp_index(). */
+       if (hv_is_perf_channel(channel))
+-              hv_update_alloced_cpus(origin_cpu, target_cpu);
++              hv_update_allocated_cpus(origin_cpu, target_cpu);
+       /* Currently set only for storvsc channels. */
+       if (channel->change_target_cpu_callback) {
+-- 
+2.39.5
+
diff --git a/queue-5.15/drivers-hv-vmbus-add-utility-function-for-querying-r.patch b/queue-5.15/drivers-hv-vmbus-add-utility-function-for-querying-r.patch
new file mode 100644 (file)
index 0000000..b70dc03
--- /dev/null
@@ -0,0 +1,94 @@
+From 205af7b258f17bc3c5ddd06f94a5b9c513a21834 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Mar 2024 01:51:57 -0700
+Subject: Drivers: hv: vmbus: Add utility function for querying ring size
+
+From: Saurabh Sengar <ssengar@linux.microsoft.com>
+
+[ Upstream commit e8c4bd6c6e6b7e7b416c42806981c2a81370001e ]
+
+Add a function to query for the preferred ring buffer size of VMBus
+device. This will allow the drivers (eg. UIO) to allocate the most
+optimized ring buffer size for devices.
+
+Signed-off-by: Saurabh Sengar <ssengar@linux.microsoft.com>
+Reviewed-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1711788723-8593-2-git-send-email-ssengar@linux.microsoft.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 0315fef2aff9 ("uio_hv_generic: Align ring size to system page")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hv/channel_mgmt.c | 15 ++++++++++++---
+ drivers/hv/hyperv_vmbus.h |  5 +++++
+ include/linux/hyperv.h    |  2 ++
+ 3 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
+index 029f8269ad15d..cd9f01b7d37dd 100644
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -119,7 +119,9 @@ const struct vmbus_device vmbus_devs[] = {
+       },
+       /* File copy */
+-      { .dev_type = HV_FCOPY,
++      /* fcopy always uses 16KB ring buffer size and is working well for last many years */
++      { .pref_ring_size = 0x4000,
++        .dev_type = HV_FCOPY,
+         HV_FCOPY_GUID,
+         .perf_device = false,
+         .allowed_in_isolated = false,
+@@ -139,12 +141,19 @@ const struct vmbus_device vmbus_devs[] = {
+         .allowed_in_isolated = false,
+       },
+-      /* Unknown GUID */
+-      { .dev_type = HV_UNKNOWN,
++      /*
++       * Unknown GUID
++       * 64 KB ring buffer + 4 KB header should be sufficient size for any Hyper-V device apart
++       * from HV_NIC and HV_SCSI. This case avoid the fallback for unknown devices to allocate
++       * much bigger (2 MB) of ring size.
++       */
++      { .pref_ring_size = 0x11000,
++        .dev_type = HV_UNKNOWN,
+         .perf_device = false,
+         .allowed_in_isolated = false,
+       },
+ };
++EXPORT_SYMBOL_GPL(vmbus_devs);
+ static const struct {
+       guid_t guid;
+diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
+index 6a0ae815a198e..b87adb3a98211 100644
+--- a/drivers/hv/hyperv_vmbus.h
++++ b/drivers/hv/hyperv_vmbus.h
+@@ -405,6 +405,11 @@ static inline bool hv_is_perf_channel(struct vmbus_channel *channel)
+       return vmbus_devs[channel->device_id].perf_device;
+ }
++static inline size_t hv_dev_ring_size(struct vmbus_channel *channel)
++{
++      return vmbus_devs[channel->device_id].pref_ring_size;
++}
++
+ static inline bool hv_is_allocated_cpu(unsigned int cpu)
+ {
+       struct vmbus_channel *channel, *sc;
+diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
+index aff435a42ead9..62d5bb1f726f6 100644
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -815,6 +815,8 @@ struct vmbus_requestor {
+ #define VMBUS_RQST_RESET (U64_MAX - 3)
+ struct vmbus_device {
++      /* preferred ring buffer size in KB, 0 means no preferred size for this device */
++      size_t pref_ring_size;
+       u16  dev_type;
+       guid_t guid;
+       bool perf_device;
+-- 
+2.39.5
+
diff --git a/queue-5.15/dummycon-trigger-redraw-when-switching-consoles-with.patch b/queue-5.15/dummycon-trigger-redraw-when-switching-consoles-with.patch
new file mode 100644 (file)
index 0000000..22fdacc
--- /dev/null
@@ -0,0 +1,96 @@
+From 7aba9b612d73fc657c2cc6906a97c307a752f521 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 May 2025 09:14:00 +0200
+Subject: dummycon: Trigger redraw when switching consoles with deferred
+ takeover
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 03bcbbb3995ba5df43af9aba45334e35f2dfe27b ]
+
+Signal vt subsystem to redraw console when switching to dummycon
+with deferred takeover enabled. Makes the console switch to fbcon
+and displays the available output.
+
+With deferred takeover enabled, dummycon acts as the placeholder
+until the first output to the console happens. At that point, fbcon
+takes over. If the output happens while dummycon is not active, it
+cannot inform fbcon. This is the case if the vt subsystem runs in
+graphics mode.
+
+A typical graphical boot starts plymouth, a display manager and a
+compositor; all while leaving out dummycon. Switching to a text-mode
+console leaves the console with dummycon even if a getty terminal
+has been started.
+
+Returning true from dummycon's con_switch helper signals the vt
+subsystem to redraw the screen. If there's output available dummycon's
+con_putc{s} helpers trigger deferred takeover of fbcon, which sets a
+display mode and displays the output. If no output is available,
+dummycon remains active.
+
+v2:
+- make the comment slightly more verbose (Javier)
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reported-by: Andrei Borzenkov <arvidjaar@gmail.com>
+Closes: https://bugzilla.suse.com/show_bug.cgi?id=1242191
+Tested-by: Andrei Borzenkov <arvidjaar@gmail.com>
+Acked-by: Javier Martinez Canillas <javierm@redhat.com>
+Fixes: 83d83bebf401 ("console/fbcon: Add support for deferred console takeover")
+Cc: Hans de Goede <hdegoede@redhat.com>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v4.19+
+Link: https://lore.kernel.org/r/20250520071418.8462-1-tzimmermann@suse.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/console/dummycon.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
+index d701f2b51f5b1..d99e1b3e4e5c1 100644
+--- a/drivers/video/console/dummycon.c
++++ b/drivers/video/console/dummycon.c
+@@ -82,6 +82,15 @@ static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
+       /* Redraw, so that we get putc(s) for output done while blanked */
+       return 1;
+ }
++
++static bool dummycon_switch(struct vc_data *vc)
++{
++      /*
++       * Redraw, so that we get putc(s) for output done while switched
++       * away. Informs deferred consoles to take over the display.
++       */
++      return true;
++}
+ #else
+ static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
+ static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
+@@ -90,6 +99,10 @@ static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
+ {
+       return 0;
+ }
++static bool dummycon_switch(struct vc_data *vc)
++{
++      return false;
++}
+ #endif
+ static const char *dummycon_startup(void)
+@@ -119,11 +132,6 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
+       return false;
+ }
+-static bool dummycon_switch(struct vc_data *vc)
+-{
+-      return false;
+-}
+-
+ /*
+  *  The console `switch' structure for the dummy console
+  *
+-- 
+2.39.5
+
diff --git a/queue-5.15/f2fs-don-t-over-report-free-space-or-inodes-in-statv.patch b/queue-5.15/f2fs-don-t-over-report-free-space-or-inodes-in-statv.patch
new file mode 100644 (file)
index 0000000..4f2035a
--- /dev/null
@@ -0,0 +1,99 @@
+From eef5a0268a4170ad101953759cfc21dd2f0cadbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 May 2025 19:25:38 +0800
+Subject: f2fs: don't over-report free space or inodes in statvfs
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit a9201960623287927bf5776de3f70fb2fbde7e02 ]
+
+This fixes an analogus bug that was fixed in modern filesystems:
+a) xfs in commit 4b8d867ca6e2 ("xfs: don't over-report free space or
+inodes in statvfs")
+b) ext4 in commit f87d3af74193 ("ext4: don't over-report free space
+or inodes in statvfs")
+where statfs can report misleading / incorrect information where
+project quota is enabled, and the free space is less than the
+remaining quota.
+
+This commit will resolve a test failure in generic/762 which tests
+for this bug.
+
+generic/762       - output mismatch (see /share/git/fstests/results//generic/762.out.bad)
+    --- tests/generic/762.out   2025-04-15 10:21:53.371067071 +0800
+    +++ /share/git/fstests/results//generic/762.out.bad 2025-05-13 16:13:37.000000000 +0800
+    @@ -6,8 +6,10 @@
+     root blocks2 is in range
+     dir blocks2 is in range
+     root bavail2 is in range
+    -dir bavail2 is in range
+    +dir bavail2 has value of 1539066
+    +dir bavail2 is NOT in range 304734.87 .. 310891.13
+     root blocks3 is in range
+    ...
+    (Run 'diff -u /share/git/fstests/tests/generic/762.out /share/git/fstests/results//generic/762.out.bad'  to see the entire diff)
+
+HINT: You _MAY_ be missing kernel fix:
+      XXXXXXXXXXXXXX xfs: don't over-report free space or inodes in statvfs
+
+Cc: stable@kernel.org
+Fixes: ddc34e328d06 ("f2fs: introduce f2fs_statfs_project")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/super.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 194d3f93ac5f2..b9da3074a1af8 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1737,26 +1737,32 @@ static int f2fs_statfs_project(struct super_block *sb,
+       limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit,
+                                       dquot->dq_dqb.dqb_bhardlimit);
+-      if (limit)
+-              limit >>= sb->s_blocksize_bits;
++      limit >>= sb->s_blocksize_bits;
++
++      if (limit) {
++              uint64_t remaining = 0;
+-      if (limit && buf->f_blocks > limit) {
+               curblock = (dquot->dq_dqb.dqb_curspace +
+                           dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits;
+-              buf->f_blocks = limit;
+-              buf->f_bfree = buf->f_bavail =
+-                      (buf->f_blocks > curblock) ?
+-                       (buf->f_blocks - curblock) : 0;
++              if (limit > curblock)
++                      remaining = limit - curblock;
++
++              buf->f_blocks = min(buf->f_blocks, limit);
++              buf->f_bfree = min(buf->f_bfree, remaining);
++              buf->f_bavail = min(buf->f_bavail, remaining);
+       }
+       limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit,
+                                       dquot->dq_dqb.dqb_ihardlimit);
+-      if (limit && buf->f_files > limit) {
+-              buf->f_files = limit;
+-              buf->f_ffree =
+-                      (buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
+-                       (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
++      if (limit) {
++              uint64_t remaining = 0;
++
++              if (limit > dquot->dq_dqb.dqb_curinodes)
++                      remaining = limit - dquot->dq_dqb.dqb_curinodes;
++
++              buf->f_files = min(buf->f_files, limit);
++              buf->f_ffree = min(buf->f_ffree, remaining);
+       }
+       spin_unlock(&dquot->dq_dqb_lock);
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-delete-a-few-unneeded-forward-decl.patch b/queue-5.15/fbcon-delete-a-few-unneeded-forward-decl.patch
new file mode 100644 (file)
index 0000000..b6802ed
--- /dev/null
@@ -0,0 +1,79 @@
+From 2b6cd27cba2f0d105d7ab11dd16116e82f609f1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:19 +0200
+Subject: fbcon: delete a few unneeded forward decl
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit 9ad7acdad1d91545b99bf9fda3de4b86cf48b272 ]
+
+I didn't bother with any code movement to fix the others, these just
+got a bit in the way.
+
+v2: Rebase on top of Helge's reverts.
+
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Acked-by: Sam Ravnborg <sam@ravnborg.org> (v1)
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org> (v1)
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Helge Deller <deller@gmx.de>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Du Cheng <ducheng2@gmail.com>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-2-daniel.vetter@ffwll.ch
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 17 +----------------
+ 1 file changed, 1 insertion(+), 16 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index a67f982fe2ec0..a3af7aacfaf11 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -163,29 +163,14 @@ static int fbcon_cursor_noblink;
+  *  Interface used by the world
+  */
+-static const char *fbcon_startup(void);
+-static void fbcon_init(struct vc_data *vc, int init);
+-static void fbcon_deinit(struct vc_data *vc);
+-static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
+-                      int width);
+-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos);
+-static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+-                      int count, int ypos, int xpos);
+ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only);
+-static void fbcon_cursor(struct vc_data *vc, int mode);
+ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
+                       int height, int width);
+-static int fbcon_switch(struct vc_data *vc);
+-static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
+ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);
+ /*
+  *  Internal routines
+  */
+-static __inline__ void ywrap_up(struct vc_data *vc, int count);
+-static __inline__ void ywrap_down(struct vc_data *vc, int count);
+-static __inline__ void ypan_up(struct vc_data *vc, int count);
+-static __inline__ void ypan_down(struct vc_data *vc, int count);
+ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx,
+                           int dy, int dx, int height, int width, u_int y_break);
+ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+@@ -194,8 +179,8 @@ static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
+                             int line, int count, int dy);
+ static void fbcon_modechanged(struct fb_info *info);
+ static void fbcon_set_all_vcs(struct fb_info *info);
+-static void fbcon_start(void);
+ static void fbcon_exit(void);
++
+ static struct device *fbcon_device;
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-extract-fbcon_open-release-helpers.patch b/queue-5.15/fbcon-extract-fbcon_open-release-helpers.patch
new file mode 100644 (file)
index 0000000..d5763c7
--- /dev/null
@@ -0,0 +1,212 @@
+From bc80d7e1d1e199f1f758528182c999d4b879b915 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:27 +0200
+Subject: fbcon: Extract fbcon_open/release helpers
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit bd6026a8c4e6b7edf4bafcb71da885b284b8f4fd ]
+
+There's two minor behaviour changes in here:
+- in error paths we now consistently call fb_ops->fb_release
+- fb_release really can't fail (fbmem.c ignores it too) and there's no
+  reasonable cleanup we can do anyway.
+
+Note that everything in fbcon.c is protected by the big console_lock()
+lock (especially all the global variables), so the minor changes in
+ordering of setup/cleanup do not matter.
+
+v2: Explain a bit better why this is all correct (Sam)
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Cc: Du Cheng <ducheng2@gmail.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-10-daniel.vetter@ffwll.ch
+Stable-dep-of: 17186f1f90d3 ("fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in fb_videomode_to_var")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 107 +++++++++++++++----------------
+ 1 file changed, 53 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index abea89d101626..2a230a6335a81 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -691,19 +691,37 @@ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+ #endif /* CONFIG_MISC_TILEBLITTING */
++static int fbcon_open(struct fb_info *info)
++{
++      if (!try_module_get(info->fbops->owner))
++              return -ENODEV;
++
++      if (info->fbops->fb_open &&
++          info->fbops->fb_open(info, 0)) {
++              module_put(info->fbops->owner);
++              return -ENODEV;
++      }
++
++      return 0;
++}
++
++static void fbcon_release(struct fb_info *info)
++{
++      if (info->fbops->fb_release)
++              info->fbops->fb_release(info, 0);
++
++      module_put(info->fbops->owner);
++}
+ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
+                                 int unit, int oldidx)
+ {
+       struct fbcon_ops *ops = NULL;
+-      int err = 0;
+-
+-      if (!try_module_get(info->fbops->owner))
+-              err = -ENODEV;
++      int err;
+-      if (!err && info->fbops->fb_open &&
+-          info->fbops->fb_open(info, 0))
+-              err = -ENODEV;
++      err = fbcon_open(info);
++      if (err)
++              return err;
+       if (!err) {
+               ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+@@ -724,7 +742,7 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
+       if (err) {
+               con2fb_map[unit] = oldidx;
+-              module_put(info->fbops->owner);
++              fbcon_release(info);
+       }
+       return err;
+@@ -735,45 +753,34 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
+                                 int oldidx, int found)
+ {
+       struct fbcon_ops *ops = oldinfo->fbcon_par;
+-      int err = 0, ret;
++      int ret;
+-      if (oldinfo->fbops->fb_release &&
+-          oldinfo->fbops->fb_release(oldinfo, 0)) {
+-              con2fb_map[unit] = oldidx;
+-              if (!found && newinfo->fbops->fb_release)
+-                      newinfo->fbops->fb_release(newinfo, 0);
+-              if (!found)
+-                      module_put(newinfo->fbops->owner);
+-              err = -ENODEV;
+-      }
++      fbcon_release(oldinfo);
+-      if (!err) {
+-              fbcon_del_cursor_work(oldinfo);
+-              kfree(ops->cursor_state.mask);
+-              kfree(ops->cursor_data);
+-              kfree(ops->cursor_src);
+-              kfree(ops->fontbuffer);
+-              kfree(oldinfo->fbcon_par);
+-              oldinfo->fbcon_par = NULL;
+-              module_put(oldinfo->fbops->owner);
+-              /*
+-                If oldinfo and newinfo are driving the same hardware,
+-                the fb_release() method of oldinfo may attempt to
+-                restore the hardware state.  This will leave the
+-                newinfo in an undefined state. Thus, a call to
+-                fb_set_par() may be needed for the newinfo.
+-              */
+-              if (newinfo && newinfo->fbops->fb_set_par) {
+-                      ret = newinfo->fbops->fb_set_par(newinfo);
++      fbcon_del_cursor_work(oldinfo);
++      kfree(ops->cursor_state.mask);
++      kfree(ops->cursor_data);
++      kfree(ops->cursor_src);
++      kfree(ops->fontbuffer);
++      kfree(oldinfo->fbcon_par);
++      oldinfo->fbcon_par = NULL;
++      /*
++        If oldinfo and newinfo are driving the same hardware,
++        the fb_release() method of oldinfo may attempt to
++        restore the hardware state.  This will leave the
++        newinfo in an undefined state. Thus, a call to
++        fb_set_par() may be needed for the newinfo.
++      */
++      if (newinfo && newinfo->fbops->fb_set_par) {
++              ret = newinfo->fbops->fb_set_par(newinfo);
+-                      if (ret)
+-                              printk(KERN_ERR "con2fb_release_oldinfo: "
+-                                      "detected unhandled fb_set_par error, "
+-                                      "error code %d\n", ret);
+-              }
++              if (ret)
++                      printk(KERN_ERR "con2fb_release_oldinfo: "
++                              "detected unhandled fb_set_par error, "
++                              "error code %d\n", ret);
+       }
+-      return err;
++      return 0;
+ }
+ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
+@@ -928,7 +935,6 @@ static const char *fbcon_startup(void)
+       struct fbcon_display *p = &fb_display[fg_console];
+       struct vc_data *vc = vc_cons[fg_console].d;
+       const struct font_desc *font = NULL;
+-      struct module *owner;
+       struct fb_info *info = NULL;
+       struct fbcon_ops *ops;
+       int rows, cols;
+@@ -947,17 +953,12 @@ static const char *fbcon_startup(void)
+       if (!info)
+               return NULL;
+       
+-      owner = info->fbops->owner;
+-      if (!try_module_get(owner))
++      if (fbcon_open(info))
+               return NULL;
+-      if (info->fbops->fb_open && info->fbops->fb_open(info, 0)) {
+-              module_put(owner);
+-              return NULL;
+-      }
+       ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+       if (!ops) {
+-              module_put(owner);
++              fbcon_release(info);
+               return NULL;
+       }
+@@ -3387,10 +3388,6 @@ static void fbcon_exit(void)
+               }
+               if (mapped) {
+-                      if (info->fbops->fb_release)
+-                              info->fbops->fb_release(info, 0);
+-                      module_put(info->fbops->owner);
+-
+                       if (info->fbcon_par) {
+                               struct fbcon_ops *ops = info->fbcon_par;
+@@ -3400,6 +3397,8 @@ static void fbcon_exit(void)
+                               kfree(info->fbcon_par);
+                               info->fbcon_par = NULL;
+                       }
++
++                      fbcon_release(info);
+               }
+       }
+ }
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-move-console_lock-for-register-unlink-unregist.patch b/queue-5.15/fbcon-move-console_lock-for-register-unlink-unregist.patch
new file mode 100644 (file)
index 0000000..3da2488
--- /dev/null
@@ -0,0 +1,195 @@
+From 1f6a3677cb84e9a94f803e4e847b3ecad77a3ed2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:32 +0200
+Subject: fbcon: Move console_lock for register/unlink/unregister
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit 6e7da3af008b72520f5318507f455f344b27f022 ]
+
+Ideally console_lock becomes an implementation detail of fbcon.c and
+doesn't show up anywhere in fbmem.c. We're still pretty far from that,
+but at least the register/unregister code is there now.
+
+With this the do_fb_ioctl() handler is the only code in fbmem.c still
+calling console_lock().
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Du Cheng <ducheng2@gmail.com>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Zheyu Ma <zheyuma97@gmail.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Zhen Lei <thunder.leizhen@huawei.com>
+Cc: Xiyu Yang <xiyuyang19@fudan.edu.cn>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-15-daniel.vetter@ffwll.ch
+Stable-dep-of: 17186f1f90d3 ("fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in fb_videomode_to_var")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 33 ++++++++++++++++++++++++++------
+ drivers/video/fbdev/core/fbmem.c | 23 ++--------------------
+ 2 files changed, 29 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 072a264ae380b..a67f982fe2ec0 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -2823,10 +2823,12 @@ void fbcon_fb_unbind(struct fb_info *info)
+       int i, new_idx = -1, ret = 0;
+       int idx = info->node;
+-      WARN_CONSOLE_UNLOCKED();
++      console_lock();
+-      if (!fbcon_has_console_bind)
++      if (!fbcon_has_console_bind) {
++              console_unlock();
+               return;
++      }
+       for (i = first_fb_vc; i <= last_fb_vc; i++) {
+               if (con2fb_map[i] != idx &&
+@@ -2866,6 +2868,8 @@ void fbcon_fb_unbind(struct fb_info *info)
+               }
+               fbcon_unbind();
+       }
++
++      console_unlock();
+ }
+ /* called with console_lock held */
+@@ -2873,10 +2877,12 @@ void fbcon_fb_unregistered(struct fb_info *info)
+ {
+       int i, idx;
+-      WARN_CONSOLE_UNLOCKED();
++      console_lock();
+-      if (deferred_takeover)
++      if (deferred_takeover) {
++              console_unlock();
+               return;
++      }
+       idx = info->node;
+       for (i = first_fb_vc; i <= last_fb_vc; i++) {
+@@ -2905,6 +2911,7 @@ void fbcon_fb_unregistered(struct fb_info *info)
+       if (!num_registered_fb)
+               do_unregister_con_driver(&fb_con);
++      console_unlock();
+ }
+ void fbcon_remap_all(struct fb_info *info)
+@@ -2962,19 +2969,27 @@ static inline void fbcon_select_primary(struct fb_info *info)
+ }
+ #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
++static bool lockless_register_fb;
++module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400);
++MODULE_PARM_DESC(lockless_register_fb,
++      "Lockless framebuffer registration for debugging [default=off]");
++
+ /* called with console_lock held */
+ int fbcon_fb_registered(struct fb_info *info)
+ {
+       int ret = 0, i, idx;
+-      WARN_CONSOLE_UNLOCKED();
++      if (!lockless_register_fb)
++              console_lock();
++      else
++              atomic_inc(&ignore_console_lock_warning);
+       idx = info->node;
+       fbcon_select_primary(info);
+       if (deferred_takeover) {
+               pr_info("fbcon: Deferring console take-over\n");
+-              return 0;
++              goto out;
+       }
+       if (info_idx == -1) {
+@@ -2994,6 +3009,12 @@ int fbcon_fb_registered(struct fb_info *info)
+               }
+       }
++out:
++      if (!lockless_register_fb)
++              console_unlock();
++      else
++              atomic_dec(&ignore_console_lock_warning);
++
+       return ret;
+ }
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index f4253ec8a6409..5e8ee360f6ba2 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -1620,14 +1620,9 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
+       }
+ }
+-static bool lockless_register_fb;
+-module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400);
+-MODULE_PARM_DESC(lockless_register_fb,
+-      "Lockless framebuffer registration for debugging [default=off]");
+-
+ static int do_register_framebuffer(struct fb_info *fb_info)
+ {
+-      int i, ret;
++      int i;
+       struct fb_videomode mode;
+       if (fb_check_foreignness(fb_info))
+@@ -1696,17 +1691,7 @@ static int do_register_framebuffer(struct fb_info *fb_info)
+       }
+ #endif
+-      if (!lockless_register_fb)
+-              console_lock();
+-      else
+-              atomic_inc(&ignore_console_lock_warning);
+-      ret = fbcon_fb_registered(fb_info);
+-
+-      if (!lockless_register_fb)
+-              console_unlock();
+-      else
+-              atomic_dec(&ignore_console_lock_warning);
+-      return ret;
++      return fbcon_fb_registered(fb_info);
+ }
+ static void unbind_console(struct fb_info *fb_info)
+@@ -1716,9 +1701,7 @@ static void unbind_console(struct fb_info *fb_info)
+       if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
+               return;
+-      console_lock();
+       fbcon_fb_unbind(fb_info);
+-      console_unlock();
+ }
+ static void unlink_framebuffer(struct fb_info *fb_info)
+@@ -1758,9 +1741,7 @@ static void do_unregister_framebuffer(struct fb_info *fb_info)
+               fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+       }
+ #endif
+-      console_lock();
+       fbcon_fb_unregistered(fb_info);
+-      console_unlock();
+       /* this may free fb info */
+       put_fb_info(fb_info);
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-move-more-common-code-into-fb_open.patch b/queue-5.15/fbcon-move-more-common-code-into-fb_open.patch
new file mode 100644 (file)
index 0000000..9e5dc28
--- /dev/null
@@ -0,0 +1,178 @@
+From bbeee6fbede2e3a3967af4884b2c2c8b31c26507 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:29 +0200
+Subject: fbcon: move more common code into fb_open()
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit d443d93864726ad68c0a741d1e7b03934a9af143 ]
+
+No idea why con2fb_acquire_newinfo() initializes much less than
+fbcon_startup(), but so be it. From a quick look most of the
+un-initialized stuff should be fairly harmless, but who knows.
+
+Note that the error handling for the con2fb_acquire_newinfo() failure
+case was very strange: Callers updated con2fb_map to the new value
+before calling this function, but upon error con2fb_acquire_newinfo
+reset it to the old value. Since I removed the call to fbcon_release
+anyway that strange error path was sticking out like a sore thumb,
+hence I removed it. Which also allows us to remove the oldidx
+parameter from that function.
+
+v2: Explain what's going on with oldidx and error paths (Sam)
+
+v3: Drop unused variable (0day)
+
+v4: Rebased over bisect fix in previous patch, unchagend end result.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org> (v2)
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: kernel test robot <lkp@intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Du Cheng <ducheng2@gmail.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-12-daniel.vetter@ffwll.ch
+Stable-dep-of: 17186f1f90d3 ("fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in fb_videomode_to_var")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 75 +++++++++++++-------------------
+ 1 file changed, 30 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 2a230a6335a81..734b8f3f81b24 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -691,8 +691,18 @@ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+ #endif /* CONFIG_MISC_TILEBLITTING */
++static void fbcon_release(struct fb_info *info)
++{
++      if (info->fbops->fb_release)
++              info->fbops->fb_release(info, 0);
++
++      module_put(info->fbops->owner);
++}
++
+ static int fbcon_open(struct fb_info *info)
+ {
++      struct fbcon_ops *ops;
++
+       if (!try_module_get(info->fbops->owner))
+               return -ENODEV;
+@@ -702,48 +712,31 @@ static int fbcon_open(struct fb_info *info)
+               return -ENODEV;
+       }
+-      return 0;
+-}
++      ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
++      if (!ops) {
++              fbcon_release(info);
++              return -ENOMEM;
++      }
+-static void fbcon_release(struct fb_info *info)
+-{
+-      if (info->fbops->fb_release)
+-              info->fbops->fb_release(info, 0);
++      INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
++      ops->info = info;
++      info->fbcon_par = ops;
++      ops->cur_blink_jiffies = HZ / 5;
+-      module_put(info->fbops->owner);
++      return 0;
+ }
+ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
+-                                int unit, int oldidx)
++                                int unit)
+ {
+-      struct fbcon_ops *ops = NULL;
+       int err;
+       err = fbcon_open(info);
+       if (err)
+               return err;
+-      if (!err) {
+-              ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+-              if (!ops)
+-                      err = -ENOMEM;
+-      }
+-
+-      if (!err) {
+-              INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
+-
+-              ops->cur_blink_jiffies = HZ / 5;
+-              ops->info = info;
+-              info->fbcon_par = ops;
+-
+-              if (vc)
+-                      set_blitting_type(vc, info);
+-      }
+-
+-      if (err) {
+-              con2fb_map[unit] = oldidx;
+-              fbcon_release(info);
+-      }
++      if (vc)
++              set_blitting_type(vc, info);
+       return err;
+ }
+@@ -854,9 +847,11 @@ static int set_con2fb_map(int unit, int newidx, int user)
+       found = search_fb_in_map(newidx);
+-      con2fb_map[unit] = newidx;
+-      if (!err && !found)
+-              err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
++      if (!err && !found) {
++              err = con2fb_acquire_newinfo(vc, info, unit);
++              if (!err)
++                      con2fb_map[unit] = newidx;
++      }
+       /*
+        * If old fb is not mapped to any of the consoles,
+@@ -956,20 +951,10 @@ static const char *fbcon_startup(void)
+       if (fbcon_open(info))
+               return NULL;
+-      ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+-      if (!ops) {
+-              fbcon_release(info);
+-              return NULL;
+-      }
+-
+-      INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
+-
++      ops = info->fbcon_par;
+       ops->currcon = -1;
+       ops->graphics = 1;
+       ops->cur_rotate = -1;
+-      ops->cur_blink_jiffies = HZ / 5;
+-      ops->info = info;
+-      info->fbcon_par = ops;
+       p->con_rotate = initial_rotation;
+       if (p->con_rotate == -1)
+@@ -1037,7 +1022,7 @@ static void fbcon_init(struct vc_data *vc, int init)
+               return;
+       if (!info->fbcon_par)
+-              con2fb_acquire_newinfo(vc, info, vc->vc_num, -1);
++              con2fb_acquire_newinfo(vc, info, vc->vc_num);
+       /* If we are not the first console on this
+          fb, copy the font from that console */
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-use-delayed-work-for-cursor.patch b/queue-5.15/fbcon-use-delayed-work-for-cursor.patch
new file mode 100644 (file)
index 0000000..9cd1622
--- /dev/null
@@ -0,0 +1,302 @@
+From 5d4b0d384bdfa97b0e09d8f5bc550bcc29d5ca07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:24 +0200
+Subject: fbcon: Use delayed work for cursor
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit 3b0fb6ab25dda03f6077bf8fce9407bb0d4db6ea ]
+
+Allows us to delete a bunch of hand-rolled stuff using a timer plus a
+separate work). Also to simplify the code we initialize the
+cursor_work completely when we allocate the fbcon_ops structure,
+instead of trying to cope with console re-initialization.
+
+The motiviation here is that fbcon code stops using the fb_info.queue,
+which helps with locking issues around cleanup and all that in a later
+patch.
+
+Also note that this allows us to ditch the hand-rolled work cleanup in
+fbcon_exit - we already call fbcon_del_cursor_timer, which takes care
+of everything. Plus this was racy anyway.
+
+v2:
+- Only INIT_DELAYED_WORK when kzalloc succeeded (Tetsuo)
+- Explain that we replace both the timer and a work with the combined
+  delayed_work (Javier)
+
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Du Cheng <ducheng2@gmail.com>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-7-daniel.vetter@ffwll.ch
+Stable-dep-of: 17186f1f90d3 ("fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in fb_videomode_to_var")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 85 +++++++++++++-------------------
+ drivers/video/fbdev/core/fbcon.h |  4 +-
+ 2 files changed, 35 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 805a4745abd86..abea89d101626 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -357,8 +357,8 @@ static int get_color(struct vc_data *vc, struct fb_info *info,
+ static void fb_flashcursor(struct work_struct *work)
+ {
+-      struct fb_info *info = container_of(work, struct fb_info, queue);
+-      struct fbcon_ops *ops = info->fbcon_par;
++      struct fbcon_ops *ops = container_of(work, struct fbcon_ops, cursor_work.work);
++      struct fb_info *info;
+       struct vc_data *vc = NULL;
+       int c;
+       int mode;
+@@ -371,7 +371,10 @@ static void fb_flashcursor(struct work_struct *work)
+       if (ret == 0)
+               return;
+-      if (ops && ops->currcon != -1)
++      /* protected by console_lock */
++      info = ops->info;
++
++      if (ops->currcon != -1)
+               vc = vc_cons[ops->currcon].d;
+       if (!vc || !con_is_visible(vc) ||
+@@ -387,42 +390,25 @@ static void fb_flashcursor(struct work_struct *work)
+       ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+                   get_color(vc, info, c, 0));
+       console_unlock();
+-}
+-static void cursor_timer_handler(struct timer_list *t)
+-{
+-      struct fbcon_ops *ops = from_timer(ops, t, cursor_timer);
+-      struct fb_info *info = ops->info;
+-
+-      queue_work(system_power_efficient_wq, &info->queue);
+-      mod_timer(&ops->cursor_timer, jiffies + ops->cur_blink_jiffies);
++      queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
++                         ops->cur_blink_jiffies);
+ }
+-static void fbcon_add_cursor_timer(struct fb_info *info)
++static void fbcon_add_cursor_work(struct fb_info *info)
+ {
+       struct fbcon_ops *ops = info->fbcon_par;
+-      if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
+-          !(ops->flags & FBCON_FLAGS_CURSOR_TIMER) &&
+-          !fbcon_cursor_noblink) {
+-              if (!info->queue.func)
+-                      INIT_WORK(&info->queue, fb_flashcursor);
+-
+-              timer_setup(&ops->cursor_timer, cursor_timer_handler, 0);
+-              mod_timer(&ops->cursor_timer, jiffies + ops->cur_blink_jiffies);
+-              ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
+-      }
++      if (!fbcon_cursor_noblink)
++              queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
++                                 ops->cur_blink_jiffies);
+ }
+-static void fbcon_del_cursor_timer(struct fb_info *info)
++static void fbcon_del_cursor_work(struct fb_info *info)
+ {
+       struct fbcon_ops *ops = info->fbcon_par;
+-      if (info->queue.func == fb_flashcursor &&
+-          ops->flags & FBCON_FLAGS_CURSOR_TIMER) {
+-              del_timer_sync(&ops->cursor_timer);
+-              ops->flags &= ~FBCON_FLAGS_CURSOR_TIMER;
+-      }
++      cancel_delayed_work_sync(&ops->cursor_work);
+ }
+ #ifndef MODULE
+@@ -726,6 +712,8 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
+       }
+       if (!err) {
++              INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
++
+               ops->cur_blink_jiffies = HZ / 5;
+               ops->info = info;
+               info->fbcon_par = ops;
+@@ -760,7 +748,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
+       }
+       if (!err) {
+-              fbcon_del_cursor_timer(oldinfo);
++              fbcon_del_cursor_work(oldinfo);
+               kfree(ops->cursor_state.mask);
+               kfree(ops->cursor_data);
+               kfree(ops->cursor_src);
+@@ -876,7 +864,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
+                                logo_shown != FBCON_LOGO_DONTSHOW);
+               if (!found)
+-                      fbcon_add_cursor_timer(info);
++                      fbcon_add_cursor_work(info);
+               con2fb_map_boot[unit] = newidx;
+               con2fb_init_display(vc, info, unit, show_logo);
+       }
+@@ -973,6 +961,8 @@ static const char *fbcon_startup(void)
+               return NULL;
+       }
++      INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
++
+       ops->currcon = -1;
+       ops->graphics = 1;
+       ops->cur_rotate = -1;
+@@ -1013,7 +1003,7 @@ static const char *fbcon_startup(void)
+                info->var.yres,
+                info->var.bits_per_pixel);
+-      fbcon_add_cursor_timer(info);
++      fbcon_add_cursor_work(info);
+       return display_desc;
+ }
+@@ -1199,7 +1189,7 @@ static void fbcon_deinit(struct vc_data *vc)
+               goto finished;
+       if (con_is_visible(vc))
+-              fbcon_del_cursor_timer(info);
++              fbcon_del_cursor_work(info);
+       ops->flags &= ~FBCON_FLAGS_INIT;
+ finished:
+@@ -1326,9 +1316,9 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
+               return;
+       if (vc->vc_cursor_type & CUR_SW)
+-              fbcon_del_cursor_timer(info);
++              fbcon_del_cursor_work(info);
+       else
+-              fbcon_add_cursor_timer(info);
++              fbcon_add_cursor_work(info);
+       ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
+@@ -2134,14 +2124,14 @@ static int fbcon_switch(struct vc_data *vc)
+               }
+               if (old_info != info)
+-                      fbcon_del_cursor_timer(old_info);
++                      fbcon_del_cursor_work(old_info);
+       }
+       if (fbcon_is_inactive(vc, info) ||
+           ops->blank_state != FB_BLANK_UNBLANK)
+-              fbcon_del_cursor_timer(info);
++              fbcon_del_cursor_work(info);
+       else
+-              fbcon_add_cursor_timer(info);
++              fbcon_add_cursor_work(info);
+       set_blitting_type(vc, info);
+       ops->cursor_reset = 1;
+@@ -2249,9 +2239,9 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
+       if (mode_switch || fbcon_is_inactive(vc, info) ||
+           ops->blank_state != FB_BLANK_UNBLANK)
+-              fbcon_del_cursor_timer(info);
++              fbcon_del_cursor_work(info);
+       else
+-              fbcon_add_cursor_timer(info);
++              fbcon_add_cursor_work(info);
+       return 0;
+ }
+@@ -3241,7 +3231,7 @@ static ssize_t show_cursor_blink(struct device *device,
+       if (!ops)
+               goto err;
+-      blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0;
++      blink = delayed_work_pending(&ops->cursor_work);
+ err:
+       console_unlock();
+       return snprintf(buf, PAGE_SIZE, "%d\n", blink);
+@@ -3270,10 +3260,10 @@ static ssize_t store_cursor_blink(struct device *device,
+       if (blink) {
+               fbcon_cursor_noblink = 0;
+-              fbcon_add_cursor_timer(info);
++              fbcon_add_cursor_work(info);
+       } else {
+               fbcon_cursor_noblink = 1;
+-              fbcon_del_cursor_timer(info);
++              fbcon_del_cursor_work(info);
+       }
+ err:
+@@ -3386,15 +3376,9 @@ static void fbcon_exit(void)
+ #endif
+       for_each_registered_fb(i) {
+-              int pending = 0;
+-
+               mapped = 0;
+               info = registered_fb[i];
+-              if (info->queue.func)
+-                      pending = cancel_work_sync(&info->queue);
+-              pr_debug("fbcon: %s pending work\n", (pending ? "canceled" : "no"));
+-
+               for (j = first_fb_vc; j <= last_fb_vc; j++) {
+                       if (con2fb_map[j] == i) {
+                               mapped = 1;
+@@ -3410,15 +3394,12 @@ static void fbcon_exit(void)
+                       if (info->fbcon_par) {
+                               struct fbcon_ops *ops = info->fbcon_par;
+-                              fbcon_del_cursor_timer(info);
++                              fbcon_del_cursor_work(info);
+                               kfree(ops->cursor_src);
+                               kfree(ops->cursor_state.mask);
+                               kfree(info->fbcon_par);
+                               info->fbcon_par = NULL;
+                       }
+-
+-                      if (info->queue.func == fb_flashcursor)
+-                              info->queue.func = NULL;
+               }
+       }
+ }
+diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
+index 3e1ec454b8aa3..a709e5796ef7e 100644
+--- a/drivers/video/fbdev/core/fbcon.h
++++ b/drivers/video/fbdev/core/fbcon.h
+@@ -14,11 +14,11 @@
+ #include <linux/types.h>
+ #include <linux/vt_buffer.h>
+ #include <linux/vt_kern.h>
++#include <linux/workqueue.h>
+ #include <asm/io.h>
+ #define FBCON_FLAGS_INIT         1
+-#define FBCON_FLAGS_CURSOR_TIMER 2
+    /*
+     *    This is the interface between the low-level console driver and the
+@@ -68,7 +68,7 @@ struct fbcon_ops {
+       int  (*update_start)(struct fb_info *info);
+       int  (*rotate_font)(struct fb_info *info, struct vc_data *vc);
+       struct fb_var_screeninfo var;  /* copy of the current fb_var_screeninfo */
+-      struct timer_list cursor_timer; /* Cursor timer */
++      struct delayed_work cursor_work; /* Cursor timer */
+       struct fb_cursor cursor_state;
+       struct fbcon_display *p;
+       struct fb_info *info;
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbcon-use-lock_fb_info-in-fbcon_open-release.patch b/queue-5.15/fbcon-use-lock_fb_info-in-fbcon_open-release.patch
new file mode 100644 (file)
index 0000000..074fe97
--- /dev/null
@@ -0,0 +1,108 @@
+From aad0fd8c1c0ea7e5b79ea269223efddf5c73720a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 23:03:30 +0200
+Subject: fbcon: use lock_fb_info in fbcon_open/release
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+[ Upstream commit 04933a294dacca3aaa480889d53e6195778d4578 ]
+
+Now we get to the real motiviation, because fbmem.c insists that
+that's the right lock for these.
+
+Ofc fbcon.c has a lot more places where it probably should call
+lock_fb_info(). But looking at fbmem.c at least most of these seem to
+be protected by console_lock() too, which is probably what papers over
+any issues.
+
+Note that this means we're shuffling around a bit the locking sections
+for some of the console takeover and unbind paths, but not all:
+- console binding/unbinding from the console layer never with
+lock_fb_info
+- unbind (as opposed to unlink) never bother with lock_fb_info
+
+Also the real serialization against set_par and set_pan are still
+doing by wrapping the entire ioctl code in console_lock(). So this
+shuffling shouldn't be worse than what we had from a "can you trigger
+races?" pov, but it's at least clearer.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: Claudio Suarez <cssk@net-c.es>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Du Cheng <ducheng2@gmail.com>
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: William Kucharski <william.kucharski@oracle.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Zheyu Ma <zheyuma97@gmail.com>
+Cc: Zhen Lei <thunder.leizhen@huawei.com>
+Cc: Xiyu Yang <xiyuyang19@fudan.edu.cn>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220405210335.3434130-13-daniel.vetter@ffwll.ch
+Stable-dep-of: 17186f1f90d3 ("fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in fb_videomode_to_var")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbcon.c | 5 +++++
+ drivers/video/fbdev/core/fbmem.c | 4 ----
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 734b8f3f81b24..072a264ae380b 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -693,8 +693,10 @@ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+ static void fbcon_release(struct fb_info *info)
+ {
++      lock_fb_info(info);
+       if (info->fbops->fb_release)
+               info->fbops->fb_release(info, 0);
++      unlock_fb_info(info);
+       module_put(info->fbops->owner);
+ }
+@@ -706,11 +708,14 @@ static int fbcon_open(struct fb_info *info)
+       if (!try_module_get(info->fbops->owner))
+               return -ENODEV;
++      lock_fb_info(info);
+       if (info->fbops->fb_open &&
+           info->fbops->fb_open(info, 0)) {
++              unlock_fb_info(info);
+               module_put(info->fbops->owner);
+               return -ENODEV;
+       }
++      unlock_fb_info(info);
+       ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+       if (!ops) {
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index d938c31e8f90a..f4253ec8a6409 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -1700,9 +1700,7 @@ static int do_register_framebuffer(struct fb_info *fb_info)
+               console_lock();
+       else
+               atomic_inc(&ignore_console_lock_warning);
+-      lock_fb_info(fb_info);
+       ret = fbcon_fb_registered(fb_info);
+-      unlock_fb_info(fb_info);
+       if (!lockless_register_fb)
+               console_unlock();
+@@ -1719,9 +1717,7 @@ static void unbind_console(struct fb_info *fb_info)
+               return;
+       console_lock();
+-      lock_fb_info(fb_info);
+       fbcon_fb_unbind(fb_info);
+-      unlock_fb_info(fb_info);
+       console_unlock();
+ }
+-- 
+2.39.5
+
diff --git a/queue-5.15/fbdev-fix-do_register_framebuffer-to-prevent-null-pt.patch b/queue-5.15/fbdev-fix-do_register_framebuffer-to-prevent-null-pt.patch
new file mode 100644 (file)
index 0000000..f78fbe3
--- /dev/null
@@ -0,0 +1,112 @@
+From 717d77b6fe020171b16ba65269413b40ff77bec7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Apr 2025 18:34:06 +0300
+Subject: fbdev: Fix do_register_framebuffer to prevent null-ptr-deref in
+ fb_videomode_to_var
+
+From: Murad Masimov <m.masimov@mt-integration.ru>
+
+[ Upstream commit 17186f1f90d34fa701e4f14e6818305151637b9e ]
+
+If fb_add_videomode() in do_register_framebuffer() fails to allocate
+memory for fb_videomode, it will later lead to a null-ptr dereference in
+fb_videomode_to_var(), as the fb_info is registered while not having the
+mode in modelist that is expected to be there, i.e. the one that is
+described in fb_info->var.
+
+================================================================
+general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI
+KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+CPU: 1 PID: 30371 Comm: syz-executor.1 Not tainted 5.10.226-syzkaller #0
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
+RIP: 0010:fb_videomode_to_var+0x24/0x610 drivers/video/fbdev/core/modedb.c:901
+Call Trace:
+ display_to_var+0x3a/0x7c0 drivers/video/fbdev/core/fbcon.c:929
+ fbcon_resize+0x3e2/0x8f0 drivers/video/fbdev/core/fbcon.c:2071
+ resize_screen drivers/tty/vt/vt.c:1176 [inline]
+ vc_do_resize+0x53a/0x1170 drivers/tty/vt/vt.c:1263
+ fbcon_modechanged+0x3ac/0x6e0 drivers/video/fbdev/core/fbcon.c:2720
+ fbcon_update_vcs+0x43/0x60 drivers/video/fbdev/core/fbcon.c:2776
+ do_fb_ioctl+0x6d2/0x740 drivers/video/fbdev/core/fbmem.c:1128
+ fb_ioctl+0xe7/0x150 drivers/video/fbdev/core/fbmem.c:1203
+ vfs_ioctl fs/ioctl.c:48 [inline]
+ __do_sys_ioctl fs/ioctl.c:753 [inline]
+ __se_sys_ioctl fs/ioctl.c:739 [inline]
+ __x64_sys_ioctl+0x19a/0x210 fs/ioctl.c:739
+ do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
+ entry_SYSCALL_64_after_hwframe+0x67/0xd1
+================================================================
+
+Even though fbcon_init() checks beforehand if fb_match_mode() in
+var_to_display() fails, it can not prevent the panic because fbcon_init()
+does not return error code. Considering this and the comment in the code
+about fb_match_mode() returning NULL - "This should not happen" - it is
+better to prevent registering the fb_info if its mode was not set
+successfully. Also move fb_add_videomode() closer to the beginning of
+do_register_framebuffer() to avoid having to do the cleanup on fail.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/core/fbmem.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index 5e8ee360f6ba2..a8d6bd465ffe4 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -1622,7 +1622,7 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
+ static int do_register_framebuffer(struct fb_info *fb_info)
+ {
+-      int i;
++      int i, err = 0;
+       struct fb_videomode mode;
+       if (fb_check_foreignness(fb_info))
+@@ -1635,10 +1635,18 @@ static int do_register_framebuffer(struct fb_info *fb_info)
+       if (num_registered_fb == FB_MAX)
+               return -ENXIO;
+-      num_registered_fb++;
+       for (i = 0 ; i < FB_MAX; i++)
+               if (!registered_fb[i])
+                       break;
++
++      if (!fb_info->modelist.prev || !fb_info->modelist.next)
++              INIT_LIST_HEAD(&fb_info->modelist);
++
++      fb_var_to_videomode(&mode, &fb_info->var);
++      err = fb_add_videomode(&mode, &fb_info->modelist);
++      if (err < 0)
++              return err;
++
+       fb_info->node = i;
+       refcount_set(&fb_info->count, 1);
+       mutex_init(&fb_info->lock);
+@@ -1671,16 +1679,12 @@ static int do_register_framebuffer(struct fb_info *fb_info)
+       if (!fb_info->pixmap.blit_y)
+               fb_info->pixmap.blit_y = ~(u32)0;
+-      if (!fb_info->modelist.prev || !fb_info->modelist.next)
+-              INIT_LIST_HEAD(&fb_info->modelist);
+-
+       if (fb_info->skip_vt_switch)
+               pm_vt_switch_required(fb_info->dev, false);
+       else
+               pm_vt_switch_required(fb_info->dev, true);
+-      fb_var_to_videomode(&mode, &fb_info->var);
+-      fb_add_videomode(&mode, &fb_info->modelist);
++      num_registered_fb++;
+       registered_fb[i] = fb_info;
+ #ifdef CONFIG_GUMSTIX_AM200EPD
+-- 
+2.39.5
+
diff --git a/queue-5.15/fs-jfs-consolidate-sanity-checking-in-dbmount.patch b/queue-5.15/fs-jfs-consolidate-sanity-checking-in-dbmount.patch
new file mode 100644 (file)
index 0000000..6e2464c
--- /dev/null
@@ -0,0 +1,81 @@
+From 4fa4e51a748bca922fce94f839a3828a7fbba5e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 10:31:19 -0600
+Subject: fs/jfs: consolidate sanity checking in dbMount
+
+From: Dave Kleikamp <dave.kleikamp@oracle.com>
+
+[ Upstream commit 0d250b1c52484d489e31df2cf9118b7c4bd49d31 ]
+
+Sanity checks have been added to dbMount as individual if clauses with
+identical error handling. Move these all into one clause.
+
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Stable-dep-of: 37bfb464ddca ("jfs: validate AG parameters in dbMount() to prevent crashes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 37 +++++++++----------------------------
+ 1 file changed, 9 insertions(+), 28 deletions(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 65a94b0121742..d668a04a71d71 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -178,45 +178,26 @@ int dbMount(struct inode *ipbmap)
+       dbmp_le = (struct dbmap_disk *) mp->data;
+       bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
+       bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
+-
+       bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
+-      if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE ||
+-              bmp->db_l2nbperpage < 0) {
+-              err = -EINVAL;
+-              goto err_release_metapage;
+-      }
+-
+       bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
+-      if (!bmp->db_numag || bmp->db_numag > MAXAG) {
+-              err = -EINVAL;
+-              goto err_release_metapage;
+-      }
+-
+       bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
+       bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
+       bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
+-      if (bmp->db_maxag >= MAXAG || bmp->db_maxag < 0 ||
+-              bmp->db_agpref >= MAXAG || bmp->db_agpref < 0) {
+-              err = -EINVAL;
+-              goto err_release_metapage;
+-      }
+-
+       bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
+       bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
+       bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
+-      if (!bmp->db_agwidth) {
+-              err = -EINVAL;
+-              goto err_release_metapage;
+-      }
+       bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart);
+       bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size);
+-      if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG ||
+-          bmp->db_agl2size < 0) {
+-              err = -EINVAL;
+-              goto err_release_metapage;
+-      }
+-      if (((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) {
++      if ((bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) ||
++          (bmp->db_l2nbperpage < 0) ||
++          !bmp->db_numag || (bmp->db_numag > MAXAG) ||
++          (bmp->db_maxag >= MAXAG) || (bmp->db_maxag < 0) ||
++          (bmp->db_agpref >= MAXAG) || (bmp->db_agpref < 0) ||
++          !bmp->db_agwidth ||
++          (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG) ||
++          (bmp->db_agl2size < 0) ||
++          ((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) {
+               err = -EINVAL;
+               goto err_release_metapage;
+       }
+-- 
+2.39.5
+
diff --git a/queue-5.15/hwmon-pmbus-max34440-fix-support-for-max34451.patch b/queue-5.15/hwmon-pmbus-max34440-fix-support-for-max34451.patch
new file mode 100644 (file)
index 0000000..d7964df
--- /dev/null
@@ -0,0 +1,144 @@
+From fdc800283b8e32a0d501dfaa05c7392b1ed22b26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Apr 2025 11:47:24 +0800
+Subject: hwmon: (pmbus/max34440) Fix support for max34451
+
+From: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
+
+[ Upstream commit 19932f844f3f51646f762f3eac4744ec3a405064 ]
+
+The max344** family has an issue with some PMBUS address being switched.
+This includes max34451 however version MAX34451-NA6 and later has this
+issue fixed and this commit supports that update.
+
+Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
+Link: https://lore.kernel.org/r/20250407-dev_adpm12160-v3-1-9cd3095445c8@analog.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/pmbus/max34440.c | 48 +++++++++++++++++++++++++++++++---
+ 1 file changed, 44 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
+index ea7609058a12f..91359647d1e78 100644
+--- a/drivers/hwmon/pmbus/max34440.c
++++ b/drivers/hwmon/pmbus/max34440.c
+@@ -34,16 +34,21 @@ enum chips { max34440, max34441, max34446, max34451, max34460, max34461 };
+ /*
+  * The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT
+  * swapped from the standard pmbus spec addresses.
++ * For max34451, version MAX34451ETNA6+ and later has this issue fixed.
+  */
+ #define MAX34440_IOUT_OC_WARN_LIMIT   0x46
+ #define MAX34440_IOUT_OC_FAULT_LIMIT  0x4A
++#define MAX34451ETNA6_MFR_REV         0x0012
++
+ #define MAX34451_MFR_CHANNEL_CONFIG   0xe4
+ #define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK  0x3f
+ struct max34440_data {
+       int id;
+       struct pmbus_driver_info info;
++      u8 iout_oc_warn_limit;
++      u8 iout_oc_fault_limit;
+ };
+ #define to_max34440_data(x)  container_of(x, struct max34440_data, info)
+@@ -60,11 +65,11 @@ static int max34440_read_word_data(struct i2c_client *client, int page,
+       switch (reg) {
+       case PMBUS_IOUT_OC_FAULT_LIMIT:
+               ret = pmbus_read_word_data(client, page, phase,
+-                                         MAX34440_IOUT_OC_FAULT_LIMIT);
++                                         data->iout_oc_fault_limit);
+               break;
+       case PMBUS_IOUT_OC_WARN_LIMIT:
+               ret = pmbus_read_word_data(client, page, phase,
+-                                         MAX34440_IOUT_OC_WARN_LIMIT);
++                                         data->iout_oc_warn_limit);
+               break;
+       case PMBUS_VIRT_READ_VOUT_MIN:
+               ret = pmbus_read_word_data(client, page, phase,
+@@ -133,11 +138,11 @@ static int max34440_write_word_data(struct i2c_client *client, int page,
+       switch (reg) {
+       case PMBUS_IOUT_OC_FAULT_LIMIT:
+-              ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_FAULT_LIMIT,
++              ret = pmbus_write_word_data(client, page, data->iout_oc_fault_limit,
+                                           word);
+               break;
+       case PMBUS_IOUT_OC_WARN_LIMIT:
+-              ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_WARN_LIMIT,
++              ret = pmbus_write_word_data(client, page, data->iout_oc_warn_limit,
+                                           word);
+               break;
+       case PMBUS_VIRT_RESET_POUT_HISTORY:
+@@ -235,6 +240,25 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
+        */
+       int page, rv;
++      bool max34451_na6 = false;
++
++      rv = i2c_smbus_read_word_data(client, PMBUS_MFR_REVISION);
++      if (rv < 0)
++              return rv;
++
++      if (rv >= MAX34451ETNA6_MFR_REV) {
++              max34451_na6 = true;
++              data->info.format[PSC_VOLTAGE_IN] = direct;
++              data->info.format[PSC_CURRENT_IN] = direct;
++              data->info.m[PSC_VOLTAGE_IN] = 1;
++              data->info.b[PSC_VOLTAGE_IN] = 0;
++              data->info.R[PSC_VOLTAGE_IN] = 3;
++              data->info.m[PSC_CURRENT_IN] = 1;
++              data->info.b[PSC_CURRENT_IN] = 0;
++              data->info.R[PSC_CURRENT_IN] = 2;
++              data->iout_oc_fault_limit = PMBUS_IOUT_OC_FAULT_LIMIT;
++              data->iout_oc_warn_limit = PMBUS_IOUT_OC_WARN_LIMIT;
++      }
+       for (page = 0; page < 16; page++) {
+               rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+@@ -251,16 +275,30 @@ static int max34451_set_supported_funcs(struct i2c_client *client,
+               case 0x20:
+                       data->info.func[page] = PMBUS_HAVE_VOUT |
+                               PMBUS_HAVE_STATUS_VOUT;
++
++                      if (max34451_na6)
++                              data->info.func[page] |= PMBUS_HAVE_VIN |
++                                      PMBUS_HAVE_STATUS_INPUT;
+                       break;
+               case 0x21:
+                       data->info.func[page] = PMBUS_HAVE_VOUT;
++
++                      if (max34451_na6)
++                              data->info.func[page] |= PMBUS_HAVE_VIN;
+                       break;
+               case 0x22:
+                       data->info.func[page] = PMBUS_HAVE_IOUT |
+                               PMBUS_HAVE_STATUS_IOUT;
++
++                      if (max34451_na6)
++                              data->info.func[page] |= PMBUS_HAVE_IIN |
++                                      PMBUS_HAVE_STATUS_INPUT;
+                       break;
+               case 0x23:
+                       data->info.func[page] = PMBUS_HAVE_IOUT;
++
++                      if (max34451_na6)
++                              data->info.func[page] |= PMBUS_HAVE_IIN;
+                       break;
+               default:
+                       break;
+@@ -494,6 +532,8 @@ static int max34440_probe(struct i2c_client *client)
+               return -ENOMEM;
+       data->id = i2c_match_id(max34440_id, client)->driver_data;
+       data->info = max34440_info[data->id];
++      data->iout_oc_fault_limit = MAX34440_IOUT_OC_FAULT_LIMIT;
++      data->iout_oc_warn_limit = MAX34440_IOUT_OC_WARN_LIMIT;
+       if (data->id == max34451) {
+               rv = max34451_set_supported_funcs(client, data);
+-- 
+2.39.5
+
diff --git a/queue-5.15/iio-pressure-zpa2326-use-aligned_s64-for-the-timesta.patch b/queue-5.15/iio-pressure-zpa2326-use-aligned_s64-for-the-timesta.patch
new file mode 100644 (file)
index 0000000..bcbe336
--- /dev/null
@@ -0,0 +1,36 @@
+From a70f1c62e85b4bbaff153b8492acf7df6e6e9366 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 13 Apr 2025 11:34:41 +0100
+Subject: iio: pressure: zpa2326: Use aligned_s64 for the timestamp
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 886a446b76afddfad307488e95e87f23a08ffd51 ]
+
+On x86_32 s64 fields are only 32-bit aligned.  Hence force the alignment of
+the field and padding in the structure by using aligned_s64 instead.
+
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Link: https://patch.msgid.link/20250413103443.2420727-19-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/pressure/zpa2326.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
+index 50f3338778daf..741c95899e4ef 100644
+--- a/drivers/iio/pressure/zpa2326.c
++++ b/drivers/iio/pressure/zpa2326.c
+@@ -582,7 +582,7 @@ static int zpa2326_fill_sample_buffer(struct iio_dev               *indio_dev,
+       struct {
+               u32 pressure;
+               u16 temperature;
+-              u64 timestamp;
++              aligned_s64 timestamp;
+       }   sample;
+       int err;
+-- 
+2.39.5
+
diff --git a/queue-5.15/jfs-validate-ag-parameters-in-dbmount-to-prevent-cra.patch b/queue-5.15/jfs-validate-ag-parameters-in-dbmount-to-prevent-cra.patch
new file mode 100644 (file)
index 0000000..9769494
--- /dev/null
@@ -0,0 +1,78 @@
+From 381fbe8668937535d79b3a3d879cdac5b4039dd3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 11:56:02 +0300
+Subject: jfs: validate AG parameters in dbMount() to prevent crashes
+
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+
+[ Upstream commit 37bfb464ddca87f203071b5bd562cd91ddc0b40a ]
+
+Validate db_agheight, db_agwidth, and db_agstart in dbMount to catch
+corrupted metadata early and avoid undefined behavior in dbAllocAG.
+Limits are derived from L2LPERCTL, LPERCTL/MAXAG, and CTLTREESIZE:
+
+- agheight: 0 to L2LPERCTL/2 (0 to 5) ensures shift
+  (L2LPERCTL - 2*agheight) >= 0.
+- agwidth: 1 to min(LPERCTL/MAXAG, 2^(L2LPERCTL - 2*agheight))
+  ensures agperlev >= 1.
+  - Ranges: 1-8 (agheight 0-3), 1-4 (agheight 4), 1 (agheight 5).
+  - LPERCTL/MAXAG = 1024/128 = 8 limits leaves per AG;
+    2^(10 - 2*agheight) prevents division to 0.
+- agstart: 0 to CTLTREESIZE-1 - agwidth*(MAXAG-1) keeps ti within
+  stree (size 1365).
+  - Ranges: 0-1237 (agwidth 1), 0-348 (agwidth 8).
+
+UBSAN: shift-out-of-bounds in fs/jfs/jfs_dmap.c:1400:9
+shift exponent -335544310 is negative
+CPU: 0 UID: 0 PID: 5822 Comm: syz-executor130 Not tainted 6.14.0-rc5-syzkaller #0
+Hardware name: Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ ubsan_epilogue lib/ubsan.c:231 [inline]
+ __ubsan_handle_shift_out_of_bounds+0x3c8/0x420 lib/ubsan.c:468
+ dbAllocAG+0x1087/0x10b0 fs/jfs/jfs_dmap.c:1400
+ dbDiscardAG+0x352/0xa20 fs/jfs/jfs_dmap.c:1613
+ jfs_ioc_trim+0x45a/0x6b0 fs/jfs/jfs_discard.c:105
+ jfs_ioctl+0x2cd/0x3e0 fs/jfs/ioctl.c:131
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:906 [inline]
+ __se_sys_ioctl+0xf5/0x170 fs/ioctl.c:892
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Cc: stable@vger.kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+fe8264911355151c487f@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=fe8264911355151c487f
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index d668a04a71d71..cfb81bf5881ed 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -194,7 +194,11 @@ int dbMount(struct inode *ipbmap)
+           !bmp->db_numag || (bmp->db_numag > MAXAG) ||
+           (bmp->db_maxag >= MAXAG) || (bmp->db_maxag < 0) ||
+           (bmp->db_agpref >= MAXAG) || (bmp->db_agpref < 0) ||
+-          !bmp->db_agwidth ||
++          (bmp->db_agheight < 0) || (bmp->db_agheight > (L2LPERCTL >> 1)) ||
++          (bmp->db_agwidth < 1) || (bmp->db_agwidth > (LPERCTL / MAXAG)) ||
++          (bmp->db_agwidth > (1 << (L2LPERCTL - (bmp->db_agheight << 1)))) ||
++          (bmp->db_agstart < 0) ||
++          (bmp->db_agstart > (CTLTREESIZE - 1 - bmp->db_agwidth * (MAXAG - 1))) ||
+           (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG) ||
+           (bmp->db_agl2size < 0) ||
+           ((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) {
+-- 
+2.39.5
+
diff --git a/queue-5.15/ksmbd-allow-a-filename-to-contain-special-characters.patch b/queue-5.15/ksmbd-allow-a-filename-to-contain-special-characters.patch
new file mode 100644 (file)
index 0000000..abb5166
--- /dev/null
@@ -0,0 +1,109 @@
+From c80a515fdf8b39dd41ad59f74316e41080d7c351 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 May 2025 11:23:01 +0900
+Subject: ksmbd: allow a filename to contain special characters on SMB3.1.1
+ posix extension
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit dc3e0f17f74558e8a2fce00608855f050de10230 ]
+
+If client send SMB2_CREATE_POSIX_CONTEXT to ksmbd, Allow a filename
+to contain special characters.
+
+Reported-by: Philipp Kerling <pkerling@casix.org>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ksmbd/smb2pdu.c | 53 +++++++++++++++++++++++-----------------------
+ 1 file changed, 27 insertions(+), 26 deletions(-)
+
+diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
+index b21601c0a457c..76334a983cd25 100644
+--- a/fs/ksmbd/smb2pdu.c
++++ b/fs/ksmbd/smb2pdu.c
+@@ -2679,7 +2679,7 @@ int smb2_open(struct ksmbd_work *work)
+       int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0;
+       int rc = 0;
+       int contxt_cnt = 0, query_disk_id = 0;
+-      int maximal_access_ctxt = 0, posix_ctxt = 0;
++      bool maximal_access_ctxt = false, posix_ctxt = false;
+       int s_type = 0;
+       int next_off = 0;
+       char *name = NULL;
+@@ -2706,6 +2706,27 @@ int smb2_open(struct ksmbd_work *work)
+               return create_smb2_pipe(work);
+       }
++      if (req->CreateContextsOffset && tcon->posix_extensions) {
++              context = smb2_find_context_vals(req, SMB2_CREATE_TAG_POSIX, 16);
++              if (IS_ERR(context)) {
++                      rc = PTR_ERR(context);
++                      goto err_out2;
++              } else if (context) {
++                      struct create_posix *posix = (struct create_posix *)context;
++
++                      if (le16_to_cpu(context->DataOffset) +
++                              le32_to_cpu(context->DataLength) <
++                          sizeof(struct create_posix) - 4) {
++                              rc = -EINVAL;
++                              goto err_out2;
++                      }
++                      ksmbd_debug(SMB, "get posix context\n");
++
++                      posix_mode = le32_to_cpu(posix->Mode);
++                      posix_ctxt = true;
++              }
++      }
++
+       if (req->NameLength) {
+               if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
+                   *(char *)req->Buffer == '\\') {
+@@ -2737,9 +2758,11 @@ int smb2_open(struct ksmbd_work *work)
+                               goto err_out2;
+               }
+-              rc = ksmbd_validate_filename(name);
+-              if (rc < 0)
+-                      goto err_out2;
++              if (posix_ctxt == false) {
++                      rc = ksmbd_validate_filename(name);
++                      if (rc < 0)
++                              goto err_out2;
++              }
+               if (ksmbd_share_veto_filename(share, name)) {
+                       rc = -ENOENT;
+@@ -2854,28 +2877,6 @@ int smb2_open(struct ksmbd_work *work)
+                       rc = -EBADF;
+                       goto err_out2;
+               }
+-
+-              if (tcon->posix_extensions) {
+-                      context = smb2_find_context_vals(req,
+-                                                       SMB2_CREATE_TAG_POSIX, 16);
+-                      if (IS_ERR(context)) {
+-                              rc = PTR_ERR(context);
+-                              goto err_out2;
+-                      } else if (context) {
+-                              struct create_posix *posix =
+-                                      (struct create_posix *)context;
+-                              if (le16_to_cpu(context->DataOffset) +
+-                                  le32_to_cpu(context->DataLength) <
+-                                  sizeof(struct create_posix) - 4) {
+-                                      rc = -EINVAL;
+-                                      goto err_out2;
+-                              }
+-                              ksmbd_debug(SMB, "get posix context\n");
+-
+-                              posix_mode = le32_to_cpu(posix->Mode);
+-                              posix_ctxt = 1;
+-                      }
+-              }
+       }
+       if (ksmbd_override_fsids(work)) {
+-- 
+2.39.5
+
diff --git a/queue-5.15/leds-multicolor-fix-intensity-setting-while-sw-blink.patch b/queue-5.15/leds-multicolor-fix-intensity-setting-while-sw-blink.patch
new file mode 100644 (file)
index 0000000..242c8eb
--- /dev/null
@@ -0,0 +1,48 @@
+From 9507b3c44db59079ce414991674354e17c648dac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Apr 2025 20:40:36 +0200
+Subject: leds: multicolor: Fix intensity setting while SW blinking
+
+From: Sven Schwermer <sven.schwermer@disruptive-technologies.com>
+
+[ Upstream commit e35ca991a777ef513040cbb36bc8245a031a2633 ]
+
+When writing to the multi_intensity file, don't unconditionally call
+led_set_brightness. By only doing this if blinking is inactive we
+prevent blinking from stopping if the blinking is in its off phase while
+the file is written.
+
+Instead, if blinking is active, the changed intensity values are applied
+upon the next blink. This is consistent with changing the brightness on
+monochrome LEDs with active blinking.
+
+Suggested-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
+Acked-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
+Acked-by: Pavel Machek <pavel@ucw.cz>
+Reviewed-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
+Tested-by: Sven Schuchmann <schuchmann@schleissheimer.de>
+Signed-off-by: Sven Schwermer <sven.schwermer@disruptive-technologies.com>
+Link: https://lore.kernel.org/r/20250404184043.227116-1-sven@svenschwermer.de
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-class-multicolor.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/leds/led-class-multicolor.c b/drivers/leds/led-class-multicolor.c
+index ec62a48116135..e0785935f4ba6 100644
+--- a/drivers/leds/led-class-multicolor.c
++++ b/drivers/leds/led-class-multicolor.c
+@@ -61,7 +61,8 @@ static ssize_t multi_intensity_store(struct device *dev,
+       for (i = 0; i < mcled_cdev->num_colors; i++)
+               mcled_cdev->subled_info[i].intensity = intensity_value[i];
+-      led_set_brightness(led_cdev, led_cdev->brightness);
++      if (!test_bit(LED_BLINK_SW, &led_cdev->work_flags))
++              led_set_brightness(led_cdev, led_cdev->brightness);
+       ret = size;
+ err_out:
+       mutex_unlock(&led_cdev->led_access);
+-- 
+2.39.5
+
diff --git a/queue-5.15/mailbox-not-protect-module_put-with-spin_lock_irqsav.patch b/queue-5.15/mailbox-not-protect-module_put-with-spin_lock_irqsav.patch
new file mode 100644 (file)
index 0000000..ff6a78e
--- /dev/null
@@ -0,0 +1,38 @@
+From 12b7337b82c647f96f4f6ec198aef68e48b5ada7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 21:14:10 +0800
+Subject: mailbox: Not protect module_put with spin_lock_irqsave
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit dddbd233e67e792bb0a3f9694a4707e6be29b2c6 ]
+
+&chan->lock is not supposed to protect 'chan->mbox'.
+And in __mbox_bind_client, try_module_get is also not protected
+by &chan->lock. So move module_put out of the lock protected
+region.
+
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mailbox/mailbox.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
+index 6f54501dc7762..cb31ad917b352 100644
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -459,8 +459,8 @@ void mbox_free_channel(struct mbox_chan *chan)
+       if (chan->txdone_method == TXDONE_BY_ACK)
+               chan->txdone_method = TXDONE_BY_POLL;
+-      module_put(chan->mbox->dev->driver->owner);
+       spin_unlock_irqrestore(&chan->lock, flags);
++      module_put(chan->mbox->dev->driver->owner);
+ }
+ EXPORT_SYMBOL_GPL(mbox_free_channel);
+-- 
+2.39.5
+
diff --git a/queue-5.15/md-md-bitmap-fix-dm-raid-max_write_behind-setting.patch b/queue-5.15/md-md-bitmap-fix-dm-raid-max_write_behind-setting.patch
new file mode 100644 (file)
index 0000000..1a08bdf
--- /dev/null
@@ -0,0 +1,36 @@
+From c8bcba63c271197435344d8be2f6fb501adeb69b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 May 2025 14:13:10 +0800
+Subject: md/md-bitmap: fix dm-raid max_write_behind setting
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 2afe17794cfed5f80295b1b9facd66e6f65e5002 ]
+
+It's supposed to be COUNTER_MAX / 2, not COUNTER_MAX.
+
+Link: https://lore.kernel.org/linux-raid/20250524061320.370630-14-yukuai1@huaweicloud.com
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md-bitmap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index b26e22dd9ba2e..cb84a4ab8d70f 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -546,7 +546,7 @@ static int md_bitmap_new_disk_sb(struct bitmap *bitmap)
+        * is a good choice?  We choose COUNTER_MAX / 2 arbitrarily.
+        */
+       write_behind = bitmap->mddev->bitmap_info.max_write_behind;
+-      if (write_behind > COUNTER_MAX)
++      if (write_behind > COUNTER_MAX / 2)
+               write_behind = COUNTER_MAX / 2;
+       sb->write_behind = cpu_to_le32(write_behind);
+       bitmap->mddev->bitmap_info.max_write_behind = write_behind;
+-- 
+2.39.5
+
diff --git a/queue-5.15/media-davinci-vpif-fix-memory-leak-in-probe-error-pa.patch b/queue-5.15/media-davinci-vpif-fix-memory-leak-in-probe-error-pa.patch
new file mode 100644 (file)
index 0000000..7e20e4b
--- /dev/null
@@ -0,0 +1,52 @@
+From 71eccbb07f9473d20ce795742a32a144860ba176 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Apr 2025 23:51:19 +0300
+Subject: media: davinci: vpif: Fix memory leak in probe error path
+
+From: Dmitry Nikiforov <Dm1tryNk@yandex.ru>
+
+[ Upstream commit 024bf40edf1155e7a587f0ec46294049777d9b02 ]
+
+If an error occurs during the initialization of `pdev_display`,
+the allocated platform device `pdev_capture` is not released properly,
+leading to a memory leak.
+
+Adjust error path handling to fix the leak.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 43acb728bbc4 ("media: davinci: vpif: fix use-after-free on driver unbind")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Nikiforov <Dm1tryNk@yandex.ru>
+Reviewed-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/davinci/vpif.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
+index 8ffc01c606d0c..a59a059008cf8 100644
+--- a/drivers/media/platform/davinci/vpif.c
++++ b/drivers/media/platform/davinci/vpif.c
+@@ -503,7 +503,7 @@ static int vpif_probe(struct platform_device *pdev)
+       pdev_display = kzalloc(sizeof(*pdev_display), GFP_KERNEL);
+       if (!pdev_display) {
+               ret = -ENOMEM;
+-              goto err_put_pdev_capture;
++              goto err_del_pdev_capture;
+       }
+       pdev_display->name = "vpif_display";
+@@ -526,6 +526,8 @@ static int vpif_probe(struct platform_device *pdev)
+ err_put_pdev_display:
+       platform_device_put(pdev_display);
++err_del_pdev_capture:
++      platform_device_del(pdev_capture);
+ err_put_pdev_capture:
+       platform_device_put(pdev_capture);
+ err_put_rpm:
+-- 
+2.39.5
+
diff --git a/queue-5.15/media-imx-jpeg-drop-the-first-error-frames.patch b/queue-5.15/media-imx-jpeg-drop-the-first-error-frames.patch
new file mode 100644 (file)
index 0000000..644f0dd
--- /dev/null
@@ -0,0 +1,59 @@
+From 075b9944d07d0055d43634f283564214affe35fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 15:06:12 +0800
+Subject: media: imx-jpeg: Drop the first error frames
+
+From: Ming Qian <ming.qian@oss.nxp.com>
+
+[ Upstream commit d52b9b7e2f10d22a49468128540533e8d76910cd ]
+
+When an output buffer contains error frame header,
+v4l2_jpeg_parse_header() will return error, then driver will mark this
+buffer and a capture buffer done with error flag in device_run().
+
+But if the error occurs in the first frames, before setup the capture
+queue, there is no chance to schedule device_run(), and there may be no
+capture to mark error.
+
+So we need to drop this buffer with error flag, and make the decoding
+can continue.
+
+Fixes: 2db16c6ed72c ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
+Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/imx-jpeg/mxc-jpeg.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c
+index 059e45aa03b7f..2ab03444f742a 100644
+--- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c
++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c
+@@ -1450,9 +1450,19 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
+       jpeg_src_buf = vb2_to_mxc_buf(vb);
+       jpeg_src_buf->jpeg_parse_error = false;
+       ret = mxc_jpeg_parse(ctx, vb);
+-      if (ret)
++      if (ret) {
+               jpeg_src_buf->jpeg_parse_error = true;
++              /*
++               * if the capture queue is not setup, the device_run() won't be scheduled,
++               * need to drop the error buffer, so that the decoding can continue
++               */
++              if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx))) {
++                      v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
++                      return;
++              }
++      }
++
+ end:
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+ }
+-- 
+2.39.5
+
diff --git a/queue-5.15/media-omap3isp-use-sgtable-based-scatterlist-wrapper.patch b/queue-5.15/media-omap3isp-use-sgtable-based-scatterlist-wrapper.patch
new file mode 100644 (file)
index 0000000..fe2410b
--- /dev/null
@@ -0,0 +1,79 @@
+From 19a68660cc87761bc396cc5445aa476e220e7611 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 May 2025 18:09:13 +0200
+Subject: media: omap3isp: use sgtable-based scatterlist wrappers
+
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+
+[ Upstream commit 3de572fe2189a4a0bd80295e1f478401e739498e ]
+
+Use common wrappers operating directly on the struct sg_table objects to
+fix incorrect use of scatterlists sync calls. dma_sync_sg_for_*()
+functions have to be called with the number of elements originally passed
+to dma_map_sg_*() function, not the one returned in sgtable's nents.
+
+Fixes: d33186d0be18 ("[media] omap3isp: ccdc: Use the DMA API for LSC")
+Fixes: 0e24e90f2ca7 ("[media] omap3isp: stat: Use the DMA API")
+CC: stable@vger.kernel.org
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/omap3isp/ispccdc.c | 8 ++++----
+ drivers/media/platform/omap3isp/ispstat.c | 6 ++----
+ 2 files changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
+index 108b5e9f82cb0..ee966f8ee0103 100644
+--- a/drivers/media/platform/omap3isp/ispccdc.c
++++ b/drivers/media/platform/omap3isp/ispccdc.c
+@@ -446,8 +446,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
+               if (ret < 0)
+                       goto done;
+-              dma_sync_sg_for_cpu(isp->dev, req->table.sgt.sgl,
+-                                  req->table.sgt.nents, DMA_TO_DEVICE);
++              dma_sync_sgtable_for_cpu(isp->dev, &req->table.sgt,
++                                       DMA_TO_DEVICE);
+               if (copy_from_user(req->table.addr, config->lsc,
+                                  req->config.size)) {
+@@ -455,8 +455,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
+                       goto done;
+               }
+-              dma_sync_sg_for_device(isp->dev, req->table.sgt.sgl,
+-                                     req->table.sgt.nents, DMA_TO_DEVICE);
++              dma_sync_sgtable_for_device(isp->dev, &req->table.sgt,
++                                          DMA_TO_DEVICE);
+       }
+       spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
+index 68cf68dbcace2..dc496ca9748a6 100644
+--- a/drivers/media/platform/omap3isp/ispstat.c
++++ b/drivers/media/platform/omap3isp/ispstat.c
+@@ -161,8 +161,7 @@ static void isp_stat_buf_sync_for_device(struct ispstat *stat,
+       if (ISP_STAT_USES_DMAENGINE(stat))
+               return;
+-      dma_sync_sg_for_device(stat->isp->dev, buf->sgt.sgl,
+-                             buf->sgt.nents, DMA_FROM_DEVICE);
++      dma_sync_sgtable_for_device(stat->isp->dev, &buf->sgt, DMA_FROM_DEVICE);
+ }
+ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
+@@ -171,8 +170,7 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
+       if (ISP_STAT_USES_DMAENGINE(stat))
+               return;
+-      dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt.sgl,
+-                          buf->sgt.nents, DMA_FROM_DEVICE);
++      dma_sync_sgtable_for_cpu(stat->isp->dev, &buf->sgt, DMA_FROM_DEVICE);
+ }
+ static void isp_stat_buf_clear(struct ispstat *stat)
+-- 
+2.39.5
+
diff --git a/queue-5.15/mfd-max14577-fix-wakeup-source-leaks-on-device-unbin.patch b/queue-5.15/mfd-max14577-fix-wakeup-source-leaks-on-device-unbin.patch
new file mode 100644 (file)
index 0000000..d97b9e7
--- /dev/null
@@ -0,0 +1,35 @@
+From ed5972efcc55f8d5c4d75327035b80707310fcd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 6 Apr 2025 21:50:11 +0200
+Subject: mfd: max14577: Fix wakeup source leaks on device unbind
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit d905d06e64b0eb3da43af6186c132f5282197998 ]
+
+Device can be unbound, so driver must also release memory for the wakeup
+source.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20250406-mfd-device-wakekup-leak-v1-3-318e14bdba0a@linaro.org
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/max14577.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
+index be185e9d5f16b..c9e56145b08bd 100644
+--- a/drivers/mfd/max14577.c
++++ b/drivers/mfd/max14577.c
+@@ -467,6 +467,7 @@ static int max14577_i2c_remove(struct i2c_client *i2c)
+ {
+       struct max14577 *max14577 = i2c_get_clientdata(i2c);
++      device_init_wakeup(max14577->dev, false);
+       mfd_remove_devices(max14577->dev);
+       regmap_del_irq_chip(max14577->irq, max14577->irq_data);
+       if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836)
+-- 
+2.39.5
+
diff --git a/queue-5.15/nfsv4-always-set-nlink-even-if-the-server-doesn-t-su.patch b/queue-5.15/nfsv4-always-set-nlink-even-if-the-server-doesn-t-su.patch
new file mode 100644 (file)
index 0000000..2077d3d
--- /dev/null
@@ -0,0 +1,41 @@
+From 3f30fe6bc840e377dd0ecf128396e1cffb375221 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 4 May 2025 20:57:04 +0800
+Subject: NFSv4: Always set NLINK even if the server doesn't support it
+
+From: Han Young <hanyang.tony@bytedance.com>
+
+[ Upstream commit 3a3065352f73381d3a1aa0ccab44aec3a5a9b365 ]
+
+fattr4_numlinks is a recommended attribute, so the client should emulate
+it even if the server doesn't support it. In decode_attr_nlink function
+in nfs4xdr.c, nlink is initialized to 1. However, this default value
+isn't set to the inode due to the check in nfs_fhget.
+
+So if the server doesn't support numlinks, inode's nlink will be zero,
+the mount will fail with error "Stale file handle". Set the nlink to 1
+if the server doesn't support it.
+
+Signed-off-by: Han Young <hanyang.tony@bytedance.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/inode.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 09922258f5a11..28c24079c57a8 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -567,6 +567,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
+                       set_nlink(inode, fattr->nlink);
+               else if (fattr_supported & NFS_ATTR_FATTR_NLINK)
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_NLINK);
++              else
++                      set_nlink(inode, 1);
+               if (fattr->valid & NFS_ATTR_FATTR_OWNER)
+                       inode->i_uid = fattr->uid;
+               else if (fattr_supported & NFS_ATTR_FATTR_OWNER)
+-- 
+2.39.5
+
diff --git a/queue-5.15/nfsv4.2-fix-listxattr-to-return-selinux-security-lab.patch b/queue-5.15/nfsv4.2-fix-listxattr-to-return-selinux-security-lab.patch
new file mode 100644 (file)
index 0000000..2fb3815
--- /dev/null
@@ -0,0 +1,56 @@
+From 8b3951e94fe4874c947b06c8d01d664ecabdc924 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 14:09:21 -0400
+Subject: NFSv4.2: fix listxattr to return selinux security label
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+[ Upstream commit 243fea134633ba3d64aceb4c16129c59541ea2c6 ]
+
+Currently, when NFS is queried for all the labels present on the
+file via a command example "getfattr -d -m . /mnt/testfile", it
+does not return the security label. Yet when asked specifically for
+the label (getfattr -n security.selinux) it will be returned.
+Include the security label when all attributes are queried.
+
+Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfs/nfs4proc.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index e4b3f25bb8e48..9d4e4146efef0 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10528,7 +10528,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
+ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
+ {
+-      ssize_t error, error2, error3;
++      ssize_t error, error2, error3, error4;
+       size_t left = size;
+       error = generic_listxattr(dentry, list, left);
+@@ -10551,8 +10551,16 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
+       error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, left);
+       if (error3 < 0)
+               return error3;
++      if (list) {
++              list += error3;
++              left -= error3;
++      }
++
++      error4 = security_inode_listsecurity(d_inode(dentry), list, left);
++      if (error4 < 0)
++              return error4;
+-      error += error2 + error3;
++      error += error2 + error3 + error4;
+       if (size && error > size)
+               return -ERANGE;
+       return error;
+-- 
+2.39.5
+
diff --git a/queue-5.15/ovl-check-for-null-d_inode-in-ovl_dentry_upper.patch b/queue-5.15/ovl-check-for-null-d_inode-in-ovl_dentry_upper.patch
new file mode 100644 (file)
index 0000000..6c173dc
--- /dev/null
@@ -0,0 +1,68 @@
+From 19724f9e23dc2bb734c662ad061f884b0d93f03d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 16:15:19 -0700
+Subject: ovl: Check for NULL d_inode() in ovl_dentry_upper()
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit 8a39f1c870e9d6fbac5638f3a42a6a6363829c49 ]
+
+In ovl_path_type() and ovl_is_metacopy_dentry() GCC notices that it is
+possible for OVL_E() to return NULL (which implies that d_inode(dentry)
+may be NULL). This would result in out of bounds reads via container_of(),
+seen with GCC 15's -Warray-bounds -fdiagnostics-details. For example:
+
+In file included from arch/x86/include/generated/asm/rwonce.h:1,
+                 from include/linux/compiler.h:339,
+                 from include/linux/export.h:5,
+                 from include/linux/linkage.h:7,
+                 from include/linux/fs.h:5,
+                 from fs/overlayfs/util.c:7:
+In function 'ovl_upperdentry_dereference',
+    inlined from 'ovl_dentry_upper' at ../fs/overlayfs/util.c:305:9,
+    inlined from 'ovl_path_type' at ../fs/overlayfs/util.c:216:6:
+include/asm-generic/rwonce.h:44:26: error: array subscript 0 is outside array bounds of 'struct inode[7486503276667837]' [-Werror=array-bounds=]
+   44 | #define __READ_ONCE(x)  (*(const volatile __unqual_scalar_typeof(x) *)&(x))
+      |                         ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+include/asm-generic/rwonce.h:50:9: note: in expansion of macro '__READ_ONCE'
+   50 |         __READ_ONCE(x);                                                 \
+      |         ^~~~~~~~~~~
+fs/overlayfs/ovl_entry.h:195:16: note: in expansion of macro 'READ_ONCE'
+  195 |         return READ_ONCE(oi->__upperdentry);
+      |                ^~~~~~~~~
+  'ovl_path_type': event 1
+  185 |         return inode ? OVL_I(inode)->oe : NULL;
+  'ovl_path_type': event 2
+
+Avoid this by allowing ovl_dentry_upper() to return NULL if d_inode() is
+NULL, as that means the problematic dereferencing can never be reached.
+Note that this fixes the over-eager compiler warning in an effort to
+being able to enable -Warray-bounds globally. There is no known
+behavioral bug here.
+
+Suggested-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/util.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index 8a9980ab2ad8f..74abba466f19b 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -215,7 +215,9 @@ enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
+ struct dentry *ovl_dentry_upper(struct dentry *dentry)
+ {
+-      return ovl_upperdentry_dereference(OVL_I(d_inode(dentry)));
++      struct inode *inode = d_inode(dentry);
++
++      return inode ? ovl_upperdentry_dereference(OVL_I(inode)) : NULL;
+ }
+ struct dentry *ovl_dentry_lower(struct dentry *dentry)
+-- 
+2.39.5
+
diff --git a/queue-5.15/platform-x86-ideapad-laptop-use-usleep_range-for-ec-.patch b/queue-5.15/platform-x86-ideapad-laptop-use-usleep_range-for-ec-.patch
new file mode 100644 (file)
index 0000000..1917a5a
--- /dev/null
@@ -0,0 +1,127 @@
+From 3764f3ca5065946882a8e7f3385ea3cbe236368c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 May 2025 04:18:07 +0800
+Subject: platform/x86: ideapad-laptop: use usleep_range() for EC polling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rong Zhang <i@rong.moe>
+
+[ Upstream commit 5808c34216954cd832bd4b8bc52dfa287049122b ]
+
+It was reported that ideapad-laptop sometimes causes some recent (since
+2024) Lenovo ThinkBook models shut down when:
+ - suspending/resuming
+ - closing/opening the lid
+ - (dis)connecting a charger
+ - reading/writing some sysfs properties, e.g., fan_mode, touchpad
+ - pressing down some Fn keys, e.g., Brightness Up/Down (Fn+F5/F6)
+ - (seldom) loading the kmod
+
+The issue has existed since the launch day of such models, and there
+have been some out-of-tree workarounds (see Link:) for the issue. One
+disables some functionalities, while another one simply shortens
+IDEAPAD_EC_TIMEOUT. The disabled functionalities have read_ec_data() in
+their call chains, which calls schedule() between each poll.
+
+It turns out that these models suffer from the indeterminacy of
+schedule() because of their low tolerance for being polled too
+frequently. Sometimes schedule() returns too soon due to the lack of
+ready tasks, causing the margin between two polls to be too short.
+In this case, the command is somehow aborted, and too many subsequent
+polls (they poll for "nothing!") may eventually break the state machine
+in the EC, resulting in a hard shutdown. This explains why shortening
+IDEAPAD_EC_TIMEOUT works around the issue - it reduces the total number
+of polls sent to the EC.
+
+Even when it doesn't lead to a shutdown, frequent polls may also disturb
+the ongoing operation and notably delay (+ 10-20ms) the availability of
+EC response. This phenomenon is unlikely to be exclusive to the models
+mentioned above, so dropping the schedule() manner should also slightly
+improve the responsiveness of various models.
+
+Fix these issues by migrating to usleep_range(150, 300). The interval is
+chosen to add some margin to the minimal 50us and considering EC
+responses are usually available after 150-2500us based on my test. It
+should be enough to fix these issues on all models subject to the EC bug
+without introducing latency on other models.
+
+Tested on ThinkBook 14 G7+ ASP and solved both issues. No regression was
+introduced in the test on a model without the EC bug (ThinkBook X IMH,
+thanks Eric).
+
+Link: https://github.com/ty2/ideapad-laptop-tb2024g6plus/commit/6c5db18c9e8109873c2c90a7d2d7f552148f7ad4
+Link: https://github.com/ferstar/ideapad-laptop-tb/commit/42d1e68e5009529d31bd23f978f636f79c023e80
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218771
+Fixes: 6a09f21dd1e2 ("ideapad: add ACPI helpers")
+Cc: stable@vger.kernel.org
+Tested-by: Felix Yan <felixonmars@archlinux.org>
+Tested-by: Eric Long <i@hack3r.moe>
+Tested-by: Jianfei Zhang <zhangjianfei3@gmail.com>
+Tested-by: Mingcong Bai <jeffbai@aosc.io>
+Tested-by: Minh Le <minhld139@gmail.com>
+Tested-by: Sicheng Zhu <Emmet_Z@outlook.com>
+Signed-off-by: Rong Zhang <i@rong.moe>
+Link: https://lore.kernel.org/r/20250525201833.37939-1-i@rong.moe
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/ideapad-laptop.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index e75b09a144a32..7c655ace4fdc2 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -13,6 +13,7 @@
+ #include <linux/bitops.h>
+ #include <linux/bug.h>
+ #include <linux/debugfs.h>
++#include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/dmi.h>
+ #include <linux/fb.h>
+@@ -158,6 +159,20 @@ MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
+  */
+ #define IDEAPAD_EC_TIMEOUT 200 /* in ms */
++/*
++ * Some models (e.g., ThinkBook since 2024) have a low tolerance for being
++ * polled too frequently. Doing so may break the state machine in the EC,
++ * resulting in a hard shutdown.
++ *
++ * It is also observed that frequent polls may disturb the ongoing operation
++ * and notably delay the availability of EC response.
++ *
++ * These values are used as the delay before the first poll and the interval
++ * between subsequent polls to solve the above issues.
++ */
++#define IDEAPAD_EC_POLL_MIN_US 150
++#define IDEAPAD_EC_POLL_MAX_US 300
++
+ static int eval_int(acpi_handle handle, const char *name, unsigned long *res)
+ {
+       unsigned long long result;
+@@ -263,7 +278,7 @@ static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *da
+       end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
+       while (time_before(jiffies, end_jiffies)) {
+-              schedule();
++              usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US);
+               err = eval_vpcr(handle, 1, &val);
+               if (err)
+@@ -294,7 +309,7 @@ static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long dat
+       end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
+       while (time_before(jiffies, end_jiffies)) {
+-              schedule();
++              usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US);
+               err = eval_vpcr(handle, 1, &val);
+               if (err)
+-- 
+2.39.5
+
diff --git a/queue-5.15/regulator-add-devm-helpers-for-get-and-enable.patch b/queue-5.15/regulator-add-devm-helpers-for-get-and-enable.patch
new file mode 100644 (file)
index 0000000..5d1b74f
--- /dev/null
@@ -0,0 +1,283 @@
+From 25cfa5112db5e8a67f5c2594214f8a6a17734e77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Aug 2022 13:10:37 +0300
+Subject: regulator: Add devm helpers for get and enable
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit da279e6965b3838e99e5c0ab8f76b87bf86b31a5 ]
+
+A few regulator consumer drivers seem to be just getting a regulator,
+enabling it and registering a devm-action to disable the regulator at
+the driver detach and then forget about it.
+
+We can simplify this a bit by adding a devm-helper for this pattern.
+Add devm_regulator_get_enable() and devm_regulator_get_enable_optional()
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Link: https://lore.kernel.org/r/ed7b8841193bb9749d426f3cb3b199c9460794cd.1660292316.git.mazziesaccount@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/devres.c         | 164 +++++++++++++++++++++++++++++
+ include/linux/regulator/consumer.h |  27 +++++
+ 2 files changed, 191 insertions(+)
+
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 32823a87fd409..3265e75e97ab4 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -70,6 +70,65 @@ struct regulator *devm_regulator_get_exclusive(struct device *dev,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
++static void regulator_action_disable(void *d)
++{
++      struct regulator *r = (struct regulator *)d;
++
++      regulator_disable(r);
++}
++
++static int _devm_regulator_get_enable(struct device *dev, const char *id,
++                                    int get_type)
++{
++      struct regulator *r;
++      int ret;
++
++      r = _devm_regulator_get(dev, id, get_type);
++      if (IS_ERR(r))
++              return PTR_ERR(r);
++
++      ret = regulator_enable(r);
++      if (!ret)
++              ret = devm_add_action_or_reset(dev, &regulator_action_disable, r);
++
++      if (ret)
++              devm_regulator_put(r);
++
++      return ret;
++}
++
++/**
++ * devm_regulator_get_enable_optional - Resource managed regulator get and enable
++ * @dev: device to supply
++ * @id:  supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get_optional() and regulator_enable() for more
++ * information.
++ */
++int devm_regulator_get_enable_optional(struct device *dev, const char *id)
++{
++      return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);
++
++/**
++ * devm_regulator_get_enable - Resource managed regulator get and enable
++ * @dev: device to supply
++ * @id:  supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get() and regulator_enable() for more
++ * information.
++ */
++int devm_regulator_get_enable(struct device *dev, const char *id)
++{
++      return _devm_regulator_get_enable(dev, id, NORMAL_GET);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable);
++
+ /**
+  * devm_regulator_get_optional - Resource managed regulator_get_optional()
+  * @dev: device to supply
+@@ -194,6 +253,111 @@ int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
++static int devm_regulator_bulk_match(struct device *dev, void *res,
++                                   void *data)
++{
++      struct regulator_bulk_devres *match = res;
++      struct regulator_bulk_data *target = data;
++
++      /*
++       * We check the put uses same consumer list as the get did.
++       * We _could_ scan all entries in consumer array and check the
++       * regulators match but ATM I don't see the need. We can change this
++       * later if needed.
++       */
++      return match->consumers == target;
++}
++
++/**
++ * devm_regulator_bulk_put - Resource managed regulator_bulk_put()
++ * @consumers: consumers to free
++ *
++ * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally
++ * this function will not need to be called and the resource management
++ * code will ensure that the resource is freed.
++ */
++void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
++{
++      int rc;
++      struct regulator *regulator = consumers[0].consumer;
++
++      rc = devres_release(regulator->dev, devm_regulator_bulk_release,
++                          devm_regulator_bulk_match, consumers);
++      if (rc != 0)
++              WARN_ON(rc);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);
++
++static void devm_regulator_bulk_disable(void *res)
++{
++      struct regulator_bulk_devres *devres = res;
++      int i;
++
++      for (i = 0; i < devres->num_consumers; i++)
++              regulator_disable(devres->consumers[i].consumer);
++}
++
++/**
++ * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators
++ *
++ * @dev:           device to supply
++ * @num_consumers: number of consumers to register
++ * @id:            list of supply names or regulator IDs
++ *
++ * @return 0 on success, an errno on failure.
++ *
++ * This helper function allows drivers to get several regulator
++ * consumers in one operation with management, the regulators will
++ * automatically be freed when the device is unbound.  If any of the
++ * regulators cannot be acquired then any regulators that were
++ * allocated will be freed before returning to the caller.
++ */
++int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
++                                 const char * const *id)
++{
++      struct regulator_bulk_devres *devres;
++      struct regulator_bulk_data *consumers;
++      int i, ret;
++
++      devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);
++      if (!devres)
++              return -ENOMEM;
++
++      devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),
++                                       GFP_KERNEL);
++      consumers = devres->consumers;
++      if (!consumers)
++              return -ENOMEM;
++
++      devres->num_consumers = num_consumers;
++
++      for (i = 0; i < num_consumers; i++)
++              consumers[i].supply = id[i];
++
++      ret = devm_regulator_bulk_get(dev, num_consumers, consumers);
++      if (ret)
++              return ret;
++
++      for (i = 0; i < num_consumers; i++) {
++              ret = regulator_enable(consumers[i].consumer);
++              if (ret)
++                      goto unwind;
++      }
++
++      ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);
++      if (!ret)
++              return 0;
++
++unwind:
++      while (--i >= 0)
++              regulator_disable(consumers[i].consumer);
++
++      devm_regulator_bulk_put(consumers);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);
++
+ static void devm_rdev_release(struct device *dev, void *res)
+ {
+       regulator_unregister(*(struct regulator_dev **)res);
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index 61f922e6fe353..a1fce0f27ce16 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -203,6 +203,8 @@ struct regulator *__must_check regulator_get_optional(struct device *dev,
+                                                     const char *id);
+ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
+                                                          const char *id);
++int devm_regulator_get_enable(struct device *dev, const char *id);
++int devm_regulator_get_enable_optional(struct device *dev, const char *id);
+ void regulator_put(struct regulator *regulator);
+ void devm_regulator_put(struct regulator *regulator);
+@@ -240,12 +242,15 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
+                                   struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                                        struct regulator_bulk_data *consumers);
++void devm_regulator_bulk_put(struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get_const(
+       struct device *dev, int num_consumers,
+       const struct regulator_bulk_data *in_consumers,
+       struct regulator_bulk_data **out_consumers);
+ int __must_check regulator_bulk_enable(int num_consumers,
+                                      struct regulator_bulk_data *consumers);
++int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
++                                 const char * const *id);
+ int regulator_bulk_disable(int num_consumers,
+                          struct regulator_bulk_data *consumers);
+ int regulator_bulk_force_disable(int num_consumers,
+@@ -350,6 +355,17 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
+       return ERR_PTR(-ENODEV);
+ }
++static inline int devm_regulator_get_enable(struct device *dev, const char *id)
++{
++      return -ENODEV;
++}
++
++static inline int devm_regulator_get_enable_optional(struct device *dev,
++                                                   const char *id)
++{
++      return -ENODEV;
++}
++
+ static inline struct regulator *__must_check
+ regulator_get_optional(struct device *dev, const char *id)
+ {
+@@ -371,6 +387,10 @@ static inline void devm_regulator_put(struct regulator *regulator)
+ {
+ }
++static inline void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
++{
++}
++
+ static inline int regulator_register_supply_alias(struct device *dev,
+                                                 const char *id,
+                                                 struct device *alias_dev,
+@@ -461,6 +481,13 @@ static inline int regulator_bulk_enable(int num_consumers,
+       return 0;
+ }
++static inline int devm_regulator_bulk_get_enable(struct device *dev,
++                                               int num_consumers,
++                                               const char * const *id)
++{
++      return 0;
++}
++
+ static inline int regulator_bulk_disable(int num_consumers,
+                                        struct regulator_bulk_data *consumers)
+ {
+-- 
+2.39.5
+
diff --git a/queue-5.15/regulator-core-allow-drivers-to-define-their-init-da.patch b/queue-5.15/regulator-core-allow-drivers-to-define-their-init-da.patch
new file mode 100644 (file)
index 0000000..452aa83
--- /dev/null
@@ -0,0 +1,110 @@
+From 73db36d8a44c4fe76143ec6b17bda1effa86c8de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Jul 2022 10:38:23 -0700
+Subject: regulator: core: Allow drivers to define their init data as const
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 1de452a0edda26f1483d1d934f692eab13ba669a ]
+
+Drivers tend to want to define the names of their regulators somewhere
+in their source file as "static const". This means, inevitable, that
+every driver out there open codes something like this:
+
+static const char * const supply_names[] = {
+ "vcc", "vccl",
+};
+
+static int get_regulators(struct my_data *data)
+{
+  int i;
+
+  data->supplies = devm_kzalloc(...)
+  if (!data->supplies)
+    return -ENOMEM;
+
+  for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+    data->supplies[i].supply = supply_names[i];
+
+  return devm_regulator_bulk_get(data->dev,
+                                 ARRAY_SIZE(supply_names),
+                                data->supplies);
+}
+
+Let's make this more convenient by doing providing a helper that does
+the copy.
+
+I have chosen to have the "const" input structure here be the exact
+same structure as the normal one passed to
+devm_regulator_bulk_get(). This is slightly inefficent since the input
+data can't possibly have anything useful for "ret" or consumer and
+thus we waste 8 bytes per structure. This seems an OK tradeoff for not
+introducing an extra structure.
+
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://lore.kernel.org/r/20220726103631.v2.6.I38fc508a73135a5c1b873851f3553ff2a3a625f5@changeid
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/devres.c         | 28 ++++++++++++++++++++++++++++
+ include/linux/regulator/consumer.h |  4 ++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 9113233f41cd1..32823a87fd409 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -166,6 +166,34 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
++/**
++ * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data
++ *
++ * @dev:           device to supply
++ * @num_consumers: number of consumers to register
++ * @in_consumers:  const configuration of consumers
++ * @out_consumers: in_consumers is copied here and this is passed to
++ *               devm_regulator_bulk_get().
++ *
++ * This is a convenience function to allow bulk regulator configuration
++ * to be stored "static const" in files.
++ *
++ * Return: 0 on success, an errno on failure.
++ */
++int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
++                                const struct regulator_bulk_data *in_consumers,
++                                struct regulator_bulk_data **out_consumers)
++{
++      *out_consumers = devm_kmemdup(dev, in_consumers,
++                                    num_consumers * sizeof(*in_consumers),
++                                    GFP_KERNEL);
++      if (*out_consumers == NULL)
++              return -ENOMEM;
++
++      return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
++
+ static void devm_rdev_release(struct device *dev, void *res)
+ {
+       regulator_unregister(*(struct regulator_dev **)res);
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index bbf6590a6dec2..61f922e6fe353 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -240,6 +240,10 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
+                                   struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                                        struct regulator_bulk_data *consumers);
++int __must_check devm_regulator_bulk_get_const(
++      struct device *dev, int num_consumers,
++      const struct regulator_bulk_data *in_consumers,
++      struct regulator_bulk_data **out_consumers);
+ int __must_check regulator_bulk_enable(int num_consumers,
+                                      struct regulator_bulk_data *consumers);
+ int regulator_bulk_disable(int num_consumers,
+-- 
+2.39.5
+
diff --git a/queue-5.15/revert-iommu-amd-prevent-binding-other-pci-drivers-t.patch b/queue-5.15/revert-iommu-amd-prevent-binding-other-pci-drivers-t.patch
new file mode 100644 (file)
index 0000000..66b1902
--- /dev/null
@@ -0,0 +1,60 @@
+From 941edc8cdffaac06c9f8339aead66417cec250fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 11:24:21 +0200
+Subject: Revert "iommu/amd: Prevent binding other PCI drivers to IOMMU PCI
+ devices"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 3be5fa236649da6404f1bca1491bf02d4b0d5cce ]
+
+Commit 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and
+pcibios_free_irq()") changed IRQ handling on PCI driver probing.
+It inadvertently broke resume from system sleep on AMD platforms:
+
+  https://lore.kernel.org/r/20150926164651.GA3640@pd.tnic/
+
+This was fixed by two independent commits:
+
+* 8affb487d4a4 ("x86/PCI: Don't alloc pcibios-irq when MSI is enabled")
+* cbbc00be2ce3 ("iommu/amd: Prevent binding other PCI drivers to IOMMU PCI devices")
+
+The breaking change and one of these two fixes were subsequently reverted:
+
+* fe25d078874f ("Revert "x86/PCI: Don't alloc pcibios-irq when MSI is enabled"")
+* 6c777e8799a9 ("Revert "PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()"")
+
+This rendered the second fix unnecessary, so revert it as well.  It used
+the match_driver flag in struct pci_dev, which is internal to the PCI core
+and not supposed to be touched by arbitrary drivers.
+
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Acked-by: Joerg Roedel <jroedel@suse.de>
+Link: https://patch.msgid.link/9a3ddff5cc49512044f963ba0904347bd404094d.1745572340.git.lukas@wunner.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/init.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index b6ee83b81d32c..625ff2486982d 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -1870,9 +1870,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
+       if (!iommu->dev)
+               return -ENODEV;
+-      /* Prevent binding other PCI device drivers to IOMMU devices */
+-      iommu->dev->match_driver = false;
+-
+       /* ACPI _PRT won't have an IRQ for IOMMU */
+       iommu->dev->irq_managed = 1;
+-- 
+2.39.5
+
diff --git a/queue-5.15/series b/queue-5.15/series
new file mode 100644 (file)
index 0000000..ac1a253
--- /dev/null
@@ -0,0 +1,58 @@
+cifs-fix-cifs_query_path_info-for-windows-nt-servers.patch
+nfsv4-always-set-nlink-even-if-the-server-doesn-t-su.patch
+nfsv4.2-fix-listxattr-to-return-selinux-security-lab.patch
+mailbox-not-protect-module_put-with-spin_lock_irqsav.patch
+mfd-max14577-fix-wakeup-source-leaks-on-device-unbin.patch
+leds-multicolor-fix-intensity-setting-while-sw-blink.patch
+hwmon-pmbus-max34440-fix-support-for-max34451.patch
+ksmbd-allow-a-filename-to-contain-special-characters.patch
+revert-iommu-amd-prevent-binding-other-pci-drivers-t.patch
+dmaengine-xilinx_dma-set-dma_device-directions.patch
+md-md-bitmap-fix-dm-raid-max_write_behind-setting.patch
+bcache-fix-null-pointer-in-cache_set_flush.patch
+iio-pressure-zpa2326-use-aligned_s64-for-the-timesta.patch
+um-add-cmpxchg8b_emu-and-checksum-functions-to-asm-p.patch
+coresight-only-check-bottom-two-claim-bits.patch
+usb-dwc2-also-exit-clock_gating-when-stopping-udc-wh.patch
+usb-potential-integer-overflow-in-usbg_make_tpg.patch
+tty-serial-uartlite-register-uart-driver-in-init.patch
+usb-common-usb-conn-gpio-use-a-unique-name-for-usb-c.patch
+usb-add-checks-for-snprintf-calls-in-usb_alloc_dev.patch
+usb-cdc-wdm-avoid-setting-wdm_read-for-zlp-s.patch
+usb-typec-displayport-receive-dp-status-update-nak-r.patch
+alsa-hda-ignore-unsol-events-for-cards-being-shut-do.patch
+alsa-hda-add-new-pci-id-for-amd-gpu-display-hd-audio.patch
+alsa-usb-audio-add-a-quirk-for-lenovo-thinkpad-thund.patch
+ceph-fix-possible-integer-overflow-in-ceph_zero_obje.patch
+ovl-check-for-null-d_inode-in-ovl_dentry_upper.patch
+fs-jfs-consolidate-sanity-checking-in-dbmount.patch
+jfs-validate-ag-parameters-in-dbmount-to-prevent-cra.patch
+media-davinci-vpif-fix-memory-leak-in-probe-error-pa.patch
+media-omap3isp-use-sgtable-based-scatterlist-wrapper.patch
+clk-ti-am43xx-add-clkctrl-data-for-am43xx-adc1.patch
+media-imx-jpeg-drop-the-first-error-frames.patch
+regulator-core-allow-drivers-to-define-their-init-da.patch
+regulator-add-devm-helpers-for-get-and-enable.patch
+asoc-codecs-wcd9335-handle-nicer-probe-deferral-and-.patch
+asoc-codec-wcd9335-convert-to-gpio-descriptors.patch
+asoc-codecs-wcd9335-fix-missing-free-of-regulator-su.patch
+f2fs-don-t-over-report-free-space-or-inodes-in-statv.patch
+fbcon-use-delayed-work-for-cursor.patch
+fbcon-extract-fbcon_open-release-helpers.patch
+fbcon-move-more-common-code-into-fb_open.patch
+fbcon-use-lock_fb_info-in-fbcon_open-release.patch
+fbcon-move-console_lock-for-register-unlink-unregist.patch
+fbdev-fix-do_register_framebuffer-to-prevent-null-pt.patch
+drivers-hv-rename-alloced-to-allocated.patch
+drivers-hv-vmbus-add-utility-function-for-querying-r.patch
+uio_hv_generic-query-the-ringbuffer-size-for-device.patch
+uio_hv_generic-align-ring-size-to-system-page.patch
+fbcon-delete-a-few-unneeded-forward-decl.patch
+tty-vt-consolemap-rename-and-document-struct-uni_pag.patch
+vgacon-switch-vgacon_scrolldelta-and-vgacon_restore_.patch
+vgacon-remove-unneeded-forward-declarations.patch
+tty-vt-make-init-parameter-of-consw-con_init-a-bool.patch
+tty-vt-sanitize-arguments-of-consw-con_clear.patch
+tty-vt-make-consw-con_switch-return-a-bool.patch
+dummycon-trigger-redraw-when-switching-consoles-with.patch
+platform-x86-ideapad-laptop-use-usleep_range-for-ec-.patch
diff --git a/queue-5.15/tty-serial-uartlite-register-uart-driver-in-init.patch b/queue-5.15/tty-serial-uartlite-register-uart-driver-in-init.patch
new file mode 100644 (file)
index 0000000..081d717
--- /dev/null
@@ -0,0 +1,101 @@
+From b56104ce4ae3bcd08e9d41be01d8cc77153f428b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Mar 2025 18:06:19 +0200
+Subject: tty: serial: uartlite: register uart driver in init
+
+From: Jakub Lewalski <jakub.lewalski@nokia.com>
+
+[ Upstream commit 6bd697b5fc39fd24e2aa418c7b7d14469f550a93 ]
+
+When two instances of uart devices are probing, a concurrency race can
+occur. If one thread calls uart_register_driver function, which first
+allocates and assigns memory to 'uart_state' member of uart_driver
+structure, the other instance can bypass uart driver registration and
+call ulite_assign. This calls uart_add_one_port, which expects the uart
+driver to be fully initialized. This leads to a kernel panic due to a
+null pointer dereference:
+
+[    8.143581] BUG: kernel NULL pointer dereference, address: 00000000000002b8
+[    8.156982] #PF: supervisor write access in kernel mode
+[    8.156984] #PF: error_code(0x0002) - not-present page
+[    8.156986] PGD 0 P4D 0
+...
+[    8.180668] RIP: 0010:mutex_lock+0x19/0x30
+[    8.188624] Call Trace:
+[    8.188629]  ? __die_body.cold+0x1a/0x1f
+[    8.195260]  ? page_fault_oops+0x15c/0x290
+[    8.209183]  ? __irq_resolve_mapping+0x47/0x80
+[    8.209187]  ? exc_page_fault+0x64/0x140
+[    8.209190]  ? asm_exc_page_fault+0x22/0x30
+[    8.209196]  ? mutex_lock+0x19/0x30
+[    8.223116]  uart_add_one_port+0x60/0x440
+[    8.223122]  ? proc_tty_register_driver+0x43/0x50
+[    8.223126]  ? tty_register_driver+0x1ca/0x1e0
+[    8.246250]  ulite_probe+0x357/0x4b0 [uartlite]
+
+To prevent it, move uart driver registration in to init function. This
+will ensure that uart_driver is always registered when probe function
+is called.
+
+Signed-off-by: Jakub Lewalski <jakub.lewalski@nokia.com>
+Signed-off-by: Elodie Decerle <elodie.decerle@nokia.com>
+Link: https://lore.kernel.org/r/20250331160732.2042-1-elodie.decerle@nokia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/uartlite.c | 25 ++++++++++++-------------
+ 1 file changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
+index 36871cebd6a0f..0345eaf969630 100644
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -808,16 +808,6 @@ static int ulite_probe(struct platform_device *pdev)
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+-      if (!ulite_uart_driver.state) {
+-              dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
+-              ret = uart_register_driver(&ulite_uart_driver);
+-              if (ret < 0) {
+-                      dev_err(&pdev->dev, "Failed to register driver\n");
+-                      clk_disable_unprepare(pdata->clk);
+-                      return ret;
+-              }
+-      }
+-
+       ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
+       pm_runtime_mark_last_busy(&pdev->dev);
+@@ -859,16 +849,25 @@ static struct platform_driver ulite_platform_driver = {
+ static int __init ulite_init(void)
+ {
++      int ret;
++
++      pr_debug("uartlite: calling uart_register_driver()\n");
++      ret = uart_register_driver(&ulite_uart_driver);
++      if (ret)
++              return ret;
+       pr_debug("uartlite: calling platform_driver_register()\n");
+-      return platform_driver_register(&ulite_platform_driver);
++      ret = platform_driver_register(&ulite_platform_driver);
++      if (ret)
++              uart_unregister_driver(&ulite_uart_driver);
++
++      return ret;
+ }
+ static void __exit ulite_exit(void)
+ {
+       platform_driver_unregister(&ulite_platform_driver);
+-      if (ulite_uart_driver.state)
+-              uart_unregister_driver(&ulite_uart_driver);
++      uart_unregister_driver(&ulite_uart_driver);
+ }
+ module_init(ulite_init);
+-- 
+2.39.5
+
diff --git a/queue-5.15/tty-vt-consolemap-rename-and-document-struct-uni_pag.patch b/queue-5.15/tty-vt-consolemap-rename-and-document-struct-uni_pag.patch
new file mode 100644 (file)
index 0000000..49c2eac
--- /dev/null
@@ -0,0 +1,242 @@
+From 7bc0695353e5925cd16dfbff9178b27fc1098271 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 12:49:12 +0200
+Subject: tty/vt: consolemap: rename and document struct uni_pagedir
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+[ Upstream commit 4173f018aae16b6496d292c234b858241f85254f ]
+
+struct uni_pagedir contains 32 unicode page directories, so the name of
+the structure is a bit misleading. Rename the structure to uni_pagedict,
+so it looks like this:
+struct uni_pagedict
+  -> 32 page dirs
+     -> 32 rows
+       -> 64 glyphs
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20220607104946.18710-2-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/vt/consolemap.c    | 47 ++++++++++++++++++++--------------
+ drivers/video/console/vgacon.c |  4 +--
+ include/linux/console_struct.h |  6 ++---
+ 3 files changed, 33 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
+index d815ac98b39e3..32fa4df121dab 100644
+--- a/drivers/tty/vt/consolemap.c
++++ b/drivers/tty/vt/consolemap.c
+@@ -186,17 +186,26 @@ static unsigned short translations[][256] = {
+ static int inv_translate[MAX_NR_CONSOLES];
+-struct uni_pagedir {
+-      u16             **uni_pgdir[32];
++/**
++ * struct uni_pagedict -- unicode directory
++ *
++ * @uni_pgdir: 32*32*64 table with glyphs
++ * @refcount: reference count of this structure
++ * @sum: checksum
++ * @inverse_translations: best-effort inverse mapping
++ * @inverse_trans_unicode: best-effort inverse mapping to unicode
++ */
++struct uni_pagedict {
++      u16             **uni_pgdir[32];
+       unsigned long   refcount;
+       unsigned long   sum;
+       unsigned char   *inverse_translations[4];
+       u16             *inverse_trans_unicode;
+ };
+-static struct uni_pagedir *dflt;
++static struct uni_pagedict *dflt;
+-static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
++static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *p, int i)
+ {
+       int j, glyph;
+       unsigned short *t = translations[i];
+@@ -221,7 +230,7 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
+ }
+ static void set_inverse_trans_unicode(struct vc_data *conp,
+-                                    struct uni_pagedir *p)
++                                    struct uni_pagedict *p)
+ {
+       int i, j, k, glyph;
+       u16 **p1, *p2;
+@@ -270,7 +279,7 @@ unsigned short *set_translate(int m, struct vc_data *vc)
+  */
+ u16 inverse_translate(const struct vc_data *conp, int glyph, int use_unicode)
+ {
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+       int m;
+       if (glyph < 0 || glyph >= MAX_GLYPH)
+               return 0;
+@@ -297,7 +306,7 @@ EXPORT_SYMBOL_GPL(inverse_translate);
+ static void update_user_maps(void)
+ {
+       int i;
+-      struct uni_pagedir *p, *q = NULL;
++      struct uni_pagedict *p, *q = NULL;
+       
+       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+               if (!vc_cons_allocated(i))
+@@ -393,7 +402,7 @@ int con_get_trans_new(ushort __user * arg)
+ extern u8 dfont_unicount[];   /* Defined in console_defmap.c */
+ extern u16 dfont_unitable[];
+-static void con_release_unimap(struct uni_pagedir *p)
++static void con_release_unimap(struct uni_pagedict *p)
+ {
+       u16 **p1;
+       int i, j;
+@@ -419,7 +428,7 @@ static void con_release_unimap(struct uni_pagedir *p)
+ /* Caller must hold the console lock */
+ void con_free_unimap(struct vc_data *vc)
+ {
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+       p = *vc->vc_uni_pagedir_loc;
+       if (!p)
+@@ -431,10 +440,10 @@ void con_free_unimap(struct vc_data *vc)
+       kfree(p);
+ }
+   
+-static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
++static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *p)
+ {
+       int i, j, k;
+-      struct uni_pagedir *q;
++      struct uni_pagedict *q;
+       
+       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+               if (!vc_cons_allocated(i))
+@@ -472,7 +481,7 @@ static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
+ }
+ static int
+-con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
++con_insert_unipair(struct uni_pagedict *p, u_short unicode, u_short fontpos)
+ {
+       int i, n;
+       u16 **p1, *p2;
+@@ -503,7 +512,7 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
+ /* Caller must hold the lock */
+ static int con_do_clear_unimap(struct vc_data *vc)
+ {
+-      struct uni_pagedir *p, *q;
++      struct uni_pagedict *p, *q;
+       p = *vc->vc_uni_pagedir_loc;
+       if (!p || --p->refcount) {
+@@ -536,7 +545,7 @@ int con_clear_unimap(struct vc_data *vc)
+ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
+ {
+       int err = 0, err1, i;
+-      struct uni_pagedir *p, *q;
++      struct uni_pagedict *p, *q;
+       struct unipair *unilist, *plist;
+       if (!ct)
+@@ -569,7 +578,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
+               
+               /*
+                * Since refcount was > 1, con_clear_unimap() allocated a
+-               * a new uni_pagedir for this vc.  Re: p != q
++               * a new uni_pagedict for this vc.  Re: p != q
+                */
+               q = *vc->vc_uni_pagedir_loc;
+@@ -660,7 +669,7 @@ int con_set_default_unimap(struct vc_data *vc)
+ {
+       int i, j, err = 0, err1;
+       u16 *q;
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+       if (dflt) {
+               p = *vc->vc_uni_pagedir_loc;
+@@ -714,7 +723,7 @@ EXPORT_SYMBOL(con_set_default_unimap);
+  */
+ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
+ {
+-      struct uni_pagedir *q;
++      struct uni_pagedict *q;
+       if (!*src_vc->vc_uni_pagedir_loc)
+               return -EINVAL;
+@@ -739,7 +748,7 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
+       int i, j, k, ret = 0;
+       ushort ect;
+       u16 **p1, *p2;
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+       struct unipair *unilist;
+       unilist = kvmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL);
+@@ -810,7 +819,7 @@ conv_uni_to_pc(struct vc_data *conp, long ucs)
+ {
+       int h;
+       u16 **p1, *p2;
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+   
+       /* Only 16-bit codes supported at this time */
+       if (ucs > 0xffff)
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index 63a6944ebb190..7bce5a174f388 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -75,7 +75,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines);
+ static int vgacon_set_origin(struct vc_data *c);
+ static void vgacon_save_screen(struct vc_data *c);
+ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
+-static struct uni_pagedir *vgacon_uni_pagedir;
++static struct uni_pagedict *vgacon_uni_pagedir;
+ static int vgacon_refcount;
+ /* Description of the hardware situation */
+@@ -363,7 +363,7 @@ static const char *vgacon_startup(void)
+ static void vgacon_init(struct vc_data *c, int init)
+ {
+-      struct uni_pagedir *p;
++      struct uni_pagedict *p;
+       /*
+        * We cannot be loaded as a module, therefore init will be 1
+diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
+index d5b9c8d40c18e..f75033f0277fc 100644
+--- a/include/linux/console_struct.h
++++ b/include/linux/console_struct.h
+@@ -17,7 +17,7 @@
+ #include <linux/vt.h>
+ #include <linux/workqueue.h>
+-struct uni_pagedir;
++struct uni_pagedict;
+ struct uni_screen;
+ #define NPAR 16
+@@ -157,8 +157,8 @@ struct vc_data {
+       unsigned int    vc_bell_duration;       /* Console bell duration */
+       unsigned short  vc_cur_blink_ms;        /* Cursor blink duration */
+       struct vc_data **vc_display_fg;         /* [!] Ptr to var holding fg console for this display */
+-      struct uni_pagedir *vc_uni_pagedir;
+-      struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
++      struct uni_pagedict *vc_uni_pagedir;
++      struct uni_pagedict **vc_uni_pagedir_loc; /* [!] Location of uni_pagedict variable for this console */
+       struct uni_screen *vc_uni_screen;       /* unicode screen content */
+       /* additional information is in vt_kern.h */
+ };
+-- 
+2.39.5
+
diff --git a/queue-5.15/tty-vt-make-consw-con_switch-return-a-bool.patch b/queue-5.15/tty-vt-make-consw-con_switch-return-a-bool.patch
new file mode 100644 (file)
index 0000000..13d887c
--- /dev/null
@@ -0,0 +1,193 @@
+From 9dd9ae6e5ddba349d059fc020672b4ad2c7c00a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 12:03:44 +0100
+Subject: tty: vt: make consw::con_switch() return a bool
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 8d5cc8eed738e3202379722295c626cba0849785 ]
+
+The non-zero (true) return value from consw::con_switch() means a redraw
+is needed. So make this return type a bool explicitly instead of int.
+The latter might imply that -Eerrors are expected. They are not.
+
+And document the hook.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: linux-parisc@vger.kernel.org
+Tested-by: Helge Deller <deller@gmx.de> # parisc STI console
+Link: https://lore.kernel.org/r/20240122110401.7289-31-jirislaby@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/vt/vt.c                 | 2 +-
+ drivers/video/console/dummycon.c    | 4 ++--
+ drivers/video/console/mdacon.c      | 4 ++--
+ drivers/video/console/newport_con.c | 4 ++--
+ drivers/video/console/sticon.c      | 4 ++--
+ drivers/video/console/vgacon.c      | 4 ++--
+ drivers/video/fbdev/core/fbcon.c    | 6 +++---
+ include/linux/console.h             | 4 +++-
+ 8 files changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index 765db5a7d5f52..a6e0c803e96ec 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -1014,7 +1014,7 @@ void redraw_screen(struct vc_data *vc, int is_switch)
+       }
+       if (redraw) {
+-              int update;
++              bool update;
+               int old_was_color = vc->vc_can_do_color;
+               set_origin(vc);
+diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
+index 6918014b02408..d701f2b51f5b1 100644
+--- a/drivers/video/console/dummycon.c
++++ b/drivers/video/console/dummycon.c
+@@ -119,9 +119,9 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
+       return false;
+ }
+-static int dummycon_switch(struct vc_data *vc)
++static bool dummycon_switch(struct vc_data *vc)
+ {
+-      return 0;
++      return false;
+ }
+ /*
+diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
+index 1ddbb6cd5b0ca..26b41a8f36c87 100644
+--- a/drivers/video/console/mdacon.c
++++ b/drivers/video/console/mdacon.c
+@@ -454,9 +454,9 @@ static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x,
+       scr_memsetw(dest, eattr, width * 2);
+ }
+-static int mdacon_switch(struct vc_data *c)
++static bool mdacon_switch(struct vc_data *c)
+ {
+-      return 1;       /* redrawing needed */
++      return true;    /* redrawing needed */
+ }
+ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
+diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
+index 5dac00c825946..1ebb18bf10983 100644
+--- a/drivers/video/console/newport_con.c
++++ b/drivers/video/console/newport_con.c
+@@ -462,7 +462,7 @@ static void newport_cursor(struct vc_data *vc, int mode)
+       }
+ }
+-static int newport_switch(struct vc_data *vc)
++static bool newport_switch(struct vc_data *vc)
+ {
+       static int logo_drawn = 0;
+@@ -476,7 +476,7 @@ static int newport_switch(struct vc_data *vc)
+               }
+       }
+-      return 1;
++      return true;
+ }
+ static int newport_blank(struct vc_data *c, int blank, int mode_switch)
+diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
+index 58e983b18f1f4..6b82194a8ef36 100644
+--- a/drivers/video/console/sticon.c
++++ b/drivers/video/console/sticon.c
+@@ -309,9 +309,9 @@ static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx,
+             conp->vc_video_erase_char, font_data[conp->vc_num]);
+ }
+-static int sticon_switch(struct vc_data *conp)
++static bool sticon_switch(struct vc_data *conp)
+ {
+-    return 1; /* needs refreshing */
++    return true;      /* needs refreshing */
+ }
+ static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index 54d79edbe85e1..448aede31b946 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -616,7 +616,7 @@ static int vgacon_doresize(struct vc_data *c,
+       return 0;
+ }
+-static int vgacon_switch(struct vc_data *c)
++static bool vgacon_switch(struct vc_data *c)
+ {
+       int x = c->vc_cols * VGA_FONTWIDTH;
+       int y = c->vc_rows * c->vc_cell_height;
+@@ -645,7 +645,7 @@ static int vgacon_switch(struct vc_data *c)
+                       vgacon_doresize(c, c->vc_cols, c->vc_rows);
+       }
+-      return 0;               /* Redrawing not needed */
++      return false;           /* Redrawing not needed */
+ }
+ static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 7467b7a27ce2f..1ce767de96c11 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -2043,7 +2043,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
+       return 0;
+ }
+-static int fbcon_switch(struct vc_data *vc)
++static bool fbcon_switch(struct vc_data *vc)
+ {
+       struct fb_info *info, *old_info = NULL;
+       struct fbcon_ops *ops;
+@@ -2166,9 +2166,9 @@ static int fbcon_switch(struct vc_data *vc)
+                             vc->vc_origin + vc->vc_size_row * vc->vc_top,
+                             vc->vc_size_row * (vc->vc_bottom -
+                                                vc->vc_top) / 2);
+-              return 0;
++              return false;
+       }
+-      return 1;
++      return true;
+ }
+ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
+diff --git a/include/linux/console.h b/include/linux/console.h
+index bd7f3a6a64cd0..e2862542a162d 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -40,6 +40,8 @@ enum vc_intensity;
+  * @con_scroll: move lines from @top to @bottom in direction @dir by @lines.
+  *            Return true if no generic handling should be done.
+  *            Invoked by csi_M and printing to the console.
++ * @con_switch: notifier about the console switch; it is supposed to return
++ *            true if a redraw is needed.
+  * @con_set_palette: sets the palette of the console to @table (optional)
+  * @con_scrolldelta: the contents of the console should be scrolled by @lines.
+  *                 Invoked by user. (optional)
+@@ -58,7 +60,7 @@ struct consw {
+       bool    (*con_scroll)(struct vc_data *vc, unsigned int top,
+                       unsigned int bottom, enum con_scroll dir,
+                       unsigned int lines);
+-      int     (*con_switch)(struct vc_data *vc);
++      bool    (*con_switch)(struct vc_data *vc);
+       int     (*con_blank)(struct vc_data *vc, int blank, int mode_switch);
+       int     (*con_font_set)(struct vc_data *vc, struct console_font *font,
+                       unsigned int flags);
+-- 
+2.39.5
+
diff --git a/queue-5.15/tty-vt-make-init-parameter-of-consw-con_init-a-bool.patch b/queue-5.15/tty-vt-make-init-parameter-of-consw-con_init-a-bool.patch
new file mode 100644 (file)
index 0000000..42c6815
--- /dev/null
@@ -0,0 +1,190 @@
+From 4795e5b506771b3b468dddf33ecdd2a91b3eb256 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 12:03:34 +0100
+Subject: tty: vt: make init parameter of consw::con_init() a bool
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit dae3e6b6180f1a2394b984c596d39ed2c57d25fe ]
+
+The 'init' parameter of consw::con_init() is true for the first call of
+the hook on a particular console. So make the parameter a bool.
+
+And document the hook.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Helge Deller <deller@gmx.de>
+Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: linux-parisc@vger.kernel.org
+Tested-by: Helge Deller <deller@gmx.de> # parisc STI console
+Link: https://lore.kernel.org/r/20240122110401.7289-21-jirislaby@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/vt/vt.c                 | 8 ++++----
+ drivers/video/console/dummycon.c    | 2 +-
+ drivers/video/console/mdacon.c      | 2 +-
+ drivers/video/console/newport_con.c | 2 +-
+ drivers/video/console/sticon.c      | 2 +-
+ drivers/video/console/vgacon.c      | 4 ++--
+ drivers/video/fbdev/core/fbcon.c    | 2 +-
+ include/linux/console.h             | 4 +++-
+ 8 files changed, 14 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index bd125ea5c51f4..0e3d7d8f5e75a 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -1050,7 +1050,7 @@ int vc_cons_allocated(unsigned int i)
+       return (i < MAX_NR_CONSOLES && vc_cons[i].d);
+ }
+-static void visual_init(struct vc_data *vc, int num, int init)
++static void visual_init(struct vc_data *vc, int num, bool init)
+ {
+       /* ++Geert: vc->vc_sw->con_init determines console size */
+       if (vc->vc_sw)
+@@ -1134,7 +1134,7 @@ int vc_allocate(unsigned int currcons)   /* return 0 on success */
+       vc->port.ops = &vc_port_ops;
+       INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
+-      visual_init(vc, currcons, 1);
++      visual_init(vc, currcons, true);
+       if (!*vc->vc_uni_pagedir_loc)
+               con_set_default_unimap(vc);
+@@ -3521,7 +3521,7 @@ static int __init con_init(void)
+               vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
+               INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
+               tty_port_init(&vc->port);
+-              visual_init(vc, currcons, 1);
++              visual_init(vc, currcons, true);
+               /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
+               vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
+               vc_init(vc, vc->vc_rows, vc->vc_cols,
+@@ -3692,7 +3692,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
+               old_was_color = vc->vc_can_do_color;
+               vc->vc_sw->con_deinit(vc);
+               vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+-              visual_init(vc, i, 0);
++              visual_init(vc, i, false);
+               set_origin(vc);
+               update_attr(vc);
+diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
+index f1711b2f9ff05..9a19eb72a18b9 100644
+--- a/drivers/video/console/dummycon.c
++++ b/drivers/video/console/dummycon.c
+@@ -97,7 +97,7 @@ static const char *dummycon_startup(void)
+     return "dummy device";
+ }
+-static void dummycon_init(struct vc_data *vc, int init)
++static void dummycon_init(struct vc_data *vc, bool init)
+ {
+     vc->vc_can_do_color = 1;
+     if (init) {
+diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
+index ef29b321967f0..c5b255c968794 100644
+--- a/drivers/video/console/mdacon.c
++++ b/drivers/video/console/mdacon.c
+@@ -352,7 +352,7 @@ static const char *mdacon_startup(void)
+       return "MDA-2";
+ }
+-static void mdacon_init(struct vc_data *c, int init)
++static void mdacon_init(struct vc_data *c, bool init)
+ {
+       c->vc_complement_mask = 0x0800;  /* reverse video */
+       c->vc_display_fg = &mda_display_fg;
+diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
+index d9c682ae03926..4b7161a81b2f6 100644
+--- a/drivers/video/console/newport_con.c
++++ b/drivers/video/console/newport_con.c
+@@ -324,7 +324,7 @@ static const char *newport_startup(void)
+       return NULL;
+ }
+-static void newport_init(struct vc_data *vc, int init)
++static void newport_init(struct vc_data *vc, bool init)
+ {
+       int cols, rows;
+diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
+index f304163e87e99..10302df885147 100644
+--- a/drivers/video/console/sticon.c
++++ b/drivers/video/console/sticon.c
+@@ -272,7 +272,7 @@ static int sticon_font_set(struct vc_data *vc, struct console_font *font,
+       return sticon_set_font(vc, font);
+ }
+-static void sticon_init(struct vc_data *c, int init)
++static void sticon_init(struct vc_data *c, bool init)
+ {
+     struct sti_struct *sti = sticon_sti;
+     int vc_cols, vc_rows;
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index 9bfe451050209..a9777fd38ad92 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -353,7 +353,7 @@ static const char *vgacon_startup(void)
+       return display_desc;
+ }
+-static void vgacon_init(struct vc_data *c, int init)
++static void vgacon_init(struct vc_data *c, bool init)
+ {
+       struct uni_pagedict *p;
+@@ -370,7 +370,7 @@ static void vgacon_init(struct vc_data *c, int init)
+       c->vc_scan_lines = vga_scan_lines;
+       c->vc_font.height = c->vc_cell_height = vga_video_font_height;
+-      /* set dimensions manually if init != 0 since vc_resize() will fail */
++      /* set dimensions manually if init is true since vc_resize() will fail */
+       if (init) {
+               c->vc_cols = vga_video_num_columns;
+               c->vc_rows = vga_video_num_lines;
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index a3af7aacfaf11..f47dbba972fbb 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -983,7 +983,7 @@ static const char *fbcon_startup(void)
+       return display_desc;
+ }
+-static void fbcon_init(struct vc_data *vc, int init)
++static void fbcon_init(struct vc_data *vc, bool init)
+ {
+       struct fb_info *info;
+       struct fbcon_ops *ops;
+diff --git a/include/linux/console.h b/include/linux/console.h
+index a97f277cfdfa3..9258cb8e0841e 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -34,6 +34,8 @@ enum vc_intensity;
+ /**
+  * struct consw - callbacks for consoles
+  *
++ * @con_init:   initialize the console on @vc. @init is true for the very first
++ *            call on this @vc.
+  * @con_scroll: move lines from @top to @bottom in direction @dir by @lines.
+  *            Return true if no generic handling should be done.
+  *            Invoked by csi_M and printing to the console.
+@@ -44,7 +46,7 @@ enum vc_intensity;
+ struct consw {
+       struct module *owner;
+       const char *(*con_startup)(void);
+-      void    (*con_init)(struct vc_data *vc, int init);
++      void    (*con_init)(struct vc_data *vc, bool init);
+       void    (*con_deinit)(struct vc_data *vc);
+       void    (*con_clear)(struct vc_data *vc, int sy, int sx, int height,
+                       int width);
+-- 
+2.39.5
+
diff --git a/queue-5.15/tty-vt-sanitize-arguments-of-consw-con_clear.patch b/queue-5.15/tty-vt-sanitize-arguments-of-consw-con_clear.patch
new file mode 100644 (file)
index 0000000..ff3f26f
--- /dev/null
@@ -0,0 +1,313 @@
+From 68914630d09ed6e78a359d0824b3e49eab1322af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 12:03:35 +0100
+Subject: tty: vt: sanitize arguments of consw::con_clear()
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 559f01a0ee6d924c6fec3eaf6a5b078b15e71070 ]
+
+In consw::con_clear():
+* Height is always 1, so drop it.
+* Offsets and width are always unsigned values, so re-type them as such.
+
+This needs a new __fbcon_clear() in the fbcon code to still handle
+height which might not be 1 when called internally.
+
+Note that tests for negative count/width are left in place -- they are
+taken care of in the next patches.
+
+And document the hook.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: linux-parisc@vger.kernel.org
+Tested-by: Helge Deller <deller@gmx.de> # parisc STI console
+Link: https://lore.kernel.org/r/20240122110401.7289-22-jirislaby@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/vt/vt.c                 |  2 +-
+ drivers/video/console/dummycon.c    |  4 ++--
+ drivers/video/console/mdacon.c      | 15 +++++---------
+ drivers/video/console/newport_con.c |  6 +++---
+ drivers/video/console/sticon.c      |  8 ++++----
+ drivers/video/console/vgacon.c      |  4 ++--
+ drivers/video/fbdev/core/fbcon.c    | 32 +++++++++++++++++------------
+ include/linux/console.h             |  5 +++--
+ 8 files changed, 39 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index 0e3d7d8f5e75a..765db5a7d5f52 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -1628,7 +1628,7 @@ static void csi_X(struct vc_data *vc, unsigned int vpar)
+       vc_uniscr_clear_line(vc, vc->state.x, count);
+       scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
+       if (con_should_update(vc))
+-              vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count);
++              vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, count);
+       vc->vc_need_wrap = 0;
+ }
+diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
+index 9a19eb72a18b9..6918014b02408 100644
+--- a/drivers/video/console/dummycon.c
++++ b/drivers/video/console/dummycon.c
+@@ -108,8 +108,8 @@ static void dummycon_init(struct vc_data *vc, bool init)
+ }
+ static void dummycon_deinit(struct vc_data *vc) { }
+-static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height,
+-                         int width) { }
++static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
++                         unsigned int width) { }
+ static void dummycon_cursor(struct vc_data *vc, int mode) { }
+ static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
+diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
+index c5b255c968794..1ddbb6cd5b0ca 100644
+--- a/drivers/video/console/mdacon.c
++++ b/drivers/video/console/mdacon.c
+@@ -442,23 +442,18 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
+       }
+ }
+-static void mdacon_clear(struct vc_data *c, int y, int x, 
+-                        int height, int width)
++static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x,
++                       unsigned int width)
+ {
+       u16 *dest = mda_addr(x, y);
+       u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+-      if (width <= 0 || height <= 0)
++      if (width <= 0)
+               return;
+-      if (x==0 && width==mda_num_columns) {
+-              scr_memsetw(dest, eattr, height*width*2);
+-      } else {
+-              for (; height > 0; height--, dest+=mda_num_columns)
+-                      scr_memsetw(dest, eattr, width*2);
+-      }
++      scr_memsetw(dest, eattr, width * 2);
+ }
+-                        
++
+ static int mdacon_switch(struct vc_data *c)
+ {
+       return 1;       /* redrawing needed */
+diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
+index 4b7161a81b2f6..5dac00c825946 100644
+--- a/drivers/video/console/newport_con.c
++++ b/drivers/video/console/newport_con.c
+@@ -346,12 +346,12 @@ static void newport_deinit(struct vc_data *c)
+       }
+ }
+-static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
+-                        int width)
++static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
++                        unsigned int width)
+ {
+       int xend = ((sx + width) << 3) - 1;
+       int ystart = ((sy << 4) + topscan) & 0x3ff;
+-      int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff;
++      int yend = (((sy + 1) << 4) + topscan - 1) & 0x3ff;
+       if (logo_active)
+               return;
+diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
+index 10302df885147..58e983b18f1f4 100644
+--- a/drivers/video/console/sticon.c
++++ b/drivers/video/console/sticon.c
+@@ -299,13 +299,13 @@ static void sticon_deinit(struct vc_data *c)
+       sticon_set_def_font(i, NULL);
+ }
+-static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
+-                       int width)
++static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx,
++                       unsigned int width)
+ {
+-    if (!height || !width)
++    if (!width)
+       return;
+-    sti_clear(sticon_sti, sy, sx, height, width,
++    sti_clear(sticon_sti, sy, sx, 1, width,
+             conp->vc_video_erase_char, font_data[conp->vc_num]);
+ }
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index a9777fd38ad92..54d79edbe85e1 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -1187,8 +1187,8 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
+  *  The console `switch' structure for the VGA based console
+  */
+-static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
+-                       int width) { }
++static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
++                       unsigned int width) { }
+ static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
+ static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
+                        int count, int ypos, int xpos) { }
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index f47dbba972fbb..7467b7a27ce2f 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -1210,8 +1210,8 @@ static void fbcon_deinit(struct vc_data *vc)
+  *  restriction is simplicity & efficiency at the moment.
+  */
+-static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
+-                      int width)
++static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
++                        unsigned int height, unsigned int width)
+ {
+       struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+       struct fbcon_ops *ops = info->fbcon_par;
+@@ -1250,6 +1250,12 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
+               ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
+ }
++static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
++                      unsigned int width)
++{
++      __fbcon_clear(vc, sy, sx, 1, width);
++}
++
+ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+                       int count, int ypos, int xpos)
+ {
+@@ -1673,7 +1679,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+               case SCROLL_MOVE:
+                       fbcon_redraw_blit(vc, info, p, t, b - t - count,
+                                    count);
+-                      fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       scr_memsetw((unsigned short *) (vc->vc_origin +
+                                                       vc->vc_size_row *
+                                                       (b - count)),
+@@ -1696,7 +1702,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                           b - t - count, vc->vc_cols);
+                       else
+                               goto redraw_up;
+-                      fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_PAN_REDRAW:
+@@ -1714,7 +1720,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                                         vc->vc_rows - b, b);
+                       } else
+                               fbcon_redraw_move(vc, p, t + count, b - t - count, t);
+-                      fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_PAN_MOVE:
+@@ -1737,14 +1743,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                           b - t - count, vc->vc_cols);
+                       else
+                               goto redraw_up;
+-                      fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_REDRAW:
+                     redraw_up:
+                       fbcon_redraw(vc, p, t, b - t - count,
+                                    count * vc->vc_cols);
+-                      fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+                       scr_memsetw((unsigned short *) (vc->vc_origin +
+                                                       vc->vc_size_row *
+                                                       (b - count)),
+@@ -1761,7 +1767,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+               case SCROLL_MOVE:
+                       fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+                                    -count);
+-                      fbcon_clear(vc, t, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       scr_memsetw((unsigned short *) (vc->vc_origin +
+                                                       vc->vc_size_row *
+                                                       t),
+@@ -1784,7 +1790,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                           b - t - count, vc->vc_cols);
+                       else
+                               goto redraw_down;
+-                      fbcon_clear(vc, t, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_PAN_MOVE:
+@@ -1806,7 +1812,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                           b - t - count, vc->vc_cols);
+                       else
+                               goto redraw_down;
+-                      fbcon_clear(vc, t, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_PAN_REDRAW:
+@@ -1823,14 +1829,14 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+                                       fbcon_redraw_move(vc, p, count, t, 0);
+                       } else
+                               fbcon_redraw_move(vc, p, t, b - t - count, t + count);
+-                      fbcon_clear(vc, t, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       break;
+               case SCROLL_REDRAW:
+                     redraw_down:
+                       fbcon_redraw(vc, p, b - 1, b - t - count,
+                                    -count * vc->vc_cols);
+-                      fbcon_clear(vc, t, 0, count, vc->vc_cols);
++                      __fbcon_clear(vc, t, 0, count, vc->vc_cols);
+                       scr_memsetw((unsigned short *) (vc->vc_origin +
+                                                       vc->vc_size_row *
+                                                       t),
+@@ -2175,7 +2181,7 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
+               oldc = vc->vc_video_erase_char;
+               vc->vc_video_erase_char &= charmask;
+-              fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
++              __fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
+               vc->vc_video_erase_char = oldc;
+       }
+ }
+diff --git a/include/linux/console.h b/include/linux/console.h
+index 9258cb8e0841e..bd7f3a6a64cd0 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -36,6 +36,7 @@ enum vc_intensity;
+  *
+  * @con_init:   initialize the console on @vc. @init is true for the very first
+  *            call on this @vc.
++ * @con_clear:  erase @count characters at [@x, @y] on @vc. @count >= 1.
+  * @con_scroll: move lines from @top to @bottom in direction @dir by @lines.
+  *            Return true if no generic handling should be done.
+  *            Invoked by csi_M and printing to the console.
+@@ -48,8 +49,8 @@ struct consw {
+       const char *(*con_startup)(void);
+       void    (*con_init)(struct vc_data *vc, bool init);
+       void    (*con_deinit)(struct vc_data *vc);
+-      void    (*con_clear)(struct vc_data *vc, int sy, int sx, int height,
+-                      int width);
++      void    (*con_clear)(struct vc_data *vc, unsigned int y,
++                           unsigned int x, unsigned int count);
+       void    (*con_putc)(struct vc_data *vc, int c, int ypos, int xpos);
+       void    (*con_putcs)(struct vc_data *vc, const unsigned short *s,
+                       int count, int ypos, int xpos);
+-- 
+2.39.5
+
diff --git a/queue-5.15/uio_hv_generic-align-ring-size-to-system-page.patch b/queue-5.15/uio_hv_generic-align-ring-size-to-system-page.patch
new file mode 100644 (file)
index 0000000..c7e9c81
--- /dev/null
@@ -0,0 +1,41 @@
+From efb2dcd0f249a4344459fb86687f659930e0413f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 May 2025 17:56:35 -0700
+Subject: uio_hv_generic: Align ring size to system page
+
+From: Long Li <longli@microsoft.com>
+
+[ Upstream commit 0315fef2aff9f251ddef8a4b53db9187429c3553 ]
+
+Following the ring header, the ring data should align to system page
+boundary. Adjust the size if necessary.
+
+Cc: stable@vger.kernel.org
+Fixes: 95096f2fbd10 ("uio-hv-generic: new userspace i/o driver for VMBus")
+Signed-off-by: Long Li <longli@microsoft.com>
+Reviewed-by: Michael Kelley <mhklinux@outlook.com>
+Link: https://lore.kernel.org/r/1746492997-4599-4-git-send-email-longli@linuxonhyperv.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Message-ID: <1746492997-4599-4-git-send-email-longli@linuxonhyperv.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/uio/uio_hv_generic.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
+index db8a450b5a19b..865a5b289e0a5 100644
+--- a/drivers/uio/uio_hv_generic.c
++++ b/drivers/uio/uio_hv_generic.c
+@@ -260,6 +260,9 @@ hv_uio_probe(struct hv_device *dev,
+       if (!ring_size)
+               ring_size = HV_RING_SIZE * PAGE_SIZE;
++      /* Adjust ring size if necessary to have it page aligned */
++      ring_size = VMBUS_RING_SIZE(ring_size);
++
+       pdata = devm_kzalloc(&dev->device, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+-- 
+2.39.5
+
diff --git a/queue-5.15/uio_hv_generic-query-the-ringbuffer-size-for-device.patch b/queue-5.15/uio_hv_generic-query-the-ringbuffer-size-for-device.patch
new file mode 100644 (file)
index 0000000..0e1e756
--- /dev/null
@@ -0,0 +1,56 @@
+From c894da74c14c39b60fb91e24d874a06aa81ffc06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Mar 2024 01:51:58 -0700
+Subject: uio_hv_generic: Query the ringbuffer size for device
+
+From: Saurabh Sengar <ssengar@linux.microsoft.com>
+
+[ Upstream commit e566ed5b64177a0c07b677568f623ed31d23406d ]
+
+Query the ring buffer size from pre defined table per device
+and use that value for allocating the ring buffer for that
+device. Keep the size as current default which is 2 MB if
+the device doesn't have any preferred ring size.
+
+Signed-off-by: Saurabh Sengar <ssengar@linux.microsoft.com>
+Reviewed-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1711788723-8593-3-git-send-email-ssengar@linux.microsoft.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 0315fef2aff9 ("uio_hv_generic: Align ring size to system page")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/uio/uio_hv_generic.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
+index 9daa1afbf9dbf..db8a450b5a19b 100644
+--- a/drivers/uio/uio_hv_generic.c
++++ b/drivers/uio/uio_hv_generic.c
+@@ -249,6 +249,7 @@ hv_uio_probe(struct hv_device *dev,
+       struct hv_uio_private_data *pdata;
+       void *ring_buffer;
+       int ret;
++      size_t ring_size = hv_dev_ring_size(channel);
+       /* Communicating with host has to be via shared memory not hypercall */
+       if (!channel->offermsg.monitor_allocated) {
+@@ -256,12 +257,14 @@ hv_uio_probe(struct hv_device *dev,
+               return -ENOTSUPP;
+       }
++      if (!ring_size)
++              ring_size = HV_RING_SIZE * PAGE_SIZE;
++
+       pdata = devm_kzalloc(&dev->device, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+-      ret = vmbus_alloc_ring(channel, HV_RING_SIZE * PAGE_SIZE,
+-                             HV_RING_SIZE * PAGE_SIZE);
++      ret = vmbus_alloc_ring(channel, ring_size, ring_size);
+       if (ret)
+               return ret;
+-- 
+2.39.5
+
diff --git a/queue-5.15/um-add-cmpxchg8b_emu-and-checksum-functions-to-asm-p.patch b/queue-5.15/um-add-cmpxchg8b_emu-and-checksum-functions-to-asm-p.patch
new file mode 100644 (file)
index 0000000..2d81c2e
--- /dev/null
@@ -0,0 +1,55 @@
+From 326abf98af6def5132cb53ac78cf44374b197e5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Mar 2025 19:05:00 +0000
+Subject: um: Add cmpxchg8b_emu and checksum functions to asm-prototypes.h
+
+From: Sami Tolvanen <samitolvanen@google.com>
+
+[ Upstream commit 674d03f6bd6b0f8327f1a4920ff5893557facfbd ]
+
+With CONFIG_GENDWARFKSYMS, um builds fail due to missing prototypes
+in asm/asm-prototypes.h. Add declarations for cmpxchg8b_emu and the
+exported checksum functions, including csum_partial_copy_generic as
+it's also exported.
+
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: linux-kbuild@vger.kernel.org
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202503251216.lE4t9Ikj-lkp@intel.com/
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+Link: https://patch.msgid.link/20250326190500.847236-2-samitolvanen@google.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/include/asm/asm-prototypes.h | 5 +++++
+ arch/x86/um/asm/checksum.h           | 3 +++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/arch/um/include/asm/asm-prototypes.h b/arch/um/include/asm/asm-prototypes.h
+index 5898a26daa0dd..408b31d591279 100644
+--- a/arch/um/include/asm/asm-prototypes.h
++++ b/arch/um/include/asm/asm-prototypes.h
+@@ -1 +1,6 @@
+ #include <asm-generic/asm-prototypes.h>
++#include <asm/checksum.h>
++
++#ifdef CONFIG_UML_X86
++extern void cmpxchg8b_emu(void);
++#endif
+diff --git a/arch/x86/um/asm/checksum.h b/arch/x86/um/asm/checksum.h
+index b07824500363f..ddc144657efad 100644
+--- a/arch/x86/um/asm/checksum.h
++++ b/arch/x86/um/asm/checksum.h
+@@ -20,6 +20,9 @@
+  */
+ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
++/* Do not call this directly. Declared for export type visibility. */
++extern __visible __wsum csum_partial_copy_generic(const void *src, void *dst, int len);
++
+ /**
+  * csum_fold - Fold and invert a 32bit checksum.
+  * sum: 32bit unfolded sum
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-add-checks-for-snprintf-calls-in-usb_alloc_dev.patch b/queue-5.15/usb-add-checks-for-snprintf-calls-in-usb_alloc_dev.patch
new file mode 100644 (file)
index 0000000..1b91a68
--- /dev/null
@@ -0,0 +1,72 @@
+From 208b49a411d28a4d4f8d19a67b0ef71812e84941 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 18:49:49 +0200
+Subject: usb: Add checks for snprintf() calls in usb_alloc_dev()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 82fe5107fa3d21d6c3fba091c9dbc50495588630 ]
+
+When creating a device path in the driver the snprintf() takes
+up to 16 characters long argument along with the additional up to
+12 characters for the signed integer (as it can't see the actual limits)
+and tries to pack this into 16 bytes array. GCC complains about that
+when build with `make W=1`:
+
+  drivers/usb/core/usb.c:705:25: note: ‘snprintf’ output between 3 and 28 bytes into a destination of size 16
+
+Since everything works until now, let's just check for the potential
+buffer overflow and bail out. It is most likely a never happen situation,
+but at least it makes GCC happy.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20250321164949.423957-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/usb.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index ec8e003f59415..a16e7ebb7f953 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -750,15 +750,16 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+               dev_set_name(&dev->dev, "usb%d", bus->busnum);
+               root_hub = 1;
+       } else {
++              int n;
++
+               /* match any labeling on the hubs; it's one-based */
+               if (parent->devpath[0] == '0') {
+-                      snprintf(dev->devpath, sizeof dev->devpath,
+-                              "%d", port1);
++                      n = snprintf(dev->devpath, sizeof(dev->devpath), "%d", port1);
+                       /* Root ports are not counted in route string */
+                       dev->route = 0;
+               } else {
+-                      snprintf(dev->devpath, sizeof dev->devpath,
+-                              "%s.%d", parent->devpath, port1);
++                      n = snprintf(dev->devpath, sizeof(dev->devpath), "%s.%d",
++                                   parent->devpath, port1);
+                       /* Route string assumes hubs have less than 16 ports */
+                       if (port1 < 15)
+                               dev->route = parent->route +
+@@ -767,6 +768,11 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
+                               dev->route = parent->route +
+                                       (15 << ((parent->level - 1)*4));
+               }
++              if (n >= sizeof(dev->devpath)) {
++                      usb_put_hcd(bus_to_hcd(bus));
++                      usb_put_dev(dev);
++                      return NULL;
++              }
+               dev->dev.parent = &parent->dev;
+               dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-cdc-wdm-avoid-setting-wdm_read-for-zlp-s.patch b/queue-5.15/usb-cdc-wdm-avoid-setting-wdm_read-for-zlp-s.patch
new file mode 100644 (file)
index 0000000..e0a511f
--- /dev/null
@@ -0,0 +1,114 @@
+From 5a31d8b28769f062c206e0b6ad8d6aa86633c3a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Apr 2025 16:40:04 +0200
+Subject: usb: cdc-wdm: avoid setting WDM_READ for ZLP-s
+
+From: Robert Hodaszi <robert.hodaszi@digi.com>
+
+[ Upstream commit 387602d8a75574fafb451b7a8215e78dfd67ee63 ]
+
+Don't set WDM_READ flag in wdm_in_callback() for ZLP-s, otherwise when
+userspace tries to poll for available data, it might - incorrectly -
+believe there is something available, and when it tries to non-blocking
+read it, it might get stuck in the read loop.
+
+For example this is what glib does for non-blocking read (briefly):
+
+  1. poll()
+  2. if poll returns with non-zero, starts a read data loop:
+    a. loop on poll() (EINTR disabled)
+    b. if revents was set, reads data
+      I. if read returns with EINTR or EAGAIN, goto 2.a.
+      II. otherwise return with data
+
+So if ZLP sets WDM_READ (#1), we expect data, and try to read it (#2).
+But as that was a ZLP, and we are doing non-blocking read, wdm_read()
+returns with EAGAIN (#2.b.I), so loop again, and try to read again
+(#2.a.).
+
+With glib, we might stuck in this loop forever, as EINTR is disabled
+(#2.a).
+
+Signed-off-by: Robert Hodaszi <robert.hodaszi@digi.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Link: https://lore.kernel.org/r/20250403144004.3889125-1-robert.hodaszi@digi.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/class/cdc-wdm.c | 23 +++++++++--------------
+ 1 file changed, 9 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index a4be6dba756b3..4b5cf1a5e30d8 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -92,7 +92,6 @@ struct wdm_device {
+       u16                     wMaxCommand;
+       u16                     wMaxPacketSize;
+       __le16                  inum;
+-      int                     reslength;
+       int                     length;
+       int                     read;
+       int                     count;
+@@ -214,6 +213,11 @@ static void wdm_in_callback(struct urb *urb)
+       if (desc->rerr == 0 && status != -EPIPE)
+               desc->rerr = status;
++      if (length == 0) {
++              dev_dbg(&desc->intf->dev, "received ZLP\n");
++              goto skip_zlp;
++      }
++
+       if (length + desc->length > desc->wMaxCommand) {
+               /* The buffer would overflow */
+               set_bit(WDM_OVERFLOW, &desc->flags);
+@@ -222,18 +226,18 @@ static void wdm_in_callback(struct urb *urb)
+               if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       memmove(desc->ubuf + desc->length, desc->inbuf, length);
+                       desc->length += length;
+-                      desc->reslength = length;
+               }
+       }
+ skip_error:
+       if (desc->rerr) {
+               /*
+-               * Since there was an error, userspace may decide to not read
+-               * any data after poll'ing.
++               * If there was a ZLP or an error, userspace may decide to not
++               * read any data after poll'ing.
+                * We should respond to further attempts from the device to send
+                * data, so that we can get unstuck.
+                */
++skip_zlp:
+               schedule_work(&desc->service_outs_intr);
+       } else {
+               set_bit(WDM_READ, &desc->flags);
+@@ -585,15 +589,6 @@ static ssize_t wdm_read
+                       goto retry;
+               }
+-              if (!desc->reslength) { /* zero length read */
+-                      dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n");
+-                      clear_bit(WDM_READ, &desc->flags);
+-                      rv = service_outstanding_interrupt(desc);
+-                      spin_unlock_irq(&desc->iuspin);
+-                      if (rv < 0)
+-                              goto err;
+-                      goto retry;
+-              }
+               cntr = desc->length;
+               spin_unlock_irq(&desc->iuspin);
+       }
+@@ -1015,7 +1010,7 @@ static void service_interrupt_work(struct work_struct *work)
+       spin_lock_irq(&desc->iuspin);
+       service_outstanding_interrupt(desc);
+-      if (!desc->resp_count) {
++      if (!desc->resp_count && (desc->length || desc->rerr)) {
+               set_bit(WDM_READ, &desc->flags);
+               wake_up(&desc->wait);
+       }
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-common-usb-conn-gpio-use-a-unique-name-for-usb-c.patch b/queue-5.15/usb-common-usb-conn-gpio-use-a-unique-name-for-usb-c.patch
new file mode 100644 (file)
index 0000000..3b40817
--- /dev/null
@@ -0,0 +1,93 @@
+From 8c4b3e51b71d1e9198ebcaef9b7d26dfd9f69f7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Apr 2025 16:33:26 +0800
+Subject: usb: common: usb-conn-gpio: use a unique name for usb connector
+ device
+
+From: Chance Yang <chance.yang@kneron.us>
+
+[ Upstream commit d4e5b10c55627e2f3fc9e5b337a28b4e2f02a55e ]
+
+The current implementation of the usb-conn-gpio driver uses a fixed
+"usb-charger" name for all USB connector devices. This causes conflicts
+in the power supply subsystem when multiple USB connectors are present,
+as duplicate names are not allowed.
+
+Use IDA to manage unique IDs for naming usb connectors (e.g.,
+usb-charger-0, usb-charger-1).
+
+Signed-off-by: Chance Yang <chance.yang@kneron.us>
+Link: https://lore.kernel.org/r/20250411-work-next-v3-1-7cd9aa80190c@kneron.us
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/common/usb-conn-gpio.c | 25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
+index 521c95935d4c3..9691a1c8d8b0e 100644
+--- a/drivers/usb/common/usb-conn-gpio.c
++++ b/drivers/usb/common/usb-conn-gpio.c
+@@ -20,6 +20,9 @@
+ #include <linux/power_supply.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/usb/role.h>
++#include <linux/idr.h>
++
++static DEFINE_IDA(usb_conn_ida);
+ #define USB_GPIO_DEB_MS               20      /* ms */
+ #define USB_GPIO_DEB_US               ((USB_GPIO_DEB_MS) * 1000)      /* us */
+@@ -29,6 +32,7 @@
+ struct usb_conn_info {
+       struct device *dev;
++      int conn_id; /* store the IDA-allocated ID */
+       struct usb_role_switch *role_sw;
+       enum usb_role last_role;
+       struct regulator *vbus;
+@@ -160,7 +164,17 @@ static int usb_conn_psy_register(struct usb_conn_info *info)
+               .of_node = dev->of_node,
+       };
+-      desc->name = "usb-charger";
++      info->conn_id = ida_alloc(&usb_conn_ida, GFP_KERNEL);
++      if (info->conn_id < 0)
++              return info->conn_id;
++
++      desc->name = devm_kasprintf(dev, GFP_KERNEL, "usb-charger-%d",
++                                  info->conn_id);
++      if (!desc->name) {
++              ida_free(&usb_conn_ida, info->conn_id);
++              return -ENOMEM;
++      }
++
+       desc->properties = usb_charger_properties;
+       desc->num_properties = ARRAY_SIZE(usb_charger_properties);
+       desc->get_property = usb_charger_get_property;
+@@ -168,8 +182,10 @@ static int usb_conn_psy_register(struct usb_conn_info *info)
+       cfg.drv_data = info;
+       info->charger = devm_power_supply_register(dev, desc, &cfg);
+-      if (IS_ERR(info->charger))
+-              dev_err(dev, "Unable to register charger\n");
++      if (IS_ERR(info->charger)) {
++              dev_err(dev, "Unable to register charger %d\n", info->conn_id);
++              ida_free(&usb_conn_ida, info->conn_id);
++      }
+       return PTR_ERR_OR_ZERO(info->charger);
+ }
+@@ -292,6 +308,9 @@ static int usb_conn_remove(struct platform_device *pdev)
+       cancel_delayed_work_sync(&info->dw_det);
++      if (info->charger)
++              ida_free(&usb_conn_ida, info->conn_id);
++
+       if (info->last_role == USB_ROLE_HOST && info->vbus)
+               regulator_disable(info->vbus);
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-dwc2-also-exit-clock_gating-when-stopping-udc-wh.patch b/queue-5.15/usb-dwc2-also-exit-clock_gating-when-stopping-udc-wh.patch
new file mode 100644 (file)
index 0000000..e41ae6a
--- /dev/null
@@ -0,0 +1,47 @@
+From 5d6b85a8756cd6d9f584795af3136234ff15539e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Apr 2025 19:40:17 +0200
+Subject: usb: dwc2: also exit clock_gating when stopping udc while suspended
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+[ Upstream commit af076a41f8a28faf9ceb9dd2d88aef2c202ef39a ]
+
+It is possible that the gadget will be disabled, while the udc is
+suspended. When enabling the udc in that case, the clock gating
+will not be enabled again. Leaving the phy unclocked. Even when the
+udc is not enabled, connecting this powered but not clocked phy leads
+to enumeration errors on the host side.
+
+To ensure that the clock gating will be in an valid state, we ensure
+that the clock gating will be enabled before stopping the udc.
+
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Acked-by: Minas Harutyunyan <hminas@synopsys.com>
+Link: https://lore.kernel.org/r/20250417-dwc2_clock_gating-v1-1-8ea7c4d53d73@pengutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc2/gadget.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
+index 7d8523398e191..525d1d0cfc249 100644
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -4602,6 +4602,12 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
+       if (!hsotg)
+               return -ENODEV;
++      /* Exit clock gating when driver is stopped. */
++      if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
++          hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
++              dwc2_gadget_exit_clock_gating(hsotg, 0);
++      }
++
+       /* all endpoints should be shutdown */
+       for (ep = 1; ep < hsotg->num_of_eps; ep++) {
+               if (hsotg->eps_in[ep])
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-potential-integer-overflow-in-usbg_make_tpg.patch b/queue-5.15/usb-potential-integer-overflow-in-usbg_make_tpg.patch
new file mode 100644 (file)
index 0000000..d262593
--- /dev/null
@@ -0,0 +1,53 @@
+From 227c3796f4241cbf4405089c3febb0eb07a402bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Apr 2025 14:58:57 +0800
+Subject: usb: potential integer overflow in usbg_make_tpg()
+
+From: Chen Yufeng <chenyufeng@iie.ac.cn>
+
+[ Upstream commit 153874010354d050f62f8ae25cbb960c17633dc5 ]
+
+The variable tpgt in usbg_make_tpg() is defined as unsigned long and is
+assigned to tpgt->tport_tpgt, which is defined as u16. This may cause an
+integer overflow when tpgt is greater than USHRT_MAX (65535). I
+haven't tried to trigger it myself, but it is possible to trigger it
+by calling usbg_make_tpg() with a large value for tpgt.
+
+I modified the type of tpgt to match tpgt->tport_tpgt and adjusted the
+relevant code accordingly.
+
+This patch is similar to commit 59c816c1f24d ("vhost/scsi: potential
+memory corruption").
+
+Signed-off-by: Chen Yufeng <chenyufeng@iie.ac.cn>
+Link: https://lore.kernel.org/r/20250415065857.1619-1-chenyufeng@iie.ac.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/function/f_tcm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
+index 934e4b2a049ff..de54b0143894f 100644
+--- a/drivers/usb/gadget/function/f_tcm.c
++++ b/drivers/usb/gadget/function/f_tcm.c
+@@ -1321,14 +1321,14 @@ static struct se_portal_group *usbg_make_tpg(struct se_wwn *wwn,
+       struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
+                       tport_wwn);
+       struct usbg_tpg *tpg;
+-      unsigned long tpgt;
++      u16 tpgt;
+       int ret;
+       struct f_tcm_opts *opts;
+       unsigned i;
+       if (strstr(name, "tpgt_") != name)
+               return ERR_PTR(-EINVAL);
+-      if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
++      if (kstrtou16(name + 5, 0, &tpgt))
+               return ERR_PTR(-EINVAL);
+       ret = -ENODEV;
+       mutex_lock(&tpg_instances_lock);
+-- 
+2.39.5
+
diff --git a/queue-5.15/usb-typec-displayport-receive-dp-status-update-nak-r.patch b/queue-5.15/usb-typec-displayport-receive-dp-status-update-nak-r.patch
new file mode 100644 (file)
index 0000000..63a179f
--- /dev/null
@@ -0,0 +1,56 @@
+From 537924287367daad854e816569ccea65b24745c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 15:19:26 +0800
+Subject: usb: typec: displayport: Receive DP Status Update NAK request exit dp
+ altmode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jos Wang <joswang@lenovo.com>
+
+[ Upstream commit b4b38ffb38c91afd4dc387608db26f6fc34ed40b ]
+
+Although some Type-C DRD devices that do not support the DP Sink
+function (such as Huawei Mate 40Pro), the Source Port initiates
+Enter Mode CMD, but the device responds to Enter Mode ACK, the
+Source port then initiates DP Status Update CMD, and the device
+responds to DP Status Update NAK.
+
+As PD2.0 spec ("6.4.4.3.4 Enter Mode Command"),A DR_Swap Message
+Shall Not be sent during Modal Operation between the Port Partners.
+At this time, the source port initiates DR_Swap message through the
+"echo device > /sys/class/typec/port0/data_role" command to switch
+the data role from host to device. The device will initiate a Hard
+Reset for recovery, resulting in the failure of data role swap.
+
+Therefore, when DP Status Update NAK is received, Exit Mode CMD is
+initiated to exit the currently entered DP altmode.
+
+Signed-off-by: Jos Wang <joswang@lenovo.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250209071926.69625-1-joswang1221@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/altmodes/displayport.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
+index 97a912f0c4eed..c76b872535d17 100644
+--- a/drivers/usb/typec/altmodes/displayport.c
++++ b/drivers/usb/typec/altmodes/displayport.c
+@@ -298,6 +298,10 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
+               break;
+       case CMDT_RSP_NAK:
+               switch (cmd) {
++              case DP_CMD_STATUS_UPDATE:
++                      if (typec_altmode_exit(alt))
++                              dev_err(&dp->alt->dev, "Exit Mode Failed!\n");
++                      break;
+               case DP_CMD_CONFIGURE:
+                       dp->data.conf = 0;
+                       ret = dp_altmode_configured(dp);
+-- 
+2.39.5
+
diff --git a/queue-5.15/vgacon-remove-unneeded-forward-declarations.patch b/queue-5.15/vgacon-remove-unneeded-forward-declarations.patch
new file mode 100644 (file)
index 0000000..016d2c9
--- /dev/null
@@ -0,0 +1,47 @@
+From cac2ff90a438e8ca9b86bb9abc7b9d601a4d1831 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 10:59:37 +0200
+Subject: vgacon: remove unneeded forward declarations
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 6ceed69cde8fe4a78fe50d62d7a88a5c1eed4709 ]
+
+Most of the forward declarations in vgacon are not needed. Drop them.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Signed-off-by: Helge Deller <deller@gmx.de>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/console/vgacon.c | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index b2180fd183307..9bfe451050209 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -65,16 +65,8 @@ static struct vgastate vgastate;
+  *  Interface used by the world
+  */
+-static const char *vgacon_startup(void);
+-static void vgacon_init(struct vc_data *c, int init);
+-static void vgacon_deinit(struct vc_data *c);
+-static void vgacon_cursor(struct vc_data *c, int mode);
+-static int vgacon_switch(struct vc_data *c);
+-static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
+-static void vgacon_scrolldelta(struct vc_data *c, int lines);
+ static int vgacon_set_origin(struct vc_data *c);
+-static void vgacon_save_screen(struct vc_data *c);
+-static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
++
+ static struct uni_pagedict *vgacon_uni_pagedir;
+ static int vgacon_refcount;
+-- 
+2.39.5
+
diff --git a/queue-5.15/vgacon-switch-vgacon_scrolldelta-and-vgacon_restore_.patch b/queue-5.15/vgacon-switch-vgacon_scrolldelta-and-vgacon_restore_.patch
new file mode 100644 (file)
index 0000000..39a505e
--- /dev/null
@@ -0,0 +1,56 @@
+From 61e5147b93d4134d997e3d2cd6cdb47b885ab77b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 10:59:36 +0200
+Subject: vgacon: switch vgacon_scrolldelta() and vgacon_restore_screen()
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 03b89a08484a88fb9e0604cab2b3eb0c2f265c74 ]
+
+Switch vgacon_scrolldelta() and vgacon_restore_screen() positions, so
+that the former is not needed to be forward-declared.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: linux-fbdev@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Signed-off-by: Helge Deller <deller@gmx.de>
+Stable-dep-of: 03bcbbb3995b ("dummycon: Trigger redraw when switching consoles with deferred takeover")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/console/vgacon.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
+index 7bce5a174f388..b2180fd183307 100644
+--- a/drivers/video/console/vgacon.c
++++ b/drivers/video/console/vgacon.c
+@@ -163,12 +163,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
+       write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
+ }
+-static void vgacon_restore_screen(struct vc_data *c)
+-{
+-      if (c->vc_origin != c->vc_visible_origin)
+-              vgacon_scrolldelta(c, 0);
+-}
+-
+ static void vgacon_scrolldelta(struct vc_data *c, int lines)
+ {
+       vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
+@@ -176,6 +170,12 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
+       vga_set_mem_top(c);
+ }
++static void vgacon_restore_screen(struct vc_data *c)
++{
++      if (c->vc_origin != c->vc_visible_origin)
++              vgacon_scrolldelta(c, 0);
++}
++
+ static const char *vgacon_startup(void)
+ {
+       const char *display_desc = NULL;
+-- 
+2.39.5
+