--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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, ®ulator_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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+