--- /dev/null
+From 9323bb3d03760f9c66c052430966b23aec4442dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Nov 2020 19:29:53 +0800
+Subject: ARM: dts: imx: add usb alias
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit 5c8b3b8a182cbc1ccdfcdeea9b25dd2c12a8148f ]
+
+Add usb alias for bootloader searching the controller in correct order.
+
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Stable-dep-of: ee70b908f77a ("ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/imx6qdl.dtsi | 4 ++++
+ arch/arm/boot/dts/imx6sl.dtsi | 3 +++
+ arch/arm/boot/dts/imx6sll.dtsi | 2 ++
+ arch/arm/boot/dts/imx6sx.dtsi | 3 +++
+ arch/arm/boot/dts/imx6ul.dtsi | 2 ++
+ arch/arm/boot/dts/imx7d.dtsi | 6 ++++++
+ arch/arm/boot/dts/imx7s.dtsi | 2 ++
+ 7 files changed, 22 insertions(+)
+
+diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
+index 7858ae5d39df7..7d81992dfafc6 100644
+--- a/arch/arm/boot/dts/imx6qdl.dtsi
++++ b/arch/arm/boot/dts/imx6qdl.dtsi
+@@ -45,6 +45,10 @@ aliases {
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
++ usb0 = &usbotg;
++ usb1 = &usbh1;
++ usb2 = &usbh2;
++ usb3 = &usbh3;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
+index c184a6d5bc420..5b4dfc62030e8 100644
+--- a/arch/arm/boot/dts/imx6sl.dtsi
++++ b/arch/arm/boot/dts/imx6sl.dtsi
+@@ -39,6 +39,9 @@ aliases {
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
++ usb0 = &usbotg1;
++ usb1 = &usbotg2;
++ usb2 = &usbh;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
+index bf5b262b91f91..eecb2f68a1c32 100644
+--- a/arch/arm/boot/dts/imx6sll.dtsi
++++ b/arch/arm/boot/dts/imx6sll.dtsi
+@@ -36,6 +36,8 @@ aliases {
+ spi1 = &ecspi2;
+ spi3 = &ecspi3;
+ spi4 = &ecspi4;
++ usb0 = &usbotg1;
++ usb1 = &usbotg2;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
+index c399919943c34..629c6a7432d9b 100644
+--- a/arch/arm/boot/dts/imx6sx.dtsi
++++ b/arch/arm/boot/dts/imx6sx.dtsi
+@@ -49,6 +49,9 @@ aliases {
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
+ spi4 = &ecspi5;
++ usb0 = &usbotg1;
++ usb1 = &usbotg2;
++ usb2 = &usbh;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
+index c40684ad11b8e..b40dd0c198028 100644
+--- a/arch/arm/boot/dts/imx6ul.dtsi
++++ b/arch/arm/boot/dts/imx6ul.dtsi
+@@ -47,6 +47,8 @@ aliases {
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
++ usb0 = &usbotg1;
++ usb1 = &usbotg2;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
+index cff875b80b60e..b0bcfa9094a30 100644
+--- a/arch/arm/boot/dts/imx7d.dtsi
++++ b/arch/arm/boot/dts/imx7d.dtsi
+@@ -7,6 +7,12 @@
+ #include <dt-bindings/reset/imx7-reset.h>
+
+ / {
++ aliases {
++ usb0 = &usbotg1;
++ usb1 = &usbotg2;
++ usb2 = &usbh;
++ };
++
+ cpus {
+ cpu0: cpu@0 {
+ clock-frequency = <996000000>;
+diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
+index 43b39ad9ddcee..334e781663cc2 100644
+--- a/arch/arm/boot/dts/imx7s.dtsi
++++ b/arch/arm/boot/dts/imx7s.dtsi
+@@ -47,6 +47,8 @@ aliases {
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
++ usb0 = &usbotg1;
++ usb1 = &usbh;
+ };
+
+ cpus {
+--
+2.40.1
+
--- /dev/null
+From a7f2ed0b27730bad07085a112189e37e56a3cd8d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Sep 2021 11:14:37 +0200
+Subject: ARM: dts: imx6sll: fixup of operating points
+
+From: Andreas Kemnade <andreas@kemnade.info>
+
+[ Upstream commit 1875903019ea6e32e6e544c1631b119e4fd60b20 ]
+
+Make operating point definitions comply with binding
+specifications.
+
+Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Stable-dep-of: ee70b908f77a ("ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/imx6sll.dtsi | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
+index eecb2f68a1c32..2873369a57c02 100644
+--- a/arch/arm/boot/dts/imx6sll.dtsi
++++ b/arch/arm/boot/dts/imx6sll.dtsi
+@@ -51,20 +51,18 @@ cpu0: cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2>;
+- operating-points = <
++ operating-points =
+ /* kHz uV */
+- 996000 1275000
+- 792000 1175000
+- 396000 1075000
+- 198000 975000
+- >;
+- fsl,soc-operating-points = <
++ <996000 1275000>,
++ <792000 1175000>,
++ <396000 1075000>,
++ <198000 975000>;
++ fsl,soc-operating-points =
+ /* ARM kHz SOC-PU uV */
+- 996000 1175000
+- 792000 1175000
+- 396000 1175000
+- 198000 1175000
+- >;
++ <996000 1175000>,
++ <792000 1175000>,
++ <396000 1175000>,
++ <198000 1175000>;
+ clock-latency = <61036>; /* two CLK32 periods */
+ #cooling-cells = <2>;
+ clocks = <&clks IMX6SLL_CLK_ARM>,
+--
+2.40.1
+
--- /dev/null
+From 005a79aa9afc6ad9731333a74c217d7f4b27f379 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 10:28:33 +0800
+Subject: ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit ee70b908f77a9d8f689dea986f09e6d7dc481934 ]
+
+Property name "phy-3p0-supply" is used instead of "phy-reg_3p0-supply".
+
+Fixes: 9f30b6b1a957 ("ARM: dts: imx: Add basic dtsi file for imx6sll")
+cc: <stable@vger.kernel.org>
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/imx6sll.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
+index 2873369a57c02..3659fd5ecfa62 100644
+--- a/arch/arm/boot/dts/imx6sll.dtsi
++++ b/arch/arm/boot/dts/imx6sll.dtsi
+@@ -552,7 +552,7 @@ usbphy2: usb-phy@20ca000 {
+ reg = <0x020ca000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SLL_CLK_USBPHY2>;
+- phy-reg_3p0-supply = <®_3p0>;
++ phy-3p0-supply = <®_3p0>;
+ fsl,anatop = <&anatop>;
+ };
+
+--
+2.40.1
+
--- /dev/null
+From fbfa24459c36e49bc4fd8d9db9c2efeea9f5abae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jul 2023 21:59:37 +0900
+Subject: exfat: check if filename entries exceeds max filename length
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit d42334578eba1390859012ebb91e1e556d51db49 ]
+
+exfat_extract_uni_name copies characters from a given file name entry into
+the 'uniname' variable. This variable is actually defined on the stack of
+the exfat_readdir() function. According to the definition of
+the 'exfat_uni_name' type, the file name should be limited 255 characters
+(+ null teminator space), but the exfat_get_uniname_from_ext_entry()
+function can write more characters because there is no check if filename
+entries exceeds max filename length. This patch add the check not to copy
+filename characters when exceeding max filename length.
+
+Cc: stable@vger.kernel.org
+Cc: Yuezhang Mo <Yuezhang.Mo@sony.com>
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/dir.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
+index d2be36ddc18a5..4e9b85d35d938 100644
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -33,6 +33,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+ {
+ int i;
+ struct exfat_entry_set_cache es;
++ unsigned int uni_len = 0, len;
+
+ if (exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES))
+ return;
+@@ -50,7 +51,10 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+ if (exfat_get_entry_type(ep) != TYPE_EXTEND)
+ break;
+
+- exfat_extract_uni_name(ep, uniname);
++ len = exfat_extract_uni_name(ep, uniname);
++ uni_len += len;
++ if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH)
++ break;
+ uniname += EXFAT_FILE_NAME_LEN;
+ }
+
+@@ -1037,7 +1041,8 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
+ if (entry_type == TYPE_EXTEND) {
+ unsigned short entry_uniname[16], unichar;
+
+- if (step != DIRENT_STEP_NAME) {
++ if (step != DIRENT_STEP_NAME ||
++ name_len >= MAX_NAME_LENGTH) {
+ step = DIRENT_STEP_FILE;
+ continue;
+ }
+--
+2.40.1
+
--- /dev/null
+From 6c290ca5ee81f3322bcc3c5a7879a0e100405040 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 11:37:13 +0800
+Subject: exfat: move exfat_entry_set_cache from heap to stack
+
+From: Yuezhang Mo <Yuezhang.Mo@sony.com>
+
+[ Upstream commit 20914ff6dd56dd6b548bf5dd90bff09ef89999e4 ]
+
+The size of struct exfat_entry_set_cache is only 56 bytes on
+64-bit system, and allocating from stack is more efficient than
+allocating from heap.
+
+Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
+Reviewed-by: Andy Wu <Andy.Wu@sony.com>
+Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: d42334578eba ("exfat: check if filename entries exceeds max filename length")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/dir.c | 35 +++++++++++++++--------------------
+ fs/exfat/exfat_fs.h | 5 +++--
+ fs/exfat/inode.c | 13 ++++++-------
+ fs/exfat/namei.c | 11 +++++------
+ 4 files changed, 29 insertions(+), 35 deletions(-)
+
+diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
+index 185aa13945d3d..d2be36ddc18a5 100644
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -32,10 +32,9 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+ struct exfat_chain *p_dir, int entry, unsigned short *uniname)
+ {
+ int i;
+- struct exfat_entry_set_cache *es;
++ struct exfat_entry_set_cache es;
+
+- es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES);
+- if (!es)
++ if (exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES))
+ return;
+
+ /*
+@@ -44,8 +43,8 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+ * Third entry : first file-name entry
+ * So, the index of first file-name dentry should start from 2.
+ */
+- for (i = 2; i < es->num_entries; i++) {
+- struct exfat_dentry *ep = exfat_get_dentry_cached(es, i);
++ for (i = 2; i < es.num_entries; i++) {
++ struct exfat_dentry *ep = exfat_get_dentry_cached(&es, i);
+
+ /* end of name entry */
+ if (exfat_get_entry_type(ep) != TYPE_EXTEND)
+@@ -55,7 +54,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
+ uniname += EXFAT_FILE_NAME_LEN;
+ }
+
+- exfat_free_dentry_set(es, false);
++ exfat_free_dentry_set(&es, false);
+ }
+
+ /* read a directory entry from the opened directory */
+@@ -613,7 +612,6 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
+ if (IS_DYNAMIC_ES(es))
+ kfree(es->bh);
+
+- kfree(es);
+ return err;
+ }
+
+@@ -813,14 +811,14 @@ struct exfat_dentry *exfat_get_dentry_cached(
+ * pointer of entry set on success,
+ * NULL on failure.
+ */
+-struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+- struct exfat_chain *p_dir, int entry, unsigned int type)
++int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
++ struct super_block *sb, struct exfat_chain *p_dir, int entry,
++ unsigned int type)
+ {
+ int ret, i, num_bh;
+ unsigned int off, byte_offset, clu = 0;
+ sector_t sec;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+- struct exfat_entry_set_cache *es;
+ struct exfat_dentry *ep;
+ int num_entries;
+ enum exfat_validate_dentry_mode mode = ES_MODE_STARTED;
+@@ -828,17 +826,15 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+
+ if (p_dir->dir == DIR_DELETED) {
+ exfat_err(sb, "access to deleted dentry");
+- return NULL;
++ return -EIO;
+ }
+
+ byte_offset = EXFAT_DEN_TO_B(entry);
+ ret = exfat_walk_fat_chain(sb, p_dir, byte_offset, &clu);
+ if (ret)
+- return NULL;
++ return ret;
+
+- es = kzalloc(sizeof(*es), GFP_KERNEL);
+- if (!es)
+- return NULL;
++ memset(es, 0, sizeof(*es));
+ es->sb = sb;
+ es->modified = false;
+
+@@ -856,7 +852,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+
+ bh = sb_bread(sb, sec);
+ if (!bh)
+- goto free_es;
++ return -EIO;
+ es->bh[es->num_bh++] = bh;
+
+ ep = exfat_get_dentry_cached(es, 0);
+@@ -872,8 +868,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+ es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_KERNEL);
+ if (!es->bh) {
+ brelse(bh);
+- kfree(es);
+- return NULL;
++ return -ENOMEM;
+ }
+ es->bh[0] = bh;
+ }
+@@ -902,11 +897,11 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+ if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
+ goto free_es;
+ }
+- return es;
++ return 0;
+
+ free_es:
+ exfat_free_dentry_set(es, false);
+- return NULL;
++ return -EIO;
+ }
+
+ enum {
+diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
+index 11e579a2598d8..6ecc7a51b4d18 100644
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -470,8 +470,9 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
+ sector_t *sector);
+ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
+ int num);
+-struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+- struct exfat_chain *p_dir, int entry, unsigned int type);
++int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
++ struct super_block *sb, struct exfat_chain *p_dir, int entry,
++ unsigned int type);
+ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync);
+ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir);
+
+diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
+index 4bd73820a4ac0..7f70284da530f 100644
+--- a/fs/exfat/inode.c
++++ b/fs/exfat/inode.c
+@@ -21,7 +21,7 @@ static int __exfat_write_inode(struct inode *inode, int sync)
+ {
+ unsigned long long on_disk_size;
+ struct exfat_dentry *ep, *ep2;
+- struct exfat_entry_set_cache *es = NULL;
++ struct exfat_entry_set_cache es;
+ struct super_block *sb = inode->i_sb;
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+@@ -42,11 +42,10 @@ static int __exfat_write_inode(struct inode *inode, int sync)
+ exfat_set_volume_dirty(sb);
+
+ /* get the directory entry of given file or directory */
+- es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES);
+- if (!es)
++ if (exfat_get_dentry_set(&es, sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES))
+ return -EIO;
+- ep = exfat_get_dentry_cached(es, 0);
+- ep2 = exfat_get_dentry_cached(es, 1);
++ ep = exfat_get_dentry_cached(&es, 0);
++ ep2 = exfat_get_dentry_cached(&es, 1);
+
+ ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode));
+
+@@ -76,8 +75,8 @@ static int __exfat_write_inode(struct inode *inode, int sync)
+ ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);
+ ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
+
+- exfat_update_dir_chksum_with_entry_set(es);
+- return exfat_free_dentry_set(es, sync);
++ exfat_update_dir_chksum_with_entry_set(&es);
++ return exfat_free_dentry_set(&es, sync);
+ }
+
+ int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
+diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
+index bd00afc5e4c16..10062b5282bd0 100644
+--- a/fs/exfat/namei.c
++++ b/fs/exfat/namei.c
+@@ -595,7 +595,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_inode_info *ei = EXFAT_I(dir);
+ struct exfat_dentry *ep, *ep2;
+- struct exfat_entry_set_cache *es;
++ struct exfat_entry_set_cache es;
+ /* for optimized dir & entry to prevent long traverse of cluster chain */
+ struct exfat_hint hint_opt;
+
+@@ -635,11 +635,10 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+ if (cdir.flags & ALLOC_NO_FAT_CHAIN)
+ cdir.size -= dentry / sbi->dentries_per_clu;
+ dentry = hint_opt.eidx;
+- es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
+- if (!es)
++ if (exfat_get_dentry_set(&es, sb, &cdir, dentry, ES_2_ENTRIES))
+ return -EIO;
+- ep = exfat_get_dentry_cached(es, 0);
+- ep2 = exfat_get_dentry_cached(es, 1);
++ ep = exfat_get_dentry_cached(&es, 0);
++ ep2 = exfat_get_dentry_cached(&es, 1);
+
+ info->type = exfat_get_entry_type(ep);
+ info->attr = le16_to_cpu(ep->dentry.file.attr);
+@@ -668,7 +667,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+ ep->dentry.file.access_time,
+ ep->dentry.file.access_date,
+ 0);
+- exfat_free_dentry_set(es, false);
++ exfat_free_dentry_set(&es, false);
+
+ if (ei->start_clu == EXFAT_FREE_CLUSTER) {
+ exfat_fs_error(sb,
+--
+2.40.1
+
--- /dev/null
+From 13ced2ee70174024313b574b2bbc769be56b2baf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Mar 2021 12:53:36 +0900
+Subject: exfat: speed up iterate/lookup by fixing start point of traversing
+ cluster chain
+
+From: Hyeongseok Kim <hyeongseok@gmail.com>
+
+[ Upstream commit c6e2f52e3051e8d898d38840104638ca8bbcdec2 ]
+
+When directory iterate and lookup is called, there's a buggy rewinding
+of start point for traversing cluster chain to the parent directory
+entry's first cluster. This caused repeated cluster chain traversing
+from the first entry of the parent directory that would show worse
+performance if huge amounts of files exist under the parent directory.
+Fix not to rewind, make continue from currently referenced cluster and
+dir entry.
+
+Tested with 50,000 files under single directory / 256GB sdcard,
+with command "time ls -l > /dev/null",
+Before : 0m08.69s real 0m00.27s user 0m05.91s system
+After : 0m07.01s real 0m00.25s user 0m04.34s system
+
+Signed-off-by: Hyeongseok Kim <hyeongseok@gmail.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
+Stable-dep-of: d42334578eba ("exfat: check if filename entries exceeds max filename length")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/dir.c | 19 +++++++++++++------
+ fs/exfat/exfat_fs.h | 2 +-
+ fs/exfat/namei.c | 9 ++++++++-
+ 3 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
+index 093f79ae3c671..0e1886f9a6241 100644
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -148,7 +148,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
+ 0);
+
+ *uni_name.name = 0x0;
+- exfat_get_uniname_from_ext_entry(sb, &dir, dentry,
++ exfat_get_uniname_from_ext_entry(sb, &clu, i,
+ uni_name.name);
+ exfat_utf16_to_nls(sb, &uni_name,
+ dir_entry->namebuf.lfn,
+@@ -902,14 +902,19 @@ enum {
+ };
+
+ /*
+- * return values:
+- * >= 0 : return dir entiry position with the name in dir
+- * -ENOENT : entry with the name does not exist
+- * -EIO : I/O error
++ * @ei: inode info of parent directory
++ * @p_dir: directory structure of parent directory
++ * @num_entries:entry size of p_uniname
++ * @hint_opt: If p_uniname is found, filled with optimized dir/entry
++ * for traversing cluster chain.
++ * @return:
++ * >= 0: file directory entry position where the name exists
++ * -ENOENT: entry with the name does not exist
++ * -EIO: I/O error
+ */
+ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
+ struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
+- int num_entries, unsigned int type)
++ int num_entries, unsigned int type, struct exfat_hint *hint_opt)
+ {
+ int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len;
+ int order, step, name_len = 0;
+@@ -986,6 +991,8 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
+
+ if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) {
+ step = DIRENT_STEP_FILE;
++ hint_opt->clu = clu.dir;
++ hint_opt->eidx = i;
+ if (type == TYPE_ALL || type == entry_type) {
+ num_ext = ep->dentry.file.num_ext;
+ step = DIRENT_STEP_STRM;
+diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
+index 07b09af57436f..436683da2515c 100644
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -458,7 +458,7 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es);
+ int exfat_calc_num_entries(struct exfat_uni_name *p_uniname);
+ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
+ struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
+- int num_entries, unsigned int type);
++ int num_entries, unsigned int type, struct exfat_hint *hint_opt);
+ int exfat_alloc_new_dir(struct inode *inode, struct exfat_chain *clu);
+ int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
+ int entry, sector_t *sector, int *offset);
+diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
+index 1382d816912c8..bd00afc5e4c16 100644
+--- a/fs/exfat/namei.c
++++ b/fs/exfat/namei.c
+@@ -596,6 +596,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+ struct exfat_inode_info *ei = EXFAT_I(dir);
+ struct exfat_dentry *ep, *ep2;
+ struct exfat_entry_set_cache *es;
++ /* for optimized dir & entry to prevent long traverse of cluster chain */
++ struct exfat_hint hint_opt;
+
+ if (qname->len == 0)
+ return -ENOENT;
+@@ -619,7 +621,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+
+ /* search the file name for directories */
+ dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name,
+- num_entries, TYPE_ALL);
++ num_entries, TYPE_ALL, &hint_opt);
+
+ if (dentry < 0)
+ return dentry; /* -error value */
+@@ -628,6 +630,11 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
+ info->entry = dentry;
+ info->num_subdirs = 0;
+
++ /* adjust cdir to the optimized value */
++ cdir.dir = hint_opt.clu;
++ if (cdir.flags & ALLOC_NO_FAT_CHAIN)
++ cdir.size -= dentry / sbi->dentries_per_clu;
++ dentry = hint_opt.eidx;
+ es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
+ if (!es)
+ return -EIO;
+--
+2.40.1
+
--- /dev/null
+From 1471114981b32b5b4deb18990e261e67e5ef6ddf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Nov 2022 13:50:22 +0800
+Subject: exfat: support dynamic allocate bh for exfat_entry_set_cache
+
+From: Yuezhang Mo <Yuezhang.Mo@sony.com>
+
+[ Upstream commit a3ff29a95fde16906304455aa8c0bd84eb770258 ]
+
+In special cases, a file or a directory may occupied more than 19
+directory entries, pre-allocating 3 bh is not enough. Such as
+ - Support vendor secondary directory entry in the future.
+ - Since file directory entry is damaged, the SecondaryCount
+ field is bigger than 18.
+
+So this commit supports dynamic allocation of bh.
+
+Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
+Reviewed-by: Andy Wu <Andy.Wu@sony.com>
+Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Stable-dep-of: d42334578eba ("exfat: check if filename entries exceeds max filename length")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/exfat/dir.c | 15 +++++++++++++++
+ fs/exfat/exfat_fs.h | 5 ++++-
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
+index 0e1886f9a6241..185aa13945d3d 100644
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -609,6 +609,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
+ bforget(es->bh[i]);
+ else
+ brelse(es->bh[i]);
++
++ if (IS_DYNAMIC_ES(es))
++ kfree(es->bh);
++
+ kfree(es);
+ return err;
+ }
+@@ -844,6 +848,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+ /* byte offset in sector */
+ off = EXFAT_BLK_OFFSET(byte_offset, sb);
+ es->start_off = off;
++ es->bh = es->__bh;
+
+ /* sector offset in cluster */
+ sec = EXFAT_B_TO_BLK(byte_offset, sb);
+@@ -863,6 +868,16 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
+ es->num_entries = num_entries;
+
+ num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
++ if (num_bh > ARRAY_SIZE(es->__bh)) {
++ es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_KERNEL);
++ if (!es->bh) {
++ brelse(bh);
++ kfree(es);
++ return NULL;
++ }
++ es->bh[0] = bh;
++ }
++
+ for (i = 1; i < num_bh; i++) {
+ /* get the next sector */
+ if (exfat_is_last_sector_in_cluster(sbi, sec)) {
+diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
+index 436683da2515c..11e579a2598d8 100644
+--- a/fs/exfat/exfat_fs.h
++++ b/fs/exfat/exfat_fs.h
+@@ -170,10 +170,13 @@ struct exfat_entry_set_cache {
+ bool modified;
+ unsigned int start_off;
+ int num_bh;
+- struct buffer_head *bh[DIR_CACHE_SIZE];
++ struct buffer_head *__bh[DIR_CACHE_SIZE];
++ struct buffer_head **bh;
+ unsigned int num_entries;
+ };
+
++#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
++
+ struct exfat_dir_entry {
+ struct exfat_chain dir;
+ int entry;
+--
+2.40.1
+
--- /dev/null
+From 961b846f4b586328bcb83c59be949312f4dbacca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Nov 2020 10:56:56 +0100
+Subject: mt76: move band capabilities in mt76_phy
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 48dbce5cb1ba3ce5b2ed3e997bcb1e4697d41b71 ]
+
+This is a preliminary patch to move properly support mt7915 dbdc
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Stable-dep-of: 421033deb915 ("wifi: mt76: mt7615: do not advertise 5 GHz on first phy of MT7615D (DBDC)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mac80211.c | 8 ++++----
+ drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
+ .../net/wireless/mediatek/mt76/mt7603/eeprom.c | 2 +-
+ drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 2 +-
+ .../net/wireless/mediatek/mt76/mt7615/eeprom.c | 16 ++++++++--------
+ .../net/wireless/mediatek/mt76/mt76x0/eeprom.c | 6 +++---
+ drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 4 ++--
+ drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 4 ++--
+ .../net/wireless/mediatek/mt76/mt76x02_eeprom.c | 8 ++++----
+ .../net/wireless/mediatek/mt76/mt7915/eeprom.c | 8 ++++----
+ drivers/net/wireless/mediatek/mt76/mt7915/init.c | 5 ++---
+ 11 files changed, 32 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
+index 81ff3b4c6c1b3..dc1191aa0443e 100644
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -160,9 +160,9 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
+
+ void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
+ {
+- if (phy->dev->cap.has_2ghz)
++ if (phy->cap.has_2ghz)
+ mt76_init_stream_cap(phy, &phy->sband_2g.sband, false);
+- if (phy->dev->cap.has_5ghz)
++ if (phy->cap.has_5ghz)
+ mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht);
+ }
+ EXPORT_SYMBOL_GPL(mt76_set_stream_caps);
+@@ -463,13 +463,13 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
+ dev_set_drvdata(dev->dev, dev);
+ mt76_phy_init(dev, hw);
+
+- if (dev->cap.has_2ghz) {
++ if (phy->cap.has_2ghz) {
+ ret = mt76_init_sband_2g(dev, rates, n_rates);
+ if (ret)
+ return ret;
+ }
+
+- if (dev->cap.has_5ghz) {
++ if (phy->cap.has_5ghz) {
+ ret = mt76_init_sband_5g(dev, rates + 4, n_rates - 4, vht);
+ if (ret)
+ return ret;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index 5a8060790a61f..16e65020a242d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -561,6 +561,7 @@ struct mt76_phy {
+ struct mt76_channel_state *chan_state;
+ ktime_t survey_time;
+
++ struct mt76_hw_cap cap;
+ struct mt76_sband sband_2g;
+ struct mt76_sband sband_5g;
+
+@@ -630,7 +631,6 @@ struct mt76_dev {
+
+ struct debugfs_blob_wrapper eeprom;
+ struct debugfs_blob_wrapper otp;
+- struct mt76_hw_cap cap;
+
+ struct mt76_rate_power rate_power;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
+index 01f1e0da5ee1e..a6df733aca492 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c
+@@ -170,7 +170,7 @@ int mt7603_eeprom_init(struct mt7603_dev *dev)
+ }
+
+ eeprom = (u8 *)dev->mt76.eeprom.data;
+- dev->mt76.cap.has_2ghz = true;
++ dev->mphy.cap.has_2ghz = true;
+ memcpy(dev->mt76.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN);
+
+ /* Check for 1SS devices */
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+index bf8ae14121dba..637ef0882436c 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
+@@ -202,7 +202,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
+ int ret;
+
+ /* Increase buffer size to receive large VHT MPDUs */
+- if (dev->mt76.cap.has_5ghz)
++ if (dev->mphy.cap.has_5ghz)
+ rx_buf_size *= 2;
+
+ mt76_dma_attach(&dev->mt76);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+index e9cdcdc54d5c3..714d1ff69c560 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+@@ -100,20 +100,20 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
+
+ if (is_mt7663(&dev->mt76)) {
+ /* dual band */
+- dev->mt76.cap.has_2ghz = true;
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_2ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ return;
+ }
+
+ if (is_mt7622(&dev->mt76)) {
+ /* 2GHz only */
+- dev->mt76.cap.has_2ghz = true;
++ dev->mphy.cap.has_2ghz = true;
+ return;
+ }
+
+ if (is_mt7611(&dev->mt76)) {
+ /* 5GHz only */
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ return;
+ }
+
+@@ -121,17 +121,17 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
+ eeprom[MT_EE_WIFI_CONF]);
+ switch (val) {
+ case MT_EE_5GHZ:
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ case MT_EE_2GHZ:
+- dev->mt76.cap.has_2ghz = true;
++ dev->mphy.cap.has_2ghz = true;
+ break;
+ case MT_EE_DBDC:
+ dev->dbdc_support = true;
+ /* fall through */
+ default:
+- dev->mt76.cap.has_2ghz = true;
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_2ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ }
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+index 9087607b621e8..ebf4c96532d31 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+@@ -52,15 +52,15 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
+
+ mt76x02_eeprom_parse_hw_cap(dev);
+ dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
+- dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
++ dev->mphy.cap.has_2ghz, dev->mphy.cap.has_5ghz);
+
+ if (dev->no_2ghz) {
+- dev->mt76.cap.has_2ghz = false;
++ dev->mphy.cap.has_2ghz = false;
+ dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
+ }
+
+ if (is_mt7630(dev)) {
+- dev->mt76.cap.has_5ghz = false;
++ dev->mphy.cap.has_5ghz = false;
+ dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");
+ }
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+index d78866bf41ba3..0bac39bf3b66d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+@@ -245,7 +245,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
+ if (ret)
+ return ret;
+
+- if (dev->mt76.cap.has_5ghz) {
++ if (dev->mphy.cap.has_5ghz) {
+ struct ieee80211_supported_band *sband;
+
+ sband = &dev->mphy.sband_5g.sband;
+@@ -253,7 +253,7 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
+ mt76x0_init_txpower(dev, sband);
+ }
+
+- if (dev->mt76.cap.has_2ghz)
++ if (dev->mphy.cap.has_2ghz)
+ mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband);
+
+ mt76x02_init_debugfs(dev);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+index 3de33aadf7941..e91c314cdfac5 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+@@ -447,11 +447,11 @@ static void mt76x0_phy_ant_select(struct mt76x02_dev *dev)
+ else
+ coex3 |= BIT(4);
+ coex3 |= BIT(3);
+- if (dev->mt76.cap.has_2ghz)
++ if (dev->mphy.cap.has_2ghz)
+ wlan |= BIT(6);
+ } else {
+ /* sigle antenna mode */
+- if (dev->mt76.cap.has_5ghz) {
++ if (dev->mphy.cap.has_5ghz) {
+ coex3 |= BIT(3) | BIT(4);
+ } else {
+ wlan |= BIT(6);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
+index c54c50fd639a9..0acabba2d1a50 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
+@@ -75,14 +75,14 @@ void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev)
+
+ switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {
+ case BOARD_TYPE_5GHZ:
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ case BOARD_TYPE_2GHZ:
+- dev->mt76.cap.has_2ghz = true;
++ dev->mphy.cap.has_2ghz = true;
+ break;
+ default:
+- dev->mt76.cap.has_2ghz = true;
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_2ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ }
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+index e4c5f968f706d..5f6c527611f20 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+@@ -57,14 +57,14 @@ static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
+ val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val);
+ switch (val) {
+ case MT_EE_5GHZ:
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ case MT_EE_2GHZ:
+- dev->mt76.cap.has_2ghz = true;
++ dev->mphy.cap.has_2ghz = true;
+ break;
+ default:
+- dev->mt76.cap.has_2ghz = true;
+- dev->mt76.cap.has_5ghz = true;
++ dev->mphy.cap.has_2ghz = true;
++ dev->mphy.cap.has_5ghz = true;
+ break;
+ }
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+index 8f01ca1694bca..99683688a8363 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+@@ -528,10 +528,9 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
+ {
+ struct ieee80211_sband_iftype_data *data;
+ struct ieee80211_supported_band *band;
+- struct mt76_dev *mdev = &phy->dev->mt76;
+ int n;
+
+- if (mdev->cap.has_2ghz) {
++ if (phy->mt76->cap.has_2ghz) {
+ data = phy->iftype[NL80211_BAND_2GHZ];
+ n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
+
+@@ -540,7 +539,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
+ band->n_iftype_data = n;
+ }
+
+- if (mdev->cap.has_5ghz) {
++ if (phy->mt76->cap.has_5ghz) {
+ data = phy->iftype[NL80211_BAND_5GHZ];
+ n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
+
+--
+2.40.1
+
--- /dev/null
+From dfd012be3e12f57e4560c60120630906b1a4e39c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 12:37:18 -0600
+Subject: mt76: mt7615: Fix fall-through warnings for Clang
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit f12758f6f929dbcd37abdb1d91d245539eca48f8 ]
+
+In preparation to enable -Wimplicit-fallthrough for Clang, fix a
+warning by replacing a /* fall through */ comment with the new
+pseudo-keyword macro fallthrough; instead of letting the code fall
+through to the next case.
+
+Notice that Clang doesn't recognize /* fall through */ comments as
+implicit fall-through markings.
+
+Link: https://github.com/KSPP/linux/issues/115
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Stable-dep-of: 421033deb915 ("wifi: mt76: mt7615: do not advertise 5 GHz on first phy of MT7615D (DBDC)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+index 714d1ff69c560..48ce24f0f77b7 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+@@ -128,7 +128,7 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
+ break;
+ case MT_EE_DBDC:
+ dev->dbdc_support = true;
+- /* fall through */
++ fallthrough;
+ default:
+ dev->mphy.cap.has_2ghz = true;
+ dev->mphy.cap.has_5ghz = true;
+--
+2.40.1
+
--- /dev/null
+From 19ecf8b860166f21bf563792f7dc0e775d3648f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jul 2023 16:57:39 +0200
+Subject: PM: sleep: wakeirq: fix wake irq arming
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 8527beb12087238d4387607597b4020bc393c4b4 ]
+
+The decision whether to enable a wake irq during suspend can not be done
+based on the runtime PM state directly as a driver may use wake irqs
+without implementing runtime PM. Such drivers specifically leave the
+state set to the default 'suspended' and the wake irq is thus never
+enabled at suspend.
+
+Add a new wake irq flag to track whether a dedicated wake irq has been
+enabled at runtime suspend and therefore must not be enabled at system
+suspend.
+
+Note that pm_runtime_enabled() can not be used as runtime PM is always
+disabled during late suspend.
+
+Fixes: 69728051f5bf ("PM / wakeirq: Fix unbalanced IRQ enable for wakeirq")
+Cc: 4.16+ <stable@vger.kernel.org> # 4.16+
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Tony Lindgren <tony@atomide.com>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/power/power.h | 1 +
+ drivers/base/power/wakeirq.c | 12 ++++++++----
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 0eb7f02b3ad59..922ed457db191 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -29,6 +29,7 @@ extern u64 pm_runtime_active_time(struct device *dev);
+ #define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
+ WAKE_IRQ_DEDICATED_MANAGED | \
+ WAKE_IRQ_DEDICATED_REVERSE)
++#define WAKE_IRQ_DEDICATED_ENABLED BIT(3)
+
+ struct wake_irq {
+ struct device *dev;
+diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
+index a6d53f0173d35..aea690c64e394 100644
+--- a/drivers/base/power/wakeirq.c
++++ b/drivers/base/power/wakeirq.c
+@@ -317,8 +317,10 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
+ return;
+
+ enable:
+- if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
++ if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {
+ enable_irq(wirq->irq);
++ wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
++ }
+ }
+
+ /**
+@@ -339,8 +341,10 @@ void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
+ if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
+ return;
+
+- if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
++ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {
++ wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;
+ disable_irq_nosync(wirq->irq);
++ }
+ }
+
+ /**
+@@ -379,7 +383,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq)
+
+ if (device_may_wakeup(wirq->dev)) {
+ if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
+- !pm_runtime_status_suspended(wirq->dev))
++ !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
+ enable_irq(wirq->irq);
+
+ enable_irq_wake(wirq->irq);
+@@ -402,7 +406,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
+ disable_irq_wake(wirq->irq);
+
+ if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
+- !pm_runtime_status_suspended(wirq->dev))
++ !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
+ disable_irq_nosync(wirq->irq);
+ }
+ }
+--
+2.40.1
+
--- /dev/null
+From 3f52d790fa0341c0dde5210361bba6b1153d215b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Oct 2021 15:01:53 +0800
+Subject: PM / wakeirq: support enabling wake-up irq after runtime_suspend
+ called
+
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+
+[ Upstream commit 259714100d98b50bf04d36a21bf50ca8b829fc11 ]
+
+When the dedicated wake IRQ is level trigger, and it uses the
+device's low-power status as the wakeup source, that means if the
+device is not in low-power state, the wake IRQ will be triggered
+if enabled; For this case, need enable the wake IRQ after running
+the device's ->runtime_suspend() which make it enter low-power state.
+
+e.g.
+Assume the wake IRQ is a low level trigger type, and the wakeup
+signal comes from the low-power status of the device.
+The wakeup signal is low level at running time (0), and becomes
+high level when the device enters low-power state (runtime_suspend
+(1) is called), a wakeup event at (2) make the device exit low-power
+state, then the wakeup signal also becomes low level.
+
+ ------------------
+ | ^ ^|
+---------------- | | --------------
+ |<---(0)--->|<--(1)--| (3) (2) (4)
+
+if enable the wake IRQ before running runtime_suspend during (0),
+a wake IRQ will arise, it causes resume immediately;
+it works if enable wake IRQ ( e.g. at (3) or (4)) after running
+->runtime_suspend().
+
+This patch introduces a new status WAKE_IRQ_DEDICATED_REVERSE to
+optionally support enabling wake IRQ after running ->runtime_suspend().
+
+Suggested-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 8527beb12087 ("PM: sleep: wakeirq: fix wake irq arming")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/power/power.h | 7 ++-
+ drivers/base/power/runtime.c | 6 ++-
+ drivers/base/power/wakeirq.c | 101 +++++++++++++++++++++++++++--------
+ include/linux/pm_wakeirq.h | 9 +++-
+ 4 files changed, 96 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 54292cdd7808b..0eb7f02b3ad59 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -25,8 +25,10 @@ extern u64 pm_runtime_active_time(struct device *dev);
+
+ #define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0)
+ #define WAKE_IRQ_DEDICATED_MANAGED BIT(1)
++#define WAKE_IRQ_DEDICATED_REVERSE BIT(2)
+ #define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
+- WAKE_IRQ_DEDICATED_MANAGED)
++ WAKE_IRQ_DEDICATED_MANAGED | \
++ WAKE_IRQ_DEDICATED_REVERSE)
+
+ struct wake_irq {
+ struct device *dev;
+@@ -39,7 +41,8 @@ extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
+ extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
+ extern void dev_pm_enable_wake_irq_check(struct device *dev,
+ bool can_change_status);
+-extern void dev_pm_disable_wake_irq_check(struct device *dev);
++extern void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable);
++extern void dev_pm_enable_wake_irq_complete(struct device *dev);
+
+ #ifdef CONFIG_PM_SLEEP
+
+diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
+index 360094692d29e..fbbc3ed143f27 100644
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -675,6 +675,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ if (retval)
+ goto fail;
+
++ dev_pm_enable_wake_irq_complete(dev);
++
+ no_callback:
+ __update_runtime_status(dev, RPM_SUSPENDED);
+ pm_runtime_deactivate_timer(dev);
+@@ -720,7 +722,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
+ return retval;
+
+ fail:
+- dev_pm_disable_wake_irq_check(dev);
++ dev_pm_disable_wake_irq_check(dev, true);
+ __update_runtime_status(dev, RPM_ACTIVE);
+ dev->power.deferred_resume = false;
+ wake_up_all(&dev->power.wait_queue);
+@@ -903,7 +905,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
+
+ callback = RPM_GET_CALLBACK(dev, runtime_resume);
+
+- dev_pm_disable_wake_irq_check(dev);
++ dev_pm_disable_wake_irq_check(dev, false);
+ retval = rpm_callback(callback, dev);
+ if (retval) {
+ __update_runtime_status(dev, RPM_SUSPENDED);
+diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
+index 8e021082dba8c..a6d53f0173d35 100644
+--- a/drivers/base/power/wakeirq.c
++++ b/drivers/base/power/wakeirq.c
+@@ -145,24 +145,7 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
+ return IRQ_HANDLED;
+ }
+
+-/**
+- * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
+- * @dev: Device entry
+- * @irq: Device wake-up interrupt
+- *
+- * Unless your hardware has separate wake-up interrupts in addition
+- * to the device IO interrupts, you don't need this.
+- *
+- * Sets up a threaded interrupt handler for a device that has
+- * a dedicated wake-up interrupt in addition to the device IO
+- * interrupt.
+- *
+- * The interrupt starts disabled, and needs to be managed for
+- * the device by the bus code or the device driver using
+- * dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq()
+- * functions.
+- */
+-int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
++static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
+ {
+ struct wake_irq *wirq;
+ int err;
+@@ -200,7 +183,7 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
+ if (err)
+ goto err_free_irq;
+
+- wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
++ wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag;
+
+ return err;
+
+@@ -213,8 +196,57 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
+
+ return err;
+ }
++
++
++/**
++ * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
++ * @dev: Device entry
++ * @irq: Device wake-up interrupt
++ *
++ * Unless your hardware has separate wake-up interrupts in addition
++ * to the device IO interrupts, you don't need this.
++ *
++ * Sets up a threaded interrupt handler for a device that has
++ * a dedicated wake-up interrupt in addition to the device IO
++ * interrupt.
++ *
++ * The interrupt starts disabled, and needs to be managed for
++ * the device by the bus code or the device driver using
++ * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
++ * functions.
++ */
++int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
++{
++ return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
++}
+ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
+
++/**
++ * dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt
++ * with reverse enable ordering
++ * @dev: Device entry
++ * @irq: Device wake-up interrupt
++ *
++ * Unless your hardware has separate wake-up interrupts in addition
++ * to the device IO interrupts, you don't need this.
++ *
++ * Sets up a threaded interrupt handler for a device that has a dedicated
++ * wake-up interrupt in addition to the device IO interrupt. It sets
++ * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
++ * to enable dedicated wake-up interrupt after running the runtime suspend
++ * callback for @dev.
++ *
++ * The interrupt starts disabled, and needs to be managed for
++ * the device by the bus code or the device driver using
++ * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
++ * functions.
++ */
++int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
++{
++ return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
++}
++EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
++
+ /**
+ * dev_pm_enable_wake_irq - Enable device wake-up interrupt
+ * @dev: Device
+@@ -285,27 +317,54 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
+ return;
+
+ enable:
+- enable_irq(wirq->irq);
++ if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
++ enable_irq(wirq->irq);
+ }
+
+ /**
+ * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
+ * @dev: Device
++ * @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE
+ *
+ * Disables wake-up interrupt conditionally based on status.
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ */
+-void dev_pm_disable_wake_irq_check(struct device *dev)
++void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
+ {
+ struct wake_irq *wirq = dev->power.wakeirq;
+
+ if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
+ return;
+
++ if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
++ return;
++
+ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+ disable_irq_nosync(wirq->irq);
+ }
+
++/**
++ * dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before
++ * @dev: Device using the wake IRQ
++ *
++ * Enable wake IRQ conditionally based on status, mainly used if want to
++ * enable wake IRQ after running ->runtime_suspend() which depends on
++ * WAKE_IRQ_DEDICATED_REVERSE.
++ *
++ * Should be only called from rpm_suspend() path.
++ */
++void dev_pm_enable_wake_irq_complete(struct device *dev)
++{
++ struct wake_irq *wirq = dev->power.wakeirq;
++
++ if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
++ return;
++
++ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
++ wirq->status & WAKE_IRQ_DEDICATED_REVERSE)
++ enable_irq(wirq->irq);
++}
++
+ /**
+ * dev_pm_arm_wake_irq - Arm device wake-up
+ * @wirq: Device wake-up interrupt
+diff --git a/include/linux/pm_wakeirq.h b/include/linux/pm_wakeirq.h
+index cd5b62db90845..e63a63aa47a37 100644
+--- a/include/linux/pm_wakeirq.h
++++ b/include/linux/pm_wakeirq.h
+@@ -17,8 +17,8 @@
+ #ifdef CONFIG_PM
+
+ extern int dev_pm_set_wake_irq(struct device *dev, int irq);
+-extern int dev_pm_set_dedicated_wake_irq(struct device *dev,
+- int irq);
++extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq);
++extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq);
+ extern void dev_pm_clear_wake_irq(struct device *dev);
+ extern void dev_pm_enable_wake_irq(struct device *dev);
+ extern void dev_pm_disable_wake_irq(struct device *dev);
+@@ -35,6 +35,11 @@ static inline int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
+ return 0;
+ }
+
++static inline int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
++{
++ return 0;
++}
++
+ static inline void dev_pm_clear_wake_irq(struct device *dev)
+ {
+ }
+--
+2.40.1
+
--- /dev/null
+From 945041e91c00299bf5298d73776ca3ce500fb85f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jun 2022 11:48:30 -0400
+Subject: selftests/rseq: check if libc rseq support is registered
+
+From: Michael Jeanson <mjeanson@efficios.com>
+
+[ Upstream commit d1a997ba4c1bf65497d956aea90de42a6398f73a ]
+
+When checking for libc rseq support in the library constructor, don't
+only depend on the symbols presence, check that the registration was
+completed.
+
+This targets a scenario where the libc has rseq support but it is not
+wired for the current architecture in 'bits/rseq.h', we want to fallback
+to our internal registration mechanism.
+
+Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Link: https://lore.kernel.org/r/20220614154830.1367382-4-mjeanson@efficios.com
+Stable-dep-of: 3bcbc20942db ("selftests/rseq: Play nice with binaries statically linked against glibc 2.35+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/rseq/rseq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
+index 986b9458efb26..4177f9507bbee 100644
+--- a/tools/testing/selftests/rseq/rseq.c
++++ b/tools/testing/selftests/rseq/rseq.c
+@@ -111,7 +111,8 @@ void rseq_init(void)
+ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+- if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p) {
++ if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
++ *libc_rseq_size_p != 0) {
+ /* rseq registration owned by glibc */
+ rseq_offset = *libc_rseq_offset_p;
+ rseq_size = *libc_rseq_size_p;
+--
+2.40.1
+
--- /dev/null
+From be2e644ce622bb85699da2eab45fe0b43cf7b8d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 15:33:52 -0700
+Subject: selftests/rseq: Play nice with binaries statically linked against
+ glibc 2.35+
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 3bcbc20942db5d738221cca31a928efc09827069 ]
+
+To allow running rseq and KVM's rseq selftests as statically linked
+binaries, initialize the various "trampoline" pointers to point directly
+at the expect glibc symbols, and skip the dlysm() lookups if the rseq
+size is non-zero, i.e. the binary is statically linked *and* the libc
+registered its own rseq.
+
+Define weak versions of the symbols so as not to break linking against
+libc versions that don't support rseq in any capacity.
+
+The KVM selftests in particular are often statically linked so that they
+can be run on targets with very limited runtime environments, i.e. test
+machines.
+
+Fixes: 233e667e1ae3 ("selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35")
+Cc: Aaron Lewis <aaronlewis@google.com>
+Cc: kvm@vger.kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20230721223352.2333911-1-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/rseq/rseq.c | 28 ++++++++++++++++++++++------
+ 1 file changed, 22 insertions(+), 6 deletions(-)
+
+diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
+index 4177f9507bbee..b736a5169aad0 100644
+--- a/tools/testing/selftests/rseq/rseq.c
++++ b/tools/testing/selftests/rseq/rseq.c
+@@ -32,9 +32,17 @@
+ #include "../kselftest.h"
+ #include "rseq.h"
+
+-static const ptrdiff_t *libc_rseq_offset_p;
+-static const unsigned int *libc_rseq_size_p;
+-static const unsigned int *libc_rseq_flags_p;
++/*
++ * Define weak versions to play nice with binaries that are statically linked
++ * against a libc that doesn't support registering its own rseq.
++ */
++__weak ptrdiff_t __rseq_offset;
++__weak unsigned int __rseq_size;
++__weak unsigned int __rseq_flags;
++
++static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;
++static const unsigned int *libc_rseq_size_p = &__rseq_size;
++static const unsigned int *libc_rseq_flags_p = &__rseq_flags;
+
+ /* Offset from the thread pointer to the rseq area. */
+ ptrdiff_t rseq_offset;
+@@ -108,9 +116,17 @@ int rseq_unregister_current_thread(void)
+ static __attribute__((constructor))
+ void rseq_init(void)
+ {
+- libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+- libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+- libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
++ /*
++ * If the libc's registered rseq size isn't already valid, it may be
++ * because the binary is dynamically linked and not necessarily due to
++ * libc not having registered a restartable sequence. Try to find the
++ * symbols if that's the case.
++ */
++ if (!*libc_rseq_size_p) {
++ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
++ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
++ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
++ }
+ if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
+ *libc_rseq_size_p != 0) {
+ /* rseq registration owned by glibc */
+--
+2.40.1
+
mtd-rawnand-omap_elm-fix-incorrect-type-in-assignmen.patch
mtd-rawnand-fsl_upm-fix-an-off-by-one-test-in-fun_ex.patch
powerpc-mm-altmap-fix-altmap-boundary-check.patch
+selftests-rseq-check-if-libc-rseq-support-is-registe.patch
+selftests-rseq-play-nice-with-binaries-statically-li.patch
+soundwire-bus-add-better-dev_dbg-to-track-complete-c.patch
+soundwire-bus-pm_runtime_request_resume-on-periphera.patch
+soundwire-fix-enumeration-completion.patch
+pm-wakeirq-support-enabling-wake-up-irq-after-runtim.patch
+pm-sleep-wakeirq-fix-wake-irq-arming.patch
+exfat-speed-up-iterate-lookup-by-fixing-start-point-.patch
+exfat-support-dynamic-allocate-bh-for-exfat_entry_se.patch
+exfat-move-exfat_entry_set_cache-from-heap-to-stack.patch
+exfat-check-if-filename-entries-exceeds-max-filename.patch
+mt76-move-band-capabilities-in-mt76_phy.patch
+mt76-mt7615-fix-fall-through-warnings-for-clang.patch
+wifi-mt76-mt7615-do-not-advertise-5-ghz-on-first-phy.patch
+arm-dts-imx-add-usb-alias.patch
+arm-dts-imx6sll-fixup-of-operating-points.patch
+arm-dts-nxp-imx6sll-fix-wrong-property-name-in-usbph.patch
--- /dev/null
+From 45c65ae606247cb635ae0300f98b651bce8da65b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Jan 2021 16:54:02 +0800
+Subject: soundwire: bus: add better dev_dbg to track complete() calls
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit f1b690261247c9895f7a4b05d14a4026739134eb ]
+
+Add a dev_dbg() log for both enumeration and initialization completion
+to better track suspend-resume issues.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Chao Song <chao.song@intel.com>
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20210126085402.4264-1-yung-chuan.liao@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: c40d6b3249b1 ("soundwire: fix enumeration completion")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/bus.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
+index 3317a02bcc170..9c7c8fa7f53e4 100644
+--- a/drivers/soundwire/bus.c
++++ b/drivers/soundwire/bus.c
+@@ -797,7 +797,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
+
+ if (status == SDW_SLAVE_UNATTACHED) {
+ dev_dbg(&slave->dev,
+- "%s: initializing completion for Slave %d\n",
++ "%s: initializing enumeration and init completion for Slave %d\n",
+ __func__, slave->dev_num);
+
+ init_completion(&slave->enumeration_complete);
+@@ -806,7 +806,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
+ } else if ((status == SDW_SLAVE_ATTACHED) &&
+ (slave->status == SDW_SLAVE_UNATTACHED)) {
+ dev_dbg(&slave->dev,
+- "%s: signaling completion for Slave %d\n",
++ "%s: signaling enumeration completion for Slave %d\n",
+ __func__, slave->dev_num);
+
+ complete(&slave->enumeration_complete);
+@@ -1734,8 +1734,13 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
+ if (ret)
+ dev_err(slave->bus->dev,
+ "Update Slave status failed:%d\n", ret);
+- if (attached_initializing)
++ if (attached_initializing) {
++ dev_dbg(&slave->dev,
++ "%s: signaling initialization completion for Slave %d\n",
++ __func__, slave->dev_num);
++
+ complete(&slave->initialization_complete);
++ }
+ }
+
+ return ret;
+--
+2.40.1
+
--- /dev/null
+From 5ffae591a68f43d3eb9e9d356ca00f0d5913a430 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Apr 2022 10:32:41 +0800
+Subject: soundwire: bus: pm_runtime_request_resume on peripheral attachment
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit e557bca49b812908f380c56b5b4b2f273848b676 ]
+
+In typical use cases, the peripheral becomes pm_runtime active as a
+result of the ALSA/ASoC framework starting up a DAI. The parent/child
+hierarchy guarantees that the manager device will be fully resumed
+beforehand.
+
+There is however a corner case where the manager device may become
+pm_runtime active, but without ALSA/ASoC requesting any functionality
+from the peripherals. In this case, the hardware peripheral device
+will report as ATTACHED and its initialization routine will be
+executed. If this initialization routine initiates any sort of
+deferred processing, there is a possibility that the manager could
+suspend without the peripheral suspend sequence being invoked: from
+the pm_runtime framework perspective, the peripheral is *already*
+suspended.
+
+To avoid such disconnects between hardware state and pm_runtime state,
+this patch adds an asynchronous pm_request_resume() upon successful
+attach/initialization which will result in the proper resume/suspend
+sequence to be followed on the peripheral side.
+
+BugLink: https://github.com/thesofproject/linux/issues/3459
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20220420023241.14335-4-yung-chuan.liao@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: c40d6b3249b1 ("soundwire: fix enumeration completion")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/bus.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
+index 9c7c8fa7f53e4..831d2d751d5de 100644
+--- a/drivers/soundwire/bus.c
++++ b/drivers/soundwire/bus.c
+@@ -1740,6 +1740,18 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
+ __func__, slave->dev_num);
+
+ complete(&slave->initialization_complete);
++
++ /*
++ * If the manager became pm_runtime active, the peripherals will be
++ * restarted and attach, but their pm_runtime status may remain
++ * suspended. If the 'update_slave_status' callback initiates
++ * any sort of deferred processing, this processing would not be
++ * cancelled on pm_runtime suspend.
++ * To avoid such zombie states, we queue a request to resume.
++ * This would be a no-op in case the peripheral was being resumed
++ * by e.g. the ALSA/ASoC framework.
++ */
++ pm_request_resume(&slave->dev);
+ }
+ }
+
+--
+2.40.1
+
--- /dev/null
+From ac0a9a3463f50897e4f926073b4aa0cc9e473401 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jul 2023 14:30:11 +0200
+Subject: soundwire: fix enumeration completion
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit c40d6b3249b11d60e09d81530588f56233d9aa44 ]
+
+The soundwire subsystem uses two completion structures that allow
+drivers to wait for soundwire device to become enumerated on the bus and
+initialised by their drivers, respectively.
+
+The code implementing the signalling is currently broken as it does not
+signal all current and future waiters and also uses the wrong
+reinitialisation function, which can potentially lead to memory
+corruption if there are still waiters on the queue.
+
+Not signalling future waiters specifically breaks sound card probe
+deferrals as codec drivers can not tell that the soundwire device is
+already attached when being reprobed. Some codec runtime PM
+implementations suffer from similar problems as waiting for enumeration
+during resume can also timeout despite the device already having been
+enumerated.
+
+Fixes: fb9469e54fa7 ("soundwire: bus: fix race condition with enumeration_complete signaling")
+Fixes: a90def068127 ("soundwire: bus: fix race condition with initialization_complete signaling")
+Cc: stable@vger.kernel.org # 5.7
+Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Cc: Rander Wang <rander.wang@linux.intel.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20230705123018.30903-2-johan+linaro@kernel.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/bus.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
+index 831d2d751d5de..0e0a19030c35b 100644
+--- a/drivers/soundwire/bus.c
++++ b/drivers/soundwire/bus.c
+@@ -800,8 +800,8 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
+ "%s: initializing enumeration and init completion for Slave %d\n",
+ __func__, slave->dev_num);
+
+- init_completion(&slave->enumeration_complete);
+- init_completion(&slave->initialization_complete);
++ reinit_completion(&slave->enumeration_complete);
++ reinit_completion(&slave->initialization_complete);
+
+ } else if ((status == SDW_SLAVE_ATTACHED) &&
+ (slave->status == SDW_SLAVE_UNATTACHED)) {
+@@ -809,7 +809,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
+ "%s: signaling enumeration completion for Slave %d\n",
+ __func__, slave->dev_num);
+
+- complete(&slave->enumeration_complete);
++ complete_all(&slave->enumeration_complete);
+ }
+ slave->status = status;
+ mutex_unlock(&slave->bus->bus_lock);
+@@ -1739,7 +1739,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
+ "%s: signaling initialization completion for Slave %d\n",
+ __func__, slave->dev_num);
+
+- complete(&slave->initialization_complete);
++ complete_all(&slave->initialization_complete);
+
+ /*
+ * If the manager became pm_runtime active, the peripherals will be
+--
+2.40.1
+
--- /dev/null
+From 89c58c4fe58d72c8530f29e1853d59b3c17750c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Jun 2023 10:34:07 +0300
+Subject: wifi: mt76: mt7615: do not advertise 5 GHz on first phy of MT7615D
+ (DBDC)
+
+From: Paul Fertser <fercerpav@gmail.com>
+
+[ Upstream commit 421033deb91521aa6a9255e495cb106741a52275 ]
+
+On DBDC devices the first (internal) phy is only capable of using
+2.4 GHz band, and the 5 GHz band is exposed via a separate phy object,
+so avoid the false advertising.
+
+Reported-by: Rani Hod <rani.hod@gmail.com>
+Closes: https://github.com/openwrt/openwrt/pull/12361
+Fixes: 7660a1bd0c22 ("mt76: mt7615: register ext_phy if DBDC is detected")
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul Fertser <fercerpav@gmail.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Acked-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230605073408.8699-1-fercerpav@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+index 48ce24f0f77b7..85f56487feff2 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+@@ -123,12 +123,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
+ case MT_EE_5GHZ:
+ dev->mphy.cap.has_5ghz = true;
+ break;
+- case MT_EE_2GHZ:
+- dev->mphy.cap.has_2ghz = true;
+- break;
+ case MT_EE_DBDC:
+ dev->dbdc_support = true;
+ fallthrough;
++ case MT_EE_2GHZ:
++ dev->mphy.cap.has_2ghz = true;
++ break;
+ default:
+ dev->mphy.cap.has_2ghz = true;
+ dev->mphy.cap.has_5ghz = true;
+--
+2.40.1
+