From ad827d8d3e6d535bc21d3c9bc1756a40e65a68b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 30 Jul 2024 16:14:21 +0200 Subject: [PATCH] 6.6-stable patches added patches: bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch mm-mglru-fix-ineffective-protection-calculation.patch nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch wifi-mac80211-track-capability-opmode-nss-separately.patch --- ...k-rtl8852be-support-id-0x13d3-0x3591.patch | 65 ++++++ ...be-device-0489-e125-to-device-tables.patch | 63 ++++++ ...he-full-path-of-the-script-in-output.patch | 60 ++++++ ...ax-scsi-fix-mis-use-of-clamp-in-sr.c.patch | 48 +++++ ...x-ineffective-protection-calculation.patch | 184 +++++++++++++++++ ...t-state-in-nilfs_btnode_create_block.patch | 97 +++++++++ ...ee-on-concurrent-dpc-and-hot-removal.patch | 87 ++++++++ ...or-device-reference-counts-and-locks.patch | 88 ++++++++ queue-6.6/series | 10 + ...the-input-filename-in-generated-file.patch | 36 ++++ ...ack-capability-opmode-nss-separately.patch | 191 ++++++++++++++++++ 11 files changed, 929 insertions(+) create mode 100644 queue-6.6/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch create mode 100644 queue-6.6/bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch create mode 100644 queue-6.6/lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch create mode 100644 queue-6.6/minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch create mode 100644 queue-6.6/mm-mglru-fix-ineffective-protection-calculation.patch create mode 100644 queue-6.6/nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch create mode 100644 queue-6.6/pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch create mode 100644 queue-6.6/pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch create mode 100644 queue-6.6/video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch create mode 100644 queue-6.6/wifi-mac80211-track-capability-opmode-nss-separately.patch diff --git a/queue-6.6/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch b/queue-6.6/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch new file mode 100644 index 00000000000..20339c27460 --- /dev/null +++ b/queue-6.6/bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch @@ -0,0 +1,65 @@ +From 473a89b4ed7fd52a419340f7c540d5c8fc96fc75 Mon Sep 17 00:00:00 2001 +From: WangYuli +Date: Sat, 22 Jun 2024 12:09:59 +0800 +Subject: Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x13d3:0x3591 + +From: WangYuli + +commit 473a89b4ed7fd52a419340f7c540d5c8fc96fc75 upstream. + +Add the support ID(0x13d3, 0x3591) to usb_device_id table for +Realtek RTL8852BE. + +The device table is as follows: + +T: Bus=01 Lev=02 Prnt=03 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=13d3 ProdID=3591 Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Cc: stable@vger.kernel.org +Signed-off-by: Wentao Guan +Signed-off-by: WangYuli +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Erpeng Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -551,6 +551,8 @@ static const struct usb_device_id quirks + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + diff --git a/queue-6.6/bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch b/queue-6.6/bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch new file mode 100644 index 00000000000..77e57251d9a --- /dev/null +++ b/queue-6.6/bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch @@ -0,0 +1,63 @@ +From 295ef07a9dae6182ad4b689aa8c6a7dbba21474c Mon Sep 17 00:00:00 2001 +From: Hilda Wu +Date: Mon, 17 Jun 2024 17:05:18 +0800 +Subject: Bluetooth: btusb: Add RTL8852BE device 0489:e125 to device tables + +From: Hilda Wu + +commit 295ef07a9dae6182ad4b689aa8c6a7dbba21474c upstream. + +Add the support ID 0489:e125 to usb_device_id table for +Realtek RTL8852B chip. + +The device info from /sys/kernel/debug/usb/devices as below. + +T: Bus=01 Lev=01 Prnt=01 Port=07 Cnt=03 Dev#= 5 Spd=12 MxCh= 0 +D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 +P: Vendor=0489 ProdID=e125 Rev= 0.00 +S: Manufacturer=Realtek +S: Product=Bluetooth Radio +S: SerialNumber=00e04c000001 +C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms +E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms +I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms +I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms +I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms +I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms +I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms +I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb +E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms +E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms + +Signed-off-by: Hilda Wu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Erpeng Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/bluetooth/btusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -551,6 +551,8 @@ static const struct usb_device_id quirks + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Realtek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), diff --git a/queue-6.6/lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch b/queue-6.6/lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch new file mode 100644 index 00000000000..1c904925789 --- /dev/null +++ b/queue-6.6/lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch @@ -0,0 +1,60 @@ +From 5ef6dc08cfde240b8c748733759185646e654570 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= +Date: Wed, 13 Mar 2024 22:19:56 +0100 +Subject: lib/build_OID_registry: don't mention the full path of the script in output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +commit 5ef6dc08cfde240b8c748733759185646e654570 upstream. + +This change strips the full path of the script generating +lib/oid_registry_data.c to just lib/build_OID_registry. The motivation +for this change is Yocto emitting a build warning + + File /usr/src/debug/linux-lxatac/6.7-r0/lib/oid_registry_data.c in package linux-lxatac-src contains reference to TMPDIR [buildpaths] + +So this change brings us one step closer to make the build result +reproducible independent of the build path. + +Link: https://lkml.kernel.org/r/20240313211957.884561-2-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Cc: Masahiro Yamada +Reviewed-by: Nicolas Schier +Signed-off-by: Andrew Morton +Cc: Fabio Estevam +Signed-off-by: Greg Kroah-Hartman +--- + lib/build_OID_registry | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/lib/build_OID_registry ++++ b/lib/build_OID_registry +@@ -8,6 +8,7 @@ + # + + use strict; ++use Cwd qw(abs_path); + + my @names = (); + my @oids = (); +@@ -17,6 +18,8 @@ if ($#ARGV != 1) { + exit(2); + } + ++my $abs_srctree = abs_path($ENV{'srctree'}); ++ + # + # Open the file to read from + # +@@ -35,7 +38,7 @@ close IN_FILE || die; + # + open C_FILE, ">$ARGV[1]" or die; + print C_FILE "/*\n"; +-print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; ++print C_FILE " * Automatically generated by ", $0 =~ s#^\Q$abs_srctree/\E##r, ". Do not edit\n"; + print C_FILE " */\n"; + + # diff --git a/queue-6.6/minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch b/queue-6.6/minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch new file mode 100644 index 00000000000..be59a768cdd --- /dev/null +++ b/queue-6.6/minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch @@ -0,0 +1,48 @@ +From 9f499b8c791d2983c0a31a543c51d1b2f15e8755 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Sun, 28 Jul 2024 17:06:20 -0700 +Subject: minmax: scsi: fix mis-use of 'clamp()' in sr.c + +From: Linus Torvalds + +commit 9f499b8c791d2983c0a31a543c51d1b2f15e8755 upstream. + +While working on simplifying the minmax functions, and avoiding +excessive macro expansion, it turns out that the sr.c use of the +'clamp()' macro has the arguments the wrong way around. + +The clamp logic is + + val = clamp(in, low, high); + +and it returns the input clamped to the low/high limits. But sr.c ddid + + speed = clamp(0, speed, 0xffff / 177); + +which clamps the value '0' to the range '[speed, 0xffff / 177]' and ends +up being nonsensical. + +Happily, I don't think anybody ever cared. + +Fixes: 9fad9d560af5 ("scsi: sr: Fix unintentional arithmetic wraparound") +Cc: Justin Stitt +Cc: Kees Cook +Cc: Martin K. Petersen +Signed-off-by: Linus Torvalds +Cc: Wentao Guan +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sr_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/sr_ioctl.c ++++ b/drivers/scsi/sr_ioctl.c +@@ -431,7 +431,7 @@ int sr_select_speed(struct cdrom_device_ + struct packet_command cgc; + + /* avoid exceeding the max speed or overflowing integer bounds */ +- speed = clamp(0, speed, 0xffff / 177); ++ speed = clamp(speed, 0, 0xffff / 177); + + if (speed == 0) + speed = 0xffff; /* set to max */ diff --git a/queue-6.6/mm-mglru-fix-ineffective-protection-calculation.patch b/queue-6.6/mm-mglru-fix-ineffective-protection-calculation.patch new file mode 100644 index 00000000000..ef587470573 --- /dev/null +++ b/queue-6.6/mm-mglru-fix-ineffective-protection-calculation.patch @@ -0,0 +1,184 @@ +From 30d77b7eef019fa4422980806e8b7cdc8674493e Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Fri, 12 Jul 2024 17:29:56 -0600 +Subject: mm/mglru: fix ineffective protection calculation + +From: Yu Zhao + +commit 30d77b7eef019fa4422980806e8b7cdc8674493e upstream. + +mem_cgroup_calculate_protection() is not stateless and should only be used +as part of a top-down tree traversal. shrink_one() traverses the per-node +memcg LRU instead of the root_mem_cgroup tree, and therefore it should not +call mem_cgroup_calculate_protection(). + +The existing misuse in shrink_one() can cause ineffective protection of +sub-trees that are grandchildren of root_mem_cgroup. Fix it by reusing +lru_gen_age_node(), which already traverses the root_mem_cgroup tree, to +calculate the protection. + +Previously lru_gen_age_node() opportunistically skips the first pass, +i.e., when scan_control->priority is DEF_PRIORITY. On the second pass, +lruvec_is_sizable() uses appropriate scan_control->priority, set by +set_initial_priority() from lru_gen_shrink_node(), to decide whether a +memcg is too small to reclaim from. + +Now lru_gen_age_node() unconditionally traverses the root_mem_cgroup tree. +So it should call set_initial_priority() upfront, to make sure +lruvec_is_sizable() uses appropriate scan_control->priority on the first +pass. Otherwise, lruvec_is_reclaimable() can return false negatives and +result in premature OOM kills when min_ttl_ms is used. + +Link: https://lkml.kernel.org/r/20240712232956.1427127-1-yuzhao@google.com +Fixes: e4dde56cd208 ("mm: multi-gen LRU: per-node lru_gen_folio lists") +Signed-off-by: Yu Zhao +Reported-by: T.J. Mercier +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/vmscan.c | 83 +++++++++++++++++++++++++++--------------------------------- + 1 file changed, 38 insertions(+), 45 deletions(-) + +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4546,6 +4546,32 @@ done: + * working set protection + ******************************************************************************/ + ++static void set_initial_priority(struct pglist_data *pgdat, struct scan_control *sc) ++{ ++ int priority; ++ unsigned long reclaimable; ++ ++ if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH) ++ return; ++ /* ++ * Determine the initial priority based on ++ * (total >> priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, ++ * where reclaimed_to_scanned_ratio = inactive / total. ++ */ ++ reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE); ++ if (can_reclaim_anon_pages(NULL, pgdat->node_id, sc)) ++ reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON); ++ ++ /* round down reclaimable and round up sc->nr_to_reclaim */ ++ priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1); ++ ++ /* ++ * The estimation is based on LRU pages only, so cap it to prevent ++ * overshoots of shrinker objects by large margins. ++ */ ++ sc->priority = clamp(priority, DEF_PRIORITY / 2, DEF_PRIORITY); ++} ++ + static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) + { + int gen, type, zone; +@@ -4579,19 +4605,17 @@ static bool lruvec_is_reclaimable(struct + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MIN_SEQ(lruvec); + +- /* see the comment on lru_gen_folio */ +- gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); +- birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); +- +- if (time_is_after_jiffies(birth + min_ttl)) ++ if (mem_cgroup_below_min(NULL, memcg)) + return false; + + if (!lruvec_is_sizable(lruvec, sc)) + return false; + +- mem_cgroup_calculate_protection(NULL, memcg); ++ /* see the comment on lru_gen_folio */ ++ gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); ++ birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); + +- return !mem_cgroup_below_min(NULL, memcg); ++ return time_is_before_jiffies(birth + min_ttl); + } + + /* to protect the working set of the last N jiffies */ +@@ -4601,23 +4625,20 @@ static void lru_gen_age_node(struct pgli + { + struct mem_cgroup *memcg; + unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); ++ bool reclaimable = !min_ttl; + + VM_WARN_ON_ONCE(!current_is_kswapd()); + +- /* check the order to exclude compaction-induced reclaim */ +- if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) +- return; ++ set_initial_priority(pgdat, sc); + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); + +- if (lruvec_is_reclaimable(lruvec, sc, min_ttl)) { +- mem_cgroup_iter_break(NULL, memcg); +- return; +- } ++ mem_cgroup_calculate_protection(NULL, memcg); + +- cond_resched(); ++ if (!reclaimable) ++ reclaimable = lruvec_is_reclaimable(lruvec, sc, min_ttl); + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); + + /* +@@ -4625,7 +4646,7 @@ static void lru_gen_age_node(struct pgli + * younger than min_ttl. However, another possibility is all memcgs are + * either too small or below min. + */ +- if (mutex_trylock(&oom_lock)) { ++ if (!reclaimable && mutex_trylock(&oom_lock)) { + struct oom_control oc = { + .gfp_mask = sc->gfp_mask, + }; +@@ -5424,8 +5445,7 @@ static int shrink_one(struct lruvec *lru + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + +- mem_cgroup_calculate_protection(NULL, memcg); +- ++ /* lru_gen_age_node() called mem_cgroup_calculate_protection() */ + if (mem_cgroup_below_min(NULL, memcg)) + return MEMCG_LRU_YOUNG; + +@@ -5565,33 +5585,6 @@ static void lru_gen_shrink_lruvec(struct + + #endif + +-static void set_initial_priority(struct pglist_data *pgdat, struct scan_control *sc) +-{ +- int priority; +- unsigned long reclaimable; +- struct lruvec *lruvec = mem_cgroup_lruvec(NULL, pgdat); +- +- if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH) +- return; +- /* +- * Determine the initial priority based on +- * (total >> priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, +- * where reclaimed_to_scanned_ratio = inactive / total. +- */ +- reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE); +- if (get_swappiness(lruvec, sc)) +- reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON); +- +- /* round down reclaimable and round up sc->nr_to_reclaim */ +- priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1); +- +- /* +- * The estimation is based on LRU pages only, so cap it to prevent +- * overshoots of shrinker objects by large margins. +- */ +- sc->priority = clamp(priority, DEF_PRIORITY / 2, DEF_PRIORITY); +-} +- + static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *sc) + { + struct blk_plug plug; diff --git a/queue-6.6/nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch b/queue-6.6/nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch new file mode 100644 index 00000000000..6660c7e327c --- /dev/null +++ b/queue-6.6/nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch @@ -0,0 +1,97 @@ +From 4811f7af6090e8f5a398fbdd766f903ef6c0d787 Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Thu, 25 Jul 2024 14:20:07 +0900 +Subject: nilfs2: handle inconsistent state in nilfs_btnode_create_block() + +From: Ryusuke Konishi + +commit 4811f7af6090e8f5a398fbdd766f903ef6c0d787 upstream. + +Syzbot reported that a buffer state inconsistency was detected in +nilfs_btnode_create_block(), triggering a kernel bug. + +It is not appropriate to treat this inconsistency as a bug; it can occur +if the argument block address (the buffer index of the newly created +block) is a virtual block number and has been reallocated due to +corruption of the bitmap used to manage its allocation state. + +So, modify nilfs_btnode_create_block() and its callers to treat it as a +possible filesystem error, rather than triggering a kernel bug. + +Link: https://lkml.kernel.org/r/20240725052007.4562-1-konishi.ryusuke@gmail.com +Fixes: a60be987d45d ("nilfs2: B-tree node cache") +Signed-off-by: Ryusuke Konishi +Reported-by: syzbot+89cc4f2324ed37988b60@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=89cc4f2324ed37988b60 +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/nilfs2/btnode.c | 25 ++++++++++++++++++++----- + fs/nilfs2/btree.c | 4 ++-- + 2 files changed, 22 insertions(+), 7 deletions(-) + +--- a/fs/nilfs2/btnode.c ++++ b/fs/nilfs2/btnode.c +@@ -51,12 +51,21 @@ nilfs_btnode_create_block(struct address + + bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node)); + if (unlikely(!bh)) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) || + buffer_dirty(bh))) { +- brelse(bh); +- BUG(); ++ /* ++ * The block buffer at the specified new address was already ++ * in use. This can happen if it is a virtual block number ++ * and has been reallocated due to corruption of the bitmap ++ * used to manage its allocation state (if not, the buffer ++ * clearing of an abandoned b-tree node is missing somewhere). ++ */ ++ nilfs_error(inode->i_sb, ++ "state inconsistency probably due to duplicate use of b-tree node block address %llu (ino=%lu)", ++ (unsigned long long)blocknr, inode->i_ino); ++ goto failed; + } + memset(bh->b_data, 0, i_blocksize(inode)); + bh->b_bdev = inode->i_sb->s_bdev; +@@ -67,6 +76,12 @@ nilfs_btnode_create_block(struct address + unlock_page(bh->b_page); + put_page(bh->b_page); + return bh; ++ ++failed: ++ unlock_page(bh->b_page); ++ put_page(bh->b_page); ++ brelse(bh); ++ return ERR_PTR(-EIO); + } + + int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, +@@ -217,8 +232,8 @@ retry: + } + + nbh = nilfs_btnode_create_block(btnc, newkey); +- if (!nbh) +- return -ENOMEM; ++ if (IS_ERR(nbh)) ++ return PTR_ERR(nbh); + + BUG_ON(nbh == obh); + ctxt->newbh = nbh; +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -63,8 +63,8 @@ static int nilfs_btree_get_new_block(con + struct buffer_head *bh; + + bh = nilfs_btnode_create_block(btnc, ptr); +- if (!bh) +- return -ENOMEM; ++ if (IS_ERR(bh)) ++ return PTR_ERR(bh); + + set_buffer_nilfs_volatile(bh); + *bhp = bh; diff --git a/queue-6.6/pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch b/queue-6.6/pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch new file mode 100644 index 00000000000..8dfaa6dd0ec --- /dev/null +++ b/queue-6.6/pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch @@ -0,0 +1,87 @@ +From 11a1f4bc47362700fcbde717292158873fb847ed Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Tue, 18 Jun 2024 12:54:55 +0200 +Subject: PCI/DPC: Fix use-after-free on concurrent DPC and hot-removal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lukas Wunner + +commit 11a1f4bc47362700fcbde717292158873fb847ed upstream. + +Keith reports a use-after-free when a DPC event occurs concurrently to +hot-removal of the same portion of the hierarchy: + +The dpc_handler() awaits readiness of the secondary bus below the +Downstream Port where the DPC event occurred. To do so, it polls the +config space of the first child device on the secondary bus. If that +child device is concurrently removed, accesses to its struct pci_dev +cause the kernel to oops. + +That's because pci_bridge_wait_for_secondary_bus() neglects to hold a +reference on the child device. Before v6.3, the function was only +called on resume from system sleep or on runtime resume. Holding a +reference wasn't necessary back then because the pciehp IRQ thread +could never run concurrently. (On resume from system sleep, IRQs are +not enabled until after the resume_noirq phase. And runtime resume is +always awaited before a PCI device is removed.) + +However starting with v6.3, pci_bridge_wait_for_secondary_bus() is also +called on a DPC event. Commit 53b54ad074de ("PCI/DPC: Await readiness +of secondary bus after reset"), which introduced that, failed to +appreciate that pci_bridge_wait_for_secondary_bus() now needs to hold a +reference on the child device because dpc_handler() and pciehp may +indeed run concurrently. The commit was backported to v5.10+ stable +kernels, so that's the oldest one affected. + +Add the missing reference acquisition. + +Abridged stack trace: + + BUG: unable to handle page fault for address: 00000000091400c0 + CPU: 15 PID: 2464 Comm: irq/53-pcie-dpc 6.9.0 + RIP: pci_bus_read_config_dword+0x17/0x50 + pci_dev_wait() + pci_bridge_wait_for_secondary_bus() + dpc_reset_link() + pcie_do_recovery() + dpc_handler() + +Fixes: 53b54ad074de ("PCI/DPC: Await readiness of secondary bus after reset") +Closes: https://lore.kernel.org/r/20240612181625.3604512-3-kbusch@meta.com/ +Link: https://lore.kernel.org/linux-pci/8e4bcd4116fd94f592f2bf2749f168099c480ddf.1718707743.git.lukas@wunner.de +Reported-by: Keith Busch +Tested-by: Keith Busch +Signed-off-by: Lukas Wunner +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Keith Busch +Reviewed-by: Mika Westerberg +Cc: stable@vger.kernel.org # v5.10+ +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -5123,7 +5123,7 @@ static int pci_bus_max_d3cold_delay(cons + */ + int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) + { +- struct pci_dev *child; ++ struct pci_dev *child __free(pci_dev_put) = NULL; + int delay; + + if (pci_dev_is_disconnected(dev)) +@@ -5152,8 +5152,8 @@ int pci_bridge_wait_for_secondary_bus(st + return 0; + } + +- child = list_first_entry(&dev->subordinate->devices, struct pci_dev, +- bus_list); ++ child = pci_dev_get(list_first_entry(&dev->subordinate->devices, ++ struct pci_dev, bus_list)); + up_read(&pci_bus_sem); + + /* diff --git a/queue-6.6/pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch b/queue-6.6/pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch new file mode 100644 index 00000000000..de3881a5f60 --- /dev/null +++ b/queue-6.6/pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch @@ -0,0 +1,88 @@ +From ced085ef369af7a2b6da962ec2fbd01339f60693 Mon Sep 17 00:00:00 2001 +From: Ira Weiny +Date: Wed, 20 Dec 2023 16:17:35 -0800 +Subject: PCI: Introduce cleanup helpers for device reference counts and locks + +From: Ira Weiny + +commit ced085ef369af7a2b6da962ec2fbd01339f60693 upstream. + +The "goto error" pattern is notorious for introducing subtle resource +leaks. Use the new cleanup.h helpers for PCI device reference counts and +locks. + +Similar to the new put_device() and device_lock() cleanup helpers, +__free(put_device) and guard(device), define the same for PCI devices, +__free(pci_dev_put) and guard(pci_dev). These helpers eliminate the +need for "goto free;" and "goto unlock;" patterns. For example, A +'struct pci_dev *' instance declared as: + + struct pci_dev *pdev __free(pci_dev_put) = NULL; + +...will automatically call pci_dev_put() if @pdev is non-NULL when @pdev +goes out of scope (automatic variable scope). If a function wants to +invoke pci_dev_put() on error, but return @pdev on success, it can do: + + return no_free_ptr(pdev); + +...or: + + return_ptr(pdev); + +For potential cleanup opportunity there are 587 open-coded calls to +pci_dev_put() in the kernel with 65 instances within 10 lines of a goto +statement with the CXL driver threatening to add another one. + +The guard() helper holds the associated lock for the remainder of the +current scope in which it was invoked. So, for example: + + func(...) + { + if (...) { + ... + guard(pci_dev); /* pci_dev_lock() invoked here */ + ... + } /* <- implied pci_dev_unlock() triggered here */ + } + +There are 15 invocations of pci_dev_unlock() in the kernel with 5 +instances within 10 lines of a goto statement. Again, the CXL driver is +threatening to add another. + +Introduce these helpers to preclude the addition of new more error prone +goto put; / goto unlock; sequences. For now, these helpers are used in +drivers/cxl/pci.c to allow ACPI error reports to be fed back into the +CXL driver associated with the PCI device identified in the report. + +Cc: Bjorn Helgaas +Signed-off-by: Ira Weiny +Link: https://lore.kernel.org/r/20231220-cxl-cper-v5-8-1bb8a4ca2c7a@intel.com +[djbw: rewrite changelog] +Acked-by: Bjorn Helgaas +Reviewed-by: Jonathan Cameron +Acked-by: Ard Biesheuvel +Signed-off-by: Dan Williams +Signed-off-by: Lukas Wunner +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/pci.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -1146,6 +1146,7 @@ int pci_get_interrupt_pin(struct pci_dev + u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp); + struct pci_dev *pci_dev_get(struct pci_dev *dev); + void pci_dev_put(struct pci_dev *dev); ++DEFINE_FREE(pci_dev_put, struct pci_dev *, if (_T) pci_dev_put(_T)) + void pci_remove_bus(struct pci_bus *b); + void pci_stop_and_remove_bus_device(struct pci_dev *dev); + void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev); +@@ -1851,6 +1852,7 @@ void pci_cfg_access_unlock(struct pci_de + void pci_dev_lock(struct pci_dev *dev); + int pci_dev_trylock(struct pci_dev *dev); + void pci_dev_unlock(struct pci_dev *dev); ++DEFINE_GUARD(pci_dev, struct pci_dev *, pci_dev_lock(_T), pci_dev_unlock(_T)) + + /* + * PCI domain support. Sometimes called PCI segment (eg by ACPI), diff --git a/queue-6.6/series b/queue-6.6/series index c69903525c4..d2afed47370 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -502,3 +502,13 @@ drm-etnaviv-don-t-block-scheduler-when-gpu-is-still-active.patch drm-panfrost-mark-simple_ondemand-governor-as-softdep.patch rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch +lib-build_oid_registry-don-t-mention-the-full-path-of-the-script-in-output.patch +video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch +bluetooth-btusb-add-rtl8852be-device-0489-e125-to-device-tables.patch +bluetooth-btusb-add-realtek-rtl8852be-support-id-0x13d3-0x3591.patch +minmax-scsi-fix-mis-use-of-clamp-in-sr.c.patch +nilfs2-handle-inconsistent-state-in-nilfs_btnode_create_block.patch +mm-mglru-fix-ineffective-protection-calculation.patch +wifi-mac80211-track-capability-opmode-nss-separately.patch +pci-introduce-cleanup-helpers-for-device-reference-counts-and-locks.patch +pci-dpc-fix-use-after-free-on-concurrent-dpc-and-hot-removal.patch diff --git a/queue-6.6/video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch b/queue-6.6/video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch new file mode 100644 index 00000000000..e959c592737 --- /dev/null +++ b/queue-6.6/video-logo-drop-full-path-of-the-input-filename-in-generated-file.patch @@ -0,0 +1,36 @@ +From fb3b9c2d217f1f51fffe19fc0f4eaf55e2d4ea4f Mon Sep 17 00:00:00 2001 +From: Lucas Stach +Date: Wed, 10 Apr 2024 15:41:21 +0200 +Subject: video: logo: Drop full path of the input filename in generated file + +From: Lucas Stach + +commit fb3b9c2d217f1f51fffe19fc0f4eaf55e2d4ea4f upstream. + +Avoid this Yocto build warning to make build reproducible: + + WARNING: linux-foo-6.8-r0 do_package_qa: QA Issue: + File /usr/src/debug/linux-foo/6.8-r0/drivers/video/logo/logo_linux_clut224.c + in package linux-foo-src contains reference to TMPDIR + +Helge modified the patch to drop the whole line. + +Signed-off-by: Lucas Stach +Signed-off-by: Helge Deller +Cc: Fabio Estevam +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/logo/pnmtologo.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/video/logo/pnmtologo.c ++++ b/drivers/video/logo/pnmtologo.c +@@ -235,8 +235,6 @@ static void write_header(void) + fputs("/*\n", out); + fputs(" * DO NOT EDIT THIS FILE!\n", out); + fputs(" *\n", out); +- fprintf(out, " * It was automatically generated from %s\n", filename); +- fputs(" *\n", out); + fprintf(out, " * Linux logo %s\n", logoname); + fputs(" */\n\n", out); + fputs("#include \n\n", out); diff --git a/queue-6.6/wifi-mac80211-track-capability-opmode-nss-separately.patch b/queue-6.6/wifi-mac80211-track-capability-opmode-nss-separately.patch new file mode 100644 index 00000000000..f0bc8259791 --- /dev/null +++ b/queue-6.6/wifi-mac80211-track-capability-opmode-nss-separately.patch @@ -0,0 +1,191 @@ +From a8bca3e9371dc5e276af4168be099b2a05554c2a Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 28 Feb 2024 12:01:57 +0100 +Subject: wifi: mac80211: track capability/opmode NSS separately + +From: Johannes Berg + +commit a8bca3e9371dc5e276af4168be099b2a05554c2a upstream. + +We're currently tracking rx_nss for each station, and that +is meant to be initialized to the capability NSS and later +reduced by the operating mode notification NSS. + +However, we're mixing up capabilities and operating mode +NSS in the same variable. This forces us to recalculate +the NSS capability on operating mode notification RX, +which is a bit strange; due to the previous fix I had to +never keep rx_nss as zero, it also means that the capa is +never taken into account properly. + +Fix all this by storing the capability value, that can be +recalculated unconditionally whenever needed, and storing +the operating mode notification NSS separately, taking it +into account when assigning the final rx_nss value. + +Cc: stable@vger.kernel.org +Fixes: dd6c064cfc3f ("wifi: mac80211: set station RX-NSS on reconfig") +Reviewed-by: Miriam Rachel Korenblit +Link: https://msgid.link/20240228120157.0e1c41924d1d.I0acaa234e0267227b7e3ef81a59117c8792116bc@changeid +Signed-off-by: Johannes Berg +[Fixed trivial merge conflict in copyright year net/mac80211/sta_info.h] +Signed-off-by: Hauke Mehrtens +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/cfg.c | 2 - + net/mac80211/ieee80211_i.h | 2 - + net/mac80211/rate.c | 2 - + net/mac80211/sta_info.h | 6 ++++- + net/mac80211/vht.c | 46 +++++++++++++++++++++------------------------ + 5 files changed, 30 insertions(+), 28 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1887,7 +1887,7 @@ static int sta_link_apply_parameters(str + sband->band); + } + +- ieee80211_sta_set_rx_nss(link_sta); ++ ieee80211_sta_init_nss(link_sta); + + return ret; + } +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2150,7 +2150,7 @@ enum ieee80211_sta_rx_bandwidth + ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); + enum ieee80211_sta_rx_bandwidth + ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta); +-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta); ++void ieee80211_sta_init_nss(struct link_sta_info *link_sta); + enum ieee80211_sta_rx_bandwidth + ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width); + enum nl80211_chan_width +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_i + struct ieee80211_supported_band *sband; + struct ieee80211_chanctx_conf *chanctx_conf; + +- ieee80211_sta_set_rx_nss(&sta->deflink); ++ ieee80211_sta_init_nss(&sta->deflink); + + if (!ref) + return; +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -3,7 +3,7 @@ + * Copyright 2002-2005, Devicescape Software, Inc. + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright(c) 2020-2022 Intel Corporation ++ * Copyright(c) 2020-2024 Intel Corporation + */ + + #ifndef STA_INFO_H +@@ -485,6 +485,8 @@ struct ieee80211_fragment_cache { + * same for non-MLD STA. This is used as key for searching link STA + * @link_id: Link ID uniquely identifying the link STA. This is 0 for non-MLD + * and set to the corresponding vif LinkId for MLD STA ++ * @op_mode_nss: NSS limit as set by operating mode notification, or 0 ++ * @capa_nss: NSS limit as determined by local and peer capabilities + * @link_hash_node: hash node for rhashtable + * @sta: Points to the STA info + * @gtk: group keys negotiated with this station, if any +@@ -521,6 +523,8 @@ struct link_sta_info { + u8 addr[ETH_ALEN]; + u8 link_id; + ++ u8 op_mode_nss, capa_nss; ++ + struct rhlist_head link_hash_node; + + struct sta_info *sta; +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -4,7 +4,7 @@ + * + * Portions of this file + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2023 Intel Corporation ++ * Copyright (C) 2018 - 2024 Intel Corporation + */ + + #include +@@ -541,15 +541,11 @@ ieee80211_sta_cur_vht_bw(struct link_sta + return bw; + } + +-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta) ++void ieee80211_sta_init_nss(struct link_sta_info *link_sta) + { + u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss; + bool support_160; + +- /* if we received a notification already don't overwrite it */ +- if (link_sta->pub->rx_nss) +- return; +- + if (link_sta->pub->eht_cap.has_eht) { + int i; + const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp; +@@ -627,7 +623,15 @@ void ieee80211_sta_set_rx_nss(struct lin + rx_nss = max(vht_rx_nss, ht_rx_nss); + rx_nss = max(he_rx_nss, rx_nss); + rx_nss = max(eht_rx_nss, rx_nss); +- link_sta->pub->rx_nss = max_t(u8, 1, rx_nss); ++ rx_nss = max_t(u8, 1, rx_nss); ++ link_sta->capa_nss = rx_nss; ++ ++ /* that shouldn't be set yet, but we can handle it anyway */ ++ if (link_sta->op_mode_nss) ++ link_sta->pub->rx_nss = ++ min_t(u8, rx_nss, link_sta->op_mode_nss); ++ else ++ link_sta->pub->rx_nss = rx_nss; + } + + u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, +@@ -637,7 +641,7 @@ u32 __ieee80211_vht_handle_opmode(struct + enum ieee80211_sta_rx_bandwidth new_bw; + struct sta_opmode_info sta_opmode = {}; + u32 changed = 0; +- u8 nss, cur_nss; ++ u8 nss; + + /* ignore - no support for BF yet */ + if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) +@@ -647,23 +651,17 @@ u32 __ieee80211_vht_handle_opmode(struct + nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; + nss += 1; + +- if (link_sta->pub->rx_nss != nss) { +- cur_nss = link_sta->pub->rx_nss; +- /* Reset rx_nss and call ieee80211_sta_set_rx_nss() which +- * will set the same to max nss value calculated based on capability. +- */ +- link_sta->pub->rx_nss = 0; +- ieee80211_sta_set_rx_nss(link_sta); +- /* Do not allow an nss change to rx_nss greater than max_nss +- * negotiated and capped to APs capability during association. +- */ +- if (nss <= link_sta->pub->rx_nss) { +- link_sta->pub->rx_nss = nss; +- sta_opmode.rx_nss = nss; +- changed |= IEEE80211_RC_NSS_CHANGED; +- sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ if (link_sta->op_mode_nss != nss) { ++ if (nss <= link_sta->capa_nss) { ++ link_sta->op_mode_nss = nss; ++ ++ if (nss != link_sta->pub->rx_nss) { ++ link_sta->pub->rx_nss = nss; ++ changed |= IEEE80211_RC_NSS_CHANGED; ++ sta_opmode.rx_nss = link_sta->pub->rx_nss; ++ sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ } + } else { +- link_sta->pub->rx_nss = cur_nss; + pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d", + link_sta->pub->addr, nss); + } -- 2.47.3