--- /dev/null
+From 9f3b0985c30ab81282a4c487f0a4c8301a42d653 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Apr 2023 17:08:37 +0200
+Subject: ARM: dts: vexpress: add missing cache properties
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 328acc5657c6197753238d7ce0a6924ead829347 ]
+
+As all level 2 and level 3 caches are unified, add required
+cache-unified property to fix warnings like:
+
+ vexpress-v2p-ca5s.dtb: cache-controller@2c0f0000: 'cache-unified' is a required property
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20230423150837.118466-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+index 3b88209bacea2..ff1f9a1bcfcfc 100644
+--- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
++++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+@@ -132,6 +132,7 @@ L2: cache-controller@2c0f0000 {
+ reg = <0x2c0f0000 0x1000>;
+ interrupts = <0 84 4>;
+ cache-level = <2>;
++ cache-unified;
+ };
+
+ pmu {
+--
+2.39.2
+
--- /dev/null
+From 143460b76c8afe1bd7dba28a5d72129885966a35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 May 2023 14:03:42 +0300
+Subject: ASoC: dwc: move DMA init to snd_soc_dai_driver probe()
+
+From: Maxim Kochetkov <fido_max@inbox.ru>
+
+[ Upstream commit 011a8719d6105dcb48077ea7a6a88ac019d4aa50 ]
+
+When using DMA mode we are facing with Oops:
+[ 396.458157] Unable to handle kernel access to user memory without uaccess routines at virtual address 000000000000000c
+[ 396.469374] Oops [#1]
+[ 396.471839] Modules linked in:
+[ 396.475144] CPU: 0 PID: 114 Comm: arecord Not tainted 6.0.0-00164-g9a8eccdaf2be-dirty #68
+[ 396.483619] Hardware name: YMP ELCT FPGA (DT)
+[ 396.488156] epc : dmaengine_pcm_open+0x1d2/0x342
+[ 396.493227] ra : dmaengine_pcm_open+0x1d2/0x342
+[ 396.498140] epc : ffffffff807fe346 ra : ffffffff807fe346 sp : ffffffc804e138f0
+[ 396.505602] gp : ffffffff817bf730 tp : ffffffd8042c8ac0 t0 : 6500000000000000
+[ 396.513045] t1 : 0000000000000064 t2 : 656e69676e65616d s0 : ffffffc804e13990
+[ 396.520477] s1 : ffffffd801b86a18 a0 : 0000000000000026 a1 : ffffffff816920f8
+[ 396.527897] a2 : 0000000000000010 a3 : fffffffffffffffe a4 : 0000000000000000
+[ 396.535319] a5 : 0000000000000000 a6 : ffffffd801b87040 a7 : 0000000000000038
+[ 396.542740] s2 : ffffffd801b94a00 s3 : 0000000000000000 s4 : ffffffd80427f5e8
+[ 396.550153] s5 : ffffffd80427f5e8 s6 : ffffffd801b44410 s7 : fffffffffffffff5
+[ 396.557569] s8 : 0000000000000800 s9 : 0000000000000001 s10: ffffffff8066d254
+[ 396.564978] s11: ffffffd8059cf768 t3 : ffffffff817d5577 t4 : ffffffff817d5577
+[ 396.572391] t5 : ffffffff817d5578 t6 : ffffffc804e136e8
+[ 396.577876] status: 0000000200000120 badaddr: 000000000000000c cause: 000000000000000d
+[ 396.586007] [<ffffffff806839f4>] snd_soc_component_open+0x1a/0x68
+[ 396.592439] [<ffffffff807fdd62>] __soc_pcm_open+0xf0/0x502
+[ 396.598217] [<ffffffff80685d86>] soc_pcm_open+0x2e/0x4e
+[ 396.603741] [<ffffffff8066cea4>] snd_pcm_open_substream+0x442/0x68e
+[ 396.610313] [<ffffffff8066d1ea>] snd_pcm_open+0xfa/0x212
+[ 396.615868] [<ffffffff8066d39c>] snd_pcm_capture_open+0x3a/0x60
+[ 396.622048] [<ffffffff8065b35a>] snd_open+0xa8/0x17a
+[ 396.627421] [<ffffffff801ae036>] chrdev_open+0xa0/0x218
+[ 396.632893] [<ffffffff801a5a28>] do_dentry_open+0x17c/0x2a6
+[ 396.638713] [<ffffffff801a6d9a>] vfs_open+0x1e/0x26
+[ 396.643850] [<ffffffff801b8544>] path_openat+0x96e/0xc96
+[ 396.649518] [<ffffffff801b9390>] do_filp_open+0x7c/0xf6
+[ 396.655034] [<ffffffff801a6ff2>] do_sys_openat2+0x8a/0x11e
+[ 396.660765] [<ffffffff801a735a>] sys_openat+0x50/0x7c
+[ 396.666068] [<ffffffff80003aca>] ret_from_syscall+0x0/0x2
+[ 396.674964] ---[ end trace 0000000000000000 ]---
+
+It happens because of play_dma_data/capture_dma_data pointers are NULL.
+Current implementation assigns these pointers at snd_soc_dai_driver
+startup() callback and reset them back to NULL at shutdown(). But
+soc_pcm_open() sequence uses DMA pointers in dmaengine_pcm_open()
+before snd_soc_dai_driver startup().
+Most generic DMA capable I2S drivers use snd_soc_dai_driver probe()
+callback to init DMA pointers only once at probe. So move DMA init
+to dw_i2s_dai_probe and drop shutdown() and startup() callbacks.
+
+Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
+Link: https://lore.kernel.org/r/20230512110343.66664-1-fido_max@inbox.ru
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/dwc/dwc-i2s.c | 41 +++++++++--------------------------------
+ 1 file changed, 9 insertions(+), 32 deletions(-)
+
+diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c
+index 14ad8023fcdcb..feed7281ba215 100644
+--- a/sound/soc/dwc/dwc-i2s.c
++++ b/sound/soc/dwc/dwc-i2s.c
+@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
+ }
+ }
+
+-static int dw_i2s_startup(struct snd_pcm_substream *substream,
+- struct snd_soc_dai *cpu_dai)
+-{
+- struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
+- union dw_i2s_snd_dma_data *dma_data = NULL;
+-
+- if (!(dev->capability & DWC_I2S_RECORD) &&
+- (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
+- return -EINVAL;
+-
+- if (!(dev->capability & DWC_I2S_PLAY) &&
+- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
+- return -EINVAL;
+-
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- dma_data = &dev->play_dma_data;
+- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+- dma_data = &dev->capture_dma_data;
+-
+- snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
+-
+- return 0;
+-}
+-
+ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
+ {
+ u32 ch_reg;
+@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
+- struct snd_soc_dai *dai)
+-{
+- snd_soc_dai_set_dma_data(dai, substream, NULL);
+-}
+-
+ static int dw_i2s_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+ {
+@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+ }
+
+ static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
+- .startup = dw_i2s_startup,
+- .shutdown = dw_i2s_shutdown,
+ .hw_params = dw_i2s_hw_params,
+ .prepare = dw_i2s_prepare,
+ .trigger = dw_i2s_trigger,
+@@ -624,6 +592,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
+
+ }
+
++static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
++{
++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
++
++ snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
++ return 0;
++}
++
+ static int dw_i2s_probe(struct platform_device *pdev)
+ {
+ const struct i2s_platform_data *pdata = pdev->dev.platform_data;
+@@ -642,6 +618,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ dw_i2s_dai->ops = &dw_i2s_dai_ops;
++ dw_i2s_dai->probe = dw_i2s_dai_probe;
+
+ dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(dev->i2s_base))
+--
+2.39.2
+
--- /dev/null
+From fe5b21d5745653ff5c9732a6b60212e40a921163 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 May 2023 13:57:31 -0500
+Subject: ASoC: soc-pcm: test if a BE can be prepared
+
+From: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+
+[ Upstream commit e123036be377ddf628226a7c6d4f9af5efd113d3 ]
+
+In the BE hw_params configuration, the existing code checks if any of the
+existing FEs are prepared, running, paused or suspended - and skips the
+configuration in those cases. This allows multiple calls of hw_params
+which the ALSA state machine supports.
+
+This check is not handled for the prepare stage, which can lead to the
+same BE being prepared multiple times. This patch adds a check similar to
+that of the hw_params, with the main difference being that the suspended
+state is allowed: the ALSA state machine allows a transition from
+suspended to prepared with hw_params skipped.
+
+This problem was detected on Intel IPC4/SoundWire devices, where the BE
+dailink .prepare stage is used to configure the SoundWire stream with a
+bank switch. Multiple .prepare calls lead to conflicts with the .trigger
+operation with IPC4 configurations. This problem was not detected earlier
+on Intel devices, HDaudio BE dailinks detect that the link is already
+prepared and skip the configuration, and for IPC3 devices there is no BE
+trigger.
+
+Link: https://github.com/thesofproject/sof/issues/7596
+Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com
+Link: https://lore.kernel.org/r/20230517185731.487124-1-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/sound/soc-dpcm.h | 4 ++++
+ sound/soc/soc-pcm.c | 20 ++++++++++++++++++++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
+index d963f3b608489..4bb3ebfdaa45e 100644
+--- a/include/sound/soc-dpcm.h
++++ b/include/sound/soc-dpcm.h
+@@ -123,6 +123,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
+ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
+ struct snd_soc_pcm_runtime *be, int stream);
+
++/* can this BE perform prepare */
++int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
++ struct snd_soc_pcm_runtime *be, int stream);
++
+ /* is the current PCM operation for this FE ? */
+ int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
+
+diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
+index 76c807372ef50..6ec248778e2fc 100644
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -2398,6 +2398,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
+ if (!snd_soc_dpcm_be_can_update(fe, be, stream))
+ continue;
+
++ if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
++ continue;
++
+ if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
+@@ -3047,3 +3050,20 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
+ return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
++
++/*
++ * We can only prepare a BE DAI if any of it's FE are not prepared,
++ * running or paused for the specified stream direction.
++ */
++int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
++ struct snd_soc_pcm_runtime *be, int stream)
++{
++ const enum snd_soc_dpcm_state state[] = {
++ SND_SOC_DPCM_STATE_START,
++ SND_SOC_DPCM_STATE_PAUSED,
++ SND_SOC_DPCM_STATE_PREPARE,
++ };
++
++ return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
++}
++EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);
+--
+2.39.2
+
--- /dev/null
+From 02f0db41f18925218848b4f58694ae9980b37622 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 May 2023 13:58:13 +0200
+Subject: btrfs: handle memory allocation failure in btrfs_csum_one_bio
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+[ Upstream commit 806570c0bb7b4847828c22c4934fcf2dc8fc572f ]
+
+Since f8a53bb58ec7 ("btrfs: handle checksum generation in the storage
+layer") the failures of btrfs_csum_one_bio() are handled via
+bio_end_io().
+
+This means, we can return BLK_STS_RESOURCE from btrfs_csum_one_bio() in
+case the allocation of the ordered sums fails.
+
+This also fixes a syzkaller report, where injecting a failure into the
+kvzalloc() call results in a BUG_ON().
+
+Reported-by: syzbot+d8941552e21eac774778@syzkaller.appspotmail.com
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/file-item.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
+index dd8b02a2a14a0..4c210b2ac6994 100644
+--- a/fs/btrfs/file-item.c
++++ b/fs/btrfs/file-item.c
+@@ -700,7 +700,9 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
+ sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
+ bytes_left), GFP_KERNEL);
+ memalloc_nofs_restore(nofs_flag);
+- BUG_ON(!sums); /* -ENOMEM */
++ if (!sums)
++ return BLK_STS_RESOURCE;
++
+ sums->len = bytes_left;
+ ordered = btrfs_lookup_ordered_extent(inode,
+ offset);
+--
+2.39.2
+
--- /dev/null
+From d7c2b1c5ea6f251045821698f4a7dd49fabc04ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Apr 2023 13:57:17 +0800
+Subject: btrfs: scrub: try harder to mark RAID56 block groups read-only
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 7561551e7ba870b9659083b95feb520fb2dacce3 ]
+
+Currently we allow a block group not to be marked read-only for scrub.
+
+But for RAID56 block groups if we require the block group to be
+read-only, then we're allowed to use cached content from scrub stripe to
+reduce unnecessary RAID56 reads.
+
+So this patch would:
+
+- Make btrfs_inc_block_group_ro() try harder
+ During my tests, for cases like btrfs/061 and btrfs/064, we can hit
+ ENOSPC from btrfs_inc_block_group_ro() calls during scrub.
+
+ The reason is if we only have one single data chunk, and trying to
+ scrub it, we won't have any space left for any newer data writes.
+
+ But this check should be done by the caller, especially for scrub
+ cases we only temporarily mark the chunk read-only.
+ And newer data writes would always try to allocate a new data chunk
+ when needed.
+
+- Return error for scrub if we failed to mark a RAID56 chunk read-only
+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/block-group.c | 14 ++++++++++++--
+ fs/btrfs/scrub.c | 9 ++++++++-
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index 19f71c305b988..a76796f153d5f 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -2576,10 +2576,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
+ }
+
+ ret = inc_block_group_ro(cache, 0);
+- if (!do_chunk_alloc || ret == -ETXTBSY)
+- goto unlock_out;
+ if (!ret)
+ goto out;
++ if (ret == -ETXTBSY)
++ goto unlock_out;
++
++ /*
++ * Skip chunk alloction if the bg is SYSTEM, this is to avoid system
++ * chunk allocation storm to exhaust the system chunk array. Otherwise
++ * we still want to try our best to mark the block group read-only.
++ */
++ if (!do_chunk_alloc && ret == -ENOSPC &&
++ (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
++ goto unlock_out;
++
+ alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
+ ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
+ if (ret < 0)
+diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
+index ca8d6979c7887..0d1715ebdef9c 100644
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -3812,13 +3812,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
+
+ if (ret == 0) {
+ ro_set = 1;
+- } else if (ret == -ENOSPC && !sctx->is_dev_replace) {
++ } else if (ret == -ENOSPC && !sctx->is_dev_replace &&
++ !(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
+ /*
+ * btrfs_inc_block_group_ro return -ENOSPC when it
+ * failed in creating new chunk for metadata.
+ * It is not a problem for scrub, because
+ * metadata are always cowed, and our scrub paused
+ * commit_transactions.
++ *
++ * For RAID56 chunks, we have to mark them read-only
++ * for scrub, as later we would use our own cache
++ * out of RAID56 realm.
++ * Thus we want the RAID56 bg to be marked RO to
++ * prevent RMW from screwing up out cache.
+ */
+ ro_set = 0;
+ } else if (ret == -ETXTBSY) {
+--
+2.39.2
+
--- /dev/null
+From e59b56dcb8fd2ff4b9ed5816a041f173d37375bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 May 2023 16:15:07 -0700
+Subject: drm:amd:amdgpu: Fix missing buffer object unlock in failure path
+
+From: Sukrut Bellary <sukrut.bellary@linux.com>
+
+[ Upstream commit 60ecaaf54886b0642d5c4744f7fbf1ff0d6b3e42 ]
+
+smatch warning -
+1) drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c:3615 gfx_v9_0_kiq_resume()
+warn: inconsistent returns 'ring->mqd_obj->tbo.base.resv'.
+
+2) drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c:6901 gfx_v10_0_kiq_resume()
+warn: inconsistent returns 'ring->mqd_obj->tbo.base.resv'.
+
+Signed-off-by: Sukrut Bellary <sukrut.bellary@linux.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 +++-
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index 9da0d5d6d73d8..938f13956aeef 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -7197,8 +7197,10 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev)
+ return r;
+
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
+- if (unlikely(r != 0))
++ if (unlikely(r != 0)) {
++ amdgpu_bo_unreserve(ring->mqd_obj);
+ return r;
++ }
+
+ gfx_v10_0_kiq_init_queue(ring);
+ amdgpu_bo_kunmap(ring->mqd_obj);
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 5f325ded7f752..de1fab165041f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -3871,8 +3871,10 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev)
+ return r;
+
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
+- if (unlikely(r != 0))
++ if (unlikely(r != 0)) {
++ amdgpu_bo_unreserve(ring->mqd_obj);
+ return r;
++ }
+
+ gfx_v9_0_kiq_init_queue(ring);
+ amdgpu_bo_kunmap(ring->mqd_obj);
+--
+2.39.2
+
--- /dev/null
+From 6dea94272466fc7fa767aa26c678ea782bd96ff1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 May 2023 11:01:22 +0100
+Subject: irqchip/gic: Correctly validate OF quirk descriptors
+
+From: Marc Zyngier <maz@kernel.org>
+
+[ Upstream commit 91539341a3b6e9c868024a4292455dae36e6f58c ]
+
+When checking for OF quirks, make sure either 'compatible' or 'property'
+is set, and give up otherwise.
+
+This avoids non-OF quirks being randomly applied as they don't have any
+of the OF data that need checking.
+
+Cc: Douglas Anderson <dianders@chromium.org>
+Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Fixes: 44bd78dd2b88 ("irqchip/gic-v3: Disable pseudo NMIs on Mediatek devices w/ firmware issues")
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-gic-common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
+index de47b51cdadbe..afd6a1841715a 100644
+--- a/drivers/irqchip/irq-gic-common.c
++++ b/drivers/irqchip/irq-gic-common.c
+@@ -16,6 +16,8 @@ void gic_enable_of_quirks(const struct device_node *np,
+ const struct gic_quirk *quirks, void *data)
+ {
+ for (; quirks->desc; quirks++) {
++ if (!quirks->compatible && !quirks->property)
++ continue;
+ if (quirks->compatible &&
+ !of_device_is_compatible(np, quirks->compatible))
+ continue;
+--
+2.39.2
+
--- /dev/null
+From 44176898974e548e21e8c7b355cf1baa45e4f066 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 May 2023 13:13:51 -0700
+Subject: irqchip/gic-v3: Disable pseudo NMIs on Mediatek devices w/ firmware
+ issues
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 44bd78dd2b8897f59b7e3963f088caadb7e4f047 ]
+
+Some Chromebooks with Mediatek SoCs have a problem where the firmware
+doesn't properly save/restore certain GICR registers. Newer
+Chromebooks should fix this issue and we may be able to do firmware
+updates for old Chromebooks. At the moment, the only known issue with
+these Chromebooks is that we can't enable "pseudo NMIs" since the
+priority register can be lost. Enabling "pseudo NMIs" on Chromebooks
+with the problematic firmware causes crashes and freezes.
+
+Let's detect devices with this problem and then disable "pseudo NMIs"
+on them. We'll detect the problem by looking for the presence of the
+"mediatek,broken-save-restore-fw" property in the GIC device tree
+node. Any devices with fixed firmware will not have this property.
+
+Our detection plan works because we never bake a Chromebook's device
+tree into firmware. Instead, device trees are always bundled with the
+kernel. We'll update the device trees of all affected Chromebooks and
+then we'll never enable "pseudo NMI" on a kernel that is bundled with
+old device trees. When a firmware update is shipped that fixes this
+issue it will know to patch the device tree to remove the property.
+
+In order to make this work, the quick detection mechanism of the GICv3
+code is extended to be able to look for properties in addition to
+looking at "compatible".
+
+Reviewed-by: Julius Werner <jwerner@chromium.org>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230515131353.v2.2.I88dc0a0eb1d9d537de61604cd8994ecc55c0cac1@changeid
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-gic-common.c | 8 ++++++--
+ drivers/irqchip/irq-gic-common.h | 1 +
+ drivers/irqchip/irq-gic-v3.c | 20 ++++++++++++++++++++
+ 3 files changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
+index a610821c8ff2a..de47b51cdadbe 100644
+--- a/drivers/irqchip/irq-gic-common.c
++++ b/drivers/irqchip/irq-gic-common.c
+@@ -16,7 +16,11 @@ void gic_enable_of_quirks(const struct device_node *np,
+ const struct gic_quirk *quirks, void *data)
+ {
+ for (; quirks->desc; quirks++) {
+- if (!of_device_is_compatible(np, quirks->compatible))
++ if (quirks->compatible &&
++ !of_device_is_compatible(np, quirks->compatible))
++ continue;
++ if (quirks->property &&
++ !of_property_read_bool(np, quirks->property))
+ continue;
+ if (quirks->init(data))
+ pr_info("GIC: enabling workaround for %s\n",
+@@ -28,7 +32,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
+ void *data)
+ {
+ for (; quirks->desc; quirks++) {
+- if (quirks->compatible)
++ if (quirks->compatible || quirks->property)
+ continue;
+ if (quirks->iidr != (quirks->mask & iidr))
+ continue;
+diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
+index 27e3d4ed4f328..3db4592cda1c0 100644
+--- a/drivers/irqchip/irq-gic-common.h
++++ b/drivers/irqchip/irq-gic-common.h
+@@ -13,6 +13,7 @@
+ struct gic_quirk {
+ const char *desc;
+ const char *compatible;
++ const char *property;
+ bool (*init)(void *data);
+ u32 iidr;
+ u32 mask;
+diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
+index 9507989bf2e1e..500e0c6d17f61 100644
+--- a/drivers/irqchip/irq-gic-v3.c
++++ b/drivers/irqchip/irq-gic-v3.c
+@@ -35,6 +35,7 @@
+
+ #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0)
+ #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1)
++#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2)
+
+ #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
+
+@@ -1646,6 +1647,15 @@ static bool gic_enable_quirk_msm8996(void *data)
+ return true;
+ }
+
++static bool gic_enable_quirk_mtk_gicr(void *data)
++{
++ struct gic_chip_data *d = data;
++
++ d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
++
++ return true;
++}
++
+ static bool gic_enable_quirk_cavium_38539(void *data)
+ {
+ struct gic_chip_data *d = data;
+@@ -1681,6 +1691,11 @@ static const struct gic_quirk gic_quirks[] = {
+ .compatible = "qcom,msm8996-gic-v3",
+ .init = gic_enable_quirk_msm8996,
+ },
++ {
++ .desc = "GICv3: Mediatek Chromebook GICR save problem",
++ .property = "mediatek,broken-save-restore-fw",
++ .init = gic_enable_quirk_mtk_gicr,
++ },
+ {
+ .desc = "GICv3: HIP06 erratum 161010803",
+ .iidr = 0x0204043b,
+@@ -1717,6 +1732,11 @@ static void gic_enable_nmi_support(void)
+ if (!gic_prio_masking_enabled())
+ return;
+
++ if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
++ pr_warn("Skipping NMI enable due to firmware issues\n");
++ return;
++ }
++
+ ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
+ if (!ppi_nmi_refs)
+ return;
+--
+2.39.2
+
--- /dev/null
+From 27317503f6557c8a9a1cabb5771df8fe9e7115fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 May 2023 17:30:10 +0200
+Subject: MIPS: Alchemy: fix dbdma2
+
+From: Manuel Lauss <manuel.lauss@gmail.com>
+
+[ Upstream commit 2d645604f69f3a772d58ead702f9a8e84ab2b342 ]
+
+Various fixes for the Au1200/Au1550/Au1300 DBDMA2 code:
+
+- skip cache invalidation if chip has working coherency circuitry.
+- invalidate KSEG0-portion of the (physical) data address.
+- force the dma channel doorbell write out to bus immediately with
+ a sync.
+
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/alchemy/common/dbdma.c | 27 +++++++++++++++------------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
+index 4ca2c28878e0f..e9ee9ab90a0c6 100644
+--- a/arch/mips/alchemy/common/dbdma.c
++++ b/arch/mips/alchemy/common/dbdma.c
+@@ -30,6 +30,7 @@
+ *
+ */
+
++#include <linux/dma-map-ops.h> /* for dma_default_coherent */
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+@@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
+ dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
+
+ /*
+- * There is an errata on the Au1200/Au1550 parts that could result
+- * in "stale" data being DMA'ed. It has to do with the snoop logic on
+- * the cache eviction buffer. DMA_NONCOHERENT is on by default for
+- * these parts. If it is fixed in the future, these dma_cache_inv will
+- * just be nothing more than empty macros. See io.h.
++ * There is an erratum on certain Au1200/Au1550 revisions that could
++ * result in "stale" data being DMA'ed. It has to do with the snoop
++ * logic on the cache eviction buffer. dma_default_coherent is set
++ * to false on these parts.
+ */
+- dma_cache_wback_inv((unsigned long)buf, nbytes);
++ if (!dma_default_coherent)
++ dma_cache_wback_inv(KSEG0ADDR(buf), nbytes);
+ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
+ wmb(); /* drain writebuffer */
+ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
+ ctp->chan_ptr->ddma_dbell = 0;
++ wmb(); /* force doorbell write out to dma engine */
+
+ /* Get next descriptor pointer. */
+ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+@@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
+ dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
+ #endif
+ /*
+- * There is an errata on the Au1200/Au1550 parts that could result in
+- * "stale" data being DMA'ed. It has to do with the snoop logic on the
+- * cache eviction buffer. DMA_NONCOHERENT is on by default for these
+- * parts. If it is fixed in the future, these dma_cache_inv will just
+- * be nothing more than empty macros. See io.h.
++ * There is an erratum on certain Au1200/Au1550 revisions that could
++ * result in "stale" data being DMA'ed. It has to do with the snoop
++ * logic on the cache eviction buffer. dma_default_coherent is set
++ * to false on these parts.
+ */
+- dma_cache_inv((unsigned long)buf, nbytes);
++ if (!dma_default_coherent)
++ dma_cache_inv(KSEG0ADDR(buf), nbytes);
+ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
+ wmb(); /* drain writebuffer */
+ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
+ ctp->chan_ptr->ddma_dbell = 0;
++ wmb(); /* force doorbell write out to dma engine */
+
+ /* Get next descriptor pointer. */
+ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+--
+2.39.2
+
--- /dev/null
+From cbe822196fef848840b99eef7036f75d8cfe5444 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 May 2023 18:29:21 +0100
+Subject: mips: Move initrd_start check after initrd address sanitisation.
+
+From: Liviu Dudau <liviu@dudau.co.uk>
+
+[ Upstream commit 4897a898a216058dec55e5e5902534e6e224fcdf ]
+
+PAGE_OFFSET is technically a virtual address so when checking the value of
+initrd_start against it we should make sure that it has been sanitised from
+the values passed by the bootloader. Without this change, even with a bootloader
+that passes correct addresses for an initrd, we are failing to load it on MT7621
+boards, for example.
+
+Signed-off-by: Liviu Dudau <liviu@dudau.co.uk>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/kernel/setup.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
+index ef73ba1e0ec10..c8d849d8a8440 100644
+--- a/arch/mips/kernel/setup.c
++++ b/arch/mips/kernel/setup.c
+@@ -156,10 +156,6 @@ static unsigned long __init init_initrd(void)
+ pr_err("initrd start must be page aligned\n");
+ goto disable;
+ }
+- if (initrd_start < PAGE_OFFSET) {
+- pr_err("initrd start < PAGE_OFFSET\n");
+- goto disable;
+- }
+
+ /*
+ * Sanitize initrd addresses. For example firmware
+@@ -172,6 +168,11 @@ static unsigned long __init init_initrd(void)
+ initrd_end = (unsigned long)__va(end);
+ initrd_start = (unsigned long)__va(__pa(initrd_start));
+
++ if (initrd_start < PAGE_OFFSET) {
++ pr_err("initrd start < PAGE_OFFSET\n");
++ goto disable;
++ }
++
+ ROOT_DEV = Root_RAM0;
+ return PFN_UP(end);
+ disable:
+--
+2.39.2
+
--- /dev/null
+From 599caaf5f2a1b25fdb4bdd5dc4221d576aa90f97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 May 2023 12:33:23 +0200
+Subject: MIPS: Restore Au1300 support
+
+From: Manuel Lauss <manuel.lauss@gmail.com>
+
+[ Upstream commit f2041708dee30a3425f680265c337acd28293782 ]
+
+The Au1300, at least the one I have to test, uses the NetLogic vendor
+ID, but commit 95b8a5e0111a ("MIPS: Remove NETLOGIC support") also
+dropped Au1300 detection. Restore Au1300 detection.
+
+Tested on DB1300 with Au1380 chip.
+
+Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/kernel/cpu-probe.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
+index 7c861e6a89529..df40880d84495 100644
+--- a/arch/mips/kernel/cpu-probe.c
++++ b/arch/mips/kernel/cpu-probe.c
+@@ -1565,6 +1565,10 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
+ break;
+ }
+ break;
++ case PRID_IMP_NETLOGIC_AU13XX:
++ c->cputype = CPU_ALCHEMY;
++ __cpu_name[cpu] = "Au1300";
++ break;
+ }
+ }
+
+@@ -2005,6 +2009,7 @@ void cpu_probe(void)
+ cpu_probe_mips(c, cpu);
+ break;
+ case PRID_COMP_ALCHEMY:
++ case PRID_COMP_NETLOGIC:
+ cpu_probe_alchemy(c, cpu);
+ break;
+ case PRID_COMP_SIBYTE:
+--
+2.39.2
+
--- /dev/null
+From d00e455d39ceb63f1b559af7a0921c1756f356a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 May 2023 20:57:44 +0200
+Subject: MIPS: unhide PATA_PLATFORM
+
+From: Manuel Lauss <manuel.lauss@gmail.com>
+
+[ Upstream commit 75b18aac6fa39a1720677970cfcb52ecea1eb44c ]
+
+Alchemy DB1200/DB1300 boards can use the pata_platform driver.
+Unhide the config entry in all of MIPS.
+
+Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 393eb2133243f..56c0f75e7a76e 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -81,6 +81,7 @@ config MIPS
+ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
+ select HAVE_MOD_ARCH_SPECIFIC
+ select HAVE_NMI
++ select HAVE_PATA_PLATFORM
+ select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
+--
+2.39.2
+
--- /dev/null
+From 93c620734425f98aae0cb794f4aa53c0e5b0514c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 May 2023 21:23:50 +0900
+Subject: NVMe: Add MAXIO 1602 to bogus nid list.
+
+From: Tatsuki Sugiura <sugi@nemui.org>
+
+[ Upstream commit a3a9d63dcd15535e7fdf4c7c1b32bfaed762973a ]
+
+HIKSEMI FUTURE M.2 SSD uses the same dummy nguid and eui64.
+I confirmed it with my two devices.
+
+This patch marks the controller as NVME_QUIRK_BOGUS_NID.
+
+---------------------------------------------------------
+sugi@tempest:~% sudo nvme id-ctrl /dev/nvme0
+NVME Identify Controller:
+vid : 0x1e4b
+ssvid : 0x1e4b
+sn : 30096022612
+mn : HS-SSD-FUTURE 2048G
+fr : SN10542
+rab : 0
+ieee : 000000
+cmic : 0
+mdts : 7
+cntlid : 0
+ver : 0x10400
+rtd3r : 0x7a120
+rtd3e : 0x1e8480
+oaes : 0x200
+ctratt : 0x2
+rrls : 0
+cntrltype : 1
+fguid : 00000000-0000-0000-0000-000000000000
+<snip...>
+---------------------------------------------------------
+
+---------------------------------------------------------
+sugi@tempest:~% sudo nvme id-ns /dev/nvme0n1
+NVME Identify Namespace 1:
+<snip...>
+nguid : 00000000000000000000000000000000
+eui64 : 0000000000000002
+lbaf 0 : ms:0 lbads:9 rp:0 (in use)
+---------------------------------------------------------
+
+Signed-off-by: Tatsuki Sugiura <sugi@nemui.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index d04c06e07fbb2..a646757f76b34 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3390,6 +3390,8 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
++ { PCI_DEVICE(0x1e4B, 0x1602), /* MAXIO MAP1602 */
++ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1cc1, 0x5350), /* ADATA XPG GAMMIX S50 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1e49, 0x0021), /* ZHITAI TiPro5000 NVMe SSD */
+--
+2.39.2
+
--- /dev/null
+From ce327b8514a21adc4de6c53d04d328fe25d1b7ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Jun 2023 11:05:02 +0900
+Subject: of: overlay: Fix missing of_node_put() in error case of
+ init_overlay_changeset()
+
+From: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+[ Upstream commit 39affd1fdf65983904fafc07cf607cff737eaf30 ]
+
+In init_overlay_changeset(), the variable "node" is from
+of_get_child_by_name(), and the "node" should be discarded in error case.
+
+Fixes: d1651b03c2df ("of: overlay: add overlay symbols to live device tree")
+Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+Link: https://lore.kernel.org/r/20230602020502.11693-1-hayashi.kunihiko@socionext.com
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/overlay.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 119dd6a0be868..74dd63089bb46 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -818,6 +818,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs)
+ if (!fragment->target) {
+ pr_err("symbols in overlay, but not in live tree\n");
+ ret = -EINVAL;
++ of_node_put(node);
+ goto err_out;
+ }
+
+--
+2.39.2
+
--- /dev/null
+From bf1f19542d9f57e34cc0f34ce805161b05b3e66b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Apr 2022 17:25:04 -0500
+Subject: of: overlay: rename variables to be consistent
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+[ Upstream commit 1e4089667c7c732dd1b92c4c6bc7bd240ca30213 ]
+
+Variables change name across function calls when there is not a good
+reason to do so. Fix by changing "fdt" to "new_fdt" and "tree" to
+"overlay_root".
+
+The name disparity was confusing when creating the following commit.
+The name changes are in this separate commit to make review of the
+following commmit less complex.
+
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20220420222505.928492-2-frowand.list@gmail.com
+Stable-dep-of: 39affd1fdf65 ("of: overlay: Fix missing of_node_put() in error case of init_overlay_changeset()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/overlay.c | 94 ++++++++++++++++++++++----------------------
+ 1 file changed, 47 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 424682372417d..56afef5594112 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -57,8 +57,8 @@ struct fragment {
+ * struct overlay_changeset
+ * @id: changeset identifier
+ * @ovcs_list: list on which we are located
+- * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @overlay_tree
+- * @overlay_tree: expanded device tree that contains the fragment nodes
++ * @new_fdt: Memory allocated to hold unflattened aligned FDT
++ * @overlay_root: expanded device tree that contains the fragment nodes
+ * @count: count of fragment structures
+ * @fragments: fragment nodes in the overlay expanded device tree
+ * @symbols_fragment: last element of @fragments[] is the __symbols__ node
+@@ -67,8 +67,8 @@ struct fragment {
+ struct overlay_changeset {
+ int id;
+ struct list_head ovcs_list;
+- const void *fdt;
+- struct device_node *overlay_tree;
++ const void *new_fdt;
++ struct device_node *overlay_root;
+ int count;
+ struct fragment *fragments;
+ bool symbols_fragment;
+@@ -183,7 +183,7 @@ static int overlay_notify(struct overlay_changeset *ovcs,
+
+ /*
+ * The values of properties in the "/__symbols__" node are paths in
+- * the ovcs->overlay_tree. When duplicating the properties, the paths
++ * the ovcs->overlay_root. When duplicating the properties, the paths
+ * need to be adjusted to be the correct path for the live device tree.
+ *
+ * The paths refer to a node in the subtree of a fragment node's "__overlay__"
+@@ -219,7 +219,7 @@ static struct property *dup_and_fixup_symbol_prop(
+
+ if (path_len < 1)
+ return NULL;
+- fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1);
++ fragment_node = __of_find_node_by_path(ovcs->overlay_root, path + 1);
+ overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/");
+ of_node_put(fragment_node);
+ of_node_put(overlay_node);
+@@ -716,19 +716,20 @@ static struct device_node *find_target(struct device_node *info_node)
+
+ /**
+ * init_overlay_changeset() - initialize overlay changeset from overlay tree
+- * @ovcs: Overlay changeset to build
+- * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @tree
+- * @tree: Contains the overlay fragments and overlay fixup nodes
++ * @ovcs: Overlay changeset to build
++ * @new_fdt: Memory allocated to hold unflattened aligned FDT
++ * @overlay_root: Contains the overlay fragments and overlay fixup nodes
+ *
+ * Initialize @ovcs. Populate @ovcs->fragments with node information from
+- * the top level of @tree. The relevant top level nodes are the fragment
+- * nodes and the __symbols__ node. Any other top level node will be ignored.
++ * the top level of @overlay_root. The relevant top level nodes are the
++ * fragment nodes and the __symbols__ node. Any other top level node will
++ * be ignored.
+ *
+ * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
+- * detected in @tree, or -ENOSPC if idr_alloc() error.
++ * detected in @overlay_root, or -ENOSPC if idr_alloc() error.
+ */
+ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+- const void *fdt, struct device_node *tree)
++ const void *new_fdt, struct device_node *overlay_root)
+ {
+ struct device_node *node, *overlay_node;
+ struct fragment *fragment;
+@@ -739,17 +740,17 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ * Warn for some issues. Can not return -EINVAL for these until
+ * of_unittest_apply_overlay() is fixed to pass these checks.
+ */
+- if (!of_node_check_flag(tree, OF_DYNAMIC))
+- pr_debug("%s() tree is not dynamic\n", __func__);
++ if (!of_node_check_flag(overlay_root, OF_DYNAMIC))
++ pr_debug("%s() overlay_root is not dynamic\n", __func__);
+
+- if (!of_node_check_flag(tree, OF_DETACHED))
+- pr_debug("%s() tree is not detached\n", __func__);
++ if (!of_node_check_flag(overlay_root, OF_DETACHED))
++ pr_debug("%s() overlay_root is not detached\n", __func__);
+
+- if (!of_node_is_root(tree))
+- pr_debug("%s() tree is not root\n", __func__);
++ if (!of_node_is_root(overlay_root))
++ pr_debug("%s() overlay_root is not root\n", __func__);
+
+- ovcs->overlay_tree = tree;
+- ovcs->fdt = fdt;
++ ovcs->overlay_root = overlay_root;
++ ovcs->new_fdt = new_fdt;
+
+ INIT_LIST_HEAD(&ovcs->ovcs_list);
+
+@@ -762,7 +763,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ cnt = 0;
+
+ /* fragment nodes */
+- for_each_child_of_node(tree, node) {
++ for_each_child_of_node(overlay_root, node) {
+ overlay_node = of_get_child_by_name(node, "__overlay__");
+ if (overlay_node) {
+ cnt++;
+@@ -770,7 +771,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ }
+ }
+
+- node = of_get_child_by_name(tree, "__symbols__");
++ node = of_get_child_by_name(overlay_root, "__symbols__");
+ if (node) {
+ cnt++;
+ of_node_put(node);
+@@ -783,7 +784,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ }
+
+ cnt = 0;
+- for_each_child_of_node(tree, node) {
++ for_each_child_of_node(overlay_root, node) {
+ overlay_node = of_get_child_by_name(node, "__overlay__");
+ if (!overlay_node)
+ continue;
+@@ -805,7 +806,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ * if there is a symbols fragment in ovcs->fragments[i] it is
+ * the final element in the array
+ */
+- node = of_get_child_by_name(tree, "__symbols__");
++ node = of_get_child_by_name(overlay_root, "__symbols__");
+ if (node) {
+ ovcs->symbols_fragment = 1;
+ fragment = &fragments[cnt];
+@@ -859,12 +860,12 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ }
+ kfree(ovcs->fragments);
+ /*
+- * There should be no live pointers into ovcs->overlay_tree and
+- * ovcs->fdt due to the policy that overlay notifiers are not allowed
+- * to retain pointers into the overlay devicetree.
++ * There should be no live pointers into ovcs->overlay_root and
++ * ovcs->new_fdt due to the policy that overlay notifiers are not
++ * allowed to retain pointers into the overlay devicetree.
+ */
+- kfree(ovcs->overlay_tree);
+- kfree(ovcs->fdt);
++ kfree(ovcs->overlay_root);
++ kfree(ovcs->new_fdt);
+ kfree(ovcs);
+ }
+
+@@ -872,16 +873,15 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ * internal documentation
+ *
+ * of_overlay_apply() - Create and apply an overlay changeset
+- * @fdt: base of memory allocated to hold the aligned FDT
+- * @tree: Expanded overlay device tree
+- * @ovcs_id: Pointer to overlay changeset id
++ * @new_fdt: Memory allocated to hold the aligned FDT
++ * @overlay_root: Expanded overlay device tree
++ * @ovcs_id: Pointer to overlay changeset id
+ *
+ * Creates and applies an overlay changeset.
+ *
+ * If an error occurs in a pre-apply notifier, then no changes are made
+ * to the device tree.
+ *
+-
+ * A non-zero return value will not have created the changeset if error is from:
+ * - parameter checks
+ * - building the changeset
+@@ -911,8 +911,8 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ * id is returned to *ovcs_id.
+ */
+
+-static int of_overlay_apply(const void *fdt, struct device_node *tree,
+- int *ovcs_id)
++static int of_overlay_apply(const void *new_fdt,
++ struct device_node *overlay_root, int *ovcs_id)
+ {
+ struct overlay_changeset *ovcs;
+ int ret = 0, ret_revert, ret_tmp;
+@@ -924,16 +924,16 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
+
+ if (devicetree_corrupt()) {
+ pr_err("devicetree state suspect, refuse to apply overlay\n");
+- kfree(fdt);
+- kfree(tree);
++ kfree(new_fdt);
++ kfree(overlay_root);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
+ if (!ovcs) {
+- kfree(fdt);
+- kfree(tree);
++ kfree(new_fdt);
++ kfree(overlay_root);
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -941,20 +941,20 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
+ of_overlay_mutex_lock();
+ mutex_lock(&of_mutex);
+
+- ret = of_resolve_phandles(tree);
++ ret = of_resolve_phandles(overlay_root);
+ if (ret)
+ goto err_free_tree;
+
+- ret = init_overlay_changeset(ovcs, fdt, tree);
++ ret = init_overlay_changeset(ovcs, new_fdt, overlay_root);
+ if (ret)
+ goto err_free_tree;
+
+ /*
+- * after overlay_notify(), ovcs->overlay_tree related pointers may have
++ * After overlay_notify(), ovcs->overlay_root related pointers may have
+ * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree;
+ * and can not free memory containing aligned fdt. The aligned fdt
+- * is contained within the memory at ovcs->fdt, possibly at an offset
+- * from ovcs->fdt.
++ * is contained within the memory at ovcs->new_fdt, possibly at an
++ * offset from ovcs->new_fdt.
+ */
+ ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
+ if (ret) {
+@@ -996,8 +996,8 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
+ goto out_unlock;
+
+ err_free_tree:
+- kfree(fdt);
+- kfree(tree);
++ kfree(new_fdt);
++ kfree(overlay_root);
+
+ err_free_overlay_changeset:
+ free_overlay_changeset(ovcs);
+--
+2.39.2
+
--- /dev/null
+From b25174708f96e76a1f72ddf249a00a545ea42561 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Apr 2022 17:25:05 -0500
+Subject: of: overlay: rework overlay apply and remove kfree()s
+
+From: Frank Rowand <frank.rowand@sony.com>
+
+[ Upstream commit 067c098766c6af667a9002d4e33cf1f3c998abbe ]
+
+Fix various kfree() issues related to of_overlay_apply().
+ - Double kfree() of fdt and tree when init_overlay_changeset()
+ returns an error.
+ - free_overlay_changeset() free the root of the unflattened
+ overlay (variable tree) instead of the memory that contains
+ the unflattened overlay.
+ - For the case of a failure during applying an overlay, move kfree()
+ of new_fdt and overlay_mem into free_overlay_changeset(), which
+ is called by the function that allocated them.
+ - For the case of removing an overlay, the kfree() of new_fdt and
+ overlay_mem remains in free_overlay_changeset().
+ - Check return value of of_fdt_unflatten_tree() for error instead
+ of checking the returned value of overlay_root.
+ - When storing pointers to allocated objects in ovcs, do so as
+ near to the allocation as possible instead of in deeply layered
+ function.
+
+More clearly document policy related to lifetime of pointers into
+overlay memory.
+
+Double kfree()
+Reported-by: Slawomir Stepien <slawomir.stepien@nokia.com>
+
+Signed-off-by: Frank Rowand <frank.rowand@sony.com>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20220420222505.928492-3-frowand.list@gmail.com
+Stable-dep-of: 39affd1fdf65 ("of: overlay: Fix missing of_node_put() in error case of init_overlay_changeset()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/devicetree/overlay-notes.rst | 30 ++-
+ drivers/of/overlay.c | 263 ++++++++++-----------
+ include/linux/of.h | 3 +-
+ 3 files changed, 153 insertions(+), 143 deletions(-)
+
+diff --git a/Documentation/devicetree/overlay-notes.rst b/Documentation/devicetree/overlay-notes.rst
+index b2b8db765b8c6..e139f22b363e9 100644
+--- a/Documentation/devicetree/overlay-notes.rst
++++ b/Documentation/devicetree/overlay-notes.rst
+@@ -119,10 +119,32 @@ Finally, if you need to remove all overlays in one-go, just call
+ of_overlay_remove_all() which will remove every single one in the correct
+ order.
+
+-In addition, there is the option to register notifiers that get called on
++There is the option to register notifiers that get called on
+ overlay operations. See of_overlay_notifier_register/unregister and
+ enum of_overlay_notify_action for details.
+
+-Note that a notifier callback is not supposed to store pointers to a device
+-tree node or its content beyond OF_OVERLAY_POST_REMOVE corresponding to the
+-respective node it received.
++A notifier callback for OF_OVERLAY_PRE_APPLY, OF_OVERLAY_POST_APPLY, or
++OF_OVERLAY_PRE_REMOVE may store pointers to a device tree node in the overlay
++or its content but these pointers must not persist past the notifier callback
++for OF_OVERLAY_POST_REMOVE. The memory containing the overlay will be
++kfree()ed after OF_OVERLAY_POST_REMOVE notifiers are called. Note that the
++memory will be kfree()ed even if the notifier for OF_OVERLAY_POST_REMOVE
++returns an error.
++
++The changeset notifiers in drivers/of/dynamic.c are a second type of notifier
++that could be triggered by applying or removing an overlay. These notifiers
++are not allowed to store pointers to a device tree node in the overlay
++or its content. The overlay code does not protect against such pointers
++remaining active when the memory containing the overlay is freed as a result
++of removing the overlay.
++
++Any other code that retains a pointer to the overlay nodes or data is
++considered to be a bug because after removing the overlay the pointer
++will refer to freed memory.
++
++Users of overlays must be especially aware of the overall operations that
++occur on the system to ensure that other kernel code does not retain any
++pointers to the overlay nodes or data. Any example of an inadvertent use
++of such pointers is if a driver or subsystem module is loaded after an
++overlay has been applied, and the driver or subsystem scans the entire
++devicetree or a large portion of it, including the overlay nodes.
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 56afef5594112..119dd6a0be868 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -58,7 +58,9 @@ struct fragment {
+ * @id: changeset identifier
+ * @ovcs_list: list on which we are located
+ * @new_fdt: Memory allocated to hold unflattened aligned FDT
++ * @overlay_mem: the memory chunk that contains @overlay_root
+ * @overlay_root: expanded device tree that contains the fragment nodes
++ * @notify_state: most recent notify action used on overlay
+ * @count: count of fragment structures
+ * @fragments: fragment nodes in the overlay expanded device tree
+ * @symbols_fragment: last element of @fragments[] is the __symbols__ node
+@@ -68,7 +70,9 @@ struct overlay_changeset {
+ int id;
+ struct list_head ovcs_list;
+ const void *new_fdt;
++ const void *overlay_mem;
+ struct device_node *overlay_root;
++ enum of_overlay_notify_action notify_state;
+ int count;
+ struct fragment *fragments;
+ bool symbols_fragment;
+@@ -115,7 +119,6 @@ void of_overlay_mutex_unlock(void)
+ mutex_unlock(&of_overlay_phandle_mutex);
+ }
+
+-
+ static LIST_HEAD(ovcs_list);
+ static DEFINE_IDR(ovcs_idr);
+
+@@ -162,6 +165,8 @@ static int overlay_notify(struct overlay_changeset *ovcs,
+ struct of_overlay_notify_data nd;
+ int i, ret;
+
++ ovcs->notify_state = action;
++
+ for (i = 0; i < ovcs->count; i++) {
+ struct fragment *fragment = &ovcs->fragments[i];
+
+@@ -717,53 +722,49 @@ static struct device_node *find_target(struct device_node *info_node)
+ /**
+ * init_overlay_changeset() - initialize overlay changeset from overlay tree
+ * @ovcs: Overlay changeset to build
+- * @new_fdt: Memory allocated to hold unflattened aligned FDT
+- * @overlay_root: Contains the overlay fragments and overlay fixup nodes
+ *
+ * Initialize @ovcs. Populate @ovcs->fragments with node information from
+ * the top level of @overlay_root. The relevant top level nodes are the
+ * fragment nodes and the __symbols__ node. Any other top level node will
+- * be ignored.
++ * be ignored. Populate other @ovcs fields.
+ *
+ * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
+- * detected in @overlay_root, or -ENOSPC if idr_alloc() error.
++ * detected in @overlay_root. On error return, the caller of
++ * init_overlay_changeset() must call free_overlay_changeset().
+ */
+-static int init_overlay_changeset(struct overlay_changeset *ovcs,
+- const void *new_fdt, struct device_node *overlay_root)
++static int init_overlay_changeset(struct overlay_changeset *ovcs)
+ {
+ struct device_node *node, *overlay_node;
+ struct fragment *fragment;
+ struct fragment *fragments;
+- int cnt, id, ret;
++ int cnt, ret;
++
++ /*
++ * None of the resources allocated by this function will be freed in
++ * the error paths. Instead the caller of this function is required
++ * to call free_overlay_changeset() (which will free the resources)
++ * if error return.
++ */
+
+ /*
+ * Warn for some issues. Can not return -EINVAL for these until
+ * of_unittest_apply_overlay() is fixed to pass these checks.
+ */
+- if (!of_node_check_flag(overlay_root, OF_DYNAMIC))
+- pr_debug("%s() overlay_root is not dynamic\n", __func__);
++ if (!of_node_check_flag(ovcs->overlay_root, OF_DYNAMIC))
++ pr_debug("%s() ovcs->overlay_root is not dynamic\n", __func__);
+
+- if (!of_node_check_flag(overlay_root, OF_DETACHED))
+- pr_debug("%s() overlay_root is not detached\n", __func__);
++ if (!of_node_check_flag(ovcs->overlay_root, OF_DETACHED))
++ pr_debug("%s() ovcs->overlay_root is not detached\n", __func__);
+
+- if (!of_node_is_root(overlay_root))
+- pr_debug("%s() overlay_root is not root\n", __func__);
+-
+- ovcs->overlay_root = overlay_root;
+- ovcs->new_fdt = new_fdt;
+-
+- INIT_LIST_HEAD(&ovcs->ovcs_list);
++ if (!of_node_is_root(ovcs->overlay_root))
++ pr_debug("%s() ovcs->overlay_root is not root\n", __func__);
+
+ of_changeset_init(&ovcs->cset);
+
+- id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
+- if (id <= 0)
+- return id;
+-
+ cnt = 0;
+
+ /* fragment nodes */
+- for_each_child_of_node(overlay_root, node) {
++ for_each_child_of_node(ovcs->overlay_root, node) {
+ overlay_node = of_get_child_by_name(node, "__overlay__");
+ if (overlay_node) {
+ cnt++;
+@@ -771,7 +772,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ }
+ }
+
+- node = of_get_child_by_name(overlay_root, "__symbols__");
++ node = of_get_child_by_name(ovcs->overlay_root, "__symbols__");
+ if (node) {
+ cnt++;
+ of_node_put(node);
+@@ -780,11 +781,12 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
+ if (!fragments) {
+ ret = -ENOMEM;
+- goto err_free_idr;
++ goto err_out;
+ }
++ ovcs->fragments = fragments;
+
+ cnt = 0;
+- for_each_child_of_node(overlay_root, node) {
++ for_each_child_of_node(ovcs->overlay_root, node) {
+ overlay_node = of_get_child_by_name(node, "__overlay__");
+ if (!overlay_node)
+ continue;
+@@ -796,7 +798,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ of_node_put(fragment->overlay);
+ ret = -EINVAL;
+ of_node_put(node);
+- goto err_free_fragments;
++ goto err_out;
+ }
+
+ cnt++;
+@@ -806,7 +808,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ * if there is a symbols fragment in ovcs->fragments[i] it is
+ * the final element in the array
+ */
+- node = of_get_child_by_name(overlay_root, "__symbols__");
++ node = of_get_child_by_name(ovcs->overlay_root, "__symbols__");
+ if (node) {
+ ovcs->symbols_fragment = 1;
+ fragment = &fragments[cnt];
+@@ -816,7 +818,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ if (!fragment->target) {
+ pr_err("symbols in overlay, but not in live tree\n");
+ ret = -EINVAL;
+- goto err_free_fragments;
++ goto err_out;
+ }
+
+ cnt++;
+@@ -825,20 +827,14 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
+ if (!cnt) {
+ pr_err("no fragments or symbols in overlay\n");
+ ret = -EINVAL;
+- goto err_free_fragments;
++ goto err_out;
+ }
+
+- ovcs->id = id;
+ ovcs->count = cnt;
+- ovcs->fragments = fragments;
+
+ return 0;
+
+-err_free_fragments:
+- kfree(fragments);
+-err_free_idr:
+- idr_remove(&ovcs_idr, id);
+-
++err_out:
+ pr_err("%s() failed, ret = %d\n", __func__, ret);
+
+ return ret;
+@@ -851,21 +847,34 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ if (ovcs->cset.entries.next)
+ of_changeset_destroy(&ovcs->cset);
+
+- if (ovcs->id)
++ if (ovcs->id) {
+ idr_remove(&ovcs_idr, ovcs->id);
++ list_del(&ovcs->ovcs_list);
++ ovcs->id = 0;
++ }
++
+
+ for (i = 0; i < ovcs->count; i++) {
+ of_node_put(ovcs->fragments[i].target);
+ of_node_put(ovcs->fragments[i].overlay);
+ }
+ kfree(ovcs->fragments);
++
+ /*
+- * There should be no live pointers into ovcs->overlay_root and
++ * There should be no live pointers into ovcs->overlay_mem and
+ * ovcs->new_fdt due to the policy that overlay notifiers are not
+- * allowed to retain pointers into the overlay devicetree.
++ * allowed to retain pointers into the overlay devicetree other
++ * than during the window from OF_OVERLAY_PRE_APPLY overlay
++ * notifiers until the OF_OVERLAY_POST_REMOVE overlay notifiers.
++ *
++ * A memory leak will occur here if within the window.
+ */
+- kfree(ovcs->overlay_root);
+- kfree(ovcs->new_fdt);
++
++ if (ovcs->notify_state == OF_OVERLAY_INIT ||
++ ovcs->notify_state == OF_OVERLAY_POST_REMOVE) {
++ kfree(ovcs->overlay_mem);
++ kfree(ovcs->new_fdt);
++ }
+ kfree(ovcs);
+ }
+
+@@ -873,27 +882,13 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ * internal documentation
+ *
+ * of_overlay_apply() - Create and apply an overlay changeset
+- * @new_fdt: Memory allocated to hold the aligned FDT
+- * @overlay_root: Expanded overlay device tree
+- * @ovcs_id: Pointer to overlay changeset id
++ * @ovcs: overlay changeset
+ *
+ * Creates and applies an overlay changeset.
+ *
+- * If an error occurs in a pre-apply notifier, then no changes are made
+- * to the device tree.
+- *
+- * A non-zero return value will not have created the changeset if error is from:
+- * - parameter checks
+- * - building the changeset
+- * - overlay changeset pre-apply notifier
+- *
+ * If an error is returned by an overlay changeset pre-apply notifier
+ * then no further overlay changeset pre-apply notifier will be called.
+ *
+- * A non-zero return value will have created the changeset if error is from:
+- * - overlay changeset entry notifier
+- * - overlay changeset post-apply notifier
+- *
+ * If an error is returned by an overlay changeset post-apply notifier
+ * then no further overlay changeset post-apply notifier will be called.
+ *
+@@ -907,64 +902,37 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
+ * following attempt to apply or remove an overlay changeset will be
+ * refused.
+ *
+- * Returns 0 on success, or a negative error number. Overlay changeset
+- * id is returned to *ovcs_id.
++ * Returns 0 on success, or a negative error number. On error return,
++ * the caller of of_overlay_apply() must call free_overlay_changeset().
+ */
+
+-static int of_overlay_apply(const void *new_fdt,
+- struct device_node *overlay_root, int *ovcs_id)
++static int of_overlay_apply(struct overlay_changeset *ovcs)
+ {
+- struct overlay_changeset *ovcs;
+ int ret = 0, ret_revert, ret_tmp;
+
+- /*
+- * As of this point, fdt and tree belong to the overlay changeset.
+- * overlay changeset code is responsible for freeing them.
+- */
+-
+ if (devicetree_corrupt()) {
+ pr_err("devicetree state suspect, refuse to apply overlay\n");
+- kfree(new_fdt);
+- kfree(overlay_root);
+ ret = -EBUSY;
+ goto out;
+ }
+
+- ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
+- if (!ovcs) {
+- kfree(new_fdt);
+- kfree(overlay_root);
+- ret = -ENOMEM;
+- goto out;
+- }
+-
+- of_overlay_mutex_lock();
+- mutex_lock(&of_mutex);
+-
+- ret = of_resolve_phandles(overlay_root);
++ ret = of_resolve_phandles(ovcs->overlay_root);
+ if (ret)
+- goto err_free_tree;
++ goto out;
+
+- ret = init_overlay_changeset(ovcs, new_fdt, overlay_root);
++ ret = init_overlay_changeset(ovcs);
+ if (ret)
+- goto err_free_tree;
++ goto out;
+
+- /*
+- * After overlay_notify(), ovcs->overlay_root related pointers may have
+- * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree;
+- * and can not free memory containing aligned fdt. The aligned fdt
+- * is contained within the memory at ovcs->new_fdt, possibly at an
+- * offset from ovcs->new_fdt.
+- */
+ ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
+ if (ret) {
+ pr_err("overlay changeset pre-apply notify error %d\n", ret);
+- goto err_free_overlay_changeset;
++ goto out;
+ }
+
+ ret = build_changeset(ovcs);
+ if (ret)
+- goto err_free_overlay_changeset;
++ goto out;
+
+ ret_revert = 0;
+ ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
+@@ -974,7 +942,7 @@ static int of_overlay_apply(const void *new_fdt,
+ ret_revert);
+ devicetree_state_flags |= DTSF_APPLY_FAIL;
+ }
+- goto err_free_overlay_changeset;
++ goto out;
+ }
+
+ ret = __of_changeset_apply_notify(&ovcs->cset);
+@@ -982,9 +950,6 @@ static int of_overlay_apply(const void *new_fdt,
+ pr_err("overlay apply changeset entry notify error %d\n", ret);
+ /* notify failure is not fatal, continue */
+
+- list_add_tail(&ovcs->ovcs_list, &ovcs_list);
+- *ovcs_id = ovcs->id;
+-
+ ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);
+ if (ret_tmp) {
+ pr_err("overlay changeset post-apply notify error %d\n",
+@@ -993,19 +958,6 @@ static int of_overlay_apply(const void *new_fdt,
+ ret = ret_tmp;
+ }
+
+- goto out_unlock;
+-
+-err_free_tree:
+- kfree(new_fdt);
+- kfree(overlay_root);
+-
+-err_free_overlay_changeset:
+- free_overlay_changeset(ovcs);
+-
+-out_unlock:
+- mutex_unlock(&of_mutex);
+- of_overlay_mutex_unlock();
+-
+ out:
+ pr_debug("%s() err=%d\n", __func__, ret);
+
+@@ -1013,15 +965,16 @@ static int of_overlay_apply(const void *new_fdt,
+ }
+
+ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
+- int *ovcs_id)
++ int *ret_ovcs_id)
+ {
+ void *new_fdt;
+ void *new_fdt_align;
++ void *overlay_mem;
+ int ret;
+ u32 size;
+- struct device_node *overlay_root = NULL;
++ struct overlay_changeset *ovcs;
+
+- *ovcs_id = 0;
++ *ret_ovcs_id = 0;
+
+ if (overlay_fdt_size < sizeof(struct fdt_header) ||
+ fdt_check_header(overlay_fdt)) {
+@@ -1033,41 +986,67 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
+ if (overlay_fdt_size < size)
+ return -EINVAL;
+
++ ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
++ if (!ovcs)
++ return -ENOMEM;
++
++ of_overlay_mutex_lock();
++ mutex_lock(&of_mutex);
++
++ /*
++ * ovcs->notify_state must be set to OF_OVERLAY_INIT before allocating
++ * ovcs resources, implicitly set by kzalloc() of ovcs
++ */
++
++ ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
++ if (ovcs->id <= 0) {
++ ret = ovcs->id;
++ goto err_free_ovcs;
++ }
++
++ INIT_LIST_HEAD(&ovcs->ovcs_list);
++ list_add_tail(&ovcs->ovcs_list, &ovcs_list);
++
+ /*
+ * Must create permanent copy of FDT because of_fdt_unflatten_tree()
+ * will create pointers to the passed in FDT in the unflattened tree.
+ */
+ new_fdt = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL);
+- if (!new_fdt)
+- return -ENOMEM;
++ if (!new_fdt) {
++ ret = -ENOMEM;
++ goto err_free_ovcs;
++ }
++ ovcs->new_fdt = new_fdt;
+
+ new_fdt_align = PTR_ALIGN(new_fdt, FDT_ALIGN_SIZE);
+ memcpy(new_fdt_align, overlay_fdt, size);
+
+- of_fdt_unflatten_tree(new_fdt_align, NULL, &overlay_root);
+- if (!overlay_root) {
++ overlay_mem = of_fdt_unflatten_tree(new_fdt_align, NULL,
++ &ovcs->overlay_root);
++ if (!overlay_mem) {
+ pr_err("unable to unflatten overlay_fdt\n");
+ ret = -EINVAL;
+- goto out_free_new_fdt;
++ goto err_free_ovcs;
+ }
++ ovcs->overlay_mem = overlay_mem;
+
+- ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
+- if (ret < 0) {
+- /*
+- * new_fdt and overlay_root now belong to the overlay
+- * changeset.
+- * overlay changeset code is responsible for freeing them.
+- */
+- goto out;
+- }
++ ret = of_overlay_apply(ovcs);
++ if (ret < 0)
++ goto err_free_ovcs;
++
++ mutex_unlock(&of_mutex);
++ of_overlay_mutex_unlock();
++
++ *ret_ovcs_id = ovcs->id;
+
+ return 0;
+
++err_free_ovcs:
++ free_overlay_changeset(ovcs);
+
+-out_free_new_fdt:
+- kfree(new_fdt);
++ mutex_unlock(&of_mutex);
++ of_overlay_mutex_unlock();
+
+-out:
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
+@@ -1204,28 +1183,26 @@ int of_overlay_remove(int *ovcs_id)
+ if (!ovcs) {
+ ret = -ENODEV;
+ pr_err("remove: Could not find overlay #%d\n", *ovcs_id);
+- goto out_unlock;
++ goto err_unlock;
+ }
+
+ if (!overlay_removal_is_ok(ovcs)) {
+ ret = -EBUSY;
+- goto out_unlock;
++ goto err_unlock;
+ }
+
+ ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE);
+ if (ret) {
+ pr_err("overlay changeset pre-remove notify error %d\n", ret);
+- goto out_unlock;
++ goto err_unlock;
+ }
+
+- list_del(&ovcs->ovcs_list);
+-
+ ret_apply = 0;
+ ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
+ if (ret) {
+ if (ret_apply)
+ devicetree_state_flags |= DTSF_REVERT_FAIL;
+- goto out_unlock;
++ goto err_unlock;
+ }
+
+ ret = __of_changeset_revert_notify(&ovcs->cset);
+@@ -1235,6 +1212,11 @@ int of_overlay_remove(int *ovcs_id)
+
+ *ovcs_id = 0;
+
++ /*
++ * Note that the overlay memory will be kfree()ed by
++ * free_overlay_changeset() even if the notifier for
++ * OF_OVERLAY_POST_REMOVE returns an error.
++ */
+ ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE);
+ if (ret_tmp) {
+ pr_err("overlay changeset post-remove notify error %d\n",
+@@ -1245,7 +1227,12 @@ int of_overlay_remove(int *ovcs_id)
+
+ free_overlay_changeset(ovcs);
+
+-out_unlock:
++err_unlock:
++ /*
++ * If jumped over free_overlay_changeset(), then did not kfree()
++ * overlay related memory. This is a memory leak unless a subsequent
++ * of_overlay_remove() of this overlay is successful.
++ */
+ mutex_unlock(&of_mutex);
+
+ out:
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 6f1c41f109bbe..83414a0b41de5 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -1486,7 +1486,8 @@ static inline bool of_device_is_system_power_controller(const struct device_node
+ */
+
+ enum of_overlay_notify_action {
+- OF_OVERLAY_PRE_APPLY = 0,
++ OF_OVERLAY_INIT = 0, /* kzalloc() of ovcs sets this value */
++ OF_OVERLAY_PRE_APPLY,
+ OF_OVERLAY_POST_APPLY,
+ OF_OVERLAY_PRE_REMOVE,
+ OF_OVERLAY_POST_REMOVE,
+--
+2.39.2
+
--- /dev/null
+From 24e6218ff57086a0db0c9f03d1303f518ff1bfbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 May 2023 15:54:40 +0200
+Subject: parisc: Flush gatt writes and adjust gatt mask in
+ parisc_agp_mask_memory()
+
+From: Helge Deller <deller@gmx.de>
+
+[ Upstream commit d703797380c540bbeac03f104ebcfc364eaf47cc ]
+
+Flush caches after changing gatt entries and calculate entry according
+to SBA requirements.
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/agp/parisc-agp.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
+index d68d05d5d3838..514f9f287a781 100644
+--- a/drivers/char/agp/parisc-agp.c
++++ b/drivers/char/agp/parisc-agp.c
+@@ -90,6 +90,9 @@ parisc_agp_tlbflush(struct agp_memory *mem)
+ {
+ struct _parisc_agp_info *info = &parisc_agp_info;
+
++ /* force fdc ops to be visible to IOMMU */
++ asm_io_sync();
++
+ writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
+ readq(info->ioc_regs+IOC_PCOM); /* flush */
+ }
+@@ -158,6 +161,7 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+ info->gatt[j] =
+ parisc_agp_mask_memory(agp_bridge,
+ paddr, type);
++ asm_io_fdc(&info->gatt[j]);
+ }
+ }
+
+@@ -191,7 +195,16 @@ static unsigned long
+ parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
+ int type)
+ {
+- return SBA_PDIR_VALID_BIT | addr;
++ unsigned ci; /* coherent index */
++ dma_addr_t pa;
++
++ pa = addr & IOVP_MASK;
++ asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pa)));
++
++ pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */
++ pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
++
++ return cpu_to_le64(pa);
+ }
+
+ static void
+--
+2.39.2
+
--- /dev/null
+From da1dc0db36c4a25bb9ecc20d00e74af3ccd06527 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 May 2023 15:52:30 +0200
+Subject: parisc: Improve cache flushing for PCXL in arch_sync_dma_for_cpu()
+
+From: Helge Deller <deller@gmx.de>
+
+[ Upstream commit 59fa12646d9f56c842b4d5b6418ed77af625c588 ]
+
+Add comment in arch_sync_dma_for_device() and handle the direction flag in
+arch_sync_dma_for_cpu().
+
+When receiving data from the device (DMA_FROM_DEVICE) unconditionally
+purge the data cache in arch_sync_dma_for_cpu().
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/parisc/kernel/pci-dma.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
+index 36a57aa38e87e..3b0227b17c070 100644
+--- a/arch/parisc/kernel/pci-dma.c
++++ b/arch/parisc/kernel/pci-dma.c
+@@ -446,11 +446,27 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr,
+ void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
+ {
++ /*
++ * fdc: The data cache line is written back to memory, if and only if
++ * it is dirty, and then invalidated from the data cache.
++ */
+ flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
+ }
+
+ void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+ enum dma_data_direction dir)
+ {
+- flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
++ unsigned long addr = (unsigned long) phys_to_virt(paddr);
++
++ switch (dir) {
++ case DMA_TO_DEVICE:
++ case DMA_BIDIRECTIONAL:
++ flush_kernel_dcache_range(addr, size);
++ return;
++ case DMA_FROM_DEVICE:
++ purge_kernel_dcache_range_asm(addr, addr + size);
++ return;
++ default:
++ BUG();
++ }
+ }
+--
+2.39.2
+
--- /dev/null
+From 4eb0dbb7d61258949ddc096e6ffb3d3a67b92c6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 May 2023 13:15:17 +0300
+Subject: platform/x86: asus-wmi: Ignore WMI events with codes 0x7B, 0xC0
+
+From: Alexandru Sorodoc <ealex95@gmail.com>
+
+[ Upstream commit 362c1f2ec82cb65940e1c73e15a395a7a891fc6f ]
+
+On ASUS GU604V the key 0x7B is issued when the charger is connected or
+disconnected, and key 0xC0 is issued when an external display is
+connected or disconnected.
+
+This commit maps them to KE_IGNORE to slience kernel messages about
+unknown keys, such as:
+
+ kernel: asus_wmi: Unknown key code 0x7b
+
+Signed-off-by: Alexandru Sorodoc <ealex95@gmail.com>
+Link: https://lore.kernel.org/r/20230512101517.47416-1-ealex95@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/asus-nb-wmi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
+index 4d7327b67a7db..2c43801a18a28 100644
+--- a/drivers/platform/x86/asus-nb-wmi.c
++++ b/drivers/platform/x86/asus-nb-wmi.c
+@@ -550,6 +550,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
+ { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */
+ { KE_IGNORE, 0x79, }, /* Charger type dectection notification */
+ { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
++ { KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */
+ { KE_KEY, 0x7c, { KEY_MICMUTE } },
+ { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
+ { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */
+@@ -575,6 +576,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
+ { KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */
+ { KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */
+ { KE_KEY, 0xB5, { KEY_CALC } },
++ { KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */
+ { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
+ { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
+ { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */
+--
+2.39.2
+
--- /dev/null
+From 821933325c29accb1997c687d5de17ca1d9bf457 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 18:07:29 +0200
+Subject: power: supply: ab8500: Fix external_power_changed race
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit a5299ce4e96f3e8930e9c051b28d8093ada87b08 ]
+
+ab8500_btemp_external_power_changed() dereferences di->btemp_psy,
+which gets sets in ab8500_btemp_probe() like this:
+
+ di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc,
+ &psy_cfg);
+
+As soon as devm_power_supply_register() has called device_add()
+the external_power_changed callback can get called. So there is a window
+where ab8500_btemp_external_power_changed() may get called while
+di->btemp_psy has not been set yet leading to a NULL pointer dereference.
+
+Fixing this is easy. The external_power_changed callback gets passed
+the power_supply which will eventually get stored in di->btemp_psy,
+so ab8500_btemp_external_power_changed() can simply directly use
+the passed in psy argument which is always valid.
+
+And the same applies to ab8500_fg_external_power_changed().
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/ab8500_btemp.c | 6 ++----
+ drivers/power/supply/ab8500_fg.c | 6 ++----
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
+index b6c9111d77d7d..896309d3cadfe 100644
+--- a/drivers/power/supply/ab8500_btemp.c
++++ b/drivers/power/supply/ab8500_btemp.c
+@@ -902,10 +902,8 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
+ */
+ static void ab8500_btemp_external_power_changed(struct power_supply *psy)
+ {
+- struct ab8500_btemp *di = power_supply_get_drvdata(psy);
+-
+- class_for_each_device(power_supply_class, NULL,
+- di->btemp_psy, ab8500_btemp_get_ext_psy_data);
++ class_for_each_device(power_supply_class, NULL, psy,
++ ab8500_btemp_get_ext_psy_data);
+ }
+
+ /* ab8500 btemp driver interrupts and their respective isr */
+diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
+index 57799a8079d44..eb7eac23da70f 100644
+--- a/drivers/power/supply/ab8500_fg.c
++++ b/drivers/power/supply/ab8500_fg.c
+@@ -2384,10 +2384,8 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
+ */
+ static void ab8500_fg_external_power_changed(struct power_supply *psy)
+ {
+- struct ab8500_fg *di = power_supply_get_drvdata(psy);
+-
+- class_for_each_device(power_supply_class, NULL,
+- di->fg_psy, ab8500_fg_get_ext_psy_data);
++ class_for_each_device(power_supply_class, NULL, psy,
++ ab8500_fg_get_ext_psy_data);
+ }
+
+ /**
+--
+2.39.2
+
--- /dev/null
+From c120e97a266faebea7e6ffa165d3ea33ca07e0b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 20:23:39 +0200
+Subject: power: supply: bq27xxx: Use mod_delayed_work() instead of cancel() +
+ schedule()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 59dddea9879713423c7b2ade43c423bb71e0d216 ]
+
+Use mod_delayed_work() instead of separate cancel_delayed_work_sync() +
+schedule_delayed_work() calls.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq27xxx_battery.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index ffb5f5c028223..7c1295986b594 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1083,10 +1083,8 @@ static int poll_interval_param_set(const char *val, const struct kernel_param *k
+ return ret;
+
+ mutex_lock(&bq27xxx_list_lock);
+- list_for_each_entry(di, &bq27xxx_battery_devices, list) {
+- cancel_delayed_work_sync(&di->work);
+- schedule_delayed_work(&di->work, 0);
+- }
++ list_for_each_entry(di, &bq27xxx_battery_devices, list)
++ mod_delayed_work(system_wq, &di->work, 0);
+ mutex_unlock(&bq27xxx_list_lock);
+
+ return ret;
+--
+2.39.2
+
--- /dev/null
+From 07ce5720c71eaa1e5685cce576286a4f90d94dbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 May 2023 13:25:40 -0500
+Subject: power: supply: Fix logic checking if system is running from battery
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 95339f40a8b652b5b1773def31e63fc53c26378a ]
+
+The logic used for power_supply_is_system_supplied() counts all power
+supplies and assumes that the system is running from AC if there is
+either a non-battery power-supply reporting to be online or if no
+power-supplies exist at all.
+
+The second rule is for desktop systems, that don't have any
+battery/charger devices. These systems will incorrectly report to be
+powered from battery once a device scope power-supply is registered
+(e.g. a HID device), since these power-supplies increase the counter.
+
+Apart from HID devices, recent dGPUs provide UCSI power supplies on a
+desktop systems. The dGPU by default doesn't have anything plugged in so
+it's 'offline'. This makes power_supply_is_system_supplied() return 0
+with a count of 1 meaning all drivers that use this get a wrong judgement.
+
+To fix this case adjust the logic to also examine the scope of the power
+supply. If the power supply is deemed a device power supply, then don't
+count it.
+
+Cc: Evan Quan <Evan.Quan@amd.com>
+Suggested-by: Lijo Lazar <Lijo.Lazar@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/power_supply_core.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
+index daf76d7885c05..8b2cd63016160 100644
+--- a/drivers/power/supply/power_supply_core.c
++++ b/drivers/power/supply/power_supply_core.c
+@@ -347,6 +347,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
+ struct power_supply *psy = dev_get_drvdata(dev);
+ unsigned int *count = data;
+
++ if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret))
++ if (ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
++ return 0;
++
+ (*count)++;
+ if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
+ if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
+@@ -365,8 +369,8 @@ int power_supply_is_system_supplied(void)
+ __power_supply_is_system_supplied);
+
+ /*
+- * If no power class device was found at all, most probably we are
+- * running on a desktop system, so assume we are on mains power.
++ * If no system scope power class device was found at all, most probably we
++ * are running on a desktop system, so assume we are on mains power.
+ */
+ if (count == 0)
+ return 1;
+--
+2.39.2
+
--- /dev/null
+From 77526e0d18f82fb3abefdd2335ab90e0c1517c89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Mar 2023 21:52:26 +0100
+Subject: power: supply: Ratelimit no data debug output
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 155c45a25679f571c2ae57d10db843a9dfc63430 ]
+
+Reduce the amount of output this dev_dbg() statement emits into logs,
+otherwise if system software polls the sysfs entry for data and keeps
+getting -ENODATA, it could end up filling the logs up.
+
+This does in fact make systemd journald choke, since during boot the
+sysfs power supply entries are polled and if journald starts at the
+same time, the journal is just being repeatedly filled up, and the
+system stops on trying to start journald without booting any further.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/power_supply_sysfs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
+index c3d7cbcd4fad5..7a0485c35ba9d 100644
+--- a/drivers/power/supply/power_supply_sysfs.c
++++ b/drivers/power/supply/power_supply_sysfs.c
+@@ -276,7 +276,8 @@ static ssize_t power_supply_show_property(struct device *dev,
+
+ if (ret < 0) {
+ if (ret == -ENODATA)
+- dev_dbg(dev, "driver has no data for `%s' property\n",
++ dev_dbg_ratelimited(dev,
++ "driver has no data for `%s' property\n",
+ attr->attr.name);
+ else if (ret != -ENODEV && ret != -EAGAIN)
+ dev_err_ratelimited(dev,
+--
+2.39.2
+
--- /dev/null
+From c9acbf41192b0510464d9c2a5a5435aa31a92fed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 18:07:32 +0200
+Subject: power: supply: sc27xx: Fix external_power_changed race
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 4d5c129d6c8993fe96e9ae712141eedcb9ca68c2 ]
+
+sc27xx_fgu_external_power_changed() dereferences data->battery,
+which gets sets in ab8500_btemp_probe() like this:
+
+ data->battery = devm_power_supply_register(dev, &sc27xx_fgu_desc,
+ &fgu_cfg);
+
+As soon as devm_power_supply_register() has called device_add()
+the external_power_changed callback can get called. So there is a window
+where sc27xx_fgu_external_power_changed() may get called while
+data->battery has not been set yet leading to a NULL pointer dereference.
+
+Fixing this is easy. The external_power_changed callback gets passed
+the power_supply which will eventually get stored in data->battery,
+so sc27xx_fgu_external_power_changed() can simply directly use
+the passed in psy argument which is always valid.
+
+After this change sc27xx_fgu_external_power_changed() is reduced to just
+"power_supply_changed(psy);" and it has the same prototype. While at it
+simply replace it with making the external_power_changed callback
+directly point to power_supply_changed.
+
+Cc: Orson Zhai <orsonzhai@gmail.com>
+Cc: Chunyan Zhang <zhang.lyra@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/sc27xx_fuel_gauge.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
+index ae45069bd5e1b..3d8a85df87f4d 100644
+--- a/drivers/power/supply/sc27xx_fuel_gauge.c
++++ b/drivers/power/supply/sc27xx_fuel_gauge.c
+@@ -733,13 +733,6 @@ static int sc27xx_fgu_set_property(struct power_supply *psy,
+ return ret;
+ }
+
+-static void sc27xx_fgu_external_power_changed(struct power_supply *psy)
+-{
+- struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
+-
+- power_supply_changed(data->battery);
+-}
+-
+ static int sc27xx_fgu_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+ {
+@@ -774,7 +767,7 @@ static const struct power_supply_desc sc27xx_fgu_desc = {
+ .num_properties = ARRAY_SIZE(sc27xx_fgu_props),
+ .get_property = sc27xx_fgu_get_property,
+ .set_property = sc27xx_fgu_set_property,
+- .external_power_changed = sc27xx_fgu_external_power_changed,
++ .external_power_changed = power_supply_changed,
+ .property_is_writeable = sc27xx_fgu_property_is_writeable,
+ .no_thermal = true,
+ };
+--
+2.39.2
+
--- /dev/null
+From af3d352ad85cb6274c1251a2faa02d9903d85cc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 May 2023 22:29:38 +0500
+Subject: regulator: Fix error checking for debugfs_create_dir
+
+From: Osama Muhammad <osmtendev@gmail.com>
+
+[ Upstream commit 2bf1c45be3b8f3a3f898d0756c1282f09719debd ]
+
+This patch fixes the error checking in core.c in debugfs_create_dir.
+The correct way to check if an error occurred is 'IS_ERR' inline function.
+
+Signed-off-by: Osama Muhammad <osmtendev@gmail.com
+Suggested-by: Ivan Orlov <ivan.orlov0322@gmail.com
+Link: https://lore.kernel.org/r/20230515172938.13338-1-osmtendev@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index 9ddb80d10dee3..211ab227b000c 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -5193,7 +5193,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
+ }
+
+ rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
+- if (!rdev->debugfs) {
++ if (IS_ERR(rdev->debugfs)) {
+ rdev_warn(rdev, "Failed to create debugfs directory\n");
+ return;
+ }
+@@ -6103,7 +6103,7 @@ static int __init regulator_init(void)
+ ret = class_register(®ulator_class);
+
+ debugfs_root = debugfs_create_dir("regulator", NULL);
+- if (!debugfs_root)
++ if (IS_ERR(debugfs_root))
+ pr_warn("regulator: Failed to create debugfs directory\n");
+
+ #ifdef CONFIG_DEBUG_FS
+--
+2.39.2
+
test_firmware-fix-a-memory-leak-with-reqs-buffer.patch
ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch
drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch
+of-overlay-rename-variables-to-be-consistent.patch
+of-overlay-rework-overlay-apply-and-remove-kfree-s.patch
+of-overlay-fix-missing-of_node_put-in-error-case-of-.patch
+power-supply-ab8500-fix-external_power_changed-race.patch
+power-supply-sc27xx-fix-external_power_changed-race.patch
+power-supply-bq27xxx-use-mod_delayed_work-instead-of.patch
+arm-dts-vexpress-add-missing-cache-properties.patch
+tools-gpio-fix-debounce_period_us-output-of-lsgpio.patch
+power-supply-ratelimit-no-data-debug-output.patch
+platform-x86-asus-wmi-ignore-wmi-events-with-codes-0.patch
+regulator-fix-error-checking-for-debugfs_create_dir.patch
+irqchip-gic-v3-disable-pseudo-nmis-on-mediatek-devic.patch
+power-supply-fix-logic-checking-if-system-is-running.patch
+btrfs-scrub-try-harder-to-mark-raid56-block-groups-r.patch
+btrfs-handle-memory-allocation-failure-in-btrfs_csum.patch
+asoc-soc-pcm-test-if-a-be-can-be-prepared.patch
+parisc-improve-cache-flushing-for-pcxl-in-arch_sync_.patch
+parisc-flush-gatt-writes-and-adjust-gatt-mask-in-par.patch
+mips-unhide-pata_platform.patch
+mips-restore-au1300-support.patch
+mips-alchemy-fix-dbdma2.patch
+mips-move-initrd_start-check-after-initrd-address-sa.patch
+asoc-dwc-move-dma-init-to-snd_soc_dai_driver-probe.patch
+xen-blkfront-only-check-req_fua-for-writes.patch
+drm-amd-amdgpu-fix-missing-buffer-object-unlock-in-f.patch
+nvme-add-maxio-1602-to-bogus-nid-list.patch
+irqchip-gic-correctly-validate-of-quirk-descriptors.patch
--- /dev/null
+From bcb7cd2765311b2a1624819b21542332e15210b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 May 2023 15:18:48 +0200
+Subject: tools: gpio: fix debounce_period_us output of lsgpio
+
+From: Milo Spadacini <milo.spadacini@gmail.com>
+
+[ Upstream commit eb4b8eca1bad98f4b8574558a74f041f9acb5a54 ]
+
+Fix incorrect output that could occur when more attributes are used and
+GPIO_V2_LINE_ATTR_ID_DEBOUNCE is not the first one.
+
+Signed-off-by: Milo Spadacini <milo.spadacini@gmail.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/gpio/lsgpio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c
+index c61d061247e17..52a0be45410c9 100644
+--- a/tools/gpio/lsgpio.c
++++ b/tools/gpio/lsgpio.c
+@@ -94,7 +94,7 @@ static void print_attributes(struct gpio_v2_line_info *info)
+ for (i = 0; i < info->num_attrs; i++) {
+ if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE)
+ fprintf(stdout, ", debounce_period=%dusec",
+- info->attrs[0].debounce_period_us);
++ info->attrs[i].debounce_period_us);
+ }
+ }
+
+--
+2.39.2
+
--- /dev/null
+From 4d425fd6a92fc856eb83e102ffa489cce3f3f74f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 17:40:05 +0100
+Subject: xen/blkfront: Only check REQ_FUA for writes
+
+From: Ross Lagerwall <ross.lagerwall@citrix.com>
+
+[ Upstream commit b6ebaa8100090092aa602530d7e8316816d0c98d ]
+
+The existing code silently converts read operations with the
+REQ_FUA bit set into write-barrier operations. This results in data
+loss as the backend scribbles zeroes over the data instead of returning
+it.
+
+While the REQ_FUA bit doesn't make sense on a read operation, at least
+one well-known out-of-tree kernel module does set it and since it
+results in data loss, let's be safe here and only look at REQ_FUA for
+writes.
+
+Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
+Acked-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/20230426164005.2213139-1-ross.lagerwall@citrix.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/xen-blkfront.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 24a86d829f92a..831747ba8113c 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -780,7 +780,8 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
+ ring_req->u.rw.handle = info->handle;
+ ring_req->operation = rq_data_dir(req) ?
+ BLKIF_OP_WRITE : BLKIF_OP_READ;
+- if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) {
++ if (req_op(req) == REQ_OP_FLUSH ||
++ (req_op(req) == REQ_OP_WRITE && (req->cmd_flags & REQ_FUA))) {
+ /*
+ * Ideally we can do an unordered flush-to-disk.
+ * In case the backend onlysupports barriers, use that.
+--
+2.39.2
+