--- /dev/null
+From 9839095f50202ea752d4ed6d18e4b358ba2c952e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jun 2024 09:27:16 +0200
+Subject: ACPI: battery: create alarm sysfs attribute atomically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit a231eed10ed5a290129fda36ad7bcc263c53ff7d ]
+
+Let the power supply core register the attribute.
+This ensures that the attribute is created before the device is
+announced to userspace, avoid a race condition.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/battery.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
+index b379401ff1c20..44ca989f16466 100644
+--- a/drivers/acpi/battery.c
++++ b/drivers/acpi/battery.c
+@@ -678,12 +678,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
+ return count;
+ }
+
+-static const struct device_attribute alarm_attr = {
++static struct device_attribute alarm_attr = {
+ .attr = {.name = "alarm", .mode = 0644},
+ .show = acpi_battery_alarm_show,
+ .store = acpi_battery_alarm_store,
+ };
+
++static struct attribute *acpi_battery_attrs[] = {
++ &alarm_attr.attr,
++ NULL
++};
++ATTRIBUTE_GROUPS(acpi_battery);
++
+ /*
+ * The Battery Hooking API
+ *
+@@ -823,7 +829,10 @@ static void __exit battery_hook_exit(void)
+
+ static int sysfs_add_battery(struct acpi_battery *battery)
+ {
+- struct power_supply_config psy_cfg = { .drv_data = battery, };
++ struct power_supply_config psy_cfg = {
++ .drv_data = battery,
++ .attr_grp = acpi_battery_groups,
++ };
+ bool full_cap_broken = false;
+
+ if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
+@@ -868,7 +877,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
+ return result;
+ }
+ battery_hook_add_battery(battery);
+- return device_create_file(&battery->bat->dev, &alarm_attr);
++ return 0;
+ }
+
+ static void sysfs_remove_battery(struct acpi_battery *battery)
+@@ -879,7 +888,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
+ return;
+ }
+ battery_hook_remove_battery(battery);
+- device_remove_file(&battery->bat->dev, &alarm_attr);
+ power_supply_unregister(battery->bat);
+ battery->bat = NULL;
+ mutex_unlock(&battery->sysfs_lock);
+--
+2.43.0
+
--- /dev/null
+From 523d65eb01f501ea407c1d38b8916cb31d08ce72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 08:58:06 -0400
+Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MU
+
+From: Tamim Khan <tamim@fusetak.com>
+
+[ Upstream commit dc41751f9e07889d078e3f06adb6e892c80b7c10 ]
+
+Like various other Asus laptops, the Asus Vivobook Pro N6506MV has a
+DSDT table that describes IRQ 1 as ActiveLow while the kernel is overriding
+it to Edge_High. This prevents the internal keyboard from working. This patch
+prevents this issue by adding this laptop to the override table that prevents
+the kernel from overriding this IRQ
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218954
+Tested-by: Lefteris <eleftherios.giapitzakis@gmail.com>
+Signed-off-by: Tamim Khan <tamim@fusetak.com>
+Link: https://patch.msgid.link/20240702125918.34683-1-tamim@fusetak.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/resource.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index b5bf8b81a050a..b3ae5f9ac5510 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -524,6 +524,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "N6506MV"),
+ },
+ },
++ {
++ /* Asus Vivobook Pro N6506MU */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BOARD_NAME, "N6506MU"),
++ },
++ },
+ {
+ /* LG Electronics 17U70P */
+ .matches = {
+--
+2.43.0
+
--- /dev/null
+From 441a4585d061c956fa28eaa5862b4992960abc6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 7 Jul 2024 20:05:50 -0400
+Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MJ
+
+From: Tamim Khan <tamim@fusetak.com>
+
+[ Upstream commit e2e7f037b400aebbb3892d8010fb3d9cae6f426e ]
+
+Similar to other Asus Vivobooks, the Asus Vivobook Pro N6506MJ has a DSDT table
+that describes IRQ 1 as ActiveLow, whereas the kernel overrides it to Edge_High.
+This discrepancy prevents the internal keyboard from functioning properly. This
+patch resolves this issue by adding this laptop to the override table that prevents
+the kernel from overriding this IRQ.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218929
+Tested-by: Amber Connelly <amb3r.dev@gmail.com>
+Signed-off-by: Tamim Khan <tamim@fusetak.com>
+Link: https://patch.msgid.link/20240708000557.83539-1-tamim@fusetak.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/resource.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index b3ae5f9ac5510..df5d5a554b388 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -531,6 +531,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "N6506MU"),
+ },
+ },
++ {
++ /* Asus Vivobook Pro N6506MJ */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BOARD_NAME, "N6506MJ"),
++ },
++ },
+ {
+ /* LG Electronics 17U70P */
+ .matches = {
+--
+2.43.0
+
--- /dev/null
+From 33ae8199c3dc00979ee1548fc374e2da87180c68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jun 2024 13:13:28 +0200
+Subject: ACPI: SBS: manage alarm sysfs attribute through psy core
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 6bad28cfc30988a845fb3f59a99f4b8a4ce8fe95 ]
+
+Let the power supply core register the attribute.
+
+This ensures that the attribute is created before the device is
+announced to userspace, avoiding a race condition.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/sbs.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
+index dc8164b182dcc..442c5905d43be 100644
+--- a/drivers/acpi/sbs.c
++++ b/drivers/acpi/sbs.c
+@@ -77,7 +77,6 @@ struct acpi_battery {
+ u16 spec;
+ u8 id;
+ u8 present:1;
+- u8 have_sysfs_alarm:1;
+ };
+
+ #define to_acpi_battery(x) power_supply_get_drvdata(x)
+@@ -462,12 +461,18 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
+ return count;
+ }
+
+-static const struct device_attribute alarm_attr = {
++static struct device_attribute alarm_attr = {
+ .attr = {.name = "alarm", .mode = 0644},
+ .show = acpi_battery_alarm_show,
+ .store = acpi_battery_alarm_store,
+ };
+
++static struct attribute *acpi_battery_attrs[] = {
++ &alarm_attr.attr,
++ NULL
++};
++ATTRIBUTE_GROUPS(acpi_battery);
++
+ /* --------------------------------------------------------------------------
+ Driver Interface
+ -------------------------------------------------------------------------- */
+@@ -518,7 +523,10 @@ static int acpi_battery_read(struct acpi_battery *battery)
+ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+ {
+ struct acpi_battery *battery = &sbs->battery[id];
+- struct power_supply_config psy_cfg = { .drv_data = battery, };
++ struct power_supply_config psy_cfg = {
++ .drv_data = battery,
++ .attr_grp = acpi_battery_groups,
++ };
+ int result;
+
+ battery->id = id;
+@@ -548,10 +556,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+ goto end;
+ }
+
+- result = device_create_file(&battery->bat->dev, &alarm_attr);
+- if (result)
+- goto end;
+- battery->have_sysfs_alarm = 1;
+ end:
+ pr_info("%s [%s]: Battery Slot [%s] (battery %s)\n",
+ ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
+@@ -563,11 +567,8 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
+ {
+ struct acpi_battery *battery = &sbs->battery[id];
+
+- if (battery->bat) {
+- if (battery->have_sysfs_alarm)
+- device_remove_file(&battery->bat->dev, &alarm_attr);
++ if (battery->bat)
+ power_supply_unregister(battery->bat);
+- }
+ }
+
+ static int acpi_charger_add(struct acpi_sbs *sbs)
+--
+2.43.0
+
--- /dev/null
+From ba95fd74d89f45c1ec46ec9e17e76c1b97f8f778 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 13:56:15 -0700
+Subject: af_unix: Don't retry after unix_state_lock_nested() in
+ unix_stream_connect().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 1ca27e0c8c13ac50a4acf9cdf77069e2d94a547d ]
+
+When a SOCK_(STREAM|SEQPACKET) socket connect()s to another one, we need
+to lock the two sockets to check their states in unix_stream_connect().
+
+We use unix_state_lock() for the server and unix_state_lock_nested() for
+client with tricky sk->sk_state check to avoid deadlock.
+
+The possible deadlock scenario are the following:
+
+ 1) Self connect()
+ 2) Simultaneous connect()
+
+The former is simple, attempt to grab the same lock, and the latter is
+AB-BA deadlock.
+
+After the server's unix_state_lock(), we check the server socket's state,
+and if it's not TCP_LISTEN, connect() fails with -EINVAL.
+
+Then, we avoid the former deadlock by checking the client's state before
+unix_state_lock_nested(). If its state is not TCP_LISTEN, we can make
+sure that the client and the server are not identical based on the state.
+
+Also, the latter deadlock can be avoided in the same way. Due to the
+server sk->sk_state requirement, AB-BA deadlock could happen only with
+TCP_LISTEN sockets. So, if the client's state is TCP_LISTEN, we can
+give up the second lock to avoid the deadlock.
+
+ CPU 1 CPU 2 CPU 3
+ connect(A -> B) connect(B -> A) listen(A)
+ --- --- ---
+ unix_state_lock(B)
+ B->sk_state == TCP_LISTEN
+ READ_ONCE(A->sk_state) == TCP_CLOSE
+ ^^^^^^^^^
+ ok, will lock A unix_state_lock(A)
+ .--------------' WRITE_ONCE(A->sk_state, TCP_LISTEN)
+ | unix_state_unlock(A)
+ |
+ | unix_state_lock(A)
+ | A->sk_sk_state == TCP_LISTEN
+ | READ_ONCE(B->sk_state) == TCP_LISTEN
+ v ^^^^^^^^^^
+ unix_state_lock_nested(A) Don't lock B !!
+
+Currently, while checking the client's state, we also check if it's
+TCP_ESTABLISHED, but this is unlikely and can be checked after we know
+the state is not TCP_CLOSE.
+
+Moreover, if it happens after the second lock, we now jump to the restart
+label, but it's unlikely that the server is not found during the retry,
+so the jump is mostly to revist the client state check.
+
+Let's remove the retry logic and check the state against TCP_CLOSE first.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/af_unix.c | 34 +++++++++-------------------------
+ 1 file changed, 9 insertions(+), 25 deletions(-)
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 11cb5badafb6d..be5266007b489 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1473,6 +1473,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ struct unix_sock *u = unix_sk(sk), *newu, *otheru;
+ struct net *net = sock_net(sk);
+ struct sk_buff *skb = NULL;
++ unsigned char state;
+ long timeo;
+ int err;
+
+@@ -1523,7 +1524,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ goto out;
+ }
+
+- /* Latch state of peer */
+ unix_state_lock(other);
+
+ /* Apparently VFS overslept socket death. Retry. */
+@@ -1553,37 +1553,21 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ goto restart;
+ }
+
+- /* Latch our state.
+-
+- It is tricky place. We need to grab our state lock and cannot
+- drop lock on peer. It is dangerous because deadlock is
+- possible. Connect to self case and simultaneous
+- attempt to connect are eliminated by checking socket
+- state. other is TCP_LISTEN, if sk is TCP_LISTEN we
+- check this before attempt to grab lock.
+-
+- Well, and we have to recheck the state after socket locked.
++ /* self connect and simultaneous connect are eliminated
++ * by rejecting TCP_LISTEN socket to avoid deadlock.
+ */
+- switch (READ_ONCE(sk->sk_state)) {
+- case TCP_CLOSE:
+- /* This is ok... continue with connect */
+- break;
+- case TCP_ESTABLISHED:
+- /* Socket is already connected */
+- err = -EISCONN;
+- goto out_unlock;
+- default:
+- err = -EINVAL;
++ state = READ_ONCE(sk->sk_state);
++ if (unlikely(state != TCP_CLOSE)) {
++ err = state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
+ goto out_unlock;
+ }
+
+ unix_state_lock_nested(sk, U_LOCK_SECOND);
+
+- if (sk->sk_state != TCP_CLOSE) {
++ if (unlikely(sk->sk_state != TCP_CLOSE)) {
++ err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EINVAL;
+ unix_state_unlock(sk);
+- unix_state_unlock(other);
+- sock_put(other);
+- goto restart;
++ goto out_unlock;
+ }
+
+ err = security_unix_stream_connect(sk, other, newsk);
+--
+2.43.0
+
--- /dev/null
+From 4925f571ef20bb3170a2c62cef6c8f55573d1fe8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 17:40:10 +0200
+Subject: block: change rq_integrity_vec to respect the iterator
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit cf546dd289e0f6d2594c25e2fb4e19ee67c6d988 ]
+
+If we allocate a bio that is larger than NVMe maximum request size,
+attach integrity metadata to it and send it to the NVMe subsystem, the
+integrity metadata will be corrupted.
+
+Splitting the bio works correctly. The function bio_split will clone the
+bio, trim the iterator of the first bio and advance the iterator of the
+second bio.
+
+However, the function rq_integrity_vec has a bug - it returns the first
+vector of the bio's metadata and completely disregards the metadata
+iterator that was advanced when the bio was split. Thus, the second bio
+uses the same metadata as the first bio and this leads to metadata
+corruption.
+
+This commit changes rq_integrity_vec, so that it calls mp_bvec_iter_bvec
+instead of returning the first vector. mp_bvec_iter_bvec reads the
+iterator and uses it to build a bvec for the current position in the
+iterator.
+
+The "queue_max_integrity_segments(rq->q) > 1" check was removed, because
+the updated rq_integrity_vec function works correctly with multiple
+segments.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reviewed-by: Anuj Gupta <anuj20.g@samsung.com>
+Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/49d1afaa-f934-6ed2-a678-e0d428c63a65@redhat.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/pci.c | 6 +++---
+ include/linux/blk-integrity.h | 14 +++++++-------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 5a93f021ca4f1..7168ff4cc62bb 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -826,9 +826,9 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
+ struct nvme_command *cmnd)
+ {
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
++ struct bio_vec bv = rq_integrity_vec(req);
+
+- iod->meta_dma = dma_map_bvec(dev->dev, rq_integrity_vec(req),
+- rq_dma_dir(req), 0);
++ iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
+ if (dma_mapping_error(dev->dev, iod->meta_dma))
+ return BLK_STS_IOERR;
+ cmnd->rw.metadata = cpu_to_le64(iod->meta_dma);
+@@ -968,7 +968,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+
+ dma_unmap_page(dev->dev, iod->meta_dma,
+- rq_integrity_vec(req)->bv_len, rq_dma_dir(req));
++ rq_integrity_vec(req).bv_len, rq_dma_dir(req));
+ }
+
+ if (blk_rq_nr_phys_segments(req))
+diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
+index 7428cb43952da..d16dd24719841 100644
+--- a/include/linux/blk-integrity.h
++++ b/include/linux/blk-integrity.h
+@@ -100,14 +100,13 @@ static inline bool blk_integrity_rq(struct request *rq)
+ }
+
+ /*
+- * Return the first bvec that contains integrity data. Only drivers that are
+- * limited to a single integrity segment should use this helper.
++ * Return the current bvec that contains the integrity data. bip_iter may be
++ * advanced to iterate over the integrity data.
+ */
+-static inline struct bio_vec *rq_integrity_vec(struct request *rq)
++static inline struct bio_vec rq_integrity_vec(struct request *rq)
+ {
+- if (WARN_ON_ONCE(queue_max_integrity_segments(rq->q) > 1))
+- return NULL;
+- return rq->bio->bi_integrity->bip_vec;
++ return mp_bvec_iter_bvec(rq->bio->bi_integrity->bip_vec,
++ rq->bio->bi_integrity->bip_iter);
+ }
+ #else /* CONFIG_BLK_DEV_INTEGRITY */
+ static inline int blk_rq_count_integrity_sg(struct request_queue *q,
+@@ -169,7 +168,8 @@ static inline int blk_integrity_rq(struct request *rq)
+
+ static inline struct bio_vec *rq_integrity_vec(struct request *rq)
+ {
+- return NULL;
++ /* the optimizer will remove all calls to this function */
++ return (struct bio_vec){ };
+ }
+ #endif /* CONFIG_BLK_DEV_INTEGRITY */
+ #endif /* _LINUX_BLK_INTEGRITY_H */
+--
+2.43.0
+
--- /dev/null
+From d48078439a68d507c4b74415591eb46c8a316afa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 19:15:35 +0800
+Subject: Bluetooth: btnxpuart: Shutdown timer and prevent rearming when driver
+ unloading
+
+From: Luke Wang <ziniu.wang_1@nxp.com>
+
+[ Upstream commit 0d0df1e750bac0fdaa77940e711c1625cff08d33 ]
+
+When unload the btnxpuart driver, its associated timer will be deleted.
+If the timer happens to be modified at this moment, it leads to the
+kernel call this timer even after the driver unloaded, resulting in
+kernel panic.
+Use timer_shutdown_sync() instead of del_timer_sync() to prevent rearming.
+
+panic log:
+ Internal error: Oops: 0000000086000007 [#1] PREEMPT SMP
+ Modules linked in: algif_hash algif_skcipher af_alg moal(O) mlan(O) crct10dif_ce polyval_ce polyval_generic snd_soc_imx_card snd_soc_fsl_asoc_card snd_soc_imx_audmux mxc_jpeg_encdec v4l2_jpeg snd_soc_wm8962 snd_soc_fsl_micfil snd_soc_fsl_sai flexcan snd_soc_fsl_utils ap130x rpmsg_ctrl imx_pcm_dma can_dev rpmsg_char pwm_fan fuse [last unloaded: btnxpuart]
+ CPU: 5 PID: 723 Comm: memtester Tainted: G O 6.6.23-lts-next-06207-g4aef2658ac28 #1
+ Hardware name: NXP i.MX95 19X19 board (DT)
+ pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+ pc : 0xffff80007a2cf464
+ lr : call_timer_fn.isra.0+0x24/0x80
+...
+ Call trace:
+ 0xffff80007a2cf464
+ __run_timers+0x234/0x280
+ run_timer_softirq+0x20/0x40
+ __do_softirq+0x100/0x26c
+ ____do_softirq+0x10/0x1c
+ call_on_irq_stack+0x24/0x4c
+ do_softirq_own_stack+0x1c/0x2c
+ irq_exit_rcu+0xc0/0xdc
+ el0_interrupt+0x54/0xd8
+ __el0_irq_handler_common+0x18/0x24
+ el0t_64_irq_handler+0x10/0x1c
+ el0t_64_irq+0x190/0x194
+ Code: ???????? ???????? ???????? ???????? (????????)
+ ---[ end trace 0000000000000000 ]---
+ Kernel panic - not syncing: Oops: Fatal exception in interrupt
+ SMP: stopping secondary CPUs
+ Kernel Offset: disabled
+ CPU features: 0x0,c0000000,40028143,1000721b
+ Memory Limit: none
+ ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
+
+Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btnxpuart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index 6a863328b8053..d310b525fbf00 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -344,7 +344,7 @@ static void ps_cancel_timer(struct btnxpuart_dev *nxpdev)
+ struct ps_data *psdata = &nxpdev->psdata;
+
+ flush_work(&psdata->work);
+- del_timer_sync(&psdata->ps_timer);
++ timer_shutdown_sync(&psdata->ps_timer);
+ }
+
+ static void ps_control(struct hci_dev *hdev, u8 ps_state)
+--
+2.43.0
+
--- /dev/null
+From 87f2a3176664f2cd87893bd0384841827205f52f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 21:58:10 +0200
+Subject: Bluetooth: hci_sync: avoid dup filtering when passive scanning with
+ adv monitor
+
+From: Anton Khirnov <anton@khirnov.net>
+
+[ Upstream commit b5431dc2803ac159d6d4645ae237d15c3cb252db ]
+
+This restores behaviour (including the comment) from now-removed
+hci_request.c, and also matches existing code for active scanning.
+
+Without this, the duplicates filter is always active when passive
+scanning, which makes it impossible to work with devices that send
+nontrivial dynamic data in their advertisement reports.
+
+Fixes: abfeea476c68 ("Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY")
+Signed-off-by: Anton Khirnov <anton@khirnov.net>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 2f26147fdf3c9..4e90bd722e7b5 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -2972,6 +2972,20 @@ static int hci_passive_scan_sync(struct hci_dev *hdev)
+ } else if (hci_is_adv_monitoring(hdev)) {
+ window = hdev->le_scan_window_adv_monitor;
+ interval = hdev->le_scan_int_adv_monitor;
++
++ /* Disable duplicates filter when scanning for advertisement
++ * monitor for the following reasons.
++ *
++ * For HW pattern filtering (ex. MSFT), Realtek and Qualcomm
++ * controllers ignore RSSI_Sampling_Period when the duplicates
++ * filter is enabled.
++ *
++ * For SW pattern filtering, when we're not doing interleaved
++ * scanning, it is necessary to disable duplicates filter,
++ * otherwise hosts can only receive one advertisement and it's
++ * impossible to know if a peer is still in range.
++ */
++ filter_dups = LE_SCAN_FILTER_DUP_DISABLE;
+ } else {
+ window = hdev->le_scan_window;
+ interval = hdev->le_scan_interval;
+--
+2.43.0
+
--- /dev/null
+From 96cd656b241ef33c9bdbc9d4621d6c92ceb9c111 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 12:19:36 +0300
+Subject: Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit c531e63871c0b50c8c4e62c048535a08886fba3e ]
+
+Add missing call to 'l2cap_chan_unlock()' on receive error handling
+path in 'l2cap_conless_channel()'.
+
+Fixes: a24cce144b98 ("Bluetooth: Fix reference counting of global L2CAP channels")
+Reported-by: syzbot+45ac74737e866894acb0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=45ac74737e866894acb0
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index c3c26bbb5ddae..9988ba382b686 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6774,6 +6774,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
+ bt_cb(skb)->l2cap.psm = psm;
+
+ if (!chan->ops->recv(chan, skb)) {
++ l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
+ return;
+ }
+--
+2.43.0
+
--- /dev/null
+From 6168307f0f39543f5d6cc0a0674beacb2d78a82b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 22:37:42 -0700
+Subject: bnxt_en : Fix memory out-of-bounds in bnxt_fill_hw_rss_tbl()
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit da03f5d1b2c319a2b74fe76edeadcd8fa5f44376 ]
+
+A recent commit has modified the code in __bnxt_reserve_rings() to
+set the default RSS indirection table to default only when the number
+of RX rings is changing. While this works for newer firmware that
+requires RX ring reservations, it causes the regression on older
+firmware not requiring RX ring resrvations (BNXT_NEW_RM() returns
+false).
+
+With older firmware, RX ring reservations are not required and so
+hw_resc->resv_rx_rings is not always set to the proper value. The
+comparison:
+
+if (old_rx_rings != bp->hw_resc.resv_rx_rings)
+
+in __bnxt_reserve_rings() may be false even when the RX rings are
+changing. This will cause __bnxt_reserve_rings() to skip setting
+the default RSS indirection table to default to match the current
+number of RX rings. This may later cause bnxt_fill_hw_rss_tbl() to
+use an out-of-range index.
+
+We already have bnxt_check_rss_tbl_no_rmgr() to handle exactly this
+scenario. We just need to move it up in bnxt_need_reserve_rings()
+to be called unconditionally when using older firmware. Without the
+fix, if the TX rings are changing, we'll skip the
+bnxt_check_rss_tbl_no_rmgr() call and __bnxt_reserve_rings() may also
+skip the bnxt_set_dflt_rss_indir_tbl() call for the reason explained
+in the last paragraph. Without setting the default RSS indirection
+table to default, it causes the regression:
+
+BUG: KASAN: slab-out-of-bounds in __bnxt_hwrm_vnic_set_rss+0xb79/0xe40
+Read of size 2 at addr ffff8881c5809618 by task ethtool/31525
+Call Trace:
+__bnxt_hwrm_vnic_set_rss+0xb79/0xe40
+ bnxt_hwrm_vnic_rss_cfg_p5+0xf7/0x460
+ __bnxt_setup_vnic_p5+0x12e/0x270
+ __bnxt_open_nic+0x2262/0x2f30
+ bnxt_open_nic+0x5d/0xf0
+ ethnl_set_channels+0x5d4/0xb30
+ ethnl_default_set_doit+0x2f1/0x620
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Closes: https://lore.kernel.org/netdev/ZrC6jpghA3PWVWSB@gmail.com/
+Fixes: 98ba1d931f61 ("bnxt_en: Fix RSS logic in __bnxt_reserve_rings()")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Tested-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20240806053742.140304-1-michael.chan@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 23627c973e40f..a2d672a698e35 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -7433,19 +7433,20 @@ static bool bnxt_need_reserve_rings(struct bnxt *bp)
+ int rx = bp->rx_nr_rings, stat;
+ int vnic, grp = rx;
+
+- if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
+- bp->hwrm_spec_code >= 0x10601)
+- return true;
+-
+ /* Old firmware does not need RX ring reservations but we still
+ * need to setup a default RSS map when needed. With new firmware
+ * we go through RX ring reservations first and then set up the
+ * RSS map for the successfully reserved RX rings when needed.
+ */
+- if (!BNXT_NEW_RM(bp)) {
++ if (!BNXT_NEW_RM(bp))
+ bnxt_check_rss_tbl_no_rmgr(bp);
++
++ if (hw_resc->resv_tx_rings != bp->tx_nr_rings &&
++ bp->hwrm_spec_code >= 0x10601)
++ return true;
++
++ if (!BNXT_NEW_RM(bp))
+ return false;
+- }
+
+ vnic = bnxt_get_total_vnics(bp, rx);
+
+--
+2.43.0
+
--- /dev/null
+From 48ece36104ccd87af1864d784b95b920e99a6b3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 06:28:56 +0000
+Subject: bpf: add missing check_func_arg_reg_off() to prevent out-of-bounds
+ memory accesses
+
+From: Matt Bobrowski <mattbobrowski@google.com>
+
+[ Upstream commit ec2b9a5e11e51fea1bb04c1e7e471952e887e874 ]
+
+Currently, it's possible to pass in a modified CONST_PTR_TO_DYNPTR to
+a global function as an argument. The adverse effects of this is that
+BPF helpers can continue to make use of this modified
+CONST_PTR_TO_DYNPTR from within the context of the global function,
+which can unintentionally result in out-of-bounds memory accesses and
+therefore compromise overall system stability i.e.
+
+[ 244.157771] BUG: KASAN: slab-out-of-bounds in bpf_dynptr_data+0x137/0x140
+[ 244.161345] Read of size 8 at addr ffff88810914be68 by task test_progs/302
+[ 244.167151] CPU: 0 PID: 302 Comm: test_progs Tainted: G O E 6.10.0-rc3-00131-g66b586715063 #533
+[ 244.174318] Call Trace:
+[ 244.175787] <TASK>
+[ 244.177356] dump_stack_lvl+0x66/0xa0
+[ 244.179531] print_report+0xce/0x670
+[ 244.182314] ? __virt_addr_valid+0x200/0x3e0
+[ 244.184908] kasan_report+0xd7/0x110
+[ 244.187408] ? bpf_dynptr_data+0x137/0x140
+[ 244.189714] ? bpf_dynptr_data+0x137/0x140
+[ 244.192020] bpf_dynptr_data+0x137/0x140
+[ 244.194264] bpf_prog_b02a02fdd2bdc5fa_global_call_bpf_dynptr_data+0x22/0x26
+[ 244.198044] bpf_prog_b0fe7b9d7dc3abde_callback_adjust_bpf_dynptr_reg_off+0x1f/0x23
+[ 244.202136] bpf_user_ringbuf_drain+0x2c7/0x570
+[ 244.204744] ? 0xffffffffc0009e58
+[ 244.206593] ? __pfx_bpf_user_ringbuf_drain+0x10/0x10
+[ 244.209795] bpf_prog_33ab33f6a804ba2d_user_ringbuf_callback_const_ptr_to_dynptr_reg_off+0x47/0x4b
+[ 244.215922] bpf_trampoline_6442502480+0x43/0xe3
+[ 244.218691] __x64_sys_prlimit64+0x9/0xf0
+[ 244.220912] do_syscall_64+0xc1/0x1d0
+[ 244.223043] entry_SYSCALL_64_after_hwframe+0x77/0x7f
+[ 244.226458] RIP: 0033:0x7ffa3eb8f059
+[ 244.228582] Code: 08 89 e8 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 8f 1d 0d 00 f7 d8 64 89 01 48
+[ 244.241307] RSP: 002b:00007ffa3e9c6eb8 EFLAGS: 00000206 ORIG_RAX: 000000000000012e
+[ 244.246474] RAX: ffffffffffffffda RBX: 00007ffa3e9c7cdc RCX: 00007ffa3eb8f059
+[ 244.250478] RDX: 00007ffa3eb162b4 RSI: 0000000000000000 RDI: 00007ffa3e9c7fb0
+[ 244.255396] RBP: 00007ffa3e9c6ed0 R08: 00007ffa3e9c76c0 R09: 0000000000000000
+[ 244.260195] R10: 0000000000000000 R11: 0000000000000206 R12: ffffffffffffff80
+[ 244.264201] R13: 000000000000001c R14: 00007ffc5d6b4260 R15: 00007ffa3e1c7000
+[ 244.268303] </TASK>
+
+Add a check_func_arg_reg_off() to the path in which the BPF verifier
+verifies the arguments of global function arguments, specifically
+those which take an argument of type ARG_PTR_TO_DYNPTR |
+MEM_RDONLY. Also, process_dynptr_func() doesn't appear to perform any
+explicit and strict type matching on the supplied register type, so
+let's also enforce that a register either type PTR_TO_STACK or
+CONST_PTR_TO_DYNPTR is by the caller.
+
+Reported-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Acked-by: Eduard Zingerman <eddyz87@gmail.com>
+Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
+Link: https://lore.kernel.org/r/20240625062857.92760-1-mattbobrowski@google.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 6b422c275f78c..a8845cc299fec 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7716,6 +7716,13 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
+ struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno];
+ int err;
+
++ if (reg->type != PTR_TO_STACK && reg->type != CONST_PTR_TO_DYNPTR) {
++ verbose(env,
++ "arg#%d expected pointer to stack or const struct bpf_dynptr\n",
++ regno);
++ return -EINVAL;
++ }
++
+ /* MEM_UNINIT and MEM_RDONLY are exclusive, when applied to an
+ * ARG_PTR_TO_DYNPTR (or ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_*):
+ */
+@@ -9465,6 +9472,10 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
+ return -EINVAL;
+ }
+ } else if (arg->arg_type == (ARG_PTR_TO_DYNPTR | MEM_RDONLY)) {
++ ret = check_func_arg_reg_off(env, reg, regno, ARG_PTR_TO_DYNPTR);
++ if (ret)
++ return ret;
++
+ ret = process_dynptr_func(env, regno, -1, arg->arg_type, 0);
+ if (ret)
+ return ret;
+@@ -11958,12 +11969,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ enum bpf_arg_type dynptr_arg_type = ARG_PTR_TO_DYNPTR;
+ int clone_ref_obj_id = 0;
+
+- if (reg->type != PTR_TO_STACK &&
+- reg->type != CONST_PTR_TO_DYNPTR) {
+- verbose(env, "arg#%d expected pointer to stack or dynptr_ptr\n", i);
+- return -EINVAL;
+- }
+-
+ if (reg->type == CONST_PTR_TO_DYNPTR)
+ dynptr_arg_type |= MEM_RDONLY;
+
+--
+2.43.0
+
--- /dev/null
+From f209ea9ea6d1f8a2351aa30d4b7b23d4a98486ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 14:50:47 +0100
+Subject: btrfs: do not BUG_ON() when freeing tree block after error
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit bb3868033a4cccff7be57e9145f2117cbdc91c11 ]
+
+When freeing a tree block, at btrfs_free_tree_block(), if we fail to
+create a delayed reference we don't deal with the error and just do a
+BUG_ON(). The error most likely to happen is -ENOMEM, and we have a
+comment mentioning that only -ENOMEM can happen, but that is not true,
+because in case qgroups are enabled any error returned from
+btrfs_qgroup_trace_extent_post() (can be -EUCLEAN or anything returned
+from btrfs_search_slot() for example) can be propagated back to
+btrfs_free_tree_block().
+
+So stop doing a BUG_ON() and return the error to the callers and make
+them abort the transaction to prevent leaking space. Syzbot was
+triggering this, likely due to memory allocation failure injection.
+
+Reported-by: syzbot+a306f914b4d01b3958fe@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/linux-btrfs/000000000000fcba1e05e998263c@google.com/
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.c | 53 ++++++++++++++++++++++++++++++--------
+ fs/btrfs/extent-tree.c | 24 ++++++++++-------
+ fs/btrfs/extent-tree.h | 8 +++---
+ fs/btrfs/free-space-tree.c | 10 ++++---
+ fs/btrfs/ioctl.c | 6 ++++-
+ fs/btrfs/qgroup.c | 6 +++--
+ 6 files changed, 76 insertions(+), 31 deletions(-)
+
+diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
+index 1a49b92329908..ca372068226d5 100644
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -620,10 +620,16 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+ atomic_inc(&cow->refs);
+ rcu_assign_pointer(root->node, cow);
+
+- btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
+- parent_start, last_ref);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
++ parent_start, last_ref);
+ free_extent_buffer(buf);
+ add_root_to_dirty_list(root);
++ if (ret < 0) {
++ btrfs_tree_unlock(cow);
++ free_extent_buffer(cow);
++ btrfs_abort_transaction(trans, ret);
++ return ret;
++ }
+ } else {
+ WARN_ON(trans->transid != btrfs_header_generation(parent));
+ ret = btrfs_tree_mod_log_insert_key(parent, parent_slot,
+@@ -648,8 +654,14 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+ return ret;
+ }
+ }
+- btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
+- parent_start, last_ref);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
++ parent_start, last_ref);
++ if (ret < 0) {
++ btrfs_tree_unlock(cow);
++ free_extent_buffer(cow);
++ btrfs_abort_transaction(trans, ret);
++ return ret;
++ }
+ }
+ if (unlock_orig)
+ btrfs_tree_unlock(buf);
+@@ -983,9 +995,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+ free_extent_buffer(mid);
+
+ root_sub_used_bytes(root);
+- btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
+ /* once for the root ptr */
+ free_extent_buffer_stale(mid);
++ if (ret < 0) {
++ btrfs_abort_transaction(trans, ret);
++ goto out;
++ }
+ return 0;
+ }
+ if (btrfs_header_nritems(mid) >
+@@ -1053,10 +1069,14 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+ goto out;
+ }
+ root_sub_used_bytes(root);
+- btrfs_free_tree_block(trans, btrfs_root_id(root), right,
+- 0, 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root),
++ right, 0, 1);
+ free_extent_buffer_stale(right);
+ right = NULL;
++ if (ret < 0) {
++ btrfs_abort_transaction(trans, ret);
++ goto out;
++ }
+ } else {
+ struct btrfs_disk_key right_key;
+ btrfs_node_key(right, &right_key, 0);
+@@ -1111,9 +1131,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
+ goto out;
+ }
+ root_sub_used_bytes(root);
+- btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
+ free_extent_buffer_stale(mid);
+ mid = NULL;
++ if (ret < 0) {
++ btrfs_abort_transaction(trans, ret);
++ goto out;
++ }
+ } else {
+ /* update the parent key to reflect our changes */
+ struct btrfs_disk_key mid_key;
+@@ -2883,7 +2907,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
+ old = root->node;
+ ret = btrfs_tree_mod_log_insert_root(root->node, c, false);
+ if (ret < 0) {
+- btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
++ int ret2;
++
++ ret2 = btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
++ if (ret2 < 0)
++ btrfs_abort_transaction(trans, ret2);
+ btrfs_tree_unlock(c);
+ free_extent_buffer(c);
+ return ret;
+@@ -4452,9 +4480,12 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
+ root_sub_used_bytes(root);
+
+ atomic_inc(&leaf->refs);
+- btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
+ free_extent_buffer_stale(leaf);
+- return 0;
++ if (ret < 0)
++ btrfs_abort_transaction(trans, ret);
++
++ return ret;
+ }
+ /*
+ * delete the item at the leaf level in path. If that empties
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index b75e14f399a01..153297cb97a4a 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3420,10 +3420,10 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
+ return 0;
+ }
+
+-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+- u64 root_id,
+- struct extent_buffer *buf,
+- u64 parent, int last_ref)
++int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
++ u64 root_id,
++ struct extent_buffer *buf,
++ u64 parent, int last_ref)
+ {
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+ struct btrfs_block_group *bg;
+@@ -3450,11 +3450,12 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+ btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf), 0, false);
+ btrfs_ref_tree_mod(fs_info, &generic_ref);
+ ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL);
+- BUG_ON(ret); /* -ENOMEM */
++ if (ret < 0)
++ return ret;
+ }
+
+ if (!last_ref)
+- return;
++ return 0;
+
+ if (btrfs_header_generation(buf) != trans->transid)
+ goto out;
+@@ -3511,6 +3512,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+ * matter anymore.
+ */
+ clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
++ return 0;
+ }
+
+ /* Can return -ENOMEM */
+@@ -5644,7 +5646,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+ struct walk_control *wc)
+ {
+ struct btrfs_fs_info *fs_info = root->fs_info;
+- int ret;
++ int ret = 0;
+ int level = wc->level;
+ struct extent_buffer *eb = path->nodes[level];
+ u64 parent = 0;
+@@ -5731,12 +5733,14 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+ goto owner_mismatch;
+ }
+
+- btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
+- wc->refs[level] == 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
++ wc->refs[level] == 1);
++ if (ret < 0)
++ btrfs_abort_transaction(trans, ret);
+ out:
+ wc->refs[level] = 0;
+ wc->flags[level] = 0;
+- return 0;
++ return ret;
+
+ owner_mismatch:
+ btrfs_err_rl(fs_info, "unexpected tree owner, have %llu expect %llu",
+diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
+index af9f8800d5aca..2ad51130c037e 100644
+--- a/fs/btrfs/extent-tree.h
++++ b/fs/btrfs/extent-tree.h
+@@ -127,10 +127,10 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
+ u64 empty_size,
+ u64 reloc_src_root,
+ enum btrfs_lock_nesting nest);
+-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+- u64 root_id,
+- struct extent_buffer *buf,
+- u64 parent, int last_ref);
++int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
++ u64 root_id,
++ struct extent_buffer *buf,
++ u64 parent, int last_ref);
+ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, u64 owner,
+ u64 offset, u64 ram_bytes,
+diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
+index 90f2938bd743d..7ba50e133921a 100644
+--- a/fs/btrfs/free-space-tree.c
++++ b/fs/btrfs/free-space-tree.c
+@@ -1300,10 +1300,14 @@ int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info)
+ btrfs_tree_lock(free_space_root->node);
+ btrfs_clear_buffer_dirty(trans, free_space_root->node);
+ btrfs_tree_unlock(free_space_root->node);
+- btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
+- free_space_root->node, 0, 1);
+-
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
++ free_space_root->node, 0, 1);
+ btrfs_put_root(free_space_root);
++ if (ret < 0) {
++ btrfs_abort_transaction(trans, ret);
++ btrfs_end_transaction(trans);
++ return ret;
++ }
+
+ return btrfs_commit_transaction(trans);
+ }
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index efd5d6e9589e0..c1b0556e40368 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -719,6 +719,8 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ ret = btrfs_insert_root(trans, fs_info->tree_root, &key,
+ root_item);
+ if (ret) {
++ int ret2;
++
+ /*
+ * Since we don't abort the transaction in this case, free the
+ * tree block so that we don't leak space and leave the
+@@ -729,7 +731,9 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ btrfs_tree_lock(leaf);
+ btrfs_clear_buffer_dirty(trans, leaf);
+ btrfs_tree_unlock(leaf);
+- btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
++ ret2 = btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
++ if (ret2 < 0)
++ btrfs_abort_transaction(trans, ret2);
+ free_extent_buffer(leaf);
+ goto out;
+ }
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 39a15cca58ca9..29d6ca3b874ec 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1446,9 +1446,11 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
+ btrfs_tree_lock(quota_root->node);
+ btrfs_clear_buffer_dirty(trans, quota_root->node);
+ btrfs_tree_unlock(quota_root->node);
+- btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
+- quota_root->node, 0, 1);
++ ret = btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
++ quota_root->node, 0, 1);
+
++ if (ret < 0)
++ btrfs_abort_transaction(trans, ret);
+
+ out:
+ btrfs_put_root(quota_root);
+--
+2.43.0
+
--- /dev/null
+From b324b0d12a6f5cfb3dd5c6bec6171e73782ebf03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Mar 2024 08:21:54 +1030
+Subject: btrfs: do not clear page dirty inside extent_write_locked_range()
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 97713b1a2ced1e4a2a6c40045903797ebd44d7e0 ]
+
+[BUG]
+For subpage + zoned case, the following workload can lead to rsv data
+leak at unmount time:
+
+ # mkfs.btrfs -f -s 4k $dev
+ # mount $dev $mnt
+ # fsstress -w -n 8 -d $mnt -s 1709539240
+ 0/0: fiemap - no filename
+ 0/1: copyrange read - no filename
+ 0/2: write - no filename
+ 0/3: rename - no source filename
+ 0/4: creat f0 x:0 0 0
+ 0/4: creat add id=0,parent=-1
+ 0/5: writev f0[259 1 0 0 0 0] [778052,113,965] 0
+ 0/6: ioctl(FIEMAP) f0[259 1 0 0 224 887097] [1294220,2291618343991484791,0x10000] -1
+ 0/7: dwrite - xfsctl(XFS_IOC_DIOINFO) f0[259 1 0 0 224 887097] return 25, fallback to stat()
+ 0/7: dwrite f0[259 1 0 0 224 887097] [696320,102400] 0
+ # umount $mnt
+
+The dmesg includes the following rsv leak detection warning (all call
+trace skipped):
+
+ ------------[ cut here ]------------
+ WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8653 btrfs_destroy_inode+0x1e0/0x200 [btrfs]
+ ---[ end trace 0000000000000000 ]---
+ ------------[ cut here ]------------
+ WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8654 btrfs_destroy_inode+0x1a8/0x200 [btrfs]
+ ---[ end trace 0000000000000000 ]---
+ ------------[ cut here ]------------
+ WARNING: CPU: 2 PID: 4528 at fs/btrfs/inode.c:8660 btrfs_destroy_inode+0x1a0/0x200 [btrfs]
+ ---[ end trace 0000000000000000 ]---
+ BTRFS info (device sda): last unmount of filesystem 1b4abba9-de34-4f07-9e7f-157cf12a18d6
+ ------------[ cut here ]------------
+ WARNING: CPU: 3 PID: 4528 at fs/btrfs/block-group.c:4434 btrfs_free_block_groups+0x338/0x500 [btrfs]
+ ---[ end trace 0000000000000000 ]---
+ BTRFS info (device sda): space_info DATA has 268218368 free, is not full
+ BTRFS info (device sda): space_info total=268435456, used=204800, pinned=0, reserved=0, may_use=12288, readonly=0 zone_unusable=0
+ BTRFS info (device sda): global_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): trans_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): chunk_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): delayed_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): delayed_refs_rsv: size 0 reserved 0
+ ------------[ cut here ]------------
+ WARNING: CPU: 3 PID: 4528 at fs/btrfs/block-group.c:4434 btrfs_free_block_groups+0x338/0x500 [btrfs]
+ ---[ end trace 0000000000000000 ]---
+ BTRFS info (device sda): space_info METADATA has 267796480 free, is not full
+ BTRFS info (device sda): space_info total=268435456, used=131072, pinned=0, reserved=0, may_use=262144, readonly=0 zone_unusable=245760
+ BTRFS info (device sda): global_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): trans_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): chunk_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): delayed_block_rsv: size 0 reserved 0
+ BTRFS info (device sda): delayed_refs_rsv: size 0 reserved 0
+
+Above $dev is a tcmu-runner emulated zoned HDD, which has a max zone
+append size of 64K, and the system has 64K page size.
+
+[CAUSE]
+I have added several trace_printk() to show the events (header skipped):
+
+ > btrfs_dirty_pages: r/i=5/259 dirty start=774144 len=114688
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=720896 off_in_page=53248 len_in_page=12288
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=786432 off_in_page=0 len_in_page=65536
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=851968 off_in_page=0 len_in_page=36864
+
+The above lines show our buffered write has dirtied 3 pages of inode
+259 of root 5:
+
+ 704K 768K 832K 896K
+ I |////I/////////////////I///////////| I
+ 756K 868K
+
+ |///| is the dirtied range using subpage bitmaps. and 'I' is the page
+ boundary.
+
+ Meanwhile all three pages (704K, 768K, 832K) have their PageDirty
+ flag set.
+
+ > btrfs_direct_write: r/i=5/259 start dio filepos=696320 len=102400
+
+Then direct IO write starts, since the range [680K, 780K) covers the
+beginning part of the above dirty range, we need to writeback the
+two pages at 704K and 768K.
+
+ > cow_file_range: r/i=5/259 add ordered extent filepos=774144 len=65536
+ > extent_write_locked_range: r/i=5/259 locked page=720896 start=774144 len=65536
+
+Now the above 2 lines show that we're writing back for dirty range
+[756K, 756K + 64K).
+We only writeback 64K because the zoned device has max zone append size
+as 64K.
+
+ > extent_write_locked_range: r/i=5/259 clear dirty for page=786432
+
+!!! The above line shows the root cause. !!!
+
+We're calling clear_page_dirty_for_io() inside extent_write_locked_range(),
+for the page 768K.
+This is because extent_write_locked_range() can go beyond the current
+locked page, here we hit the page at 768K and clear its page dirt.
+
+In fact this would lead to the desync between subpage dirty and page
+dirty flags. We have the page dirty flag cleared, but the subpage range
+[820K, 832K) is still dirty.
+
+After the writeback of range [756K, 820K), the dirty flags look like
+this, as page 768K no longer has dirty flag set.
+
+ 704K 768K 832K 896K
+ I I | I/////////////| I
+ 820K 868K
+
+This means we will no longer writeback range [820K, 832K), thus the
+reserved data/metadata space would never be properly released.
+
+ > extent_write_cache_pages: r/i=5/259 skip non-dirty folio=786432
+
+Now even though we try to start writeback for page 768K, since the
+page is not dirty, we completely skip it at extent_write_cache_pages()
+time.
+
+ > btrfs_direct_write: r/i=5/259 dio done filepos=696320 len=0
+
+Now the direct IO finished.
+
+ > cow_file_range: r/i=5/259 add ordered extent filepos=851968 len=36864
+ > extent_write_locked_range: r/i=5/259 locked page=851968 start=851968 len=36864
+
+Now we writeback the remaining dirty range, which is [832K, 868K).
+Causing the range [820K, 832K) never to be submitted, thus leaking the
+reserved space.
+
+This bug only affects subpage and zoned case. For non-subpage and zoned
+case, we have exactly one sector for each page, thus no such partial dirty
+cases.
+
+For subpage and non-zoned case, we never go into run_delalloc_cow(), and
+normally all the dirty subpage ranges would be properly submitted inside
+__extent_writepage_io().
+
+[FIX]
+Just do not clear the page dirty at all inside extent_write_locked_range().
+As __extent_writepage_io() would do a more accurate, subpage compatible
+clear for page and subpage dirty flags anyway.
+
+Now the correct trace would look like this:
+
+ > btrfs_dirty_pages: r/i=5/259 dirty start=774144 len=114688
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=720896 off_in_page=53248 len_in_page=12288
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=786432 off_in_page=0 len_in_page=65536
+ > btrfs_dirty_pages: r/i=5/259 dirty part of page=851968 off_in_page=0 len_in_page=36864
+
+The page dirty part is still the same 3 pages.
+
+ > btrfs_direct_write: r/i=5/259 start dio filepos=696320 len=102400
+ > cow_file_range: r/i=5/259 add ordered extent filepos=774144 len=65536
+ > extent_write_locked_range: r/i=5/259 locked page=720896 start=774144 len=65536
+
+And the writeback for the first 64K is still correct.
+
+ > cow_file_range: r/i=5/259 add ordered extent filepos=839680 len=49152
+ > extent_write_locked_range: r/i=5/259 locked page=786432 start=839680 len=49152
+
+Now with the fix, we can properly writeback the range [820K, 832K), and
+properly release the reserved data/metadata space.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 958155cc43a81..0486b1f911248 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2246,10 +2246,8 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page,
+
+ page = find_get_page(mapping, cur >> PAGE_SHIFT);
+ ASSERT(PageLocked(page));
+- if (pages_dirty && page != locked_page) {
++ if (pages_dirty && page != locked_page)
+ ASSERT(PageDirty(page));
+- clear_page_dirty_for_io(page);
+- }
+
+ ret = __extent_writepage_io(BTRFS_I(inode), page, &bio_ctrl,
+ i_size, &nr);
+--
+2.43.0
+
--- /dev/null
+From 88797b3ae2188e7c474bbf49ff51949478a26db2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 15:40:59 +0100
+Subject: btrfs: fix bitmap leak when loading free space cache on duplicate
+ entry
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 320d8dc612660da84c3b70a28658bb38069e5a9a ]
+
+If we failed to link a free space entry because there's already a
+conflicting entry for the same offset, we free the free space entry but
+we don't free the associated bitmap that we had just allocated before.
+Fix that by freeing the bitmap before freeing the entry.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/free-space-cache.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
+index d674f2106593a..62c3dea9572ab 100644
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -858,6 +858,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
+ spin_unlock(&ctl->tree_lock);
+ btrfs_err(fs_info,
+ "Duplicate entries in free space cache, dumping");
++ kmem_cache_free(btrfs_free_space_bitmap_cachep, e->bitmap);
+ kmem_cache_free(btrfs_free_space_cachep, e);
+ goto free_cache;
+ }
+--
+2.43.0
+
--- /dev/null
+From eecc72d6ce5b65bd37c4112bb1e9a401c51fac93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jul 2024 10:51:28 +0100
+Subject: btrfs: fix data race when accessing the last_trans field of a root
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit ca84529a842f3a15a5f17beac6252aa11955923f ]
+
+KCSAN complains about a data race when accessing the last_trans field of a
+root:
+
+ [ 199.553628] BUG: KCSAN: data-race in btrfs_record_root_in_trans [btrfs] / record_root_in_trans [btrfs]
+
+ [ 199.555186] read to 0x000000008801e308 of 8 bytes by task 2812 on cpu 1:
+ [ 199.555210] btrfs_record_root_in_trans+0x9a/0x128 [btrfs]
+ [ 199.555999] start_transaction+0x154/0xcd8 [btrfs]
+ [ 199.556780] btrfs_join_transaction+0x44/0x60 [btrfs]
+ [ 199.557559] btrfs_dirty_inode+0x9c/0x140 [btrfs]
+ [ 199.558339] btrfs_update_time+0x8c/0xb0 [btrfs]
+ [ 199.559123] touch_atime+0x16c/0x1e0
+ [ 199.559151] pipe_read+0x6a8/0x7d0
+ [ 199.559179] vfs_read+0x466/0x498
+ [ 199.559204] ksys_read+0x108/0x150
+ [ 199.559230] __s390x_sys_read+0x68/0x88
+ [ 199.559257] do_syscall+0x1c6/0x210
+ [ 199.559286] __do_syscall+0xc8/0xf0
+ [ 199.559318] system_call+0x70/0x98
+
+ [ 199.559431] write to 0x000000008801e308 of 8 bytes by task 2808 on cpu 0:
+ [ 199.559464] record_root_in_trans+0x196/0x228 [btrfs]
+ [ 199.560236] btrfs_record_root_in_trans+0xfe/0x128 [btrfs]
+ [ 199.561097] start_transaction+0x154/0xcd8 [btrfs]
+ [ 199.561927] btrfs_join_transaction+0x44/0x60 [btrfs]
+ [ 199.562700] btrfs_dirty_inode+0x9c/0x140 [btrfs]
+ [ 199.563493] btrfs_update_time+0x8c/0xb0 [btrfs]
+ [ 199.564277] file_update_time+0xb8/0xf0
+ [ 199.564301] pipe_write+0x8ac/0xab8
+ [ 199.564326] vfs_write+0x33c/0x588
+ [ 199.564349] ksys_write+0x108/0x150
+ [ 199.564372] __s390x_sys_write+0x68/0x88
+ [ 199.564397] do_syscall+0x1c6/0x210
+ [ 199.564424] __do_syscall+0xc8/0xf0
+ [ 199.564452] system_call+0x70/0x98
+
+This is because we update and read last_trans concurrently without any
+type of synchronization. This should be generally harmless and in the
+worst case it can make us do extra locking (btrfs_record_root_in_trans())
+trigger some warnings at ctree.c or do extra work during relocation - this
+would probably only happen in case of load or store tearing.
+
+So fix this by always reading and updating the field using READ_ONCE()
+and WRITE_ONCE(), this silences KCSAN and prevents load and store tearing.
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.c | 4 ++--
+ fs/btrfs/ctree.h | 10 ++++++++++
+ fs/btrfs/defrag.c | 2 +-
+ fs/btrfs/disk-io.c | 4 ++--
+ fs/btrfs/relocation.c | 8 ++++----
+ fs/btrfs/transaction.c | 8 ++++----
+ 6 files changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
+index ca372068226d5..8a791b648ac53 100644
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -321,7 +321,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
+ WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+ trans->transid != fs_info->running_transaction->transid);
+ WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+- trans->transid != root->last_trans);
++ trans->transid != btrfs_get_root_last_trans(root));
+
+ level = btrfs_header_level(buf);
+ if (level == 0)
+@@ -551,7 +551,7 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
+ WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+ trans->transid != fs_info->running_transaction->transid);
+ WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+- trans->transid != root->last_trans);
++ trans->transid != btrfs_get_root_last_trans(root));
+
+ level = btrfs_header_level(buf);
+
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index c03c58246033b..b2e4b30b8fae9 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -354,6 +354,16 @@ static inline void btrfs_set_root_last_log_commit(struct btrfs_root *root, int c
+ WRITE_ONCE(root->last_log_commit, commit_id);
+ }
+
++static inline u64 btrfs_get_root_last_trans(const struct btrfs_root *root)
++{
++ return READ_ONCE(root->last_trans);
++}
++
++static inline void btrfs_set_root_last_trans(struct btrfs_root *root, u64 transid)
++{
++ WRITE_ONCE(root->last_trans, transid);
++}
++
+ /*
+ * Structure that conveys information about an extent that is going to replace
+ * all the extents in a file range.
+diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
+index 407ccec3e57ed..f664678c71d15 100644
+--- a/fs/btrfs/defrag.c
++++ b/fs/btrfs/defrag.c
+@@ -139,7 +139,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
+ if (trans)
+ transid = trans->transid;
+ else
+- transid = inode->root->last_trans;
++ transid = btrfs_get_root_last_trans(root);
+
+ defrag = kmem_cache_zalloc(btrfs_inode_defrag_cachep, GFP_NOFS);
+ if (!defrag)
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index cabb558dbdaa8..3791813dc7b62 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -658,7 +658,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
+ root->state = 0;
+ RB_CLEAR_NODE(&root->rb_node);
+
+- root->last_trans = 0;
++ btrfs_set_root_last_trans(root, 0);
+ root->free_objectid = 0;
+ root->nr_delalloc_inodes = 0;
+ root->nr_ordered_extents = 0;
+@@ -1010,7 +1010,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
+ return ret;
+ }
+
+- log_root->last_trans = trans->transid;
++ btrfs_set_root_last_trans(log_root, trans->transid);
+ log_root->root_key.offset = btrfs_root_id(root);
+
+ inode_item = &log_root->root_item.inode;
+diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
+index 8b24bb5a0aa18..f2935252b981a 100644
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -817,7 +817,7 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
+ goto abort;
+ }
+ set_bit(BTRFS_ROOT_SHAREABLE, &reloc_root->state);
+- reloc_root->last_trans = trans->transid;
++ btrfs_set_root_last_trans(reloc_root, trans->transid);
+ return reloc_root;
+ fail:
+ kfree(root_item);
+@@ -864,7 +864,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
+ */
+ if (root->reloc_root) {
+ reloc_root = root->reloc_root;
+- reloc_root->last_trans = trans->transid;
++ btrfs_set_root_last_trans(reloc_root, trans->transid);
+ return 0;
+ }
+
+@@ -1739,7 +1739,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
+ * btrfs_update_reloc_root() and update our root item
+ * appropriately.
+ */
+- reloc_root->last_trans = trans->transid;
++ btrfs_set_root_last_trans(reloc_root, trans->transid);
+ trans->block_rsv = rc->block_rsv;
+
+ replaced = 0;
+@@ -2082,7 +2082,7 @@ static int record_reloc_root_in_trans(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root;
+ int ret;
+
+- if (reloc_root->last_trans == trans->transid)
++ if (btrfs_get_root_last_trans(reloc_root) == trans->transid)
+ return 0;
+
+ root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, false);
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index 3388c836b9a56..76117bb2c726c 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -405,7 +405,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+ int ret = 0;
+
+ if ((test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
+- root->last_trans < trans->transid) || force) {
++ btrfs_get_root_last_trans(root) < trans->transid) || force) {
+ WARN_ON(!force && root->commit_root != root->node);
+
+ /*
+@@ -421,7 +421,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+ smp_wmb();
+
+ spin_lock(&fs_info->fs_roots_radix_lock);
+- if (root->last_trans == trans->transid && !force) {
++ if (btrfs_get_root_last_trans(root) == trans->transid && !force) {
+ spin_unlock(&fs_info->fs_roots_radix_lock);
+ return 0;
+ }
+@@ -429,7 +429,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
+ (unsigned long)btrfs_root_id(root),
+ BTRFS_ROOT_TRANS_TAG);
+ spin_unlock(&fs_info->fs_roots_radix_lock);
+- root->last_trans = trans->transid;
++ btrfs_set_root_last_trans(root, trans->transid);
+
+ /* this is pretty tricky. We don't want to
+ * take the relocation lock in btrfs_record_root_in_trans
+@@ -491,7 +491,7 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
+ * and barriers
+ */
+ smp_rmb();
+- if (root->last_trans == trans->transid &&
++ if (btrfs_get_root_last_trans(root) == trans->transid &&
+ !test_bit(BTRFS_ROOT_IN_TRANS_SETUP, &root->state))
+ return 0;
+
+--
+2.43.0
+
--- /dev/null
+From 5a0873e18421183cf695cc5f2c851aac4e1d832c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 11:52:19 +0100
+Subject: btrfs: reduce nesting for extent processing at
+ btrfs_lookup_extent_info()
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 5c83b3beaee06aa88d4015408ac2d8bb35380b06 ]
+
+Instead of using an if-else statement when processing the extent item at
+btrfs_lookup_extent_info(), use a single if statement for the error case
+since it does a goto at the end and leave the success (expected) case
+following the if statement, reducing indentation and making the logic a
+bit easier to follow. Also make the if statement's condition as unlikely
+since it's not expected to ever happen, as it signals some corruption,
+making it clear and hint the compiler to generate more efficient code.
+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent-tree.c | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 153297cb97a4a..844b677d054ec 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -104,10 +104,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+ struct btrfs_delayed_ref_head *head;
+ struct btrfs_delayed_ref_root *delayed_refs;
+ struct btrfs_path *path;
+- struct btrfs_extent_item *ei;
+- struct extent_buffer *leaf;
+ struct btrfs_key key;
+- u32 item_size;
+ u64 num_refs;
+ u64 extent_flags;
+ u64 owner = 0;
+@@ -157,16 +154,11 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+ }
+
+ if (ret == 0) {
+- leaf = path->nodes[0];
+- item_size = btrfs_item_size(leaf, path->slots[0]);
+- if (item_size >= sizeof(*ei)) {
+- ei = btrfs_item_ptr(leaf, path->slots[0],
+- struct btrfs_extent_item);
+- num_refs = btrfs_extent_refs(leaf, ei);
+- extent_flags = btrfs_extent_flags(leaf, ei);
+- owner = btrfs_get_extent_owner_root(fs_info, leaf,
+- path->slots[0]);
+- } else {
++ struct extent_buffer *leaf = path->nodes[0];
++ struct btrfs_extent_item *ei;
++ const u32 item_size = btrfs_item_size(leaf, path->slots[0]);
++
++ if (unlikely(item_size < sizeof(*ei))) {
+ ret = -EUCLEAN;
+ btrfs_err(fs_info,
+ "unexpected extent item size, has %u expect >= %zu",
+@@ -179,6 +171,10 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
+ goto out_free;
+ }
+
++ ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
++ num_refs = btrfs_extent_refs(leaf, ei);
++ extent_flags = btrfs_extent_flags(leaf, ei);
++ owner = btrfs_get_extent_owner_root(fs_info, leaf, path->slots[0]);
+ BUG_ON(num_refs == 0);
+ } else {
+ num_refs = 0;
+--
+2.43.0
+
--- /dev/null
+From 55b694b7967c21c8bf443c4a0eecf4136161a8fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Jan 2023 21:30:41 +0100
+Subject: can: mcp251xfd: tef: prepare to workaround broken TEF FIFO tail index
+ erratum
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b8e0ddd36ce9536ad7478dd27df06c9ae92370ba ]
+
+This is a preparatory patch to work around a problem similar to
+erratum DS80000789E 6 of the mcp2518fd, the other variants of the chip
+family (mcp2517fd and mcp251863) are probably also affected.
+
+Erratum DS80000789E 6 says "reading of the FIFOCI bits in the FIFOSTA
+register for an RX FIFO may be corrupted". However observation shows
+that this problem is not limited to RX FIFOs but also effects the TEF
+FIFO.
+
+When handling the TEF interrupt, the driver reads the FIFO header
+index from the TEF FIFO STA register of the chip.
+
+In the bad case, the driver reads a too large head index. In the
+original code, the driver always trusted the read value, which caused
+old CAN transmit complete events that were already processed to be
+re-processed.
+
+Instead of reading and trusting the head index, read the head index
+and calculate the number of CAN frames that were supposedly received -
+replace mcp251xfd_tef_ring_update() with mcp251xfd_get_tef_len().
+
+The mcp251xfd_handle_tefif() function reads the CAN transmit complete
+events from the chip, iterates over them and pushes them into the
+network stack. The original driver already contains code to detect old
+CAN transmit complete events, that will be updated in the next patch.
+
+Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
+Cc: Thomas Kopp <thomas.kopp@microchip.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/can/spi/mcp251xfd/mcp251xfd-ring.c | 2 +
+ drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 54 +++++++++++++------
+ drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 13 ++---
+ 3 files changed, 43 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+index bfe4caa0c99d4..4cb79a4f24612 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+@@ -485,6 +485,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
+ clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
+ }
+
++ tx_ring->obj_num_shift_to_u8 = BITS_PER_TYPE(tx_ring->obj_num) -
++ ilog2(tx_ring->obj_num);
+ tx_ring->obj_size = tx_obj_size;
+
+ rem = priv->rx_obj_num;
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+index e5bd57b65aafe..b41fad3b37c06 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+@@ -2,7 +2,7 @@
+ //
+ // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
+ //
+-// Copyright (c) 2019, 2020, 2021 Pengutronix,
++// Copyright (c) 2019, 2020, 2021, 2023 Pengutronix,
+ // Marc Kleine-Budde <kernel@pengutronix.de>
+ //
+ // Based on:
+@@ -16,6 +16,11 @@
+
+ #include "mcp251xfd.h"
+
++static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta)
++{
++ return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
++}
++
+ static inline int
+ mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
+ u8 *tef_tail)
+@@ -120,28 +125,44 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
+ return 0;
+ }
+
+-static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
++static int
++mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
+ {
+ const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+- unsigned int new_head;
+- u8 chip_tx_tail;
++ const u8 shift = tx_ring->obj_num_shift_to_u8;
++ u8 chip_tx_tail, tail, len;
++ u32 fifo_sta;
+ int err;
+
+- err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
++ err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr),
++ &fifo_sta);
+ if (err)
+ return err;
+
+- /* chip_tx_tail, is the next TX-Object send by the HW.
+- * The new TEF head must be >= the old head, ...
++ if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) {
++ *len_p = tx_ring->obj_num;
++ return 0;
++ }
++
++ chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
++
++ err = mcp251xfd_check_tef_tail(priv);
++ if (err)
++ return err;
++ tail = mcp251xfd_get_tef_tail(priv);
++
++ /* First shift to full u8. The subtraction works on signed
++ * values, that keeps the difference steady around the u8
++ * overflow. The right shift acts on len, which is an u8.
+ */
+- new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
+- if (new_head <= priv->tef->head)
+- new_head += tx_ring->obj_num;
++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail));
++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail));
++ BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
+
+- /* ... but it cannot exceed the TX head. */
+- priv->tef->head = min(new_head, tx_ring->head);
++ len = (chip_tx_tail << shift) - (tail << shift);
++ *len_p = len >> shift;
+
+- return mcp251xfd_check_tef_tail(priv);
++ return 0;
+ }
+
+ static inline int
+@@ -182,13 +203,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+ u8 tef_tail, len, l;
+ int err, i;
+
+- err = mcp251xfd_tef_ring_update(priv);
++ err = mcp251xfd_get_tef_len(priv, &len);
+ if (err)
+ return err;
+
+ tef_tail = mcp251xfd_get_tef_tail(priv);
+- len = mcp251xfd_get_tef_len(priv);
+- l = mcp251xfd_get_tef_linear_len(priv);
++ l = mcp251xfd_get_tef_linear_len(priv, len);
+ err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
+ if (err)
+ return err;
+@@ -223,6 +243,8 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+ struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+ int offset;
+
++ ring->head += len;
++
+ /* Increment the TEF FIFO tail pointer 'len' times in
+ * a single SPI message.
+ *
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+index b35bfebd23f29..4628bf847bc9b 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+@@ -524,6 +524,7 @@ struct mcp251xfd_tef_ring {
+
+ /* u8 obj_num equals tx_ring->obj_num */
+ /* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
++ /* u8 obj_num_shift_to_u8 equals tx_ring->obj_num_shift_to_u8 */
+
+ union mcp251xfd_write_reg_buf irq_enable_buf;
+ struct spi_transfer irq_enable_xfer;
+@@ -542,6 +543,7 @@ struct mcp251xfd_tx_ring {
+ u8 nr;
+ u8 fifo_nr;
+ u8 obj_num;
++ u8 obj_num_shift_to_u8;
+ u8 obj_size;
+
+ struct mcp251xfd_tx_obj obj[MCP251XFD_TX_OBJ_NUM_MAX];
+@@ -861,17 +863,8 @@ static inline u8 mcp251xfd_get_tef_tail(const struct mcp251xfd_priv *priv)
+ return priv->tef->tail & (priv->tx->obj_num - 1);
+ }
+
+-static inline u8 mcp251xfd_get_tef_len(const struct mcp251xfd_priv *priv)
++static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv, u8 len)
+ {
+- return priv->tef->head - priv->tef->tail;
+-}
+-
+-static inline u8 mcp251xfd_get_tef_linear_len(const struct mcp251xfd_priv *priv)
+-{
+- u8 len;
+-
+- len = mcp251xfd_get_tef_len(priv);
+-
+ return min_t(u8, len, priv->tx->obj_num - mcp251xfd_get_tef_tail(priv));
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 1809c96bd0c5a7fe492d4a8e60840da50642ecc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Jan 2023 22:35:03 +0100
+Subject: can: mcp251xfd: tef: update workaround for erratum DS80000789E 6 of
+ mcp2518fd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 3a0a88fcbaf9e027ecca3fe8775be9700b4d6460 ]
+
+This patch updates the workaround for a problem similar to erratum
+DS80000789E 6 of the mcp2518fd, the other variants of the chip
+family (mcp2517fd and mcp251863) are probably also affected.
+
+Erratum DS80000789E 6 says "reading of the FIFOCI bits in the FIFOSTA
+register for an RX FIFO may be corrupted". However observation shows
+that this problem is not limited to RX FIFOs but also effects the TEF
+FIFO.
+
+In the bad case, the driver reads a too large head index. As the FIFO
+is implemented as a ring buffer, this results in re-handling old CAN
+transmit complete events.
+
+Every transmit complete event contains with a sequence number that
+equals to the sequence number of the corresponding TX request. This
+way old TX complete events can be detected.
+
+If the original driver detects a non matching sequence number, it
+prints an info message and tries again later. As wrong sequence
+numbers can be explained by the erratum DS80000789E 6, demote the info
+message to debug level, streamline the code and update the comments.
+
+Keep the behavior: If an old CAN TX complete event is detected, abort
+the iteration and mark the number of valid CAN TX complete events as
+processed in the chip by incrementing the FIFO's tail index.
+
+Cc: Stefan Althöfer <Stefan.Althoefer@janztec.com>
+Cc: Thomas Kopp <thomas.kopp@microchip.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c | 71 +++++++------------
+ 1 file changed, 27 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+index b41fad3b37c06..5b0c7890d4b44 100644
+--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+@@ -60,56 +60,39 @@ static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
+ return 0;
+ }
+
+-static int
+-mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
+-{
+- const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
+- u32 tef_sta;
+- int err;
+-
+- err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta);
+- if (err)
+- return err;
+-
+- if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) {
+- netdev_err(priv->ndev,
+- "Transmit Event FIFO buffer overflow.\n");
+- return -ENOBUFS;
+- }
+-
+- netdev_info(priv->ndev,
+- "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n",
+- tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
+- "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
+- "not empty" : "empty",
+- seq, priv->tef->tail, priv->tef->head, tx_ring->head);
+-
+- /* The Sequence Number in the TEF doesn't match our tef_tail. */
+- return -EAGAIN;
+-}
+-
+ static int
+ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
+ const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
+ unsigned int *frame_len_ptr)
+ {
+ struct net_device_stats *stats = &priv->ndev->stats;
++ u32 seq, tef_tail_masked, tef_tail;
+ struct sk_buff *skb;
+- u32 seq, seq_masked, tef_tail_masked, tef_tail;
+
+- seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
++ /* Use the MCP2517FD mask on the MCP2518FD, too. We only
++ * compare 7 bits, this is enough to detect old TEF objects.
++ */
++ seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK,
+ hw_tef_obj->flags);
+-
+- /* Use the MCP2517FD mask on the MCP2518FD, too. We only
+- * compare 7 bits, this should be enough to detect
+- * net-yet-completed, i.e. old TEF objects.
+- */
+- seq_masked = seq &
+- field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
+ tef_tail_masked = priv->tef->tail &
+ field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
+- if (seq_masked != tef_tail_masked)
+- return mcp251xfd_handle_tefif_recover(priv, seq);
++
++ /* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
++ * bits of a FIFOSTA register, here the TX FIFO tail index
++ * might be corrupted and we might process past the TEF FIFO's
++ * head into old CAN frames.
++ *
++ * Compare the sequence number of the currently processed CAN
++ * frame with the expected sequence number. Abort with
++ * -EBADMSG if an old CAN frame is detected.
++ */
++ if (seq != tef_tail_masked) {
++ netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__,
++ seq, tef_tail_masked);
++ stats->tx_fifo_errors++;
++
++ return -EBADMSG;
++ }
+
+ tef_tail = mcp251xfd_get_tef_tail(priv);
+ skb = priv->can.echo_skb[tef_tail];
+@@ -223,12 +206,12 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
+ unsigned int frame_len = 0;
+
+ err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
+- /* -EAGAIN means the Sequence Number in the TEF
+- * doesn't match our tef_tail. This can happen if we
+- * read the TEF objects too early. Leave loop let the
+- * interrupt handler call us again.
++ /* -EBADMSG means we're affected by mcp2518fd erratum
++ * DS80000789E 6., i.e. the Sequence Number in the TEF
++ * doesn't match our tef_tail. Don't process any
++ * further and mark processed frames as good.
+ */
+- if (err == -EAGAIN)
++ if (err == -EBADMSG)
+ goto out_netif_wake_queue;
+ if (err)
+ return err;
+--
+2.43.0
+
--- /dev/null
+From 0952ac7e4caa804c44d3e373719c10c5e566a0b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jul 2024 21:02:30 +0200
+Subject: clocksource/drivers/sh_cmt: Address race condition for clock events
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit db19d3aa77612983a02bd223b3f273f896b243cf ]
+
+There is a race condition in the CMT interrupt handler. In the interrupt
+handler the driver sets a driver private flag, FLAG_IRQCONTEXT. This
+flag is used to indicate any call to set_next_event() should not be
+directly propagated to the device, but instead cached. This is done as
+the interrupt handler itself reprograms the device when needed before it
+completes and this avoids this operation to take place twice.
+
+It is unclear why this design was chosen, my suspicion is to allow the
+struct clock_event_device.event_handler callback, which is called while
+the FLAG_IRQCONTEXT is set, can update the next event without having to
+write to the device twice.
+
+Unfortunately there is a race between when the FLAG_IRQCONTEXT flag is
+set and later cleared where the interrupt handler have already started to
+write the next event to the device. If set_next_event() is called in
+this window the value is only cached in the driver but not written. This
+leads to the board to misbehave, or worse lockup and produce a splat.
+
+ rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
+ rcu: 0-...!: (0 ticks this GP) idle=f5e0/0/0x0 softirq=519/519 fqs=0 (false positive?)
+ rcu: (detected by 1, t=6502 jiffies, g=-595, q=77 ncpus=2)
+ Sending NMI from CPU 1 to CPUs 0:
+ NMI backtrace for cpu 0
+ CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.10.0-rc5-arm64-renesas-00019-g74a6f86eaf1c-dirty #20
+ Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
+ pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+ pc : tick_check_broadcast_expired+0xc/0x40
+ lr : cpu_idle_poll.isra.0+0x8c/0x168
+ sp : ffff800081c63d70
+ x29: ffff800081c63d70 x28: 00000000580000c8 x27: 00000000bfee5610
+ x26: 0000000000000027 x25: 0000000000000000 x24: 0000000000000000
+ x23: ffff00007fbb9100 x22: ffff8000818f1008 x21: ffff8000800ef07c
+ x20: ffff800081c79ec0 x19: ffff800081c70c28 x18: 0000000000000000
+ x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffffc2c717d8
+ x14: 0000000000000000 x13: ffff000009c18080 x12: ffff8000825f7fc0
+ x11: 0000000000000000 x10: ffff8000818f3cd4 x9 : 0000000000000028
+ x8 : ffff800081c79ec0 x7 : ffff800081c73000 x6 : 0000000000000000
+ x5 : 0000000000000000 x4 : ffff7ffffe286000 x3 : 0000000000000000
+ x2 : ffff7ffffe286000 x1 : ffff800082972900 x0 : ffff8000818f1008
+ Call trace:
+ tick_check_broadcast_expired+0xc/0x40
+ do_idle+0x9c/0x280
+ cpu_startup_entry+0x34/0x40
+ kernel_init+0x0/0x11c
+ do_one_initcall+0x0/0x260
+ __primary_switched+0x80/0x88
+ rcu: rcu_preempt kthread timer wakeup didn't happen for 6501 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402
+ rcu: Possible timer handling issue on cpu=0 timer-softirq=262
+ rcu: rcu_preempt kthread starved for 6502 jiffies! g-595 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=0
+ rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior.
+ rcu: RCU grace-period kthread stack dump:
+ task:rcu_preempt state:I stack:0 pid:15 tgid:15 ppid:2 flags:0x00000008
+ Call trace:
+ __switch_to+0xbc/0x100
+ __schedule+0x358/0xbe0
+ schedule+0x48/0x148
+ schedule_timeout+0xc4/0x138
+ rcu_gp_fqs_loop+0x12c/0x764
+ rcu_gp_kthread+0x208/0x298
+ kthread+0x10c/0x110
+ ret_from_fork+0x10/0x20
+
+The design have been part of the driver since it was first merged in
+early 2009. It becomes increasingly harder to trigger the issue the
+older kernel version one tries. It only takes a few boots on v6.10-rc5,
+while hundreds of boots are needed to trigger it on v5.10.
+
+Close the race condition by using the CMT channel lock for the two
+competing sections. The channel lock was added to the driver after its
+initial design.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Link: https://lore.kernel.org/r/20240702190230.3825292-1-niklas.soderlund+renesas@ragnatech.se
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clocksource/sh_cmt.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
+index 26919556ef5f0..b72b36e0abed8 100644
+--- a/drivers/clocksource/sh_cmt.c
++++ b/drivers/clocksource/sh_cmt.c
+@@ -528,6 +528,7 @@ static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
+ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+ {
+ struct sh_cmt_channel *ch = dev_id;
++ unsigned long flags;
+
+ /* clear flags */
+ sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
+@@ -558,6 +559,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+
+ ch->flags &= ~FLAG_SKIPEVENT;
+
++ raw_spin_lock_irqsave(&ch->lock, flags);
++
+ if (ch->flags & FLAG_REPROGRAM) {
+ ch->flags &= ~FLAG_REPROGRAM;
+ sh_cmt_clock_event_program_verify(ch, 1);
+@@ -570,6 +573,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
+
+ ch->flags &= ~FLAG_IRQCONTEXT;
+
++ raw_spin_unlock_irqrestore(&ch->lock, flags);
++
+ return IRQ_HANDLED;
+ }
+
+@@ -780,12 +785,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
+ struct clock_event_device *ced)
+ {
+ struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
++ unsigned long flags;
+
+ BUG_ON(!clockevent_state_oneshot(ced));
++
++ raw_spin_lock_irqsave(&ch->lock, flags);
++
+ if (likely(ch->flags & FLAG_IRQCONTEXT))
+ ch->next_match_value = delta - 1;
+ else
+- sh_cmt_set_next(ch, delta - 1);
++ __sh_cmt_set_next(ch, delta - 1);
++
++ raw_spin_unlock_irqrestore(&ch->lock, flags);
+
+ return 0;
+ }
+--
+2.43.0
+
--- /dev/null
+From b949cff9e9a86ae2343320d9045a38da5fbae431 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 09:20:49 -0500
+Subject: cpufreq: amd-pstate: Allow users to write 'default' EPP string
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit fc6e0837264a8b2504b6160e63ec92eb012540f3 ]
+
+The EPP string for 'default' represents what the firmware had configured
+as the default EPP value but once a user changes EPP to another string
+they can't reset it back to 'default'.
+
+Cache the firmware EPP value and allow the user to write 'default' using
+this value.
+
+Reported-by: Artem S. Tashkinov <aros@gmx.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217931#c61
+Reviewed-by: Perry Yuan <perry.yuan@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 8 +++-----
+ drivers/cpufreq/amd-pstate.h | 1 +
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index a092b13ffbc2f..874ee90b1cf10 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -304,10 +304,8 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
+ int epp = -EINVAL;
+ int ret;
+
+- if (!pref_index) {
+- pr_debug("EPP pref_index is invalid\n");
+- return -EINVAL;
+- }
++ if (!pref_index)
++ epp = cpudata->epp_default;
+
+ if (epp == -EINVAL)
+ epp = epp_values[pref_index];
+@@ -1439,7 +1437,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+
+ policy->driver_data = cpudata;
+
+- cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0);
++ cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0);
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
+index e6a28e7f4dbf1..f80b33fa5d43a 100644
+--- a/drivers/cpufreq/amd-pstate.h
++++ b/drivers/cpufreq/amd-pstate.h
+@@ -99,6 +99,7 @@ struct amd_cpudata {
+ u32 policy;
+ u64 cppc_cap1_cached;
+ bool suspended;
++ s16 epp_default;
+ };
+
+ #endif /* _LINUX_AMD_PSTATE_H */
+--
+2.43.0
+
--- /dev/null
+From 6b48e8f74e1ba147eb68634476b85012f1386776 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Jun 2024 23:40:19 +0800
+Subject: cpufreq: amd-pstate: auto-load pstate driver by default
+
+From: Perry Yuan <perry.yuan@amd.com>
+
+[ Upstream commit 4e4f600ee750facedf6a5dc97e8ae0b627ab4573 ]
+
+If the `amd-pstate` driver is not loaded automatically by default,
+it is because the kernel command line parameter has not been added.
+To resolve this issue, it is necessary to call the `amd_pstate_set_driver()`
+function to enable the desired mode (passive/active/guided) before registering
+the driver instance.
+
+This ensures that the driver is loaded correctly without relying on the kernel
+command line parameter.
+
+When there is no parameter added to command line, Kernel config will
+provide the default mode to load.
+
+Meanwhile, user can add driver mode in command line which will override
+the kernel config default option.
+
+Reported-by: Andrei Amuraritei <andamu@posteo.net>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218705
+Signed-off-by: Perry Yuan <perry.yuan@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://lore.kernel.org/r/83301c4cea4f92fb19e14b23f2bac7facfd8bdbb.1718811234.git.perry.yuan@amd.com
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/amd-pstate.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 874ee90b1cf10..67c4a6a0ef124 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -1764,8 +1764,13 @@ static int __init amd_pstate_init(void)
+ /* check if this machine need CPPC quirks */
+ dmi_check_system(amd_pstate_quirks_table);
+
+- switch (cppc_state) {
+- case AMD_PSTATE_UNDEFINED:
++ /*
++ * determine the driver mode from the command line or kernel config.
++ * If no command line input is provided, cppc_state will be AMD_PSTATE_UNDEFINED.
++ * command line options will override the kernel config settings.
++ */
++
++ if (cppc_state == AMD_PSTATE_UNDEFINED) {
+ /* Disable on the following configs by default:
+ * 1. Undefined platforms
+ * 2. Server platforms
+@@ -1777,15 +1782,20 @@ static int __init amd_pstate_init(void)
+ pr_info("driver load is disabled, boot with specific mode to enable this\n");
+ return -ENODEV;
+ }
+- ret = amd_pstate_set_driver(CONFIG_X86_AMD_PSTATE_DEFAULT_MODE);
+- if (ret)
+- return ret;
+- break;
++ /* get driver mode from kernel config option [1:4] */
++ cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE;
++ }
++
++ switch (cppc_state) {
+ case AMD_PSTATE_DISABLE:
++ pr_info("driver load is disabled, boot with specific mode to enable this\n");
+ return -ENODEV;
+ case AMD_PSTATE_PASSIVE:
+ case AMD_PSTATE_ACTIVE:
+ case AMD_PSTATE_GUIDED:
++ ret = amd_pstate_set_driver(cppc_state);
++ if (ret)
++ return ret;
+ break;
+ default:
+ return -EINVAL;
+@@ -1806,7 +1816,7 @@ static int __init amd_pstate_init(void)
+ /* enable amd pstate feature */
+ ret = amd_pstate_enable(true);
+ if (ret) {
+- pr_err("failed to enable with return %d\n", ret);
++ pr_err("failed to enable driver mode(%d)\n", cppc_state);
+ return ret;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 2914c33c3aba36a09f17f7d6d1b0305db31c2e7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 02:18:12 -0700
+Subject: debugobjects: Annotate racy debug variables
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 5b5baba6222255d29626f63c41f101379ec5400b ]
+
+KCSAN has identified a potential data race in debugobjects, where the
+global variable debug_objects_maxchain is accessed for both reading and
+writing simultaneously in separate and parallel data paths. This results in
+the following splat printed by KCSAN:
+
+ BUG: KCSAN: data-race in debug_check_no_obj_freed / debug_object_activate
+
+ write to 0xffffffff847ccfc8 of 4 bytes by task 734 on cpu 41:
+ debug_object_activate (lib/debugobjects.c:199 lib/debugobjects.c:564 lib/debugobjects.c:710)
+ call_rcu (kernel/rcu/rcu.h:227 kernel/rcu/tree.c:2719 kernel/rcu/tree.c:2838)
+ security_inode_free (security/security.c:1626)
+ __destroy_inode (./include/linux/fsnotify.h:222 fs/inode.c:287)
+ ...
+ read to 0xffffffff847ccfc8 of 4 bytes by task 384 on cpu 31:
+ debug_check_no_obj_freed (lib/debugobjects.c:1000 lib/debugobjects.c:1019)
+ kfree (mm/slub.c:2081 mm/slub.c:4280 mm/slub.c:4390)
+ percpu_ref_exit (lib/percpu-refcount.c:147)
+ css_free_rwork_fn (kernel/cgroup/cgroup.c:5357)
+ ...
+ value changed: 0x00000070 -> 0x00000071
+
+The data race is actually harmless as this is just used for debugfs
+statistics, as all other debug variables.
+
+Annotate all debug variables as racy explicitly, since these variables
+are known to be racy and harmless.
+
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20240611091813.1189860-1-leitao@debian.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/debugobjects.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/lib/debugobjects.c b/lib/debugobjects.c
+index fb12a9bacd2fa..7cea91e193a8f 100644
+--- a/lib/debugobjects.c
++++ b/lib/debugobjects.c
+@@ -78,16 +78,17 @@ static bool obj_freeing;
+ /* The number of objs on the global free list */
+ static int obj_nr_tofree;
+
+-static int debug_objects_maxchain __read_mostly;
+-static int __maybe_unused debug_objects_maxchecked __read_mostly;
+-static int debug_objects_fixups __read_mostly;
+-static int debug_objects_warnings __read_mostly;
+-static int debug_objects_enabled __read_mostly
+- = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
+-static int debug_objects_pool_size __read_mostly
+- = ODEBUG_POOL_SIZE;
+-static int debug_objects_pool_min_level __read_mostly
+- = ODEBUG_POOL_MIN_LEVEL;
++static int __data_racy debug_objects_maxchain __read_mostly;
++static int __data_racy __maybe_unused debug_objects_maxchecked __read_mostly;
++static int __data_racy debug_objects_fixups __read_mostly;
++static int __data_racy debug_objects_warnings __read_mostly;
++static int __data_racy debug_objects_enabled __read_mostly
++ = CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT;
++static int __data_racy debug_objects_pool_size __read_mostly
++ = ODEBUG_POOL_SIZE;
++static int __data_racy debug_objects_pool_min_level __read_mostly
++ = ODEBUG_POOL_MIN_LEVEL;
++
+ static const struct debug_obj_descr *descr_test __read_mostly;
+ static struct kmem_cache *obj_cache __ro_after_init;
+
+--
+2.43.0
+
--- /dev/null
+From 964d2008dd63f9d6bb493c452c4663fc96447d5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 10:57:04 +0800
+Subject: drm/admgpu: fix dereferencing null pointer context
+
+From: Jesse Zhang <jesse.zhang@amd.com>
+
+[ Upstream commit 030ffd4d43b433bc6671d9ec34fc12c59220b95d ]
+
+When user space sets an invalid ta type, the pointer context will be empty.
+So it need to check the pointer context before using it
+
+Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
+Suggested-by: Tim Huang <Tim.Huang@amd.com>
+Reviewed-by: Tim Huang <Tim.Huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+index ca5c86e5f7cd6..8e8afbd237bcd 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+@@ -334,7 +334,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
+
+ set_ta_context_funcs(psp, ta_type, &context);
+
+- if (!context->initialized) {
++ if (!context || !context->initialized) {
+ dev_err(adev->dev, "TA is not initialized\n");
+ ret = -EINVAL;
+ goto err_free_shared_buf;
+--
+2.43.0
+
--- /dev/null
+From aba2f0eef21c63e0287c2047a788e849cc57ded2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 15:24:46 -0500
+Subject: drm/amd/amdkfd: Fix a resource leak in svm_range_validate_and_map()
+
+From: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
+
+[ Upstream commit d2d3a44008fea01ec7d5a9d9ca527286be2e0257 ]
+
+Analysis of code by Coverity, a static code analyser, has identified
+a resource leak in the symbol hmm_range. This leak occurs when one of
+the prior steps before it is released encounters an error.
+
+Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index 31e500859ab01..92485251247a0 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -1658,7 +1658,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+ start = map_start << PAGE_SHIFT;
+ end = (map_last + 1) << PAGE_SHIFT;
+ for (addr = start; !r && addr < end; ) {
+- struct hmm_range *hmm_range;
++ struct hmm_range *hmm_range = NULL;
+ unsigned long map_start_vma;
+ unsigned long map_last_vma;
+ struct vm_area_struct *vma;
+@@ -1696,7 +1696,12 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+ }
+
+ svm_range_lock(prange);
+- if (!r && amdgpu_hmm_range_get_pages_done(hmm_range)) {
++
++ /* Free backing memory of hmm_range if it was initialized
++ * Overrride return value to TRY AGAIN only if prior returns
++ * were successful
++ */
++ if (hmm_range && amdgpu_hmm_range_get_pages_done(hmm_range) && !r) {
+ pr_debug("hmm update the range, need validate again\n");
+ r = -EAGAIN;
+ }
+--
+2.43.0
+
--- /dev/null
+From dd0e44e843b878e839f6ae5379f413c37bf30a44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 12:00:34 -0400
+Subject: drm/amd/display: Add delay to improve LTTPR UHBR interop
+
+From: Michael Strauss <michael.strauss@amd.com>
+
+[ Upstream commit 10839ee6a977ed1f7d0f4deb29f2d7e5d1f2a9dd ]
+
+[WHY]
+Avoid race condition which puts LTTPR into bad state during UHBR LT.
+
+[HOW]
+Delay 30ms between starting UHBR TPS1 PHY output and sending TPS1 via DPCD.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Michael Strauss <michael.strauss@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+index 3e6c7be7e2786..5302d2c9c7607 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
++++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+@@ -165,7 +165,12 @@ static void set_hpo_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *lin
+ link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
+ link_res->hpo_dp_link_enc, tp_params);
+ }
++
+ link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
++
++ // Give retimer extra time to lock before updating DP_TRAINING_PATTERN_SET to TPS1
++ if (tp_params->dp_phy_pattern == DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE)
++ msleep(30);
+ }
+
+ static void set_hpo_fixed_vs_pe_retimer_dp_lane_settings(struct dc_link *link,
+--
+2.43.0
+
--- /dev/null
+From 2a26e9c9acd06183ee0c1c13acce22ec926243ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 21:13:40 +0530
+Subject: drm/amd/display: Add NULL check for 'afb' before dereferencing in
+ amdgpu_dm_plane_handle_cursor_update
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 38e6f715b02b572f74677eb2f29d3b4bc6f1ddff ]
+
+This commit adds a null check for the 'afb' variable in the
+amdgpu_dm_plane_handle_cursor_update function. Previously, 'afb' was
+assumed to be null, but was used later in the code without a null check.
+This could potentially lead to a null pointer dereference.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_plane.c:1298 amdgpu_dm_plane_handle_cursor_update() error: we previously assumed 'afb' could be null (see line 1252)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Hersen Wu <hersenxs.wu@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+index 8a4c40b4c27e4..918c880739a2a 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+@@ -1231,14 +1231,22 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
+ {
+ struct amdgpu_device *adev = drm_to_adev(plane->dev);
+ struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
+- struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
+- struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
+- struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+- uint64_t address = afb ? afb->address : 0;
++ struct drm_crtc *crtc;
++ struct dm_crtc_state *crtc_state;
++ struct amdgpu_crtc *amdgpu_crtc;
++ u64 address;
+ struct dc_cursor_position position = {0};
+ struct dc_cursor_attributes attributes;
+ int ret;
+
++ if (!afb)
++ return;
++
++ crtc = plane->state->crtc ? plane->state->crtc : old_plane_state->crtc;
++ crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
++ amdgpu_crtc = to_amdgpu_crtc(crtc);
++ address = afb->address;
++
+ if (!plane->state->fb && !old_plane_state->fb)
+ return;
+
+--
+2.43.0
+
--- /dev/null
+From 579cb49b6beebcd3b45775f9848614e7110d888d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 16:33:18 -0600
+Subject: drm/amd/display: Add null checker before passing variables
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 8092aa3ab8f7b737a34b71f91492c676a843043a ]
+
+Checks null pointer before passing variables to functions.
+
+This fixes 3 NULL_RETURNS issues reported by Coverity.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 3cdcadd41be1a..964bb6d0a3833 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2701,7 +2701,8 @@ static int dm_suspend(void *handle)
+
+ dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
+
+- dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
++ if (dm->cached_dc_state)
++ dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
+
+ amdgpu_dm_commit_zero_streams(dm->dc);
+
+@@ -6788,7 +6789,8 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
+ aconnector->dc_sink = aconnector->dc_link->local_sink ?
+ aconnector->dc_link->local_sink :
+ aconnector->dc_em_sink;
+- dc_sink_retain(aconnector->dc_sink);
++ if (aconnector->dc_sink)
++ dc_sink_retain(aconnector->dc_sink);
+ }
+ }
+
+@@ -7615,7 +7617,8 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+ drm_add_modes_noedid(connector, 1920, 1080);
+ } else {
+ amdgpu_dm_connector_ddc_get_modes(connector, edid);
+- amdgpu_dm_connector_add_common_modes(encoder, connector);
++ if (encoder)
++ amdgpu_dm_connector_add_common_modes(encoder, connector);
+ amdgpu_dm_connector_add_freesync_modes(connector, edid);
+ }
+ amdgpu_dm_fbc_init(connector);
+--
+2.43.0
+
--- /dev/null
+From 867f093dea3e42437521b9dd2c3c9dddf17d07de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 20:15:21 +0530
+Subject: drm/amd/display: Add null checks for 'stream' and 'plane' before
+ dereferencing
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 15c2990e0f0108b9c3752d7072a97d45d4283aea ]
+
+This commit adds null checks for the 'stream' and 'plane' variables in
+the dcn30_apply_idle_power_optimizations function. These variables were
+previously assumed to be null at line 922, but they were used later in
+the code without checking if they were null. This could potentially lead
+to a null pointer dereference, which would cause a crash.
+
+The null checks ensure that 'stream' and 'plane' are not null before
+they are used, preventing potential crashes.
+
+Fixes the below static smatch checker:
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:938 dcn30_apply_idle_power_optimizations() error: we previously assumed 'stream' could be null (see line 922)
+drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:940 dcn30_apply_idle_power_optimizations() error: we previously assumed 'plane' could be null (see line 922)
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Cc: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Hersen Wu <hersenxs.wu@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+index ed9141a67db37..5b09d95cc5b8f 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+@@ -919,6 +919,9 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
+ stream = dc->current_state->streams[0];
+ plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
+
++ if (!stream || !plane)
++ return false;
++
+ if (stream && plane) {
+ cursor_cache_enable = stream->cursor_position.enable &&
+ plane->address.grph.cursor_cache_addr.quad_part;
+--
+2.43.0
+
--- /dev/null
+From cb0c1a81dfd1ac47ece50a420d61e102df1eac95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 11:54:26 +0800
+Subject: drm/amd/display: Don't refer to dc_sink in is_dsc_need_re_compute
+
+From: Wayne Lin <wayne.lin@amd.com>
+
+[ Upstream commit fcf6a49d79923a234844b8efe830a61f3f0584e4 ]
+
+[Why]
+When unplug one of monitors connected after mst hub, encounter null pointer dereference.
+
+It's due to dc_sink get released immediately in early_unregister() or detect_ctx(). When
+commit new state which directly referring to info stored in dc_sink will cause null pointer
+dereference.
+
+[how]
+Remove redundant checking condition. Relevant condition should already be covered by checking
+if dsc_aux is null or not. Also reset dsc_aux to NULL when the connector is disconnected.
+
+Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index e90f9d6975111..7c405ffae1a3d 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -182,6 +182,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
+ dc_sink_release(dc_sink);
+ aconnector->dc_sink = NULL;
+ aconnector->edid = NULL;
++ aconnector->dsc_aux = NULL;
++ port->passthrough_aux = NULL;
+ }
+
+ aconnector->mst_status = MST_STATUS_DEFAULT;
+@@ -494,6 +496,8 @@ dm_dp_mst_detect(struct drm_connector *connector,
+ dc_sink_release(aconnector->dc_sink);
+ aconnector->dc_sink = NULL;
+ aconnector->edid = NULL;
++ aconnector->dsc_aux = NULL;
++ port->passthrough_aux = NULL;
+
+ amdgpu_dm_set_mst_status(&aconnector->mst_status,
+ MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
+@@ -1233,14 +1237,6 @@ static bool is_dsc_need_re_compute(
+ if (!aconnector || !aconnector->dsc_aux)
+ continue;
+
+- /*
+- * check if cached virtual MST DSC caps are available and DSC is supported
+- * as per specifications in their Virtual DPCD registers.
+- */
+- if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported ||
+- aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
+- continue;
+-
+ stream_on_link[new_stream_on_link_num] = aconnector;
+ new_stream_on_link_num++;
+
+--
+2.43.0
+
--- /dev/null
+From 379467002e520422ebc323a6a68552741ad8b0f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 13:13:57 -0400
+Subject: drm/amd/display: Fix null pointer deref in dcn20_resource.c
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+[ Upstream commit ecbf60782662f0a388493685b85a645a0ba1613c ]
+
+Fixes a hang thats triggered when MPV is run on a DCN401 dGPU:
+
+mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all
+
+and then enabling fullscreen playback (double click on the video)
+
+The following calltrace will be seen:
+
+[ 181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[ 181.843997] #PF: supervisor instruction fetch in kernel mode
+[ 181.844003] #PF: error_code(0x0010) - not-present page
+[ 181.844009] PGD 0 P4D 0
+[ 181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI
+[ 181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G W OE 6.5.0-41-generic #41~22.04.2-Ubuntu
+[ 181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018
+[ 181.844044] RIP: 0010:0x0
+[ 181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[ 181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246
+[ 181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004
+[ 181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400
+[ 181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c
+[ 181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8
+[ 181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005
+[ 181.844121] FS: 00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000
+[ 181.844128] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0
+[ 181.844141] Call Trace:
+[ 181.844146] <TASK>
+[ 181.844153] ? show_regs+0x6d/0x80
+[ 181.844167] ? __die+0x24/0x80
+[ 181.844179] ? page_fault_oops+0x99/0x1b0
+[ 181.844192] ? do_user_addr_fault+0x31d/0x6b0
+[ 181.844204] ? exc_page_fault+0x83/0x1b0
+[ 181.844216] ? asm_exc_page_fault+0x27/0x30
+[ 181.844237] dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu]
+[ 181.845115] amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu]
+[ 181.845985] amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu]
+[ 181.846848] fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu]
+[ 181.847734] fill_dc_plane_attributes+0x162/0x350 [amdgpu]
+[ 181.848748] dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[ 181.849791] ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[ 181.850840] amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu]
+
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/resource/dcn20/dcn20_resource.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+index 0a939437e19f1..6b380e037e3f8 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+@@ -2193,10 +2193,11 @@ bool dcn20_get_dcc_compression_cap(const struct dc *dc,
+ const struct dc_dcc_surface_param *input,
+ struct dc_surface_dcc_cap *output)
+ {
+- return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
+- dc->res_pool->hubbub,
+- input,
+- output);
++ if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap)
++ return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
++ dc->res_pool->hubbub, input, output);
++
++ return false;
+ }
+
+ static void dcn20_destroy_resource_pool(struct resource_pool **pool)
+--
+2.43.0
+
--- /dev/null
+From 81599e460038b57347811bc8d3d5a8879c8acf61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Jun 2024 15:31:15 -0600
+Subject: drm/amd/display: Fix NULL pointer dereference for DTN log in DCN401
+
+From: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+
+[ Upstream commit 5af757124792817f8eb1bd0c80ad60fab519586b ]
+
+When users run the command:
+
+cat /sys/kernel/debug/dri/0/amdgpu_dm_dtn_log
+
+The following NULL pointer dereference happens:
+
+[ +0.000003] BUG: kernel NULL pointer dereference, address: NULL
+[ +0.000005] #PF: supervisor instruction fetch in kernel mode
+[ +0.000002] #PF: error_code(0x0010) - not-present page
+[ +0.000002] PGD 0 P4D 0
+[ +0.000004] Oops: 0010 [#1] PREEMPT SMP NOPTI
+[ +0.000003] RIP: 0010:0x0
+[ +0.000008] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[...]
+[ +0.000002] PKRU: 55555554
+[ +0.000002] Call Trace:
+[ +0.000002] <TASK>
+[ +0.000003] ? show_regs+0x65/0x70
+[ +0.000006] ? __die+0x24/0x70
+[ +0.000004] ? page_fault_oops+0x160/0x470
+[ +0.000006] ? do_user_addr_fault+0x2b5/0x690
+[ +0.000003] ? prb_read_valid+0x1c/0x30
+[ +0.000005] ? exc_page_fault+0x8c/0x1a0
+[ +0.000005] ? asm_exc_page_fault+0x27/0x30
+[ +0.000012] dcn10_log_color_state+0xf9/0x510 [amdgpu]
+[ +0.000306] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000003] ? vsnprintf+0x2fb/0x600
+[ +0.000009] dcn10_log_hw_state+0xfd0/0xfe0 [amdgpu]
+[ +0.000218] ? __mod_memcg_lruvec_state+0xe8/0x170
+[ +0.000008] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000002] ? debug_smp_processor_id+0x17/0x20
+[ +0.000003] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000002] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000002] ? set_ptes.isra.0+0x2b/0x90
+[ +0.000004] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000002] ? _raw_spin_unlock+0x19/0x40
+[ +0.000004] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000002] ? do_anonymous_page+0x337/0x700
+[ +0.000004] dtn_log_read+0x82/0x120 [amdgpu]
+[ +0.000207] full_proxy_read+0x66/0x90
+[ +0.000007] vfs_read+0xb0/0x340
+[ +0.000005] ? __count_memcg_events+0x79/0xe0
+[ +0.000002] ? srso_alias_return_thunk+0x5/0xfbef5
+[ +0.000003] ? count_memcg_events.constprop.0+0x1e/0x40
+[ +0.000003] ? handle_mm_fault+0xb2/0x370
+[ +0.000003] ksys_read+0x6b/0xf0
+[ +0.000004] __x64_sys_read+0x19/0x20
+[ +0.000003] do_syscall_64+0x60/0x130
+[ +0.000004] entry_SYSCALL_64_after_hwframe+0x6e/0x76
+[ +0.000003] RIP: 0033:0x7fdf32f147e2
+[...]
+
+This error happens when the color log tries to read the gamut remap
+information from DCN401 which is not initialized in the dcn401_dpp_funcs
+which leads to a null pointer dereference. This commit addresses this
+issue by adding a proper guard to access the gamut_remap callback in
+case the specific ASIC did not implement this function.
+
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 49 ++++++++++---------
+ 1 file changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index 0c4aef8ffe2c5..3306684e805ac 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -288,6 +288,7 @@ static void dcn10_log_color_state(struct dc *dc,
+ {
+ struct dc_context *dc_ctx = dc->ctx;
+ struct resource_pool *pool = dc->res_pool;
++ bool is_gamut_remap_available = false;
+ int i;
+
+ DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
+@@ -300,16 +301,15 @@ static void dcn10_log_color_state(struct dc *dc,
+ struct dcn_dpp_state s = {0};
+
+ dpp->funcs->dpp_read_state(dpp, &s);
+- dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
++ if (dpp->funcs->dpp_get_gamut_remap) {
++ dpp->funcs->dpp_get_gamut_remap(dpp, &s.gamut_remap);
++ is_gamut_remap_available = true;
++ }
+
+ if (!s.is_enabled)
+ continue;
+
+- DTN_INFO("[%2d]: %11xh %11s %9s %9s"
+- " %12s "
+- "%010lld %010lld %010lld %010lld "
+- "%010lld %010lld %010lld %010lld "
+- "%010lld %010lld %010lld %010lld",
++ DTN_INFO("[%2d]: %11xh %11s %9s %9s",
+ dpp->inst,
+ s.igam_input_format,
+ (s.igam_lut_mode == 0) ? "BypassFixed" :
+@@ -328,22 +328,27 @@ static void dcn10_log_color_state(struct dc *dc,
+ ((s.rgam_lut_mode == 2) ? "Ycc" :
+ ((s.rgam_lut_mode == 3) ? "RAM" :
+ ((s.rgam_lut_mode == 4) ? "RAM" :
+- "Unknown")))),
+- (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
+- ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" :
+- "SW"),
+- s.gamut_remap.temperature_matrix[0].value,
+- s.gamut_remap.temperature_matrix[1].value,
+- s.gamut_remap.temperature_matrix[2].value,
+- s.gamut_remap.temperature_matrix[3].value,
+- s.gamut_remap.temperature_matrix[4].value,
+- s.gamut_remap.temperature_matrix[5].value,
+- s.gamut_remap.temperature_matrix[6].value,
+- s.gamut_remap.temperature_matrix[7].value,
+- s.gamut_remap.temperature_matrix[8].value,
+- s.gamut_remap.temperature_matrix[9].value,
+- s.gamut_remap.temperature_matrix[10].value,
+- s.gamut_remap.temperature_matrix[11].value);
++ "Unknown")))));
++ if (is_gamut_remap_available)
++ DTN_INFO(" %12s "
++ "%010lld %010lld %010lld %010lld "
++ "%010lld %010lld %010lld %010lld "
++ "%010lld %010lld %010lld %010lld",
++ (s.gamut_remap.gamut_adjust_type == 0) ? "Bypass" :
++ ((s.gamut_remap.gamut_adjust_type == 1) ? "HW" : "SW"),
++ s.gamut_remap.temperature_matrix[0].value,
++ s.gamut_remap.temperature_matrix[1].value,
++ s.gamut_remap.temperature_matrix[2].value,
++ s.gamut_remap.temperature_matrix[3].value,
++ s.gamut_remap.temperature_matrix[4].value,
++ s.gamut_remap.temperature_matrix[5].value,
++ s.gamut_remap.temperature_matrix[6].value,
++ s.gamut_remap.temperature_matrix[7].value,
++ s.gamut_remap.temperature_matrix[8].value,
++ s.gamut_remap.temperature_matrix[9].value,
++ s.gamut_remap.temperature_matrix[10].value,
++ s.gamut_remap.temperature_matrix[11].value);
++
+ DTN_INFO("\n");
+ }
+ DTN_INFO("\n");
+--
+2.43.0
+
--- /dev/null
+From ccc1ac5cd979220dd3625dcdf773aec5e68997c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 14:40:32 +0800
+Subject: drm/amd/display: Handle HPD_IRQ for internal link
+
+From: Sung-huai Wang <danny.wang@amd.com>
+
+[ Upstream commit 239b31bd5c3fef3698440bf6436b2068c6bb08a3 ]
+
+[Why]
+TCON data is corrupted after electro static discharge test.
+Once the TCON data get corrupted, they will get themselves
+reset and send HPD_IRQ to source side.
+
+[How]
+Support HPD_IRQ for internal link, and restore the PSR/Replay setup.
+
+Reviewed-by: Robin Chen <robin.chen@amd.com>
+Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Sung-huai Wang <danny.wang@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dc/link/protocols/link_dp_irq_handler.c | 25 ++++++++++++-------
+ 1 file changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+index 0fcf0b8530acf..659b8064d3618 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+@@ -373,6 +373,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ union device_service_irq device_service_clear = {0};
+ enum dc_status result;
+ bool status = false;
++ bool allow_active = false;
+
+ if (out_link_loss)
+ *out_link_loss = false;
+@@ -427,12 +428,6 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ return false;
+ }
+
+- if (handle_hpd_irq_psr_sink(link))
+- /* PSR-related error was detected and handled */
+- return true;
+-
+- handle_hpd_irq_replay_sink(link);
+-
+ /* If PSR-related error handled, Main link may be off,
+ * so do not handle as a normal sink status change interrupt.
+ */
+@@ -454,9 +449,8 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ * If we got sink count changed it means
+ * Downstream port status changed,
+ * then DM should call DC to do the detection.
+- * NOTE: Do not handle link loss on eDP since it is internal link*/
+- if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
+- dp_parse_link_loss_status(
++ */
++ if (dp_parse_link_loss_status(
+ link,
+ &hpd_irq_dpcd_data)) {
+ /* Connectivity log: link loss */
+@@ -465,6 +459,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ sizeof(hpd_irq_dpcd_data),
+ "Status: ");
+
++ if (link->psr_settings.psr_feature_enabled)
++ edp_set_psr_allow_active(link, &allow_active, true, false, NULL);
++ else if (link->replay_settings.replay_allow_active)
++ edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
++
+ if (defer_handling && has_left_work)
+ *has_left_work = true;
+ else
+@@ -477,6 +476,14 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
+ dp_trace_link_loss_increment(link);
+ }
+
++ if (*out_link_loss == false) {
++ if (handle_hpd_irq_psr_sink(link))
++ /* PSR-related error was detected and handled */
++ return true;
++
++ handle_hpd_irq_replay_sink(link);
++ }
++
+ if (link->type == dc_connection_sst_branch &&
+ hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+ != link->dpcd_sink_count)
+--
+2.43.0
+
--- /dev/null
+From 757d529cb7d14863eea92bc0754ace8f1e0626c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 May 2024 17:05:41 -0400
+Subject: drm/amd/display: reduce ODM slice count to initial new dc state only
+ when needed
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit 9a29c4adb0997be6ba3dd92dfba14ea75a8c6ce4 ]
+
+[why]
+We need to decrease ODM slice when adding or removing planes because MPO
+support takes precedence over dynamic ODM combine. However there is a case where
+we remove ODM combine even for ODM combine required timing in the initial new
+dc state. This is normally okay because ODM will be added back after we pass DML
+bandwidth validation. However since we remove ODM combine in the initial new
+state, the previous ODM pipe allocation is lost. This may cause the new plane to
+take away the original secondary OPP head pipe that is still required in the new
+state.
+
+For a timing that requires ODM 2:1 but optimized with ODM 4:1, if we add an MPO
+plane, we will not have enough pipe to preserve ODM 4:1. In this case we should
+reduce ODM slice count then try to add the MPO plane again. By reducing, we are
+gradually remove 1 ODM slice from right most side one at a time until we have
+enough free pipes for the new plane. If we remove ODM combine entirely, we could
+use the pipe at ODM slice index 1 as a DPP pipe for the new plane. But ODM slice
+1 is still needed as the timing requires ODM 2:1. This transition is not
+seamless and user will see corruption on the screen.
+
+[how]
+Remove single ODM slice one at time until we have enough pipes for a new plane.
+Remove previous logic to always remove ODM combine entirely.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 45 +++++++------
+ .../gpu/drm/amd/display/dc/core/dc_state.c | 67 +++++++++++++------
+ 2 files changed, 71 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index 15819416a2f36..a2ca66a268c2d 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -2508,6 +2508,17 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
+ }
+ }
+
++static int get_num_of_free_pipes(const struct resource_pool *pool, const struct dc_state *context)
++{
++ int i;
++ int count = 0;
++
++ for (i = 0; i < pool->pipe_count; i++)
++ if (resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], FREE_PIPE))
++ count++;
++ return count;
++}
++
+ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ctx,
+ const struct resource_pool *pool,
+ struct dc_stream_state *stream)
+@@ -2641,37 +2652,33 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
+ struct dc_state *cur_ctx,
+ struct resource_pool *pool)
+ {
+- struct pipe_ctx *opp_head_pipe, *sec_pipe, *tail_pipe;
++ struct pipe_ctx *sec_pipe, *tail_pipe;
++ struct pipe_ctx *opp_heads[MAX_PIPES];
++ int opp_head_count;
++ int i;
+
+ if (!pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe) {
+ ASSERT(0);
+ return false;
+ }
+
+- opp_head_pipe = otg_master_pipe;
+- while (opp_head_pipe) {
++ opp_head_count = resource_get_opp_heads_for_otg_master(otg_master_pipe,
++ &new_ctx->res_ctx, opp_heads);
++ if (get_num_of_free_pipes(pool, new_ctx) < opp_head_count)
++ /* not enough free pipes */
++ return false;
++
++ for (i = 0; i < opp_head_count; i++) {
+ sec_pipe = pool->funcs->acquire_free_pipe_as_secondary_dpp_pipe(
+ cur_ctx,
+ new_ctx,
+ pool,
+- opp_head_pipe);
+- if (!sec_pipe) {
+- /* try tearing down MPCC combine */
+- int pipe_idx = acquire_first_split_pipe(
+- &new_ctx->res_ctx, pool,
+- otg_master_pipe->stream);
+-
+- if (pipe_idx >= 0)
+- sec_pipe = &new_ctx->res_ctx.pipe_ctx[pipe_idx];
+- }
+-
+- if (!sec_pipe)
+- return false;
+-
++ opp_heads[i]);
++ ASSERT(sec_pipe);
+ sec_pipe->plane_state = plane_state;
+
+ /* establish pipe relationship */
+- tail_pipe = get_tail_pipe(opp_head_pipe);
++ tail_pipe = get_tail_pipe(opp_heads[i]);
+ tail_pipe->bottom_pipe = sec_pipe;
+ sec_pipe->top_pipe = tail_pipe;
+ sec_pipe->bottom_pipe = NULL;
+@@ -2682,8 +2689,6 @@ static bool acquire_secondary_dpp_pipes_and_add_plane(
+ } else {
+ sec_pipe->prev_odm_pipe = NULL;
+ }
+-
+- opp_head_pipe = opp_head_pipe->next_odm_pipe;
+ }
+ return true;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index 76bb05f4d6bf3..52a1cfc5feed8 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -437,6 +437,19 @@ enum dc_status dc_state_remove_stream(
+ return DC_OK;
+ }
+
++static void remove_mpc_combine_for_stream(const struct dc *dc,
++ struct dc_state *new_ctx,
++ const struct dc_state *cur_ctx,
++ struct dc_stream_status *status)
++{
++ int i;
++
++ for (i = 0; i < status->plane_count; i++)
++ resource_update_pipes_for_plane_with_slice_count(
++ new_ctx, cur_ctx, dc->res_pool,
++ status->plane_states[i], 1);
++}
++
+ bool dc_state_add_plane(
+ const struct dc *dc,
+ struct dc_stream_state *stream,
+@@ -447,8 +460,12 @@ bool dc_state_add_plane(
+ struct pipe_ctx *otg_master_pipe;
+ struct dc_stream_status *stream_status = NULL;
+ bool added = false;
++ int odm_slice_count;
++ int i;
+
+ stream_status = dc_state_get_stream_status(state, stream);
++ otg_master_pipe = resource_get_otg_master_for_stream(
++ &state->res_ctx, stream);
+ if (stream_status == NULL) {
+ dm_error("Existing stream not found; failed to attach surface!\n");
+ goto out;
+@@ -456,22 +473,39 @@ bool dc_state_add_plane(
+ dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
+ plane_state, MAX_SURFACE_NUM);
+ goto out;
++ } else if (!otg_master_pipe) {
++ goto out;
+ }
+
+- if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
+- /* ODM combine could prevent us from supporting more planes
+- * we will reset ODM slice count back to 1 when all planes have
+- * been removed to maximize the amount of planes supported when
+- * new planes are added.
+- */
+- resource_update_pipes_for_stream_with_slice_count(
+- state, dc->current_state, dc->res_pool, stream, 1);
++ added = resource_append_dpp_pipes_for_plane_composition(state,
++ dc->current_state, pool, otg_master_pipe, plane_state);
+
+- otg_master_pipe = resource_get_otg_master_for_stream(
+- &state->res_ctx, stream);
+- if (otg_master_pipe)
++ if (!added) {
++ /* try to remove MPC combine to free up pipes */
++ for (i = 0; i < state->stream_count; i++)
++ remove_mpc_combine_for_stream(dc, state,
++ dc->current_state,
++ &state->stream_status[i]);
+ added = resource_append_dpp_pipes_for_plane_composition(state,
+- dc->current_state, pool, otg_master_pipe, plane_state);
++ dc->current_state, pool,
++ otg_master_pipe, plane_state);
++ }
++
++ if (!added) {
++ /* try to decrease ODM slice count gradually to free up pipes */
++ odm_slice_count = resource_get_odm_slice_count(otg_master_pipe);
++ for (i = odm_slice_count - 1; i > 0; i--) {
++ resource_update_pipes_for_stream_with_slice_count(state,
++ dc->current_state, dc->res_pool, stream,
++ i);
++ added = resource_append_dpp_pipes_for_plane_composition(
++ state,
++ dc->current_state, pool,
++ otg_master_pipe, plane_state);
++ if (added)
++ break;
++ }
++ }
+
+ if (added) {
+ stream_status->plane_states[stream_status->plane_count] =
+@@ -531,15 +565,6 @@ bool dc_state_remove_plane(
+
+ stream_status->plane_states[stream_status->plane_count] = NULL;
+
+- if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
+- /* ODM combine could prevent us from supporting more planes
+- * we will reset ODM slice count back to 1 when all planes have
+- * been removed to maximize the amount of planes supported when
+- * new planes are added.
+- */
+- resource_update_pipes_for_stream_with_slice_count(
+- state, dc->current_state, dc->res_pool, stream, 1);
+-
+ return true;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From c023cd7163dd6984148c259b8048d987cd6fa8d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 14:17:34 -0400
+Subject: drm/amd/display: remove dpp pipes on failure to update pipe params
+
+From: Wenjing Liu <wenjing.liu@amd.com>
+
+[ Upstream commit 3ddd9c83ff7ac0ead38188425b14d03dc2f2c133 ]
+
+[why]
+There are cases where update pipe params could fail but dpp pipes are already
+added to the state. In this case, we should remove dpp pipes so dc state is
+restored back. If it is not restored, dc state is corrupted after calling this
+function, so if we call the same interface with the corrupted state again, we
+may end up programming pipe topology based on a corrupted dc state.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Acked-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
+Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index a2ca66a268c2d..a51e5de6554ee 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -2701,6 +2701,7 @@ bool resource_append_dpp_pipes_for_plane_composition(
+ struct dc_plane_state *plane_state)
+ {
+ bool success;
++
+ if (otg_master_pipe->plane_state == NULL)
+ success = add_plane_to_opp_head_pipes(otg_master_pipe,
+ plane_state, new_ctx);
+@@ -2708,10 +2709,15 @@ bool resource_append_dpp_pipes_for_plane_composition(
+ success = acquire_secondary_dpp_pipes_and_add_plane(
+ otg_master_pipe, plane_state, new_ctx,
+ cur_ctx, pool);
+- if (success)
++ if (success) {
+ /* when appending a plane mpc slice count changes from 0 to 1 */
+ success = update_pipe_params_after_mpc_slice_count_change(
+ plane_state, new_ctx, pool);
++ if (!success)
++ resource_remove_dpp_pipes_for_plane_composition(new_ctx,
++ pool, plane_state);
++ }
++
+ return success;
+ }
+
+@@ -2721,6 +2727,7 @@ void resource_remove_dpp_pipes_for_plane_composition(
+ const struct dc_plane_state *plane_state)
+ {
+ int i;
++
+ for (i = pool->pipe_count - 1; i >= 0; i--) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+--
+2.43.0
+
--- /dev/null
+From 7df4a098a4fe0480fd292647816550d4d176cfd9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 16:35:04 -0500
+Subject: drm/amd/display: Wake DMCUB before sending a command for replay
+ feature
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 3601a35a2e9d640233f4bc3496f7603b93f9c143 ]
+
+[Why]
+We can hang in place trying to send commands when the DMCUB isn't
+powered on.
+
+[How]
+For functions that execute within a DC context or DC lock we can wrap
+the direct calls to dm_execute_dmub_cmd/list with code that exits idle
+power optimizations and reallows once we're done with the command
+submission on success.
+
+For DM direct submissions the DM will need to manage the enter/exit
+sequencing manually.
+
+We cannot invoke a DMCUB command directly within the DM execution helper
+or we can deadlock.
+
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+index 4f559a025cf00..f820647443d16 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+@@ -84,7 +84,7 @@ static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait,
+
+ cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data);
+
+- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ /* Below loops 1000 x 500us = 500 ms.
+ * Exit REPLAY may need to wait 1-2 frames to power up. Timeout after at
+@@ -127,7 +127,7 @@ static void dmub_replay_set_power_opt(struct dmub_replay *dmub, unsigned int pow
+ cmd.replay_set_power_opt.replay_set_power_opt_data.power_opt = power_opt;
+ cmd.replay_set_power_opt.replay_set_power_opt_data.panel_inst = panel_inst;
+
+- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ }
+
+ /*
+@@ -231,7 +231,7 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
+ cmd.replay_set_coasting_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
+ cmd.replay_set_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
+
+- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 3debc8183b07e5eb1494d60687490d81b00e42fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 May 2024 15:01:22 +0800
+Subject: drm/amd/pm: Fix the null pointer dereference for vega10_hwmgr
+
+From: Bob Zhou <bob.zhou@amd.com>
+
+[ Upstream commit 50151b7f1c79a09117837eb95b76c2de76841dab ]
+
+Check return value and conduct null pointer handling to avoid null pointer dereference.
+
+Signed-off-by: Bob Zhou <bob.zhou@amd.com>
+Reviewed-by: Tim Huang <Tim.Huang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 29 ++++++++++++++++---
+ 1 file changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+index 8d7dc0e5417ed..f4acdb2267416 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -3418,13 +3418,17 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co
+ const struct vega10_power_state *vega10_ps =
+ cast_const_phw_vega10_power_state(states->pnew_state);
+ struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
+- uint32_t sclk = vega10_ps->performance_levels
+- [vega10_ps->performance_level_count - 1].gfx_clock;
+ struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
+- uint32_t mclk = vega10_ps->performance_levels
+- [vega10_ps->performance_level_count - 1].mem_clock;
++ uint32_t sclk, mclk;
+ uint32_t i;
+
++ if (vega10_ps == NULL)
++ return -EINVAL;
++ sclk = vega10_ps->performance_levels
++ [vega10_ps->performance_level_count - 1].gfx_clock;
++ mclk = vega10_ps->performance_levels
++ [vega10_ps->performance_level_count - 1].mem_clock;
++
+ for (i = 0; i < sclk_table->count; i++) {
+ if (sclk == sclk_table->dpm_levels[i].value)
+ break;
+@@ -3731,6 +3735,9 @@ static int vega10_generate_dpm_level_enable_mask(
+ cast_const_phw_vega10_power_state(states->pnew_state);
+ int i;
+
++ if (vega10_ps == NULL)
++ return -EINVAL;
++
+ PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
+ "Attempt to Trim DPM States Failed!",
+ return -1);
+@@ -4998,6 +5005,8 @@ static int vega10_check_states_equal(struct pp_hwmgr *hwmgr,
+
+ vega10_psa = cast_const_phw_vega10_power_state(pstate1);
+ vega10_psb = cast_const_phw_vega10_power_state(pstate2);
++ if (vega10_psa == NULL || vega10_psb == NULL)
++ return -EINVAL;
+
+ /* If the two states don't even have the same number of performance levels
+ * they cannot be the same state.
+@@ -5131,6 +5140,8 @@ static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
+ return -EINVAL;
+
+ vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++ if (vega10_ps == NULL)
++ return -EINVAL;
+
+ vega10_ps->performance_levels
+ [vega10_ps->performance_level_count - 1].gfx_clock =
+@@ -5182,6 +5193,8 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
+ return -EINVAL;
+
+ vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++ if (vega10_ps == NULL)
++ return -EINVAL;
+
+ vega10_ps->performance_levels
+ [vega10_ps->performance_level_count - 1].mem_clock =
+@@ -5423,6 +5436,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
+ return;
+
+ vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++ if (vega10_ps == NULL)
++ return;
++
+ max_level = vega10_ps->performance_level_count - 1;
+
+ if (vega10_ps->performance_levels[max_level].gfx_clock !=
+@@ -5445,6 +5461,9 @@ static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr)
+
+ ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1));
+ vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
++ if (vega10_ps == NULL)
++ return;
++
+ max_level = vega10_ps->performance_level_count - 1;
+
+ if (vega10_ps->performance_levels[max_level].gfx_clock !=
+@@ -5635,6 +5654,8 @@ static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_
+ return -EINVAL;
+
+ vega10_ps = cast_const_phw_vega10_power_state(state);
++ if (vega10_ps == NULL)
++ return -EINVAL;
+
+ i = index > vega10_ps->performance_level_count - 1 ?
+ vega10_ps->performance_level_count - 1 : index;
+--
+2.43.0
+
--- /dev/null
+From cc1128f2104fda9f2e9e1ed13407fa7017242ff9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 16:10:43 -0400
+Subject: drm/amdgpu: Add lock around VF RLCG interface
+
+From: Victor Skvortsov <victor.skvortsov@amd.com>
+
+[ Upstream commit e864180ee49b4d30e640fd1e1d852b86411420c9 ]
+
+flush_gpu_tlb may be called from another thread while
+device_gpu_recover is running.
+
+Both of these threads access registers through the VF
+RLCG interface during VF Full Access. Add a lock around this interface
+to prevent race conditions between these threads.
+
+Signed-off-by: Victor Skvortsov <victor.skvortsov@amd.com>
+Reviewed-by: Zhigang Luo <zhigang.luo@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 ++
+ 3 files changed, 9 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index ee7df1d84e028..89cf9ac6da174 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4048,6 +4048,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
+ mutex_init(&adev->grbm_idx_mutex);
+ mutex_init(&adev->mn_lock);
+ mutex_init(&adev->virt.vf_errors.lock);
++ mutex_init(&adev->virt.rlcg_reg_lock);
+ hash_init(adev->mn_hash);
+ mutex_init(&adev->psp.mutex);
+ mutex_init(&adev->notifier_lock);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+index 54ab51a4ada77..972a58f0f4924 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -980,6 +980,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
+ scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1;
+ scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2;
+ scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3;
++
++ mutex_lock(&adev->virt.rlcg_reg_lock);
++
+ if (reg_access_ctrl->spare_int)
+ spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int;
+
+@@ -1036,6 +1039,9 @@ u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 f
+ }
+
+ ret = readl(scratch_reg0);
++
++ mutex_unlock(&adev->virt.rlcg_reg_lock);
++
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+index 642f1fd287d83..0ec246c74570c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+@@ -272,6 +272,8 @@ struct amdgpu_virt {
+
+ /* the ucode id to signal the autoload */
+ uint32_t autoload_ucode_id;
++
++ struct mutex rlcg_reg_lock;
+ };
+
+ struct amdgpu_video_codec_info;
+--
+2.43.0
+
--- /dev/null
+From 257f1201243d672e09b0728c33db390a06232c81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 11:09:00 +0800
+Subject: drm/amdgpu: fix potential resource leak warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tim Huang <Tim.Huang@amd.com>
+
+[ Upstream commit 22a5daaec0660dd19740c4c6608b78f38760d1e6 ]
+
+Clear resource leak warning that when the prepare fails,
+the allocated amdgpu job object will never be released.
+
+Signed-off-by: Tim Huang <Tim.Huang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+index 66e8a016126b8..9b748d7058b5c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+@@ -102,6 +102,11 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
+ if (!r)
+ r = amdgpu_sync_push_to_job(&sync, p->job);
+ amdgpu_sync_free(&sync);
++
++ if (r) {
++ p->num_dw_left = 0;
++ amdgpu_job_free(p->job);
++ }
+ return r;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From ac585cb8a2f143e114b9deeb29b8030200d36b76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 May 2024 15:48:02 +0800
+Subject: drm/amdgpu: Fix the null pointer dereference to ras_manager
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit 4c11d30c95576937c6c35e6f29884761f2dddb43 ]
+
+Check ras_manager before using it
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+index 1adc81a55734d..0c4ee06451e9c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+@@ -2172,12 +2172,15 @@ static void amdgpu_ras_interrupt_process_handler(struct work_struct *work)
+ int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
+ struct ras_dispatch_if *info)
+ {
+- struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
+- struct ras_ih_data *data = &obj->ih_data;
++ struct ras_manager *obj;
++ struct ras_ih_data *data;
+
++ obj = amdgpu_ras_find_obj(adev, &info->head);
+ if (!obj)
+ return -EINVAL;
+
++ data = &obj->ih_data;
++
+ if (data->inuse == 0)
+ return 0;
+
+--
+2.43.0
+
--- /dev/null
+From ab9b20b8a7b373daa083ef37d79c719d918552a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 15:01:59 +0800
+Subject: drm/amdgpu/pm: Fix the null pointer dereference for smu7
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit c02c1960c93eede587576625a1221205a68a904f ]
+
+optimize the code to avoid pass a null pointer (hwmgr->backend)
+to function smu7_update_edc_leakage_table.
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 50 +++++++++----------
+ 1 file changed, 24 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+index 1fcd4451001fa..5d0c281f2378c 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -2957,6 +2957,7 @@ static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
+
+ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+ {
++ struct amdgpu_device *adev = hwmgr->adev;
+ struct smu7_hwmgr *data;
+ int result = 0;
+
+@@ -2993,40 +2994,37 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+ /* Initalize Dynamic State Adjustment Rule Settings */
+ result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
+
+- if (0 == result) {
+- struct amdgpu_device *adev = hwmgr->adev;
++ if (result)
++ goto fail;
+
+- data->is_tlu_enabled = false;
++ data->is_tlu_enabled = false;
+
+- hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
++ hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+ SMU7_MAX_HARDWARE_POWERLEVELS;
+- hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
+- hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
++ hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
++ hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
+
+- data->pcie_gen_cap = adev->pm.pcie_gen_mask;
+- if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+- data->pcie_spc_cap = 20;
+- else
+- data->pcie_spc_cap = 16;
+- data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
+-
+- hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
+-/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
+- hwmgr->platform_descriptor.clockStep.engineClock = 500;
+- hwmgr->platform_descriptor.clockStep.memoryClock = 500;
+- smu7_thermal_parameter_init(hwmgr);
+- } else {
+- /* Ignore return value in here, we are cleaning up a mess. */
+- smu7_hwmgr_backend_fini(hwmgr);
+- }
++ data->pcie_gen_cap = adev->pm.pcie_gen_mask;
++ if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
++ data->pcie_spc_cap = 20;
++ else
++ data->pcie_spc_cap = 16;
++ data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
++
++ hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
++ /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
++ hwmgr->platform_descriptor.clockStep.engineClock = 500;
++ hwmgr->platform_descriptor.clockStep.memoryClock = 500;
++ smu7_thermal_parameter_init(hwmgr);
+
+ result = smu7_update_edc_leakage_table(hwmgr);
+- if (result) {
+- smu7_hwmgr_backend_fini(hwmgr);
+- return result;
+- }
++ if (result)
++ goto fail;
+
+ return 0;
++fail:
++ smu7_hwmgr_backend_fini(hwmgr);
++ return result;
+ }
+
+ static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
+--
+2.43.0
+
--- /dev/null
+From e27959baf16e47ed93ddbfb86cb622554af866cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 15:51:35 +0800
+Subject: drm/amdgpu/pm: Fix the null pointer dereference in
+ apply_state_adjust_rules
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit d19fb10085a49b77578314f69fff21562f7cd054 ]
+
+Check the pointer value to fix potential null pointer
+dereference
+
+Acked-by: Yang Wang<kevinyang.wang@amd.com>
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 7 +++++--
+ .../gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c | 14 ++++++++------
+ .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 7 +++++--
+ 3 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+index 5d0c281f2378c..f1c369945ac5d 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -3314,8 +3314,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+ const struct pp_power_state *current_ps)
+ {
+ struct amdgpu_device *adev = hwmgr->adev;
+- struct smu7_power_state *smu7_ps =
+- cast_phw_smu7_power_state(&request_ps->hardware);
++ struct smu7_power_state *smu7_ps;
+ uint32_t sclk;
+ uint32_t mclk;
+ struct PP_Clocks minimum_clocks = {0};
+@@ -3332,6 +3331,10 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+ uint32_t latency;
+ bool latency_allowed = false;
+
++ smu7_ps = cast_phw_smu7_power_state(&request_ps->hardware);
++ if (!smu7_ps)
++ return -EINVAL;
++
+ data->battery_state = (PP_StateUILabel_Battery ==
+ request_ps->classification.ui_label);
+ data->mclk_ignore_signal = false;
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
+index b015a601b385a..eb744401e0567 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c
+@@ -1065,16 +1065,18 @@ static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+ struct pp_power_state *prequest_ps,
+ const struct pp_power_state *pcurrent_ps)
+ {
+- struct smu8_power_state *smu8_ps =
+- cast_smu8_power_state(&prequest_ps->hardware);
+-
+- const struct smu8_power_state *smu8_current_ps =
+- cast_const_smu8_power_state(&pcurrent_ps->hardware);
+-
++ struct smu8_power_state *smu8_ps;
++ const struct smu8_power_state *smu8_current_ps;
+ struct smu8_hwmgr *data = hwmgr->backend;
+ struct PP_Clocks clocks = {0, 0, 0, 0};
+ bool force_high;
+
++ smu8_ps = cast_smu8_power_state(&prequest_ps->hardware);
++ smu8_current_ps = cast_const_smu8_power_state(&pcurrent_ps->hardware);
++
++ if (!smu8_ps || !smu8_current_ps)
++ return -EINVAL;
++
+ smu8_ps->need_dfs_bypass = true;
+
+ data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+index 9f5bd998c6bff..8d7dc0e5417ed 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -3259,8 +3259,7 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+ const struct pp_power_state *current_ps)
+ {
+ struct amdgpu_device *adev = hwmgr->adev;
+- struct vega10_power_state *vega10_ps =
+- cast_phw_vega10_power_state(&request_ps->hardware);
++ struct vega10_power_state *vega10_ps;
+ uint32_t sclk;
+ uint32_t mclk;
+ struct PP_Clocks minimum_clocks = {0};
+@@ -3278,6 +3277,10 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+ uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+ uint32_t latency;
+
++ vega10_ps = cast_phw_vega10_power_state(&request_ps->hardware);
++ if (!vega10_ps)
++ return -EINVAL;
++
+ data->battery_state = (PP_StateUILabel_Battery ==
+ request_ps->classification.ui_label);
+
+--
+2.43.0
+
--- /dev/null
+From d6949fe3402e882edaff83a660883e4d83c296ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Apr 2024 15:58:10 +0800
+Subject: drm/amdgpu/pm: Fix the param type of set_power_profile_mode
+
+From: Ma Jun <Jun.Ma2@amd.com>
+
+[ Upstream commit f683f24093dd94a831085fe0ea8e9dc4c6c1a2d1 ]
+
+Function .set_power_profile_mode need an array as input
+parameter. So define variable workload as an array to fix
+the below coverity warning.
+
+"Passing &workload to function hwmgr->hwmgr_func->set_power_profile_mode
+which uses it as an array. This might corrupt or misinterpret adjacent
+memory locations"
+
+Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 8 ++++----
+ drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c | 8 ++++----
+ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 16 ++++++++--------
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+index 5fb21a0508cd9..f531ce1d2b1dc 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+@@ -929,7 +929,7 @@ static int pp_dpm_switch_power_profile(void *handle,
+ enum PP_SMC_POWER_PROFILE type, bool en)
+ {
+ struct pp_hwmgr *hwmgr = handle;
+- long workload;
++ long workload[1];
+ uint32_t index;
+
+ if (!hwmgr || !hwmgr->pm_en)
+@@ -947,12 +947,12 @@ static int pp_dpm_switch_power_profile(void *handle,
+ hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
+ index = fls(hwmgr->workload_mask);
+ index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+- workload = hwmgr->workload_setting[index];
++ workload[0] = hwmgr->workload_setting[index];
+ } else {
+ hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
+ index = fls(hwmgr->workload_mask);
+ index = index <= Workload_Policy_Max ? index - 1 : 0;
+- workload = hwmgr->workload_setting[index];
++ workload[0] = hwmgr->workload_setting[index];
+ }
+
+ if (type == PP_SMC_POWER_PROFILE_COMPUTE &&
+@@ -962,7 +962,7 @@ static int pp_dpm_switch_power_profile(void *handle,
+ }
+
+ if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+- hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
++ hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
+index 1d829402cd2e2..f4bd8e9357e22 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
+@@ -269,7 +269,7 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set
+ struct pp_power_state *new_ps)
+ {
+ uint32_t index;
+- long workload;
++ long workload[1];
+
+ if (hwmgr->not_vf) {
+ if (!skip_display_settings)
+@@ -294,10 +294,10 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_set
+ if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
+ index = fls(hwmgr->workload_mask);
+ index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+- workload = hwmgr->workload_setting[index];
++ workload[0] = hwmgr->workload_setting[index];
+
+- if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode)
+- hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
++ if (hwmgr->power_profile_mode != workload[0] && hwmgr->hwmgr_func->set_power_profile_mode)
++ hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);
+ }
+
+ return 0;
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index e1796ecf9c05c..06409133b09b1 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -2220,7 +2220,7 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,
+ {
+ int ret = 0;
+ int index = 0;
+- long workload;
++ long workload[1];
+ struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+
+ if (!skip_display_settings) {
+@@ -2260,10 +2260,10 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,
+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
+ index = fls(smu->workload_mask);
+ index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+- workload = smu->workload_setting[index];
++ workload[0] = smu->workload_setting[index];
+
+- if (smu->power_profile_mode != workload)
+- smu_bump_power_profile_mode(smu, &workload, 0);
++ if (smu->power_profile_mode != workload[0])
++ smu_bump_power_profile_mode(smu, workload, 0);
+ }
+
+ return ret;
+@@ -2313,7 +2313,7 @@ static int smu_switch_power_profile(void *handle,
+ {
+ struct smu_context *smu = handle;
+ struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+- long workload;
++ long workload[1];
+ uint32_t index;
+
+ if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
+@@ -2326,17 +2326,17 @@ static int smu_switch_power_profile(void *handle,
+ smu->workload_mask &= ~(1 << smu->workload_prority[type]);
+ index = fls(smu->workload_mask);
+ index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+- workload = smu->workload_setting[index];
++ workload[0] = smu->workload_setting[index];
+ } else {
+ smu->workload_mask |= (1 << smu->workload_prority[type]);
+ index = fls(smu->workload_mask);
+ index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+- workload = smu->workload_setting[index];
++ workload[0] = smu->workload_setting[index];
+ }
+
+ if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
+- smu_bump_power_profile_mode(smu, &workload, 0);
++ smu_bump_power_profile_mode(smu, workload, 0);
+
+ return 0;
+ }
+--
+2.43.0
+
--- /dev/null
+From 01d5e852b29741df41afd95b2a1e478f1003046b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Apr 2024 15:46:31 +0100
+Subject: drm/xe/preempt_fence: enlarge the fence critical section
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit 3cd1585e57908b6efcd967465ef7685f40b2a294 ]
+
+It is really easy to introduce subtle deadlocks in
+preempt_fence_work_func() since we operate on single global ordered-wq
+for signalling our preempt fences behind the scenes, so even though we
+signal a particular fence, everything in the callback should be in the
+fence critical section, since blocking in the callback will prevent
+other published fences from signalling. If we enlarge the fence critical
+section to cover the entire callback, then lockdep should be able to
+understand this better, and complain if we grab a sensitive lock like
+vm->lock, which is also held when waiting on preempt fences.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240418144630.299531-2-matthew.auld@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_preempt_fence.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_preempt_fence.c b/drivers/gpu/drm/xe/xe_preempt_fence.c
+index 7d50c6e89d8e7..5b243b7feb59d 100644
+--- a/drivers/gpu/drm/xe/xe_preempt_fence.c
++++ b/drivers/gpu/drm/xe/xe_preempt_fence.c
+@@ -23,11 +23,19 @@ static void preempt_fence_work_func(struct work_struct *w)
+ q->ops->suspend_wait(q);
+
+ dma_fence_signal(&pfence->base);
+- dma_fence_end_signalling(cookie);
+-
++ /*
++ * Opt for keep everything in the fence critical section. This looks really strange since we
++ * have just signalled the fence, however the preempt fences are all signalled via single
++ * global ordered-wq, therefore anything that happens in this callback can easily block
++ * progress on the entire wq, which itself may prevent other published preempt fences from
++ * ever signalling. Therefore try to keep everything here in the callback in the fence
++ * critical section. For example if something below grabs a scary lock like vm->lock,
++ * lockdep should complain since we also hold that lock whilst waiting on preempt fences to
++ * complete.
++ */
+ xe_vm_queue_rebind_worker(q->vm);
+-
+ xe_exec_queue_put(q);
++ dma_fence_end_signalling(cookie);
+ }
+
+ static const char *
+--
+2.43.0
+
--- /dev/null
+From 631e1848172aa763280eb4fe20ba9db6779a7829 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 12:45:38 -0700
+Subject: drm/xe/xe_guc_submit: Fix exec queue stop race condition
+
+From: Jonathan Cavitt <jonathan.cavitt@intel.com>
+
+[ Upstream commit 1564d411e17f51e2f64655b4e4da015be1ba7eaa ]
+
+Reorder the xe_sched_tdr_queue_imm and set_exec_queue_banned calls in
+guc_exec_queue_stop. This prevents a possible race condition between
+the two events in which it's possible for xe_sched_tdr_queue_imm to
+wake the ufence waiter before the exec queue is banned, causing the
+ufence waiter to miss the banned state.
+
+Suggested-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Stuart Summers <stuart.summers@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240510194540.3246991-1-jonathan.cavitt@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_submit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index e4e3658e6a138..0f42971ff0a83 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -1429,8 +1429,8 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
+ !xe_sched_job_completed(job)) ||
+ xe_sched_invalidate_job(job, 2)) {
+ trace_xe_sched_job_ban(job);
+- xe_sched_tdr_queue_imm(&q->guc->sched);
+ set_exec_queue_banned(q);
++ xe_sched_tdr_queue_imm(&q->guc->sched);
+ }
+ }
+ }
+--
+2.43.0
+
--- /dev/null
+From 938069bddcc6d7de73703b002f19c47de12aa14b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 20:30:17 -0700
+Subject: ext4: fix uninitialized variable in ext4_inlinedir_to_tree
+
+From: Xiaxi Shen <shenxiaxi26@gmail.com>
+
+[ Upstream commit 8dc9c3da79c84b13fdb135e2fb0a149a8175bffe ]
+
+Syzbot has found an uninit-value bug in ext4_inlinedir_to_tree
+
+This error happens because ext4_inlinedir_to_tree does not
+handle the case when ext4fs_dirhash returns an error
+
+This can be avoided by checking the return value of ext4fs_dirhash
+and propagating the error,
+similar to how it's done with ext4_htree_store_dirent
+
+Signed-off-by: Xiaxi Shen <shenxiaxi26@gmail.com>
+Reported-and-tested-by: syzbot+eaba5abe296837a640c0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=eaba5abe296837a640c0
+Link: https://patch.msgid.link/20240501033017.220000-1-shenxiaxi26@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inline.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index d5bd1e3a5d36c..e7a09a99837b9 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -1410,7 +1410,11 @@ int ext4_inlinedir_to_tree(struct file *dir_file,
+ hinfo->hash = EXT4_DIRENT_HASH(de);
+ hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de);
+ } else {
+- ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
++ err = ext4fs_dirhash(dir, de->name, de->name_len, hinfo);
++ if (err) {
++ ret = err;
++ goto out;
++ }
+ }
+ if ((hinfo->hash < start_hash) ||
+ ((hinfo->hash == start_hash) &&
+--
+2.43.0
+
--- /dev/null
+From 19bd2510608703f6f8c0ac7639edb98a16d3cf45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 09:01:12 +0200
+Subject: ext4: sanity check for NULL pointer after ext4_force_shutdown
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wojciech Gładysz <wojciech.gladysz@infogain.com>
+
+[ Upstream commit 83f4414b8f84249d538905825b088ff3ae555652 ]
+
+Test case: 2 threads write short inline data to a file.
+In ext4_page_mkwrite the resulting inline data is converted.
+Handling ext4_grp_locked_error with description "block bitmap
+and bg descriptor inconsistent: X vs Y free clusters" calls
+ext4_force_shutdown. The conversion clears
+EXT4_STATE_MAY_INLINE_DATA but fails for
+ext4_destroy_inline_data_nolock and ext4_mark_iloc_dirty due
+to ext4_forced_shutdown. The restoration of inline data fails
+for the same reason not setting EXT4_STATE_MAY_INLINE_DATA.
+Without the flag set a regular process path in ext4_da_write_end
+follows trying to dereference page folio private pointer that has
+not been set. The fix calls early return with -EIO error shall the
+pointer to private be NULL.
+
+Sample crash report:
+
+Unable to handle kernel paging request at virtual address dfff800000000004
+KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027]
+Mem abort info:
+ ESR = 0x0000000096000005
+ EC = 0x25: DABT (current EL), IL = 32 bits
+ SET = 0, FnV = 0
+ EA = 0, S1PTW = 0
+ FSC = 0x05: level 1 translation fault
+Data abort info:
+ ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
+ CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+ GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[dfff800000000004] address between user and kernel address ranges
+Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
+Modules linked in:
+CPU: 1 PID: 20274 Comm: syz-executor185 Not tainted 6.9.0-rc7-syzkaller-gfda5695d692c #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024
+pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : __block_commit_write+0x64/0x2b0 fs/buffer.c:2167
+lr : __block_commit_write+0x3c/0x2b0 fs/buffer.c:2160
+sp : ffff8000a1957600
+x29: ffff8000a1957610 x28: dfff800000000000 x27: ffff0000e30e34b0
+x26: 0000000000000000 x25: dfff800000000000 x24: dfff800000000000
+x23: fffffdffc397c9e0 x22: 0000000000000020 x21: 0000000000000020
+x20: 0000000000000040 x19: fffffdffc397c9c0 x18: 1fffe000367bd196
+x17: ffff80008eead000 x16: ffff80008ae89e3c x15: 00000000200000c0
+x14: 1fffe0001cbe4e04 x13: 0000000000000000 x12: 0000000000000000
+x11: 0000000000000001 x10: 0000000000ff0100 x9 : 0000000000000000
+x8 : 0000000000000004 x7 : 0000000000000000 x6 : 0000000000000000
+x5 : fffffdffc397c9c0 x4 : 0000000000000020 x3 : 0000000000000020
+x2 : 0000000000000040 x1 : 0000000000000020 x0 : fffffdffc397c9c0
+Call trace:
+ __block_commit_write+0x64/0x2b0 fs/buffer.c:2167
+ block_write_end+0xb4/0x104 fs/buffer.c:2253
+ ext4_da_do_write_end fs/ext4/inode.c:2955 [inline]
+ ext4_da_write_end+0x2c4/0xa40 fs/ext4/inode.c:3028
+ generic_perform_write+0x394/0x588 mm/filemap.c:3985
+ ext4_buffered_write_iter+0x2c0/0x4ec fs/ext4/file.c:299
+ ext4_file_write_iter+0x188/0x1780
+ call_write_iter include/linux/fs.h:2110 [inline]
+ new_sync_write fs/read_write.c:497 [inline]
+ vfs_write+0x968/0xc3c fs/read_write.c:590
+ ksys_write+0x15c/0x26c fs/read_write.c:643
+ __do_sys_write fs/read_write.c:655 [inline]
+ __se_sys_write fs/read_write.c:652 [inline]
+ __arm64_sys_write+0x7c/0x90 fs/read_write.c:652
+ __invoke_syscall arch/arm64/kernel/syscall.c:34 [inline]
+ invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:48
+ el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:133
+ do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:152
+ el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:712
+ el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730
+ el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598
+Code: 97f85911 f94002da 91008356 d343fec8 (38796908)
+---[ end trace 0000000000000000 ]---
+----------------
+Code disassembly (best guess):
+ 0: 97f85911 bl 0xffffffffffe16444
+ 4: f94002da ldr x26, [x22]
+ 8: 91008356 add x22, x26, #0x20
+ c: d343fec8 lsr x8, x22, #3
+* 10: 38796908 ldrb w8, [x8, x25] <-- trapping instruction
+
+Reported-by: syzbot+18df508cf00a0598d9a6@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=18df508cf00a0598d9a6
+Link: https://lore.kernel.org/all/000000000000f19a1406109eb5c5@google.com/T/
+Signed-off-by: Wojciech Gładysz <wojciech.gladysz@infogain.com>
+Link: https://patch.msgid.link/20240703070112.10235-1-wojciech.gladysz@infogain.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/buffer.c | 2 ++
+ fs/ext4/inode.c | 5 +++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/fs/buffer.c b/fs/buffer.c
+index 8c19e705b9c33..645f0387dfe1d 100644
+--- a/fs/buffer.c
++++ b/fs/buffer.c
+@@ -2187,6 +2187,8 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to)
+ struct buffer_head *bh, *head;
+
+ bh = head = folio_buffers(folio);
++ if (!bh)
++ return;
+ blocksize = bh->b_size;
+
+ block_start = 0;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 4b0d64a76e88e..238e196338234 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2973,6 +2973,11 @@ static int ext4_da_do_write_end(struct address_space *mapping,
+ bool disksize_changed = false;
+ loff_t new_i_size;
+
++ if (unlikely(!folio_buffers(folio))) {
++ folio_unlock(folio);
++ folio_put(folio);
++ return -EIO;
++ }
+ /*
+ * block_write_end() will mark the inode as dirty with I_DIRTY_PAGES
+ * flag, which all that's needed to trigger page writeback.
+--
+2.43.0
+
--- /dev/null
+From 326813cd370e4a615d144750cc76857c60105b7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 May 2024 08:53:32 +0000
+Subject: gpio: prevent potential speculation leaks in gpio_device_get_desc()
+
+From: Hagar Hemdan <hagarhem@amazon.com>
+
+[ Upstream commit d795848ecce24a75dfd46481aee066ae6fe39775 ]
+
+Userspace may trigger a speculative read of an address outside the gpio
+descriptor array.
+Users can do that by calling gpio_ioctl() with an offset out of range.
+Offset is copied from user and then used as an array index to get
+the gpio descriptor without sanitization in gpio_device_get_desc().
+
+This change ensures that the offset is sanitized by using
+array_index_nospec() to mitigate any possibility of speculative
+information leaks.
+
+This bug was discovered and resolved using Coverity Static Analysis
+Security Testing (SAST) by Synopsys, Inc.
+
+Signed-off-by: Hagar Hemdan <hagarhem@amazon.com>
+Link: https://lore.kernel.org/r/20240523085332.1801-1-hagarhem@amazon.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index fa62367ee9290..1a9aadd4c803c 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -17,6 +17,7 @@
+ #include <linux/list.h>
+ #include <linux/lockdep.h>
+ #include <linux/module.h>
++#include <linux/nospec.h>
+ #include <linux/of.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/seq_file.h>
+@@ -198,7 +199,7 @@ gpio_device_get_desc(struct gpio_device *gdev, unsigned int hwnum)
+ if (hwnum >= gdev->ngpio)
+ return ERR_PTR(-EINVAL);
+
+- return &gdev->descs[hwnum];
++ return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
+ }
+ EXPORT_SYMBOL_GPL(gpio_device_get_desc);
+
+--
+2.43.0
+
--- /dev/null
+From 280dfdbc195fd9e86fdd021104ef7fce411313d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 13:56:19 -0700
+Subject: gve: Fix use of netif_carrier_ok()
+
+From: Praveen Kaligineedi <pkaligineedi@google.com>
+
+[ Upstream commit fba917b169bea5f8f2ee300e19d5f7a6341a5251 ]
+
+GVE driver wrongly relies on netif_carrier_ok() to check the
+interface administrative state when resources are being
+allocated/deallocated for queue(s). netif_carrier_ok() needs
+to be replaced with netif_running() for all such cases.
+
+Administrative state is the result of "ip link set dev <dev>
+up/down". It reflects whether the administrator wants to use
+the device for traffic and the corresponding resources have
+been allocated.
+
+Fixes: 5f08cd3d6423 ("gve: Alloc before freeing when adjusting queues")
+Signed-off-by: Praveen Kaligineedi <pkaligineedi@google.com>
+Reviewed-by: Shailend Chand <shailend@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20240801205619.987396-1-pkaligineedi@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/google/gve/gve_ethtool.c | 2 +-
+ drivers/net/ethernet/google/gve/gve_main.c | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
+index fe1741d482b4a..cf816ede05f69 100644
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -492,7 +492,7 @@ static int gve_set_channels(struct net_device *netdev,
+ return -EINVAL;
+ }
+
+- if (!netif_carrier_ok(netdev)) {
++ if (!netif_running(netdev)) {
+ priv->tx_cfg.num_queues = new_tx;
+ priv->rx_cfg.num_queues = new_rx;
+ return 0;
+diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
+index cabf7d4bcecb8..8b14efd14a505 100644
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -1511,7 +1511,7 @@ static int gve_set_xdp(struct gve_priv *priv, struct bpf_prog *prog,
+ u32 status;
+
+ old_prog = READ_ONCE(priv->xdp_prog);
+- if (!netif_carrier_ok(priv->dev)) {
++ if (!netif_running(priv->dev)) {
+ WRITE_ONCE(priv->xdp_prog, prog);
+ if (old_prog)
+ bpf_prog_put(old_prog);
+@@ -1784,7 +1784,7 @@ int gve_adjust_queues(struct gve_priv *priv,
+ rx_alloc_cfg.qcfg = &new_rx_config;
+ tx_alloc_cfg.num_rings = new_tx_config.num_queues;
+
+- if (netif_carrier_ok(priv->dev)) {
++ if (netif_running(priv->dev)) {
+ err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
+ return err;
+ }
+@@ -2001,7 +2001,7 @@ static int gve_set_features(struct net_device *netdev,
+
+ if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
+ netdev->features ^= NETIF_F_LRO;
+- if (netif_carrier_ok(netdev)) {
++ if (netif_running(netdev)) {
+ err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
+ if (err) {
+ /* Revert the change on error. */
+@@ -2290,7 +2290,7 @@ static int gve_reset_recovery(struct gve_priv *priv, bool was_up)
+
+ int gve_reset(struct gve_priv *priv, bool attempt_teardown)
+ {
+- bool was_up = netif_carrier_ok(priv->dev);
++ bool was_up = netif_running(priv->dev);
+ int err;
+
+ dev_info(&priv->pdev->dev, "Performing reset\n");
+@@ -2631,7 +2631,7 @@ static void gve_shutdown(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct gve_priv *priv = netdev_priv(netdev);
+- bool was_up = netif_carrier_ok(priv->dev);
++ bool was_up = netif_running(priv->dev);
+
+ rtnl_lock();
+ if (was_up && gve_close(priv->dev)) {
+@@ -2649,7 +2649,7 @@ static int gve_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct gve_priv *priv = netdev_priv(netdev);
+- bool was_up = netif_carrier_ok(priv->dev);
++ bool was_up = netif_running(priv->dev);
+
+ priv->suspend_cnt++;
+ rtnl_lock();
+--
+2.43.0
+
--- /dev/null
+From 6193b8c2c40664cb3fba9b9e6a35f8ed53e6bead Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 04:38:11 +0000
+Subject: hwmon: corsair-psu: add USB id of HX1200i Series 2023 psu
+
+From: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+
+[ Upstream commit b9c15c96ccb47ad860af2e075c5f3c90c4cd1730 ]
+
+Add the usb id of the HX1200i Series 2023. Update the documentation
+accordingly. Also fix the version comments, there are no Series 2022
+products. That are legacy or first version products going back many
+many years.
+
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
+Link: https://lore.kernel.org/r/ZlAZs4u0dU7JxtDf@monster.localdomain
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/hwmon/corsair-psu.rst | 6 +++---
+ drivers/hwmon/corsair-psu.c | 7 ++++---
+ 2 files changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst
+index 16db34d464dd6..7ed794087f848 100644
+--- a/Documentation/hwmon/corsair-psu.rst
++++ b/Documentation/hwmon/corsair-psu.rst
+@@ -15,11 +15,11 @@ Supported devices:
+
+ Corsair HX850i
+
+- Corsair HX1000i (Series 2022 and 2023)
++ Corsair HX1000i (Legacy and Series 2023)
+
+- Corsair HX1200i
++ Corsair HX1200i (Legacy and Series 2023)
+
+- Corsair HX1500i (Series 2022 and 2023)
++ Corsair HX1500i (Legacy and Series 2023)
+
+ Corsair RM550i
+
+diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
+index 2c7c92272fe39..f8f22b8a67cdf 100644
+--- a/drivers/hwmon/corsair-psu.c
++++ b/drivers/hwmon/corsair-psu.c
+@@ -875,15 +875,16 @@ static const struct hid_device_id corsairpsu_idtable[] = {
+ { HID_USB_DEVICE(0x1b1c, 0x1c04) }, /* Corsair HX650i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c05) }, /* Corsair HX750i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c06) }, /* Corsair HX850i */
+- { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Series 2022 */
+- { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i */
++ { HID_USB_DEVICE(0x1b1c, 0x1c07) }, /* Corsair HX1000i Legacy */
++ { HID_USB_DEVICE(0x1b1c, 0x1c08) }, /* Corsair HX1200i Legacy */
+ { HID_USB_DEVICE(0x1b1c, 0x1c09) }, /* Corsair RM550i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c0a) }, /* Corsair RM650i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c0b) }, /* Corsair RM750i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c0c) }, /* Corsair RM850i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c0d) }, /* Corsair RM1000i */
+ { HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */
+- { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Series 2022 and 2023 */
++ { HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */
++ { HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */
+ { },
+ };
+ MODULE_DEVICE_TABLE(hid, corsairpsu_idtable);
+--
+2.43.0
+
--- /dev/null
+From 9f00e4f8b752d687416d233e2a16915ac6c6c2e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jul 2024 17:39:10 +0200
+Subject: ice: Fix reset handler
+
+From: Grzegorz Nitka <grzegorz.nitka@intel.com>
+
+[ Upstream commit 25a7123579ecac9a89a7e5b8d8a580bee4b68acd ]
+
+Synchronize OICR IRQ when preparing for reset to avoid potential
+race conditions between the reset procedure and OICR
+
+Fixes: 4aad5335969f ("ice: add individual interrupt allocation")
+Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index 9b075dd48889e..f16d13e9ff6e3 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -560,6 +560,8 @@ ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
+ if (test_bit(ICE_PREPARED_FOR_RESET, pf->state))
+ return;
+
++ synchronize_irq(pf->oicr_irq.virq);
++
+ ice_unplug_aux_dev(pf);
+
+ /* Notify VFs of impending reset */
+--
+2.43.0
+
--- /dev/null
+From 48d1b9ca863052b0adc33c883a25f95c6bf51f26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 15:09:20 -0700
+Subject: idpf: fix memory leaks and crashes while performing a soft reset
+
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+
+[ Upstream commit f01032a2ca099ec8d619aaa916c3762aa62495df ]
+
+The second tagged commit introduced a UAF, as it removed restoring
+q_vector->vport pointers after reinitializating the structures.
+This is due to that all queue allocation functions are performed here
+with the new temporary vport structure and those functions rewrite
+the backpointers to the vport. Then, this new struct is freed and
+the pointers start leading to nowhere.
+
+But generally speaking, the current logic is very fragile. It claims
+to be more reliable when the system is low on memory, but in fact, it
+consumes two times more memory as at the moment of running this
+function, there are two vports allocated with their queues and vectors.
+Moreover, it claims to prevent the driver from running into "bad state",
+but in fact, any error during the rebuild leaves the old vport in the
+partially allocated state.
+Finally, if the interface is down when the function is called, it always
+allocates a new queue set, but when the user decides to enable the
+interface later on, vport_open() allocates them once again, IOW there's
+a clear memory leak here.
+
+Just don't allocate a new queue set when performing a reset, that solves
+crashes and memory leaks. Readd the old queue number and reopen the
+interface on rollback - that solves limbo states when the device is left
+disabled and/or without HW queues enabled.
+
+Fixes: 02cbfba1add5 ("idpf: add ethtool callbacks")
+Fixes: e4891e4687c8 ("idpf: split &idpf_queue into 4 strictly-typed queue structures")
+Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20240806220923.3359860-2-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/idpf/idpf_lib.c | 30 +++++++++++-----------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+index f1ee5584e8fa2..32b6f0d52e3c5 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+@@ -1337,9 +1337,8 @@ static void idpf_rx_init_buf_tail(struct idpf_vport *vport)
+ /**
+ * idpf_vport_open - Bring up a vport
+ * @vport: vport to bring up
+- * @alloc_res: allocate queue resources
+ */
+-static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
++static int idpf_vport_open(struct idpf_vport *vport)
+ {
+ struct idpf_netdev_priv *np = netdev_priv(vport->netdev);
+ struct idpf_adapter *adapter = vport->adapter;
+@@ -1352,11 +1351,9 @@ static int idpf_vport_open(struct idpf_vport *vport, bool alloc_res)
+ /* we do not allow interface up just yet */
+ netif_carrier_off(vport->netdev);
+
+- if (alloc_res) {
+- err = idpf_vport_queues_alloc(vport);
+- if (err)
+- return err;
+- }
++ err = idpf_vport_queues_alloc(vport);
++ if (err)
++ return err;
+
+ err = idpf_vport_intr_alloc(vport);
+ if (err) {
+@@ -1541,7 +1538,7 @@ void idpf_init_task(struct work_struct *work)
+ np = netdev_priv(vport->netdev);
+ np->state = __IDPF_VPORT_DOWN;
+ if (test_and_clear_bit(IDPF_VPORT_UP_REQUESTED, vport_config->flags))
+- idpf_vport_open(vport, true);
++ idpf_vport_open(vport);
+
+ /* Spawn and return 'idpf_init_task' work queue until all the
+ * default vports are created
+@@ -1900,9 +1897,6 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
+ goto free_vport;
+ }
+
+- err = idpf_vport_queues_alloc(new_vport);
+- if (err)
+- goto free_vport;
+ if (current_state <= __IDPF_VPORT_DOWN) {
+ idpf_send_delete_queues_msg(vport);
+ } else {
+@@ -1974,17 +1968,23 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
+
+ err = idpf_set_real_num_queues(vport);
+ if (err)
+- goto err_reset;
++ goto err_open;
+
+ if (current_state == __IDPF_VPORT_UP)
+- err = idpf_vport_open(vport, false);
++ err = idpf_vport_open(vport);
+
+ kfree(new_vport);
+
+ return err;
+
+ err_reset:
+- idpf_vport_queues_rel(new_vport);
++ idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq,
++ vport->num_rxq, vport->num_bufq);
++
++err_open:
++ if (current_state == __IDPF_VPORT_UP)
++ idpf_vport_open(vport);
++
+ free_vport:
+ kfree(new_vport);
+
+@@ -2213,7 +2213,7 @@ static int idpf_open(struct net_device *netdev)
+ idpf_vport_ctrl_lock(netdev);
+ vport = idpf_netdev_to_vport(netdev);
+
+- err = idpf_vport_open(vport, true);
++ err = idpf_vport_open(vport);
+
+ idpf_vport_ctrl_unlock(netdev);
+
+--
+2.43.0
+
--- /dev/null
+From 1af8bab4a3f2749b1597ae7f8ef4daaac1130494 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 15:09:22 -0700
+Subject: idpf: fix UAFs when destroying the queues
+
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+
+[ Upstream commit 290f1c033281c1a502a3cd1c53c3a549259c491f ]
+
+The second tagged commit started sometimes (very rarely, but possible)
+throwing WARNs from
+net/core/page_pool.c:page_pool_disable_direct_recycling().
+Turned out idpf frees interrupt vectors with embedded NAPIs *before*
+freeing the queues making page_pools' NAPI pointers lead to freed
+memory before these pools are destroyed by libeth.
+It's not clear whether there are other accesses to the freed vectors
+when destroying the queues, but anyway, we usually free queue/interrupt
+vectors only when the queues are destroyed and the NAPIs are guaranteed
+to not be referenced anywhere.
+
+Invert the allocation and freeing logic making queue/interrupt vectors
+be allocated first and freed last. Vectors don't require queues to be
+present, so this is safe. Additionally, this change allows to remove
+that useless queue->q_vector pointer cleanup, as vectors are still
+valid when freeing the queues (+ both are freed within one function,
+so it's not clear why nullify the pointers at all).
+
+Fixes: 1c325aac10a8 ("idpf: configure resources for TX queues")
+Fixes: 90912f9f4f2d ("idpf: convert header split mode to libeth + napi_build_skb()")
+Reported-by: Michal Kubiak <michal.kubiak@intel.com>
+Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20240806220923.3359860-4-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/idpf/idpf_lib.c | 24 ++++++++++-----------
+ drivers/net/ethernet/intel/idpf/idpf_txrx.c | 24 +--------------------
+ 2 files changed, 13 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+index 32b6f0d52e3c5..3ac9d7ab83f20 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
+@@ -905,8 +905,8 @@ static void idpf_vport_stop(struct idpf_vport *vport)
+
+ vport->link_up = false;
+ idpf_vport_intr_deinit(vport);
+- idpf_vport_intr_rel(vport);
+ idpf_vport_queues_rel(vport);
++ idpf_vport_intr_rel(vport);
+ np->state = __IDPF_VPORT_DOWN;
+ }
+
+@@ -1351,43 +1351,43 @@ static int idpf_vport_open(struct idpf_vport *vport)
+ /* we do not allow interface up just yet */
+ netif_carrier_off(vport->netdev);
+
+- err = idpf_vport_queues_alloc(vport);
+- if (err)
+- return err;
+-
+ err = idpf_vport_intr_alloc(vport);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
+ vport->vport_id, err);
+- goto queues_rel;
++ return err;
+ }
+
++ err = idpf_vport_queues_alloc(vport);
++ if (err)
++ goto intr_rel;
++
+ err = idpf_vport_queue_ids_init(vport);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
+ vport->vport_id, err);
+- goto intr_rel;
++ goto queues_rel;
+ }
+
+ err = idpf_vport_intr_init(vport);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
+ vport->vport_id, err);
+- goto intr_rel;
++ goto queues_rel;
+ }
+
+ err = idpf_rx_bufs_init_all(vport);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
+ vport->vport_id, err);
+- goto intr_rel;
++ goto queues_rel;
+ }
+
+ err = idpf_queue_reg_init(vport);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
+ vport->vport_id, err);
+- goto intr_rel;
++ goto queues_rel;
+ }
+
+ idpf_rx_init_buf_tail(vport);
+@@ -1454,10 +1454,10 @@ static int idpf_vport_open(struct idpf_vport *vport)
+ idpf_send_map_unmap_queue_vector_msg(vport, false);
+ intr_deinit:
+ idpf_vport_intr_deinit(vport);
+-intr_rel:
+- idpf_vport_intr_rel(vport);
+ queues_rel:
+ idpf_vport_queues_rel(vport);
++intr_rel:
++ idpf_vport_intr_rel(vport);
+
+ return err;
+ }
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+index b023704bbbdab..0c22e524e56db 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+@@ -3436,9 +3436,7 @@ static void idpf_vport_intr_napi_dis_all(struct idpf_vport *vport)
+ */
+ void idpf_vport_intr_rel(struct idpf_vport *vport)
+ {
+- int i, j, v_idx;
+-
+- for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
++ for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
+ struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx];
+
+ kfree(q_vector->bufq);
+@@ -3449,26 +3447,6 @@ void idpf_vport_intr_rel(struct idpf_vport *vport)
+ q_vector->rx = NULL;
+ }
+
+- /* Clean up the mapping of queues to vectors */
+- for (i = 0; i < vport->num_rxq_grp; i++) {
+- struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];
+-
+- if (idpf_is_queue_model_split(vport->rxq_model))
+- for (j = 0; j < rx_qgrp->splitq.num_rxq_sets; j++)
+- rx_qgrp->splitq.rxq_sets[j]->rxq.q_vector = NULL;
+- else
+- for (j = 0; j < rx_qgrp->singleq.num_rxq; j++)
+- rx_qgrp->singleq.rxqs[j]->q_vector = NULL;
+- }
+-
+- if (idpf_is_queue_model_split(vport->txq_model))
+- for (i = 0; i < vport->num_txq_grp; i++)
+- vport->txq_grps[i].complq->q_vector = NULL;
+- else
+- for (i = 0; i < vport->num_txq_grp; i++)
+- for (j = 0; j < vport->txq_grps[i].num_txq; j++)
+- vport->txq_grps[i].txqs[j]->q_vector = NULL;
+-
+ kfree(vport->q_vectors);
+ vport->q_vectors = NULL;
+ }
+--
+2.43.0
+
--- /dev/null
+From cb6803bff3500e0963d27f0ba8b9808ceb7f47bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 14:34:40 +0100
+Subject: irqchip/gic-v3: Don't return errors from gic_acpi_match_gicc()
+
+From: James Morse <james.morse@arm.com>
+
+[ Upstream commit fa2dabe57220e6af78ed7a2f7016bf250a618204 ]
+
+gic_acpi_match_gicc() is only called via gic_acpi_count_gicr_regions().
+It should only count the number of enabled redistributors, but it
+also tries to sanity check the GICC entry, currently returning an
+error if the Enabled bit is set, but the gicr_base_address is zero.
+
+Adding support for the online-capable bit to the sanity check will
+complicate it, for no benefit. The existing check implicitly depends on
+gic_acpi_count_gicr_regions() previous failing to find any GICR regions
+(as it is valid to have gicr_base_address of zero if the redistributors
+are described via a GICR entry).
+
+Instead of complicating the check, remove it. Failures that happen at
+this point cause the irqchip not to register, meaning no irqs can be
+requested. The kernel grinds to a panic() pretty quickly.
+
+Without the check, MADT tables that exhibit this problem are still
+caught by gic_populate_rdist(), which helpfully also prints what went
+wrong:
+| CPU4: mpidr 100 has no re-distributor!
+
+Signed-off-by: James Morse <james.morse@arm.com>
+Reviewed-by: Gavin Shan <gshan@redhat.com>
+Tested-by: Miguel Luis <miguel.luis@oracle.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20240529133446.28446-14-Jonathan.Cameron@huawei.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-gic-v3.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
+index 6fb276504bcc8..10af15f93d4d4 100644
+--- a/drivers/irqchip/irq-gic-v3.c
++++ b/drivers/irqchip/irq-gic-v3.c
+@@ -2415,19 +2415,10 @@ static int __init gic_acpi_match_gicc(union acpi_subtable_headers *header,
+ * If GICC is enabled and has valid gicr base address, then it means
+ * GICR base is presented via GICC
+ */
+- if (acpi_gicc_is_usable(gicc) && gicc->gicr_base_address) {
++ if (acpi_gicc_is_usable(gicc) && gicc->gicr_base_address)
+ acpi_data.enabled_rdists++;
+- return 0;
+- }
+
+- /*
+- * It's perfectly valid firmware can pass disabled GICC entry, driver
+- * should not treat as errors, skip the entry instead of probe fail.
+- */
+- if (!acpi_gicc_is_usable(gicc))
+- return 0;
+-
+- return -ENODEV;
++ return 0;
+ }
+
+ static int __init gic_acpi_count_gicr_regions(void)
+--
+2.43.0
+
--- /dev/null
+From 5f106f43bb5fce672ba9267df68be411bd460179 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 09:44:00 +0800
+Subject: irqchip/mbigen: Fix mbigen node address layout
+
+From: Yipeng Zou <zouyipeng@huawei.com>
+
+[ Upstream commit 6be6cba9c4371d27f78d900ccfe34bb880d9ee20 ]
+
+The mbigen interrupt chip has its per node registers located in a
+contiguous region of page sized chunks. The code maps them into virtual
+address space as a contiguous region and determines the address of a node
+by using the node ID as index.
+
+ mbigen chip
+ |-----------------|------------|--------------|
+ mgn_node_0 mgn_node_1 ... mgn_node_i
+|--------------| |--------------| |----------------------|
+[0x0000, 0x0x0FFF] [0x1000, 0x1FFF] [i*0x1000, (i+1)*0x1000 - 1]
+
+This works correctly up to 10 nodes, but then fails because the 11th's
+array slot is used for the MGN_CLEAR registers.
+
+ mbigen chip
+ |-----------|--------|--------|---------------|--------|
+mgn_node_0 mgn_node_1 ... mgn_clear_register ... mgn_node_i
+ |-----------------|
+ [0xA000, 0xAFFF]
+
+Skip the MGN_CLEAR register space when calculating the offset for node IDs
+greater than or equal to ten.
+
+Fixes: a6c2f87b8820 ("irqchip/mbigen: Implement the mbigen irq chip operation functions")
+Signed-off-by: Yipeng Zou <zouyipeng@huawei.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20240730014400.1751530-1-zouyipeng@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-mbigen.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
+index 58881d3139792..244a8d489cac6 100644
+--- a/drivers/irqchip/irq-mbigen.c
++++ b/drivers/irqchip/irq-mbigen.c
+@@ -64,6 +64,20 @@ struct mbigen_device {
+ void __iomem *base;
+ };
+
++static inline unsigned int get_mbigen_node_offset(unsigned int nid)
++{
++ unsigned int offset = nid * MBIGEN_NODE_OFFSET;
++
++ /*
++ * To avoid touched clear register in unexpected way, we need to directly
++ * skip clear register when access to more than 10 mbigen nodes.
++ */
++ if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
++ offset += MBIGEN_NODE_OFFSET;
++
++ return offset;
++}
++
+ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
+ {
+ unsigned int nid, pin;
+@@ -72,8 +86,7 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
+ nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
+ pin = hwirq % IRQS_PER_MBIGEN_NODE;
+
+- return pin * 4 + nid * MBIGEN_NODE_OFFSET
+- + REG_MBIGEN_VEC_OFFSET;
++ return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
+ }
+
+ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
+@@ -88,8 +101,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
+ *mask = 1 << (irq_ofst % 32);
+ ofst = irq_ofst / 32 * 4;
+
+- *addr = ofst + nid * MBIGEN_NODE_OFFSET
+- + REG_MBIGEN_TYPE_OFFSET;
++ *addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
+ }
+
+ static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
+--
+2.43.0
+
--- /dev/null
+From 2a7f4000bc674db6d88b0dcc7ef33f06f3dabda5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 May 2024 19:24:30 +0800
+Subject: jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
+
+From: Kemeng Shi <shikemeng@huaweicloud.com>
+
+[ Upstream commit cc102aa24638b90e04364d64e4f58a1fa91a1976 ]
+
+The new_bh is from alloc_buffer_head, we should call free_buffer_head to
+free it in error case.
+
+Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240514112438.1269037-2-shikemeng@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/journal.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index ae5b544ed0cc0..c8d9d85e0e871 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -399,6 +399,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
+ tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
+ if (!tmp) {
+ brelse(new_bh);
++ free_buffer_head(new_bh);
+ return -ENOMEM;
+ }
+ spin_lock(&jh_in->b_state_lock);
+--
+2.43.0
+
--- /dev/null
+From 5f26cebd62e22fd6022ca20f0ac44ecad8b381cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 12:43:21 +0200
+Subject: jump_label: Fix the fix, brown paper bags galore
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 224fa3552029a3d14bec7acf72ded8171d551b88 ]
+
+Per the example of:
+
+ !atomic_cmpxchg(&key->enabled, 0, 1)
+
+the inverse was written as:
+
+ atomic_cmpxchg(&key->enabled, 1, 0)
+
+except of course, that while !old is only true for old == 0, old is
+true for everything except old == 0.
+
+Fix it to read:
+
+ atomic_cmpxchg(&key->enabled, 1, 0) == 1
+
+such that only the 1->0 transition returns true and goes on to disable
+the keys.
+
+Fixes: 83ab38ef0a0b ("jump_label: Fix concurrency issues in static_key_slow_dec()")
+Reported-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Tested-by: Darrick J. Wong <djwong@kernel.org>
+Link: https://lkml.kernel.org/r/20240731105557.GY33588@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/jump_label.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/jump_label.c b/kernel/jump_label.c
+index 1f05a19918f47..c6ac0d0377d72 100644
+--- a/kernel/jump_label.c
++++ b/kernel/jump_label.c
+@@ -231,7 +231,7 @@ void static_key_disable_cpuslocked(struct static_key *key)
+ }
+
+ jump_label_lock();
+- if (atomic_cmpxchg(&key->enabled, 1, 0))
++ if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
+ jump_label_update(key);
+ jump_label_unlock();
+ }
+@@ -284,7 +284,7 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key)
+ return;
+
+ guard(mutex)(&jump_label_mutex);
+- if (atomic_cmpxchg(&key->enabled, 1, 0))
++ if (atomic_cmpxchg(&key->enabled, 1, 0) == 1)
+ jump_label_update(key);
+ else
+ WARN_ON_ONCE(!static_key_slow_try_dec(key));
+--
+2.43.0
+
--- /dev/null
+From eb851d4bba57158911fe10573dbd59bd358f7fed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 17:06:26 +0100
+Subject: l2tp: fix lockdep splat
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit 86a41ea9fd79ddb6145cb8ebf5aeafceabca6f7d ]
+
+When l2tp tunnels use a socket provided by userspace, we can hit
+lockdep splats like the below when data is transmitted through another
+(unrelated) userspace socket which then gets routed over l2tp.
+
+This issue was previously discussed here:
+https://lore.kernel.org/netdev/87sfialu2n.fsf@cloudflare.com/
+
+The solution is to have lockdep treat socket locks of l2tp tunnel
+sockets separately than those of standard INET sockets. To do so, use
+a different lockdep subclass where lock nesting is possible.
+
+ ============================================
+ WARNING: possible recursive locking detected
+ 6.10.0+ #34 Not tainted
+ --------------------------------------------
+ iperf3/771 is trying to acquire lock:
+ ffff8881027601d8 (slock-AF_INET/1){+.-.}-{2:2}, at: l2tp_xmit_skb+0x243/0x9d0
+
+ but task is already holding lock:
+ ffff888102650d98 (slock-AF_INET/1){+.-.}-{2:2}, at: tcp_v4_rcv+0x1848/0x1e10
+
+ other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+ CPU0
+ ----
+ lock(slock-AF_INET/1);
+ lock(slock-AF_INET/1);
+
+ *** DEADLOCK ***
+
+ May be due to missing lock nesting notation
+
+ 10 locks held by iperf3/771:
+ #0: ffff888102650258 (sk_lock-AF_INET){+.+.}-{0:0}, at: tcp_sendmsg+0x1a/0x40
+ #1: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x4b/0xbc0
+ #2: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x17a/0x1130
+ #3: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: process_backlog+0x28b/0x9f0
+ #4: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_local_deliver_finish+0xf9/0x260
+ #5: ffff888102650d98 (slock-AF_INET/1){+.-.}-{2:2}, at: tcp_v4_rcv+0x1848/0x1e10
+ #6: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x4b/0xbc0
+ #7: ffffffff822ac220 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x17a/0x1130
+ #8: ffffffff822ac1e0 (rcu_read_lock_bh){....}-{1:2}, at: __dev_queue_xmit+0xcc/0x1450
+ #9: ffff888101f33258 (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock#2){+...}-{2:2}, at: __dev_queue_xmit+0x513/0x1450
+
+ stack backtrace:
+ CPU: 2 UID: 0 PID: 771 Comm: iperf3 Not tainted 6.10.0+ #34
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+ Call Trace:
+ <IRQ>
+ dump_stack_lvl+0x69/0xa0
+ dump_stack+0xc/0x20
+ __lock_acquire+0x135d/0x2600
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ lock_acquire+0xc4/0x2a0
+ ? l2tp_xmit_skb+0x243/0x9d0
+ ? __skb_checksum+0xa3/0x540
+ _raw_spin_lock_nested+0x35/0x50
+ ? l2tp_xmit_skb+0x243/0x9d0
+ l2tp_xmit_skb+0x243/0x9d0
+ l2tp_eth_dev_xmit+0x3c/0xc0
+ dev_hard_start_xmit+0x11e/0x420
+ sch_direct_xmit+0xc3/0x640
+ __dev_queue_xmit+0x61c/0x1450
+ ? ip_finish_output2+0xf4c/0x1130
+ ip_finish_output2+0x6b6/0x1130
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __ip_finish_output+0x217/0x380
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ __ip_finish_output+0x217/0x380
+ ip_output+0x99/0x120
+ __ip_queue_xmit+0xae4/0xbc0
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? tcp_options_write.constprop.0+0xcb/0x3e0
+ ip_queue_xmit+0x34/0x40
+ __tcp_transmit_skb+0x1625/0x1890
+ __tcp_send_ack+0x1b8/0x340
+ tcp_send_ack+0x23/0x30
+ __tcp_ack_snd_check+0xa8/0x530
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ tcp_rcv_established+0x412/0xd70
+ tcp_v4_do_rcv+0x299/0x420
+ tcp_v4_rcv+0x1991/0x1e10
+ ip_protocol_deliver_rcu+0x50/0x220
+ ip_local_deliver_finish+0x158/0x260
+ ip_local_deliver+0xc8/0xe0
+ ip_rcv+0xe5/0x1d0
+ ? __pfx_ip_rcv+0x10/0x10
+ __netif_receive_skb_one_core+0xce/0xe0
+ ? process_backlog+0x28b/0x9f0
+ __netif_receive_skb+0x34/0xd0
+ ? process_backlog+0x28b/0x9f0
+ process_backlog+0x2cb/0x9f0
+ __napi_poll.constprop.0+0x61/0x280
+ net_rx_action+0x332/0x670
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? find_held_lock+0x2b/0x80
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ handle_softirqs+0xda/0x480
+ ? __dev_queue_xmit+0xa2c/0x1450
+ do_softirq+0xa1/0xd0
+ </IRQ>
+ <TASK>
+ __local_bh_enable_ip+0xc8/0xe0
+ ? __dev_queue_xmit+0xa2c/0x1450
+ __dev_queue_xmit+0xa48/0x1450
+ ? ip_finish_output2+0xf4c/0x1130
+ ip_finish_output2+0x6b6/0x1130
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __ip_finish_output+0x217/0x380
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ __ip_finish_output+0x217/0x380
+ ip_output+0x99/0x120
+ __ip_queue_xmit+0xae4/0xbc0
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? tcp_options_write.constprop.0+0xcb/0x3e0
+ ip_queue_xmit+0x34/0x40
+ __tcp_transmit_skb+0x1625/0x1890
+ tcp_write_xmit+0x766/0x2fb0
+ ? __entry_text_end+0x102ba9/0x102bad
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? __might_fault+0x74/0xc0
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ __tcp_push_pending_frames+0x56/0x190
+ tcp_push+0x117/0x310
+ tcp_sendmsg_locked+0x14c1/0x1740
+ tcp_sendmsg+0x28/0x40
+ inet_sendmsg+0x5d/0x90
+ sock_write_iter+0x242/0x2b0
+ vfs_write+0x68d/0x800
+ ? __pfx_sock_write_iter+0x10/0x10
+ ksys_write+0xc8/0xf0
+ __x64_sys_write+0x3d/0x50
+ x64_sys_call+0xfaf/0x1f50
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+ RIP: 0033:0x7f4d143af992
+ Code: c3 8b 07 85 c0 75 24 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> e9 01 cc ff ff 41 54 b8 02 00 00 0
+ RSP: 002b:00007ffd65032058 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
+ RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f4d143af992
+ RDX: 0000000000000025 RSI: 00007f4d143f3bcc RDI: 0000000000000005
+ RBP: 00007f4d143f2b28 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000246 R12: 00007f4d143f3bcc
+ R13: 0000000000000005 R14: 0000000000000000 R15: 00007ffd650323f0
+ </TASK>
+
+Fixes: 0b2c59720e65 ("l2tp: close all race conditions in l2tp_tunnel_register()")
+Suggested-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot+6acef9e0a4d1f46c83d4@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=6acef9e0a4d1f46c83d4
+CC: gnault@redhat.com
+CC: cong.wang@bytedance.com
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Link: https://patch.msgid.link/20240806160626.1248317-1-jchapman@katalix.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/l2tp/l2tp_core.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 88a34db265d86..7ea4adf81d859 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -88,6 +88,11 @@
+ /* Default trace flags */
+ #define L2TP_DEFAULT_DEBUG_FLAGS 0
+
++#define L2TP_DEPTH_NESTING 2
++#if L2TP_DEPTH_NESTING == SINGLE_DEPTH_NESTING
++#error "L2TP requires its own lockdep subclass"
++#endif
++
+ /* Private data stored for received packets in the skb.
+ */
+ struct l2tp_skb_cb {
+@@ -1085,7 +1090,13 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+ nf_reset_ct(skb);
+
+- bh_lock_sock_nested(sk);
++ /* L2TP uses its own lockdep subclass to avoid lockdep splats caused by
++ * nested socket calls on the same lockdep socket class. This can
++ * happen when data from a user socket is routed over l2tp, which uses
++ * another userspace socket.
++ */
++ spin_lock_nested(&sk->sk_lock.slock, L2TP_DEPTH_NESTING);
++
+ if (sock_owned_by_user(sk)) {
+ kfree_skb(skb);
+ ret = NET_XMIT_DROP;
+@@ -1137,7 +1148,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
+ ret = l2tp_xmit_queue(tunnel, skb, &inet->cork.fl);
+
+ out_unlock:
+- bh_unlock_sock(sk);
++ spin_unlock(&sk->sk_lock.slock);
+
+ return ret;
+ }
+--
+2.43.0
+
--- /dev/null
+From fed28319395deb213e9ffec499733460f57640c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 21 Jul 2024 18:45:41 +0200
+Subject: locking/pvqspinlock: Correct the type of "old" variable in
+ pv_kick_node()
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit 6623b0217d0c9bed80bfa43b778ce1c0eb03b497 ]
+
+"enum vcpu_state" is not compatible with "u8" type for all targets,
+resulting in:
+
+error: initialization of 'u8 *' {aka 'unsigned char *'} from incompatible pointer type 'enum vcpu_state *'
+
+for LoongArch. Correct the type of "old" variable to "u8".
+
+Fixes: fea0e1820b51 ("locking/pvqspinlock: Use try_cmpxchg() in qspinlock_paravirt.h")
+Closes: https://lore.kernel.org/lkml/20240719024010.3296488-1-maobibo@loongson.cn/
+Reported-by: Bibo Mao <maobibo@loongson.cn>
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Waiman Long <longman@redhat.com>
+Link: https://lore.kernel.org/r/20240721164552.50175-1-ubizjak@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/locking/qspinlock_paravirt.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h
+index f5a36e67b5935..ac2e225027410 100644
+--- a/kernel/locking/qspinlock_paravirt.h
++++ b/kernel/locking/qspinlock_paravirt.h
+@@ -357,7 +357,7 @@ static void pv_wait_node(struct mcs_spinlock *node, struct mcs_spinlock *prev)
+ static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node)
+ {
+ struct pv_node *pn = (struct pv_node *)node;
+- enum vcpu_state old = vcpu_halted;
++ u8 old = vcpu_halted;
+ /*
+ * If the vCPU is indeed halted, advance its state to match that of
+ * pv_wait_node(). If OTOH this fails, the vCPU was running and will
+--
+2.43.0
+
--- /dev/null
+From 1c475a309fe6d4cf4dab2a21d8bf742e4f7d95b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 May 2024 02:52:56 +0800
+Subject: md: change the return value type of md_write_start to void
+
+From: Li Nan <linan122@huawei.com>
+
+[ Upstream commit 03e792eaf18ec2e93e2c623f9f1a4bdb97fe4126 ]
+
+Commit cc27b0c78c79 ("md: fix deadlock between mddev_suspend() and
+md_write_start()") aborted md_write_start() with false when mddev is
+suspended, which fixed a deadlock if calling mddev_suspend() with
+holding reconfig_mutex(). Since mddev_suspend() now includes
+lockdep_assert_not_held(), it no longer holds the reconfig_mutex. This
+makes previous abort unnecessary. Now, remove unnecessary abort and
+change function return value to void.
+
+Signed-off-by: Li Nan <linan122@huawei.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240525185257.3896201-2-linan666@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 14 ++++----------
+ drivers/md/md.h | 2 +-
+ drivers/md/raid1.c | 3 +--
+ drivers/md/raid10.c | 3 +--
+ drivers/md/raid5.c | 3 +--
+ 5 files changed, 8 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 60a5fda7c8aea..a5b5801baa9e8 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -8638,12 +8638,12 @@ EXPORT_SYMBOL(md_done_sync);
+ * A return value of 'false' means that the write wasn't recorded
+ * and cannot proceed as the array is being suspend.
+ */
+-bool md_write_start(struct mddev *mddev, struct bio *bi)
++void md_write_start(struct mddev *mddev, struct bio *bi)
+ {
+ int did_change = 0;
+
+ if (bio_data_dir(bi) != WRITE)
+- return true;
++ return;
+
+ BUG_ON(mddev->ro == MD_RDONLY);
+ if (mddev->ro == MD_AUTO_READ) {
+@@ -8676,15 +8676,9 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
+ if (did_change)
+ sysfs_notify_dirent_safe(mddev->sysfs_state);
+ if (!mddev->has_superblocks)
+- return true;
++ return;
+ wait_event(mddev->sb_wait,
+- !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) ||
+- is_md_suspended(mddev));
+- if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
+- percpu_ref_put(&mddev->writes_pending);
+- return false;
+- }
+- return true;
++ !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
+ }
+ EXPORT_SYMBOL(md_write_start);
+
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index ca085ecad5044..487582058f741 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -785,7 +785,7 @@ extern void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **t
+ extern void md_wakeup_thread(struct md_thread __rcu *thread);
+ extern void md_check_recovery(struct mddev *mddev);
+ extern void md_reap_sync_thread(struct mddev *mddev);
+-extern bool md_write_start(struct mddev *mddev, struct bio *bi);
++extern void md_write_start(struct mddev *mddev, struct bio *bi);
+ extern void md_write_inc(struct mddev *mddev, struct bio *bi);
+ extern void md_write_end(struct mddev *mddev);
+ extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 22bbd06ba6a29..5ea57b6748c53 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1688,8 +1688,7 @@ static bool raid1_make_request(struct mddev *mddev, struct bio *bio)
+ if (bio_data_dir(bio) == READ)
+ raid1_read_request(mddev, bio, sectors, NULL);
+ else {
+- if (!md_write_start(mddev,bio))
+- return false;
++ md_write_start(mddev,bio);
+ raid1_write_request(mddev, bio, sectors);
+ }
+ return true;
+diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
+index a4556d2e46bf9..f8d7c02c6ed56 100644
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1836,8 +1836,7 @@ static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
+ && md_flush_request(mddev, bio))
+ return true;
+
+- if (!md_write_start(mddev, bio))
+- return false;
++ md_write_start(mddev, bio);
+
+ if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
+ if (!raid10_handle_discard(mddev, bio))
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 1c6b58adec133..d600030c20f46 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -6097,8 +6097,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
+ ctx.do_flush = bi->bi_opf & REQ_PREFLUSH;
+ }
+
+- if (!md_write_start(mddev, bi))
+- return false;
++ md_write_start(mddev, bi);
+ /*
+ * If array is degraded, better not do chunk aligned read because
+ * later we might have to read it again in order to reconstruct
+--
+2.43.0
+
--- /dev/null
+From b44ae01194d94f931c56978e6000e1674ea25cf6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 17:20:53 +0800
+Subject: md: do not delete safemode_timer in mddev_suspend
+
+From: Li Nan <linan122@huawei.com>
+
+[ Upstream commit a8768a134518e406d41799a3594aeb74e0889cf7 ]
+
+The deletion of safemode_timer in mddev_suspend() is redundant and
+potentially harmful now. If timer is about to be woken up but gets
+deleted, 'in_sync' will remain 0 until the next write, causing array
+to stay in the 'active' state instead of transitioning to 'clean'.
+
+Commit 0d9f4f135eb6 ("MD: Add del_timer_sync to mddev_suspend (fix
+nasty panic))" introduced this deletion for dm, because if timer fired
+after dm is destroyed, the resource which the timer depends on might
+have been freed.
+
+However, commit 0dd84b319352 ("md: call __md_stop_writes in md_stop")
+added __md_stop_writes() to md_stop(), which is called before freeing
+resource. Timer is deleted in __md_stop_writes(), and the origin issue
+is resolved. Therefore, delete safemode_timer can be removed safely now.
+
+Signed-off-by: Li Nan <linan122@huawei.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240508092053.1447930-1-linan666@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 9c5be016e5073..60a5fda7c8aea 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -479,7 +479,6 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
+ */
+ WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
+
+- del_timer_sync(&mddev->safemode_timer);
+ /* restrict memory reclaim I/O during raid array is suspend */
+ mddev->noio_flag = memalloc_noio_save();
+
+--
+2.43.0
+
--- /dev/null
+From d60b757a4fd882e728f3fda3bc803ba357d9bb5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 21:22:51 +0800
+Subject: md/raid5: avoid BUG_ON() while continue reshape after reassembling
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 305a5170dc5cf3d395bb4c4e9239bca6d0b54b49 ]
+
+Currently, mdadm support --revert-reshape to abort the reshape while
+reassembling, as the test 07revert-grow. However, following BUG_ON()
+can be triggerred by the test:
+
+kernel BUG at drivers/md/raid5.c:6278!
+invalid opcode: 0000 [#1] PREEMPT SMP PTI
+irq event stamp: 158985
+CPU: 6 PID: 891 Comm: md0_reshape Not tainted 6.9.0-03335-g7592a0b0049a #94
+RIP: 0010:reshape_request+0x3f1/0xe60
+Call Trace:
+ <TASK>
+ raid5_sync_request+0x43d/0x550
+ md_do_sync+0xb7a/0x2110
+ md_thread+0x294/0x2b0
+ kthread+0x147/0x1c0
+ ret_from_fork+0x59/0x70
+ ret_from_fork_asm+0x1a/0x30
+ </TASK>
+
+Root cause is that --revert-reshape update the raid_disks from 5 to 4,
+while reshape position is still set, and after reassembling the array,
+reshape position will be read from super block, then during reshape the
+checking of 'writepos' that is caculated by old reshape position will
+fail.
+
+Fix this panic the easy way first, by converting the BUG_ON() to
+WARN_ON(), and stop the reshape if checkings fail.
+
+Noted that mdadm must fix --revert-shape as well, and probably md/raid
+should enhance metadata validation as well, however this means
+reassemble will fail and there must be user tools to fix the wrong
+metadata.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240611132251.1967786-13-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid5.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index d600030c20f46..ff9f4751c0965 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -6272,7 +6272,9 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
+ safepos = conf->reshape_safe;
+ sector_div(safepos, data_disks);
+ if (mddev->reshape_backwards) {
+- BUG_ON(writepos < reshape_sectors);
++ if (WARN_ON(writepos < reshape_sectors))
++ return MaxSector;
++
+ writepos -= reshape_sectors;
+ readpos += reshape_sectors;
+ safepos += reshape_sectors;
+@@ -6290,14 +6292,18 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk
+ * to set 'stripe_addr' which is where we will write to.
+ */
+ if (mddev->reshape_backwards) {
+- BUG_ON(conf->reshape_progress == 0);
++ if (WARN_ON(conf->reshape_progress == 0))
++ return MaxSector;
++
+ stripe_addr = writepos;
+- BUG_ON((mddev->dev_sectors &
+- ~((sector_t)reshape_sectors - 1))
+- - reshape_sectors - stripe_addr
+- != sector_nr);
++ if (WARN_ON((mddev->dev_sectors &
++ ~((sector_t)reshape_sectors - 1)) -
++ reshape_sectors - stripe_addr != sector_nr))
++ return MaxSector;
+ } else {
+- BUG_ON(writepos != sector_nr + reshape_sectors);
++ if (WARN_ON(writepos != sector_nr + reshape_sectors))
++ return MaxSector;
++
+ stripe_addr = sector_nr;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 8aa23f4e314d0dd9f62062228ae18c02fdcd89f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 May 2024 17:49:17 +0900
+Subject: media: amphion: Remove lock in s_ctrl callback
+
+From: Ming Qian <ming.qian@nxp.com>
+
+[ Upstream commit 065927b51eb1f042c3e026cebfd55e72ccc26093 ]
+
+There is no need to add a lock in s_ctrl callback, it has been
+synchronized by the ctrl_handler's lock, otherwise it may led to
+a deadlock if the driver calls v4l2_ctrl_s_ctrl().
+
+Signed-off-by: Ming Qian <ming.qian@nxp.com>
+Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/amphion/vdec.c | 2 --
+ drivers/media/platform/amphion/venc.c | 2 --
+ 2 files changed, 4 deletions(-)
+
+diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c
+index a57f9f4f3b876..6a38a0fa0e2d4 100644
+--- a/drivers/media/platform/amphion/vdec.c
++++ b/drivers/media/platform/amphion/vdec.c
+@@ -195,7 +195,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+ struct vdec_t *vdec = inst->priv;
+ int ret = 0;
+
+- vpu_inst_lock(inst);
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
+ vdec->params.display_delay_enable = ctrl->val;
+@@ -207,7 +206,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
+ ret = -EINVAL;
+ break;
+ }
+- vpu_inst_unlock(inst);
+
+ return ret;
+ }
+diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
+index 4eb57d793a9c0..16ed4d21519cd 100644
+--- a/drivers/media/platform/amphion/venc.c
++++ b/drivers/media/platform/amphion/venc.c
+@@ -518,7 +518,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+ struct venc_t *venc = inst->priv;
+ int ret = 0;
+
+- vpu_inst_lock(inst);
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+ venc->params.profile = ctrl->val;
+@@ -579,7 +578,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
+ ret = -EINVAL;
+ break;
+ }
+- vpu_inst_unlock(inst);
+
+ return ret;
+ }
+--
+2.43.0
+
--- /dev/null
+From eef42813941642af47101e5524f80d8824ad39c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 06:51:58 -0400
+Subject: media: i2c: ov5647: replacing of_node_put with __free(device_node)
+
+From: Abdulrasaq Lawani <abdulrasaqolawani@gmail.com>
+
+[ Upstream commit 971b4eef86ccb8b107ad2875993e510eec4fdeae ]
+
+Replace instance of of_node_put with __free(device_node)
+to protect against any memory leaks due to future changes
+in control flow.
+
+Signed-off-by: Abdulrasaq Lawani <abdulrasaqolawani@gmail.com>
+Acked-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/ov5647.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
+index 7e1ecdf2485f7..0fb4d7bff9d14 100644
+--- a/drivers/media/i2c/ov5647.c
++++ b/drivers/media/i2c/ov5647.c
+@@ -1360,24 +1360,21 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np)
+ struct v4l2_fwnode_endpoint bus_cfg = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY,
+ };
+- struct device_node *ep;
++ struct device_node *ep __free(device_node) =
++ of_graph_get_endpoint_by_regs(np, 0, -1);
+ int ret;
+
+- ep = of_graph_get_endpoint_by_regs(np, 0, -1);
+ if (!ep)
+ return -EINVAL;
+
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
+ if (ret)
+- goto out;
++ return ret;
+
+ sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
+ V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
+
+-out:
+- of_node_put(ep);
+-
+- return ret;
++ return 0;
+ }
+
+ static int ov5647_probe(struct i2c_client *client)
+--
+2.43.0
+
--- /dev/null
+From 21532cf722d3213bd830a52ca71e6f316e3141e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Apr 2024 19:00:40 +0200
+Subject: media: uvcvideo: Fix the bandwdith quirk on USB 3.x
+
+From: Michal Pecio <michal.pecio@gmail.com>
+
+[ Upstream commit 9e3d55fbd160b3ca376599a68b4cddfdc67d4153 ]
+
+The bandwidth fixup quirk doesn't know that SuperSpeed exists and has
+the same 8 service intervals per millisecond as High Speed, hence its
+calculations are wrong.
+
+Assume that all speeds from HS up use 8 intervals per millisecond.
+
+No further changes are needed, updated code has been confirmed to work
+with all speeds from FS to SS.
+
+Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Link: https://lore.kernel.org/r/20240414190040.2255a0bc@foxbook
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 0055a05470c47..5bebe1460a9f7 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -214,13 +214,13 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
+ * Compute a bandwidth estimation by multiplying the frame
+ * size by the number of video frames per second, divide the
+ * result by the number of USB frames (or micro-frames for
+- * high-speed devices) per second and add the UVC header size
+- * (assumed to be 12 bytes long).
++ * high- and super-speed devices) per second and add the UVC
++ * header size (assumed to be 12 bytes long).
+ */
+ bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
+ bandwidth *= 10000000 / interval + 1;
+ bandwidth /= 1000;
+- if (stream->dev->udev->speed == USB_SPEED_HIGH)
++ if (stream->dev->udev->speed >= USB_SPEED_HIGH)
+ bandwidth /= 8;
+ bandwidth += 12;
+
+--
+2.43.0
+
--- /dev/null
+From e05394917945485e8c7b7f986e3fe7bc17d5a9e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Mar 2024 10:48:03 +0000
+Subject: media: uvcvideo: Ignore empty TS packets
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 5cd7c25f6f0576073b3d03bc4cfb1e8ca63a1195 ]
+
+Some SunplusIT cameras took a borderline interpretation of the UVC 1.5
+standard, and fill the PTS and SCR fields with invalid data if the
+package does not contain data.
+
+"STC must be captured when the first video data of a video frame is put
+on the USB bus."
+
+Some SunplusIT devices send, e.g.,
+
+buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000
+buffer: 0xa7755c00 len 000012 header:0x8c stc 00000000 sof 0000 pts 00000000
+buffer: 0xa7755c00 len 000668 header:0x8c stc 73779dba sof 070c pts 7376d37a
+
+While the UVC specification meant that the first two packets shouldn't
+have had the SCR bit set in the header.
+
+This borderline/buggy interpretation has been implemented in a variety
+of devices, from directly SunplusIT and from other OEMs that rebrand
+SunplusIT products. So quirking based on VID:PID will be problematic.
+
+All the affected modules have the following extension unit:
+VideoControl Interface Descriptor:
+ guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d221d}
+
+But the vendor plans to use that GUID in the future and fix the bug,
+this means that we should use heuristic to figure out the broken
+packets.
+
+This patch takes care of this.
+
+lsusb of one of the affected cameras:
+
+Bus 001 Device 003: ID 1bcf:2a01 Sunplus Innovation Technology Inc.
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 2.01
+ bDeviceClass 239 Miscellaneous Device
+ bDeviceSubClass 2 ?
+ bDeviceProtocol 1 Interface Association
+ bMaxPacketSize0 64
+ idVendor 0x1bcf Sunplus Innovation Technology Inc.
+ idProduct 0x2a01
+ bcdDevice 0.02
+ iManufacturer 1 SunplusIT Inc
+ iProduct 2 HanChen Wise Camera
+ iSerial 3 01.00.00
+ bNumConfigurations 1
+
+Tested-by: HungNien Chen <hn.chen@sunplusit.com>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-2-b08e590d97c7@chromium.org
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 51f4f653b983d..0055a05470c47 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -478,6 +478,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+ ktime_t time;
+ u16 host_sof;
+ u16 dev_sof;
++ u32 dev_stc;
+
+ switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+ case UVC_STREAM_PTS | UVC_STREAM_SCR:
+@@ -526,6 +527,34 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+ if (dev_sof == stream->clock.last_sof)
+ return;
+
++ dev_stc = get_unaligned_le32(&data[header_size - 6]);
++
++ /*
++ * STC (Source Time Clock) is the clock used by the camera. The UVC 1.5
++ * standard states that it "must be captured when the first video data
++ * of a video frame is put on the USB bus". This is generally understood
++ * as requiring devices to clear the payload header's SCR bit before
++ * the first packet containing video data.
++ *
++ * Most vendors follow that interpretation, but some (namely SunplusIT
++ * on some devices) always set the `UVC_STREAM_SCR` bit, fill the SCR
++ * field with 0's,and expect that the driver only processes the SCR if
++ * there is data in the packet.
++ *
++ * Ignore all the hardware timestamp information if we haven't received
++ * any data for this frame yet, the packet contains no data, and both
++ * STC and SOF are zero. This heuristics should be safe on compliant
++ * devices. This should be safe with compliant devices, as in the very
++ * unlikely case where a UVC 1.1 device would send timing information
++ * only before the first packet containing data, and both STC and SOF
++ * happen to be zero for a particular frame, we would only miss one
++ * clock sample from many and the clock recovery algorithm wouldn't
++ * suffer from this condition.
++ */
++ if (buf && buf->bytesused == 0 && len == header_size &&
++ dev_stc == 0 && dev_sof == 0)
++ return;
++
+ stream->clock.last_sof = dev_sof;
+
+ host_sof = usb_get_current_frame_number(stream->dev->udev);
+@@ -575,7 +604,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+ spin_lock_irqsave(&stream->clock.lock, flags);
+
+ sample = &stream->clock.samples[stream->clock.head];
+- sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
++ sample->dev_stc = dev_stc;
+ sample->dev_sof = dev_sof;
+ sample->host_sof = host_sof;
+ sample->host_time = time;
+--
+2.43.0
+
--- /dev/null
+From f4afc234a5ac4ee3af59108a4e74abb8da0d3af6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 08:22:25 -0700
+Subject: media: xc2028: avoid use-after-free in load_firmware_cb()
+
+From: Chi Zhiling <chizhiling@kylinos.cn>
+
+[ Upstream commit 68594cec291ff9523b9feb3f43fd853dcddd1f60 ]
+
+syzkaller reported use-after-free in load_firmware_cb() [1].
+The reason is because the module allocated a struct tuner in tuner_probe(),
+and then the module initialization failed, the struct tuner was released.
+A worker which created during module initialization accesses this struct
+tuner later, it caused use-after-free.
+
+The process is as follows:
+
+task-6504 worker_thread
+tuner_probe <= alloc dvb_frontend [2]
+...
+request_firmware_nowait <= create a worker
+...
+tuner_remove <= free dvb_frontend
+...
+ request_firmware_work_func <= the firmware is ready
+ load_firmware_cb <= but now the dvb_frontend has been freed
+
+To fix the issue, check the dvd_frontend in load_firmware_cb(), if it is
+null, report a warning and just return.
+
+[1]:
+ ==================================================================
+ BUG: KASAN: use-after-free in load_firmware_cb+0x1310/0x17a0
+ Read of size 8 at addr ffff8000d7ca2308 by task kworker/2:3/6504
+
+ Call trace:
+ load_firmware_cb+0x1310/0x17a0
+ request_firmware_work_func+0x128/0x220
+ process_one_work+0x770/0x1824
+ worker_thread+0x488/0xea0
+ kthread+0x300/0x430
+ ret_from_fork+0x10/0x20
+
+ Allocated by task 6504:
+ kzalloc
+ tuner_probe+0xb0/0x1430
+ i2c_device_probe+0x92c/0xaf0
+ really_probe+0x678/0xcd0
+ driver_probe_device+0x280/0x370
+ __device_attach_driver+0x220/0x330
+ bus_for_each_drv+0x134/0x1c0
+ __device_attach+0x1f4/0x410
+ device_initial_probe+0x20/0x30
+ bus_probe_device+0x184/0x200
+ device_add+0x924/0x12c0
+ device_register+0x24/0x30
+ i2c_new_device+0x4e0/0xc44
+ v4l2_i2c_new_subdev_board+0xbc/0x290
+ v4l2_i2c_new_subdev+0xc8/0x104
+ em28xx_v4l2_init+0x1dd0/0x3770
+
+ Freed by task 6504:
+ kfree+0x238/0x4e4
+ tuner_remove+0x144/0x1c0
+ i2c_device_remove+0xc8/0x290
+ __device_release_driver+0x314/0x5fc
+ device_release_driver+0x30/0x44
+ bus_remove_device+0x244/0x490
+ device_del+0x350/0x900
+ device_unregister+0x28/0xd0
+ i2c_unregister_device+0x174/0x1d0
+ v4l2_device_unregister+0x224/0x380
+ em28xx_v4l2_init+0x1d90/0x3770
+
+ The buggy address belongs to the object at ffff8000d7ca2000
+ which belongs to the cache kmalloc-2k of size 2048
+ The buggy address is located 776 bytes inside of
+ 2048-byte region [ffff8000d7ca2000, ffff8000d7ca2800)
+ The buggy address belongs to the page:
+ page:ffff7fe00035f280 count:1 mapcount:0 mapping:ffff8000c001f000 index:0x0
+ flags: 0x7ff800000000100(slab)
+ raw: 07ff800000000100 ffff7fe00049d880 0000000300000003 ffff8000c001f000
+ raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
+ page dumped because: kasan: bad access detected
+
+ Memory state around the buggy address:
+ ffff8000d7ca2200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff8000d7ca2280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ >ffff8000d7ca2300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ^
+ ffff8000d7ca2380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff8000d7ca2400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ==================================================================
+
+[2]
+ Actually, it is allocated for struct tuner, and dvb_frontend is inside.
+
+Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/tuners/xc2028.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/tuners/xc2028.c b/drivers/media/tuners/xc2028.c
+index 5a967edceca93..352b8a3679b72 100644
+--- a/drivers/media/tuners/xc2028.c
++++ b/drivers/media/tuners/xc2028.c
+@@ -1361,9 +1361,16 @@ static void load_firmware_cb(const struct firmware *fw,
+ void *context)
+ {
+ struct dvb_frontend *fe = context;
+- struct xc2028_data *priv = fe->tuner_priv;
++ struct xc2028_data *priv;
+ int rc;
+
++ if (!fe) {
++ pr_warn("xc2028: No frontend in %s\n", __func__);
++ return;
++ }
++
++ priv = fe->tuner_priv;
++
+ tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
+ if (!fw) {
+ tuner_err("Could not load firmware %s.\n", priv->fname);
+--
+2.43.0
+
--- /dev/null
+From 54c51fb53554f5c2a50bd288002f8407f33ff2aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jul 2024 16:23:42 +0200
+Subject: mlxsw: pci: Lock configuration space of upstream bridge during reset
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 0970836c348b6bc2ea77ce4348a136d6febfd440 ]
+
+The driver triggers a "Secondary Bus Reset" (SBR) by calling
+__pci_reset_function_locked() which asserts the SBR bit in the "Bridge
+Control Register" in the configuration space of the upstream bridge for
+2ms. This is done without locking the configuration space of the
+upstream bridge port, allowing user space to access it concurrently.
+
+Linux 6.11 will start warning about such unlocked resets [1][2]:
+
+pcieport 0000:00:01.0: unlocked secondary bus reset via: pci_reset_bus_function+0x51c/0x6a0
+
+Avoid the warning and the concurrent access by locking the configuration
+space of the upstream bridge prior to the reset and unlocking it
+afterwards.
+
+[1] https://lore.kernel.org/all/171711746953.1628941.4692125082286867825.stgit@dwillia2-xfh.jf.intel.com/
+[2] https://lore.kernel.org/all/20240531213150.GA610983@bhelgaas/
+
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Link: https://patch.msgid.link/9937b0afdb50f2f2825945393c94c093c04a5897.1720447210.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/pci.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+index c0ced4d315f3d..d92f640bae575 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+@@ -1599,6 +1599,7 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+ {
+ struct pci_dev *pdev = mlxsw_pci->pdev;
+ char mrsr_pl[MLXSW_REG_MRSR_LEN];
++ struct pci_dev *bridge;
+ int err;
+
+ if (!pci_reset_sbr_supported) {
+@@ -1615,6 +1616,9 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+ sbr:
+ device_lock_assert(&pdev->dev);
+
++ bridge = pci_upstream_bridge(pdev);
++ if (bridge)
++ pci_cfg_access_lock(bridge);
+ pci_cfg_access_lock(pdev);
+ pci_save_state(pdev);
+
+@@ -1624,6 +1628,8 @@ static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
+
+ pci_restore_state(pdev);
+ pci_cfg_access_unlock(pdev);
++ if (bridge)
++ pci_cfg_access_unlock(bridge);
+
+ return err;
+ }
+--
+2.43.0
+
--- /dev/null
+From fe3cc5d6e1596c945a8d0c3d4a383f3bd16b1864 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 10:56:59 -0700
+Subject: net: bcmgenet: Properly overlay PHY and MAC Wake-on-LAN capabilities
+
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+
+[ Upstream commit 9ee09edc05f20422e7ced84b1f8a5d3359926ac8 ]
+
+Some Wake-on-LAN modes such as WAKE_FILTER may only be supported by the MAC,
+while others might be only supported by the PHY. Make sure that the .get_wol()
+returns the union of both rather than only that of the PHY if the PHY supports
+Wake-on-LAN.
+
+Fixes: 7e400ff35cbe ("net: bcmgenet: Add support for PHY-based Wake-on-LAN")
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240806175659.3232204-1-florian.fainelli@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+index 1248792d7fd4d..0715ea5bf13ed 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+@@ -42,19 +42,15 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ struct device *kdev = &priv->pdev->dev;
+
+- if (dev->phydev) {
++ if (dev->phydev)
+ phy_ethtool_get_wol(dev->phydev, wol);
+- if (wol->supported)
+- return;
+- }
+
+- if (!device_can_wakeup(kdev)) {
+- wol->supported = 0;
+- wol->wolopts = 0;
++ /* MAC is not wake-up capable, return what the PHY does */
++ if (!device_can_wakeup(kdev))
+ return;
+- }
+
+- wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
++ /* Overlay MAC capabilities with that of the PHY queried before */
++ wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
+ wol->wolopts = priv->wolopts;
+ memset(wol->sopass, 0, sizeof(wol->sopass));
+
+--
+2.43.0
+
--- /dev/null
+From 2c2fcaa66479fa8e5132b282b9d8ddca68cf4ce8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 11:07:30 +0300
+Subject: net: bridge: mcast: wait for previous gc cycles when removing port
+
+From: Nikolay Aleksandrov <razor@blackwall.org>
+
+[ Upstream commit 92c4ee25208d0f35dafc3213cdf355fbe449e078 ]
+
+syzbot hit a use-after-free[1] which is caused because the bridge doesn't
+make sure that all previous garbage has been collected when removing a
+port. What happens is:
+ CPU 1 CPU 2
+ start gc cycle remove port
+ acquire gc lock first
+ wait for lock
+ call br_multicasg_gc() directly
+ acquire lock now but free port
+ the port can be freed
+ while grp timers still
+ running
+
+Make sure all previous gc cycles have finished by using flush_work before
+freeing the port.
+
+[1]
+ BUG: KASAN: slab-use-after-free in br_multicast_port_group_expired+0x4c0/0x550 net/bridge/br_multicast.c:861
+ Read of size 8 at addr ffff888071d6d000 by task syz.5.1232/9699
+
+ CPU: 1 PID: 9699 Comm: syz.5.1232 Not tainted 6.10.0-rc5-syzkaller-00021-g24ca36a562d6 #0
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/07/2024
+ Call Trace:
+ <IRQ>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:114
+ print_address_description mm/kasan/report.c:377 [inline]
+ print_report+0xc3/0x620 mm/kasan/report.c:488
+ kasan_report+0xd9/0x110 mm/kasan/report.c:601
+ br_multicast_port_group_expired+0x4c0/0x550 net/bridge/br_multicast.c:861
+ call_timer_fn+0x1a3/0x610 kernel/time/timer.c:1792
+ expire_timers kernel/time/timer.c:1843 [inline]
+ __run_timers+0x74b/0xaf0 kernel/time/timer.c:2417
+ __run_timer_base kernel/time/timer.c:2428 [inline]
+ __run_timer_base kernel/time/timer.c:2421 [inline]
+ run_timer_base+0x111/0x190 kernel/time/timer.c:2437
+
+Reported-by: syzbot+263426984509be19c9a0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=263426984509be19c9a0
+Fixes: e12cec65b554 ("net: bridge: mcast: destroy all entries via gc")
+Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20240802080730.3206303-1-razor@blackwall.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_multicast.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 9a1cb5079a7a0..b2ae0d2434d2e 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -2045,16 +2045,14 @@ void br_multicast_del_port(struct net_bridge_port *port)
+ {
+ struct net_bridge *br = port->br;
+ struct net_bridge_port_group *pg;
+- HLIST_HEAD(deleted_head);
+ struct hlist_node *n;
+
+ /* Take care of the remaining groups, only perm ones should be left */
+ spin_lock_bh(&br->multicast_lock);
+ hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
+ br_multicast_find_del_pg(br, pg);
+- hlist_move_list(&br->mcast_gc_list, &deleted_head);
+ spin_unlock_bh(&br->multicast_lock);
+- br_multicast_gc(&deleted_head);
++ flush_work(&br->mcast_gc_work);
+ br_multicast_port_ctx_deinit(&port->multicast_ctx);
+ free_percpu(port->mcast_stats);
+ }
+--
+2.43.0
+
--- /dev/null
+From 0a021dbaf4b0a8000aeb7c742070e461b17e0821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 10:13:27 +0900
+Subject: net: dsa: bcm_sf2: Fix a possible memory leak in
+ bcm_sf2_mdio_register()
+
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+
+[ Upstream commit e3862093ee93fcfbdadcb7957f5f8974fffa806a ]
+
+bcm_sf2_mdio_register() calls of_phy_find_device() and then
+phy_device_remove() in a loop to remove existing PHY devices.
+of_phy_find_device() eventually calls bus_find_device(), which calls
+get_device() on the returned struct device * to increment the refcount.
+The current implementation does not decrement the refcount, which causes
+memory leak.
+
+This commit adds the missing phy_device_free() call to decrement the
+refcount via put_device() to balance the refcount.
+
+Fixes: 771089c2a485 ("net: dsa: bcm_sf2: Ensure that MDIO diversion is used")
+Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240806011327.3817861-1-joe@pf.is.s.u-tokyo.ac.jp
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/bcm_sf2.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
+index ed1e6560df25e..0e663ec0c12a3 100644
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -675,8 +675,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
+ of_remove_property(child, prop);
+
+ phydev = of_phy_find_device(child);
+- if (phydev)
++ if (phydev) {
+ phy_device_remove(phydev);
++ phy_device_free(phydev);
++ }
+ }
+
+ err = mdiobus_register(priv->user_mii_bus);
+--
+2.43.0
+
--- /dev/null
+From 38765944c6c8500c34eee8c1514f3701656032e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 21:52:09 +0100
+Subject: net: dsa: microchip: disable EEE for KSZ8567/KSZ9567/KSZ9896/KSZ9897.
+
+From: Martin Whitaker <foss@martin-whitaker.me.uk>
+
+[ Upstream commit 0411f73c13afcf619d7aa7546edbc5710a871cae ]
+
+As noted in the device errata [1-8], EEE support is not fully operational
+in the KSZ8567, KSZ9477, KSZ9567, KSZ9896, and KSZ9897 devices, causing
+link drops when connected to another device that supports EEE. The patch
+series "net: add EEE support for KSZ9477 switch family" merged in commit
+9b0bf4f77162 caused EEE support to be enabled in these devices. A fix for
+this regression for the KSZ9477 alone was merged in commit 08c6d8bae48c2.
+This patch extends this fix to the other affected devices.
+
+[1] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ8567R-Errata-DS80000752.pdf
+[2] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ8567S-Errata-DS80000753.pdf
+[3] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9477S-Errata-DS80000754.pdf
+[4] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9567R-Errata-DS80000755.pdf
+[5] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9567S-Errata-DS80000756.pdf
+[6] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9896C-Errata-DS80000757.pdf
+[7] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9897R-Errata-DS80000758.pdf
+[8] https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/Errata/KSZ9897S-Errata-DS80000759.pdf
+
+Fixes: 69d3b36ca045 ("net: dsa: microchip: enable EEE support") # for KSZ8567/KSZ9567/KSZ9896/KSZ9897
+Link: https://lore.kernel.org/netdev/137ce1ee-0b68-4c96-a717-c8164b514eec@martin-whitaker.me.uk/
+Signed-off-by: Martin Whitaker <foss@martin-whitaker.me.uk>
+Acked-by: Arun Ramadoss <arun.ramadoss@microchip.com>
+Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Lukasz Majewski <lukma@denx.de>
+Link: https://patch.msgid.link/20240807205209.21464-1-foss@martin-whitaker.me.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/microchip/ksz_common.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index 077935cf5e381..3103e1b32d0ba 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -2578,7 +2578,11 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
+ if (!port)
+ return MICREL_KSZ8_P1_ERRATA;
+ break;
++ case KSZ8567_CHIP_ID:
+ case KSZ9477_CHIP_ID:
++ case KSZ9567_CHIP_ID:
++ case KSZ9896_CHIP_ID:
++ case KSZ9897_CHIP_ID:
+ /* KSZ9477 Errata DS80000754C
+ *
+ * Module 4: Energy Efficient Ethernet (EEE) feature select must
+@@ -2588,6 +2592,13 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
+ * controls. If not disabled, the PHY ports can auto-negotiate
+ * to enable EEE, and this feature can cause link drops when
+ * linked to another device supporting EEE.
++ *
++ * The same item appears in the errata for the KSZ9567, KSZ9896,
++ * and KSZ9897.
++ *
++ * A similar item appears in the errata for the KSZ8567, but
++ * provides an alternative workaround. For now, use the simple
++ * workaround of disabling the EEE feature for this device too.
+ */
+ return MICREL_NO_EEE;
+ }
+--
+2.43.0
+
--- /dev/null
+From 881f1d5fb207a51add1fd66cf2aabf4c58f6ae8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 16:52:00 -0700
+Subject: net: dsa: microchip: Fix Wake-on-LAN check to not return an error
+
+From: Tristram Ha <tristram.ha@microchip.com>
+
+[ Upstream commit c7a19018bd557c24072b59088ad2684fd83ea3f4 ]
+
+The wol variable in ksz_port_set_mac_address() is declared with random
+data, but the code in ksz_get_wol call may not be executed so the
+WAKE_MAGIC check may be invalid resulting in an error message when
+setting a MAC address after starting the DSA driver.
+
+Fixes: 3b454b6390c3 ("net: dsa: microchip: ksz9477: Add Wake on Magic Packet support")
+Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
+Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://patch.msgid.link/20240805235200.24982-1-Tristram.Ha@microchip.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/microchip/ksz_common.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index baa1eeb9a1b04..077935cf5e381 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -3763,6 +3763,11 @@ static int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
+ return -EBUSY;
+ }
+
++ /* Need to initialize variable as the code to fill in settings may
++ * not be executed.
++ */
++ wol.wolopts = 0;
++
+ ksz_get_wol(ds, dp->index, &wol);
+ if (wol.wolopts & WAKE_MAGIC) {
+ dev_err(ds->dev,
+--
+2.43.0
+
--- /dev/null
+From 3cc8f38bc5dd1f1dfbf076ba3441e413537e79c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 10:09:56 +0200
+Subject: net: fec: Stop PPS on driver remove
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Csókás, Bence <csokas.bence@prolan.hu>
+
+[ Upstream commit 8fee6d5ad5fa18c270eedb2a2cdf58dbadefb94b ]
+
+PPS was not stopped in `fec_ptp_stop()`, called when
+the adapter was removed. Consequentially, you couldn't
+safely reload the driver with the PPS signal on.
+
+Fixes: 32cba57ba74b ("net: fec: introduce fec_ptp_stop and use in probe fail path")
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Link: https://lore.kernel.org/netdev/CAOMZO5BzcZR8PwKKwBssQq_wAGzVgf1ffwe_nhpQJjviTdxy-w@mail.gmail.com/T/#m01dcb810bfc451a492140f6797ca77443d0cb79f
+Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20240807080956.2556602-1-csokas.bence@prolan.hu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_ptp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
+index e32f6724f5681..2e4f3e1782a25 100644
+--- a/drivers/net/ethernet/freescale/fec_ptp.c
++++ b/drivers/net/ethernet/freescale/fec_ptp.c
+@@ -775,6 +775,9 @@ void fec_ptp_stop(struct platform_device *pdev)
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
++ if (fep->pps_enable)
++ fec_ptp_enable_pps(fep, 0);
++
+ cancel_delayed_work_sync(&fep->time_keep);
+ hrtimer_cancel(&fep->perout_timer);
+ if (fep->ptp_clock)
+--
+2.43.0
+
--- /dev/null
+From 9c8f913bb330d9a6562b9335958ccbb3413ab95d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 08:58:21 +0000
+Subject: net: linkwatch: use system_unbound_wq
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3e7917c0cdad835a5121520fc5686d954b7a61ab ]
+
+linkwatch_event() grabs possibly very contended RTNL mutex.
+
+system_wq is not suitable for such work.
+
+Inspired by many noisy syzbot reports.
+
+3 locks held by kworker/0:7/5266:
+ #0: ffff888015480948 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3206 [inline]
+ #0: ffff888015480948 ((wq_completion)events){+.+.}-{0:0}, at: process_scheduled_works+0x90a/0x1830 kernel/workqueue.c:3312
+ #1: ffffc90003f6fd00 ((linkwatch_work).work){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3207 [inline]
+ , at: process_scheduled_works+0x945/0x1830 kernel/workqueue.c:3312
+ #2: ffffffff8fa6f208 (rtnl_mutex){+.+.}-{3:3}, at: linkwatch_event+0xe/0x60 net/core/link_watch.c:276
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20240805085821.1616528-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/link_watch.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/link_watch.c b/net/core/link_watch.c
+index 8ec35194bfcb8..ab150641142aa 100644
+--- a/net/core/link_watch.c
++++ b/net/core/link_watch.c
+@@ -148,9 +148,9 @@ static void linkwatch_schedule_work(int urgent)
+ * override the existing timer.
+ */
+ if (test_bit(LW_URGENT, &linkwatch_flags))
+- mod_delayed_work(system_wq, &linkwatch_work, 0);
++ mod_delayed_work(system_unbound_wq, &linkwatch_work, 0);
+ else
+- schedule_delayed_work(&linkwatch_work, delay);
++ queue_delayed_work(system_unbound_wq, &linkwatch_work, delay);
+ }
+
+
+--
+2.43.0
+
--- /dev/null
+From 249809b1f8b24bf6aec02e7ce3d455bb954958d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 00:22:08 +0300
+Subject: net/mlx5e: SHAMPO, Fix invalid WQ linked list unlink
+
+From: Dragos Tatulea <dtatulea@nvidia.com>
+
+[ Upstream commit fba8334721e266f92079632598e46e5f89082f30 ]
+
+When all the strides in a WQE have been consumed, the WQE is unlinked
+from the WQ linked list (mlx5_wq_ll_pop()). For SHAMPO, it is possible
+to receive CQEs with 0 consumed strides for the same WQE even after the
+WQE is fully consumed and unlinked. This triggers an additional unlink
+for the same wqe which corrupts the linked list.
+
+Fix this scenario by accepting 0 sized consumed strides without
+unlinking the WQE again.
+
+Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://lore.kernel.org/r/20240603212219.1037656-4-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+index b5333da20e8a7..cdc84a27a04ed 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+@@ -2374,6 +2374,9 @@ static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cq
+ if (likely(wi->consumed_strides < rq->mpwqe.num_strides))
+ return;
+
++ if (unlikely(!cstrides))
++ return;
++
+ wq = &rq->mpwqe.wq;
+ wqe = mlx5_wq_ll_get_wqe(wq, wqe_id);
+ mlx5_wq_ll_pop(wq, cqe->wqe_id, &wqe->next.next_wqe_index);
+--
+2.43.0
+
--- /dev/null
+From 8e55abe94209a3f0f393ba56da6f21124dbbe2dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 15:42:14 +0000
+Subject: net: pse-pd: tps23881: Fix the device ID check
+
+From: Kyle Swenson <kyle.swenson@est.tech>
+
+[ Upstream commit 89108cb5c28527c1882df2987394e5c261a1f4aa ]
+
+The DEVID register contains two pieces of information: the device ID in
+the upper nibble, and the silicon revision number in the lower nibble.
+The driver should work fine with any silicon revision, so let's mask
+that out in the device ID check.
+
+Fixes: 20e6d190ffe1 ("net: pse-pd: Add TI TPS23881 PSE controller driver")
+Signed-off-by: Kyle Swenson <kyle.swenson@est.tech>
+Reviewed-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20240731154152.4020668-1-kyle.swenson@est.tech
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pse-pd/tps23881.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c
+index 98ffbb1bbf13c..e95109c1130dc 100644
+--- a/drivers/net/pse-pd/tps23881.c
++++ b/drivers/net/pse-pd/tps23881.c
+@@ -29,6 +29,8 @@
+ #define TPS23881_REG_TPON BIT(0)
+ #define TPS23881_REG_FWREV 0x41
+ #define TPS23881_REG_DEVID 0x43
++#define TPS23881_REG_DEVID_MASK 0xF0
++#define TPS23881_DEVICE_ID 0x02
+ #define TPS23881_REG_SRAM_CTRL 0x60
+ #define TPS23881_REG_SRAM_DATA 0x61
+
+@@ -750,7 +752,7 @@ static int tps23881_i2c_probe(struct i2c_client *client)
+ if (ret < 0)
+ return ret;
+
+- if (ret != 0x22) {
++ if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
+ dev_err(dev, "Wrong device ID\n");
+ return -ENXIO;
+ }
+--
+2.43.0
+
--- /dev/null
+From 05c3d118aef4464fad29d0171d84e21b2b3e6dbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Aug 2024 09:54:22 +0200
+Subject: net: pse-pd: tps23881: include missing bitfield.h header
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit a70b637db15b4de25af3c5946c4399144b3bc241 ]
+
+Using FIELD_GET() fails in configurations that don't already include
+the header file indirectly:
+
+drivers/net/pse-pd/tps23881.c: In function 'tps23881_i2c_probe':
+drivers/net/pse-pd/tps23881.c:755:13: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
+ 755 | if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
+ | ^~~~~~~~~
+
+Fixes: 89108cb5c285 ("net: pse-pd: tps23881: Fix the device ID check")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20240807075455.2055224-1-arnd@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pse-pd/tps23881.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c
+index e95109c1130dc..2d1c2e5706f8b 100644
+--- a/drivers/net/pse-pd/tps23881.c
++++ b/drivers/net/pse-pd/tps23881.c
+@@ -5,6 +5,7 @@
+ * Copyright (c) 2023 Bootlin, Kory Maincent <kory.maincent@bootlin.com>
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/delay.h>
+ #include <linux/firmware.h>
+ #include <linux/i2c.h>
+--
+2.43.0
+
--- /dev/null
+From 12b7a3a48179413fe2ed1554c15a9fdd40c7faae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 15:22:04 +0200
+Subject: net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 401cb7dae8130fd34eb84648e02ab4c506df7d5e ]
+
+The XDP redirect process is two staged:
+- bpf_prog_run_xdp() is invoked to run a eBPF program which inspects the
+ packet and makes decisions. While doing that, the per-CPU variable
+ bpf_redirect_info is used.
+
+- Afterwards xdp_do_redirect() is invoked and accesses bpf_redirect_info
+ and it may also access other per-CPU variables like xskmap_flush_list.
+
+At the very end of the NAPI callback, xdp_do_flush() is invoked which
+does not access bpf_redirect_info but will touch the individual per-CPU
+lists.
+
+The per-CPU variables are only used in the NAPI callback hence disabling
+bottom halves is the only protection mechanism. Users from preemptible
+context (like cpu_map_kthread_run()) explicitly disable bottom halves
+for protections reasons.
+Without locking in local_bh_disable() on PREEMPT_RT this data structure
+requires explicit locking.
+
+PREEMPT_RT has forced-threaded interrupts enabled and every
+NAPI-callback runs in a thread. If each thread has its own data
+structure then locking can be avoided.
+
+Create a struct bpf_net_context which contains struct bpf_redirect_info.
+Define the variable on stack, use bpf_net_ctx_set() to save a pointer to
+it, bpf_net_ctx_clear() removes it again.
+The bpf_net_ctx_set() may nest. For instance a function can be used from
+within NET_RX_SOFTIRQ/ net_rx_action which uses bpf_net_ctx_set() and
+NET_TX_SOFTIRQ which does not. Therefore only the first invocations
+updates the pointer.
+Use bpf_net_ctx_get_ri() as a wrapper to retrieve the current struct
+bpf_redirect_info. The returned data structure is zero initialized to
+ensure nothing is leaked from stack. This is done on first usage of the
+struct. bpf_net_ctx_set() sets bpf_redirect_info::kern_flags to 0 to
+note that initialisation is required. First invocation of
+bpf_net_ctx_get_ri() will memset() the data structure and update
+bpf_redirect_info::kern_flags.
+bpf_redirect_info::nh is excluded from memset because it is only used
+once BPF_F_NEIGH is set which also sets the nh member. The kern_flags is
+moved past nh to exclude it from memset.
+
+The pointer to bpf_net_context is saved task's task_struct. Using
+always the bpf_net_context approach has the advantage that there is
+almost zero differences between PREEMPT_RT and non-PREEMPT_RT builds.
+
+Cc: Andrii Nakryiko <andrii@kernel.org>
+Cc: Eduard Zingerman <eddyz87@gmail.com>
+Cc: Hao Luo <haoluo@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: John Fastabend <john.fastabend@gmail.com>
+Cc: KP Singh <kpsingh@kernel.org>
+Cc: Martin KaFai Lau <martin.lau@linux.dev>
+Cc: Song Liu <song@kernel.org>
+Cc: Stanislav Fomichev <sdf@google.com>
+Cc: Yonghong Song <yonghong.song@linux.dev>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://patch.msgid.link/20240620132727.660738-15-bigeasy@linutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h | 56 ++++++++++++++++++++++++++++++++++--------
+ include/linux/sched.h | 3 +++
+ kernel/bpf/cpumap.c | 3 +++
+ kernel/bpf/devmap.c | 9 ++++++-
+ kernel/fork.c | 1 +
+ net/bpf/test_run.c | 11 ++++++++-
+ net/core/dev.c | 29 +++++++++++++++++++++-
+ net/core/filter.c | 44 +++++++++------------------------
+ net/core/lwt_bpf.c | 3 +++
+ 9 files changed, 114 insertions(+), 45 deletions(-)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 5669da513cd7c..b2dc932fdc35e 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -733,21 +733,59 @@ struct bpf_nh_params {
+ };
+ };
+
++/* flags for bpf_redirect_info kern_flags */
++#define BPF_RI_F_RF_NO_DIRECT BIT(0) /* no napi_direct on return_frame */
++#define BPF_RI_F_RI_INIT BIT(1)
++
+ struct bpf_redirect_info {
+ u64 tgt_index;
+ void *tgt_value;
+ struct bpf_map *map;
+ u32 flags;
+- u32 kern_flags;
+ u32 map_id;
+ enum bpf_map_type map_type;
+ struct bpf_nh_params nh;
++ u32 kern_flags;
+ };
+
+-DECLARE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
++struct bpf_net_context {
++ struct bpf_redirect_info ri;
++};
+
+-/* flags for bpf_redirect_info kern_flags */
+-#define BPF_RI_F_RF_NO_DIRECT BIT(0) /* no napi_direct on return_frame */
++static inline struct bpf_net_context *bpf_net_ctx_set(struct bpf_net_context *bpf_net_ctx)
++{
++ struct task_struct *tsk = current;
++
++ if (tsk->bpf_net_context != NULL)
++ return NULL;
++ bpf_net_ctx->ri.kern_flags = 0;
++
++ tsk->bpf_net_context = bpf_net_ctx;
++ return bpf_net_ctx;
++}
++
++static inline void bpf_net_ctx_clear(struct bpf_net_context *bpf_net_ctx)
++{
++ if (bpf_net_ctx)
++ current->bpf_net_context = NULL;
++}
++
++static inline struct bpf_net_context *bpf_net_ctx_get(void)
++{
++ return current->bpf_net_context;
++}
++
++static inline struct bpf_redirect_info *bpf_net_ctx_get_ri(void)
++{
++ struct bpf_net_context *bpf_net_ctx = bpf_net_ctx_get();
++
++ if (!(bpf_net_ctx->ri.kern_flags & BPF_RI_F_RI_INIT)) {
++ memset(&bpf_net_ctx->ri, 0, offsetof(struct bpf_net_context, ri.nh));
++ bpf_net_ctx->ri.kern_flags |= BPF_RI_F_RI_INIT;
++ }
++
++ return &bpf_net_ctx->ri;
++}
+
+ /* Compute the linear packet data range [data, data_end) which
+ * will be accessed by various program types (cls_bpf, act_bpf,
+@@ -1018,25 +1056,23 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
+ const struct bpf_insn *patch, u32 len);
+ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
+
+-void bpf_clear_redirect_map(struct bpf_map *map);
+-
+ static inline bool xdp_return_frame_no_direct(void)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ return ri->kern_flags & BPF_RI_F_RF_NO_DIRECT;
+ }
+
+ static inline void xdp_set_return_frame_no_direct(void)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ ri->kern_flags |= BPF_RI_F_RF_NO_DIRECT;
+ }
+
+ static inline void xdp_clear_return_frame_no_direct(void)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ ri->kern_flags &= ~BPF_RI_F_RF_NO_DIRECT;
+ }
+@@ -1592,7 +1628,7 @@ static __always_inline long __bpf_xdp_redirect_map(struct bpf_map *map, u64 inde
+ u64 flags, const u64 flag_mask,
+ void *lookup_elem(struct bpf_map *map, u32 key))
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ const u64 action_mask = XDP_ABORTED | XDP_DROP | XDP_PASS | XDP_TX;
+
+ /* Lower bits of the flags are used as return code on lookup failure */
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 76214d7c819de..550d9dd8ceb58 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -53,6 +53,7 @@ struct bio_list;
+ struct blk_plug;
+ struct bpf_local_storage;
+ struct bpf_run_ctx;
++struct bpf_net_context;
+ struct capture_control;
+ struct cfs_rq;
+ struct fs_struct;
+@@ -1506,6 +1507,8 @@ struct task_struct {
+ /* Used for BPF run context */
+ struct bpf_run_ctx *bpf_ctx;
+ #endif
++ /* Used by BPF for per-TASK xdp storage */
++ struct bpf_net_context *bpf_net_context;
+
+ #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
+ unsigned long lowest_stack;
+diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
+index a8e34416e960f..66974bd027109 100644
+--- a/kernel/bpf/cpumap.c
++++ b/kernel/bpf/cpumap.c
+@@ -240,12 +240,14 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
+ int xdp_n, struct xdp_cpumap_stats *stats,
+ struct list_head *list)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int nframes;
+
+ if (!rcpu->prog)
+ return xdp_n;
+
+ rcu_read_lock_bh();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+
+ nframes = cpu_map_bpf_prog_run_xdp(rcpu, frames, xdp_n, stats);
+
+@@ -255,6 +257,7 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
+ if (unlikely(!list_empty(list)))
+ cpu_map_bpf_prog_run_skb(rcpu, list, stats);
+
++ bpf_net_ctx_clear(bpf_net_ctx);
+ rcu_read_unlock_bh(); /* resched point, may call do_softirq() */
+
+ return nframes;
+diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
+index 7f3b34452243c..fbfdfb60db8d7 100644
+--- a/kernel/bpf/devmap.c
++++ b/kernel/bpf/devmap.c
+@@ -196,7 +196,14 @@ static void dev_map_free(struct bpf_map *map)
+ list_del_rcu(&dtab->list);
+ spin_unlock(&dev_map_lock);
+
+- bpf_clear_redirect_map(map);
++ /* bpf_redirect_info->map is assigned in __bpf_xdp_redirect_map()
++ * during NAPI callback and cleared after the XDP redirect. There is no
++ * explicit RCU read section which protects bpf_redirect_info->map but
++ * local_bh_disable() also marks the beginning an RCU section. This
++ * makes the complete softirq callback RCU protected. Thus after
++ * following synchronize_rcu() there no bpf_redirect_info->map == map
++ * assignment.
++ */
+ synchronize_rcu();
+
+ /* Make sure prior __dev_map_entry_free() have completed. */
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 99076dbe27d83..f314bdd7e6108 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2355,6 +2355,7 @@ __latent_entropy struct task_struct *copy_process(
+ RCU_INIT_POINTER(p->bpf_storage, NULL);
+ p->bpf_ctx = NULL;
+ #endif
++ p->bpf_net_context = NULL;
+
+ /* Perform scheduler related setup. Assign this task to a CPU. */
+ retval = sched_fork(clone_flags, p);
+diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
+index 36ae54f57bf57..a6d7f790cdda8 100644
+--- a/net/bpf/test_run.c
++++ b/net/bpf/test_run.c
+@@ -283,9 +283,10 @@ static int xdp_recv_frames(struct xdp_frame **frames, int nframes,
+ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+ u32 repeat)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int err = 0, act, ret, i, nframes = 0, batch_sz;
+ struct xdp_frame **frames = xdp->frames;
++ struct bpf_redirect_info *ri;
+ struct xdp_page_head *head;
+ struct xdp_frame *frm;
+ bool redirect = false;
+@@ -295,6 +296,8 @@ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+ batch_sz = min_t(u32, repeat, xdp->batch_size);
+
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++ ri = bpf_net_ctx_get_ri();
+ xdp_set_return_frame_no_direct();
+
+ for (i = 0; i < batch_sz; i++) {
+@@ -359,6 +362,7 @@ static int xdp_test_run_batch(struct xdp_test_data *xdp, struct bpf_prog *prog,
+ }
+
+ xdp_clear_return_frame_no_direct();
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+ return err;
+ }
+@@ -394,6 +398,7 @@ static int bpf_test_run_xdp_live(struct bpf_prog *prog, struct xdp_buff *ctx,
+ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
+ u32 *retval, u32 *time, bool xdp)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ struct bpf_prog_array_item item = {.prog = prog};
+ struct bpf_run_ctx *old_ctx;
+ struct bpf_cg_run_ctx run_ctx;
+@@ -419,10 +424,14 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
+ do {
+ run_ctx.prog_item = &item;
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+ if (xdp)
+ *retval = bpf_prog_run_xdp(prog, ctx);
+ else
+ *retval = bpf_prog_run(prog, ctx);
++
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+ } while (bpf_test_timer_continue(&t, 1, repeat, &ret, time));
+ bpf_reset_run_ctx(old_ctx);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 2b4819b610b8a..195aa4d488bec 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4029,10 +4029,13 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+ {
+ struct bpf_mprog_entry *entry = rcu_dereference_bh(skb->dev->tcx_ingress);
+ enum skb_drop_reason drop_reason = SKB_DROP_REASON_TC_INGRESS;
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int sch_ret;
+
+ if (!entry)
+ return skb;
++
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ if (*pt_prev) {
+ *ret = deliver_skb(skb, *pt_prev, orig_dev);
+ *pt_prev = NULL;
+@@ -4061,10 +4064,12 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+ break;
+ }
+ *ret = NET_RX_SUCCESS;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ case TC_ACT_SHOT:
+ kfree_skb_reason(skb, drop_reason);
+ *ret = NET_RX_DROP;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ /* used by tc_run */
+ case TC_ACT_STOLEN:
+@@ -4074,8 +4079,10 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
+ fallthrough;
+ case TC_ACT_CONSUMED:
+ *ret = NET_RX_SUCCESS;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ }
++ bpf_net_ctx_clear(bpf_net_ctx);
+
+ return skb;
+ }
+@@ -4085,11 +4092,14 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+ {
+ struct bpf_mprog_entry *entry = rcu_dereference_bh(dev->tcx_egress);
+ enum skb_drop_reason drop_reason = SKB_DROP_REASON_TC_EGRESS;
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int sch_ret;
+
+ if (!entry)
+ return skb;
+
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+ /* qdisc_skb_cb(skb)->pkt_len & tcx_set_ingress() was
+ * already set by the caller.
+ */
+@@ -4105,10 +4115,12 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+ /* No need to push/pop skb's mac_header here on egress! */
+ skb_do_redirect(skb);
+ *ret = NET_XMIT_SUCCESS;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ case TC_ACT_SHOT:
+ kfree_skb_reason(skb, drop_reason);
+ *ret = NET_XMIT_DROP;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ /* used by tc_run */
+ case TC_ACT_STOLEN:
+@@ -4118,8 +4130,10 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
+ fallthrough;
+ case TC_ACT_CONSUMED:
+ *ret = NET_XMIT_SUCCESS;
++ bpf_net_ctx_clear(bpf_net_ctx);
+ return NULL;
+ }
++ bpf_net_ctx_clear(bpf_net_ctx);
+
+ return skb;
+ }
+@@ -6301,6 +6315,7 @@ enum {
+ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+ unsigned flags, u16 budget)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ bool skip_schedule = false;
+ unsigned long timeout;
+ int rc;
+@@ -6318,6 +6333,7 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+ clear_bit(NAPI_STATE_IN_BUSY_POLL, &napi->state);
+
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+
+ if (flags & NAPI_F_PREFER_BUSY_POLL) {
+ napi->defer_hard_irqs_count = READ_ONCE(napi->dev->napi_defer_hard_irqs);
+@@ -6340,6 +6356,7 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock,
+ netpoll_poll_unlock(have_poll_lock);
+ if (rc == budget)
+ __busy_poll_stop(napi, skip_schedule);
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+ }
+
+@@ -6349,6 +6366,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+ {
+ unsigned long start_time = loop_end ? busy_loop_current_time() : 0;
+ int (*napi_poll)(struct napi_struct *napi, int budget);
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ void *have_poll_lock = NULL;
+ struct napi_struct *napi;
+
+@@ -6367,6 +6385,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+ int work = 0;
+
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ if (!napi_poll) {
+ unsigned long val = READ_ONCE(napi->state);
+
+@@ -6397,6 +6416,7 @@ static void __napi_busy_loop(unsigned int napi_id,
+ __NET_ADD_STATS(dev_net(napi->dev),
+ LINUX_MIB_BUSYPOLLRXPACKETS, work);
+ skb_defer_free_flush(this_cpu_ptr(&softnet_data));
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+
+ if (!loop_end || loop_end(loop_end_arg, start_time))
+@@ -6824,6 +6844,7 @@ static int napi_thread_wait(struct napi_struct *napi)
+
+ static void napi_threaded_poll_loop(struct napi_struct *napi)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ struct softnet_data *sd;
+ unsigned long last_qs = jiffies;
+
+@@ -6832,6 +6853,8 @@ static void napi_threaded_poll_loop(struct napi_struct *napi)
+ void *have;
+
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
++
+ sd = this_cpu_ptr(&softnet_data);
+ sd->in_napi_threaded_poll = true;
+
+@@ -6847,6 +6870,7 @@ static void napi_threaded_poll_loop(struct napi_struct *napi)
+ net_rps_action_and_irq_enable(sd);
+ }
+ skb_defer_free_flush(sd);
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+
+ if (!repoll)
+@@ -6872,10 +6896,12 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
+ struct softnet_data *sd = this_cpu_ptr(&softnet_data);
+ unsigned long time_limit = jiffies +
+ usecs_to_jiffies(READ_ONCE(net_hotdata.netdev_budget_usecs));
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int budget = READ_ONCE(net_hotdata.netdev_budget);
+ LIST_HEAD(list);
+ LIST_HEAD(repoll);
+
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ start:
+ sd->in_net_rx_action = true;
+ local_irq_disable();
+@@ -6928,7 +6954,8 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
+ sd->in_net_rx_action = false;
+
+ net_rps_action_and_irq_enable(sd);
+-end:;
++end:
++ bpf_net_ctx_clear(bpf_net_ctx);
+ }
+
+ struct netdev_adjacent {
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 110692c1dd95a..05296c289cefb 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -2476,9 +2476,6 @@ static const struct bpf_func_proto bpf_clone_redirect_proto = {
+ .arg3_type = ARG_ANYTHING,
+ };
+
+-DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
+-EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
+-
+ static struct net_device *skb_get_peer_dev(struct net_device *dev)
+ {
+ const struct net_device_ops *ops = dev->netdev_ops;
+@@ -2491,7 +2488,7 @@ static struct net_device *skb_get_peer_dev(struct net_device *dev)
+
+ int skb_do_redirect(struct sk_buff *skb)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ struct net *net = dev_net(skb->dev);
+ struct net_device *dev;
+ u32 flags = ri->flags;
+@@ -2524,7 +2521,7 @@ int skb_do_redirect(struct sk_buff *skb)
+
+ BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))
+ return TC_ACT_SHOT;
+@@ -2545,7 +2542,7 @@ static const struct bpf_func_proto bpf_redirect_proto = {
+
+ BPF_CALL_2(bpf_redirect_peer, u32, ifindex, u64, flags)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ if (unlikely(flags))
+ return TC_ACT_SHOT;
+@@ -2567,7 +2564,7 @@ static const struct bpf_func_proto bpf_redirect_peer_proto = {
+ BPF_CALL_4(bpf_redirect_neigh, u32, ifindex, struct bpf_redir_neigh *, params,
+ int, plen, u64, flags)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ if (unlikely((plen && plen < sizeof(*params)) || flags))
+ return TC_ACT_SHOT;
+@@ -4300,30 +4297,13 @@ void xdp_do_check_flushed(struct napi_struct *napi)
+ }
+ #endif
+
+-void bpf_clear_redirect_map(struct bpf_map *map)
+-{
+- struct bpf_redirect_info *ri;
+- int cpu;
+-
+- for_each_possible_cpu(cpu) {
+- ri = per_cpu_ptr(&bpf_redirect_info, cpu);
+- /* Avoid polluting remote cacheline due to writes if
+- * not needed. Once we pass this test, we need the
+- * cmpxchg() to make sure it hasn't been changed in
+- * the meantime by remote CPU.
+- */
+- if (unlikely(READ_ONCE(ri->map) == map))
+- cmpxchg(&ri->map, map, NULL);
+- }
+-}
+-
+ DEFINE_STATIC_KEY_FALSE(bpf_master_redirect_enabled_key);
+ EXPORT_SYMBOL_GPL(bpf_master_redirect_enabled_key);
+
+ u32 xdp_master_redirect(struct xdp_buff *xdp)
+ {
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ struct net_device *master, *slave;
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
+
+ master = netdev_master_upper_dev_get_rcu(xdp->rxq->dev);
+ slave = master->netdev_ops->ndo_xdp_get_xmit_slave(master, xdp);
+@@ -4395,7 +4375,7 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+ map = READ_ONCE(ri->map);
+
+ /* The map pointer is cleared when the map is being torn
+- * down by bpf_clear_redirect_map()
++ * down by dev_map_free()
+ */
+ if (unlikely(!map)) {
+ err = -ENOENT;
+@@ -4440,7 +4420,7 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
+ struct bpf_prog *xdp_prog)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ enum bpf_map_type map_type = ri->map_type;
+
+ if (map_type == BPF_MAP_TYPE_XSKMAP)
+@@ -4454,7 +4434,7 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect);
+ int xdp_do_redirect_frame(struct net_device *dev, struct xdp_buff *xdp,
+ struct xdp_frame *xdpf, struct bpf_prog *xdp_prog)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ enum bpf_map_type map_type = ri->map_type;
+
+ if (map_type == BPF_MAP_TYPE_XSKMAP)
+@@ -4471,7 +4451,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ enum bpf_map_type map_type, u32 map_id,
+ u32 flags)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ struct bpf_map *map;
+ int err;
+
+@@ -4483,7 +4463,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ map = READ_ONCE(ri->map);
+
+ /* The map pointer is cleared when the map is being torn
+- * down by bpf_clear_redirect_map()
++ * down by dev_map_free()
+ */
+ if (unlikely(!map)) {
+ err = -ENOENT;
+@@ -4525,7 +4505,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+ struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+ enum bpf_map_type map_type = ri->map_type;
+ void *fwd = ri->tgt_value;
+ u32 map_id = ri->map_id;
+@@ -4561,7 +4541,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+
+ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
+ {
+- struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
++ struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
+
+ if (unlikely(flags))
+ return XDP_ABORTED;
+diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
+index 4a0797f0a154b..5350dce2e52d6 100644
+--- a/net/core/lwt_bpf.c
++++ b/net/core/lwt_bpf.c
+@@ -38,6 +38,7 @@ static inline struct bpf_lwt *bpf_lwt_lwtunnel(struct lwtunnel_state *lwt)
+ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+ struct dst_entry *dst, bool can_redirect)
+ {
++ struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
+ int ret;
+
+ /* Migration disable and BH disable are needed to protect per-cpu
+@@ -45,6 +46,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+ */
+ migrate_disable();
+ local_bh_disable();
++ bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx);
+ bpf_compute_data_pointers(skb);
+ ret = bpf_prog_run_save_cb(lwt->prog, skb);
+
+@@ -77,6 +79,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
+ break;
+ }
+
++ bpf_net_ctx_clear(bpf_net_ctx);
+ local_bh_enable();
+ migrate_enable();
+
+--
+2.43.0
+
--- /dev/null
+From aa4bc1c51cd7d1ddf365ba2035b0b3df1c672833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 12:38:56 +0800
+Subject: net/smc: add the max value of fallback reason count
+
+From: Zhengchao Shao <shaozhengchao@huawei.com>
+
+[ Upstream commit d27a835f41d947f62e6a95e89ba523299c9e6437 ]
+
+The number of fallback reasons defined in the smc_clc.h file has reached
+36. For historical reasons, some are no longer quoted, and there's 33
+actually in use. So, add the max value of fallback reason count to 36.
+
+Fixes: 6ac1e6563f59 ("net/smc: support smc v2.x features validate")
+Fixes: 7f0620b9940b ("net/smc: support max connections per lgr negotiation")
+Fixes: 69b888e3bb4b ("net/smc: support max links per lgr negotiation in clc handshake")
+Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
+Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
+Reviewed-by: D. Wythe <alibuda@linux.alibaba.com>
+Link: https://patch.msgid.link/20240805043856.565677-1-shaozhengchao@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_stats.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_stats.h b/net/smc/smc_stats.h
+index 9d32058db2b5d..e19177ce40923 100644
+--- a/net/smc/smc_stats.h
++++ b/net/smc/smc_stats.h
+@@ -19,7 +19,7 @@
+
+ #include "smc_clc.h"
+
+-#define SMC_MAX_FBACK_RSN_CNT 30
++#define SMC_MAX_FBACK_RSN_CNT 36
+
+ enum {
+ SMC_BUF_8K,
+--
+2.43.0
+
--- /dev/null
+From 517a8082696b6dc917e704b8aaa5fe512ef1924f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 20:14:59 +0200
+Subject: net: stmmac: qcom-ethqos: enable SGMII loopback during DMA reset on
+ sa8775p-ride-r3
+
+From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+[ Upstream commit 3c466d6537b99f801b3f68af3d8124d4312437a0 ]
+
+On sa8775p-ride-r3 the RX clocks from the AQR115C PHY are not available at
+the time of the DMA reset. We can however extract the RX clock from the
+internal SERDES block. Once the link is up, we can revert to the
+previous state.
+
+The AQR115C PHY doesn't support in-band signalling so we can count on
+getting the link up notification and safely reuse existing callbacks
+which are already used by another HW quirk workaround which enables the
+functional clock to avoid a DMA reset due to timeout.
+
+Only enable loopback on revision 3 of the board - check the phy_mode to
+make sure.
+
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20240703181500.28491-3-brgl@bgdev.pl
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../stmicro/stmmac/dwmac-qcom-ethqos.c | 23 +++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+index 466c4002f00d4..3a7f3a8b06718 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+@@ -21,6 +21,7 @@
+ #define RGMII_IO_MACRO_CONFIG2 0x1C
+ #define RGMII_IO_MACRO_DEBUG1 0x20
+ #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28
++#define EMAC_WRAPPER_SGMII_PHY_CNTRL1 0xf4
+
+ /* RGMII_IO_MACRO_CONFIG fields */
+ #define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
+@@ -79,6 +80,9 @@
+ #define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14)
+ #define ETHQOS_MAC_CTRL_PORT_SEL BIT(15)
+
++/* EMAC_WRAPPER_SGMII_PHY_CNTRL1 bits */
++#define SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN BIT(3)
++
+ #define SGMII_10M_RX_CLK_DVDR 0x31
+
+ struct ethqos_emac_por {
+@@ -95,6 +99,7 @@ struct ethqos_emac_driver_data {
+ bool has_integrated_pcs;
+ u32 dma_addr_width;
+ struct dwmac4_addrs dwmac4_addrs;
++ bool needs_sgmii_loopback;
+ };
+
+ struct qcom_ethqos {
+@@ -114,6 +119,7 @@ struct qcom_ethqos {
+ unsigned int num_por;
+ bool rgmii_config_loopback_en;
+ bool has_emac_ge_3;
++ bool needs_sgmii_loopback;
+ };
+
+ static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
+@@ -191,8 +197,22 @@ ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed)
+ clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate);
+ }
+
++static void
++qcom_ethqos_set_sgmii_loopback(struct qcom_ethqos *ethqos, bool enable)
++{
++ if (!ethqos->needs_sgmii_loopback ||
++ ethqos->phy_mode != PHY_INTERFACE_MODE_2500BASEX)
++ return;
++
++ rgmii_updatel(ethqos,
++ SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN,
++ enable ? SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN : 0,
++ EMAC_WRAPPER_SGMII_PHY_CNTRL1);
++}
++
+ static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
+ {
++ qcom_ethqos_set_sgmii_loopback(ethqos, true);
+ rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
+ RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
+ }
+@@ -277,6 +297,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
+ .has_emac_ge_3 = true,
+ .link_clk_name = "phyaux",
+ .has_integrated_pcs = true,
++ .needs_sgmii_loopback = true,
+ .dma_addr_width = 36,
+ .dwmac4_addrs = {
+ .dma_chan = 0x00008100,
+@@ -674,6 +695,7 @@ static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mo
+ {
+ struct qcom_ethqos *ethqos = priv;
+
++ qcom_ethqos_set_sgmii_loopback(ethqos, false);
+ ethqos->speed = speed;
+ ethqos_update_link_clk(ethqos, speed);
+ ethqos_configure(ethqos);
+@@ -809,6 +831,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
+ ethqos->num_por = data->num_por;
+ ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
+ ethqos->has_emac_ge_3 = data->has_emac_ge_3;
++ ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback;
+
+ ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii");
+ if (IS_ERR(ethqos->link_clk))
+--
+2.43.0
+
--- /dev/null
+From 9bd3cba08d7a9f2686e4c4b80a515d8ce29946ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 15:55:12 +0200
+Subject: net: usb: qmi_wwan: fix memory leak for not ip packets
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Daniele Palmas <dnlplm@gmail.com>
+
+[ Upstream commit 7ab107544b777c3bd7feb9fe447367d8edd5b202 ]
+
+Free the unused skb when not ip packets arrive.
+
+Fixes: c6adf77953bc ("net: usb: qmi_wwan: add qmap mux protocol support")
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/qmi_wwan.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 386d62769dedb..cfda32047cffb 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -201,6 +201,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ break;
+ default:
+ /* not ip - do not know what to do */
++ kfree_skb(skbn);
+ goto skip;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 88109c7f7caabe4f2a816e8918b2bacc920ddf76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 11:59:04 -0700
+Subject: nvme: apple: fix device reference counting
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ Upstream commit b9ecbfa45516182cd062fecd286db7907ba84210 ]
+
+Drivers must call nvme_uninit_ctrl after a successful nvme_init_ctrl.
+Split the allocation side out to make the error handling boundary easier
+to navigate. The apple driver had been doing this wrong, leaking the
+controller device memory on a tagset failure.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/apple.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
+index 0cfa39361d3b6..25ecc1a005c5a 100644
+--- a/drivers/nvme/host/apple.c
++++ b/drivers/nvme/host/apple.c
+@@ -1388,7 +1388,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
+ mempool_destroy(data);
+ }
+
+-static int apple_nvme_probe(struct platform_device *pdev)
++static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct apple_nvme *anv;
+@@ -1396,7 +1396,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
+
+ anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
+ if (!anv)
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+
+ anv->dev = get_device(dev);
+ anv->adminq.is_adminq = true;
+@@ -1516,10 +1516,26 @@ static int apple_nvme_probe(struct platform_device *pdev)
+ goto put_dev;
+ }
+
++ return anv;
++put_dev:
++ put_device(anv->dev);
++ return ERR_PTR(ret);
++}
++
++static int apple_nvme_probe(struct platform_device *pdev)
++{
++ struct apple_nvme *anv;
++ int ret;
++
++ anv = apple_nvme_alloc(pdev);
++ if (IS_ERR(anv))
++ return PTR_ERR(anv);
++
+ anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
+ if (IS_ERR(anv->ctrl.admin_q)) {
+ ret = -ENOMEM;
+- goto put_dev;
++ anv->ctrl.admin_q = NULL;
++ goto out_uninit_ctrl;
+ }
+
+ nvme_reset_ctrl(&anv->ctrl);
+@@ -1527,8 +1543,9 @@ static int apple_nvme_probe(struct platform_device *pdev)
+
+ return 0;
+
+-put_dev:
+- put_device(anv->dev);
++out_uninit_ctrl:
++ nvme_uninit_ctrl(&anv->ctrl);
++ nvme_put_ctrl(&anv->ctrl);
+ return ret;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From cb4eaff98e9f6c9bb7b03ac27c7e4561423684e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jun 2024 08:55:01 +0900
+Subject: PCI: Add Edimax Vendor ID to pci_ids.h
+
+From: FUJITA Tomonori <fujita.tomonori@gmail.com>
+
+[ Upstream commit eee5528890d54b22b46f833002355a5ee94c3bb4 ]
+
+Add the Edimax Vendor ID (0x1432) for an ethernet driver for Tehuti
+Networks TN40xx chips. This ID can be used for Realtek 8180 and Ralink
+rt28xx wireless drivers.
+
+Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Link: https://patch.msgid.link/20240623235507.108147-2-fujita.tomonori@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/pci_ids.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 942a587bb97e3..677aea20d3e11 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2126,6 +2126,8 @@
+
+ #define PCI_VENDOR_ID_CHELSIO 0x1425
+
++#define PCI_VENDOR_ID_EDIMAX 0x1432
++
+ #define PCI_VENDOR_ID_ADLINK 0x144a
+
+ #define PCI_VENDOR_ID_SAMSUNG 0x144d
+--
+2.43.0
+
--- /dev/null
+From 7aea1d980841c78c46186af0ade988b6db7de3ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 12:16:14 +0200
+Subject: perf/x86/amd: Use try_cmpxchg() in events/amd/{un,}core.c
+
+From: Uros Bizjak <ubizjak@gmail.com>
+
+[ Upstream commit cd84351c8c1baec86342d784feb884ace007d51c ]
+
+Replace this pattern in events/amd/{un,}core.c:
+
+ cmpxchg(*ptr, old, new) == old
+
+... with the simpler and faster:
+
+ try_cmpxchg(*ptr, &old, new)
+
+The x86 CMPXCHG instruction returns success in the ZF flag, so this change
+saves a compare after the CMPXCHG.
+
+No functional change intended.
+
+Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20240425101708.5025-1-ubizjak@gmail.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/core.c | 4 +++-
+ arch/x86/events/amd/uncore.c | 8 ++++++--
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 1fc4ce44e743c..18bfe3451f3aa 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -433,7 +433,9 @@ static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+ * when we come here
+ */
+ for (i = 0; i < x86_pmu.num_counters; i++) {
+- if (cmpxchg(nb->owners + i, event, NULL) == event)
++ struct perf_event *tmp = event;
++
++ if (try_cmpxchg(nb->owners + i, &tmp, NULL))
+ break;
+ }
+ }
+diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
+index 5a4bfe9aea237..0bfde2ea5cb8c 100644
+--- a/arch/x86/events/amd/uncore.c
++++ b/arch/x86/events/amd/uncore.c
+@@ -162,7 +162,9 @@ static int amd_uncore_add(struct perf_event *event, int flags)
+ /* if not, take the first available counter */
+ hwc->idx = -1;
+ for (i = 0; i < pmu->num_counters; i++) {
+- if (cmpxchg(&ctx->events[i], NULL, event) == NULL) {
++ struct perf_event *tmp = NULL;
++
++ if (try_cmpxchg(&ctx->events[i], &tmp, event)) {
+ hwc->idx = i;
+ break;
+ }
+@@ -196,7 +198,9 @@ static void amd_uncore_del(struct perf_event *event, int flags)
+ event->pmu->stop(event, PERF_EF_UPDATE);
+
+ for (i = 0; i < pmu->num_counters; i++) {
+- if (cmpxchg(&ctx->events[i], event, NULL) == event)
++ struct perf_event *tmp = event;
++
++ if (try_cmpxchg(&ctx->events[i], &tmp, NULL))
+ break;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From ade587b6d2d92bc9bed6cb7147eb464f4066b969 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 06:09:28 +0800
+Subject: perf/x86: Fix smp_processor_id()-in-preemptible warnings
+
+From: Li Huafei <lihuafei1@huawei.com>
+
+[ Upstream commit f73cefa3b72eaa90abfc43bf6d68137ba059d4b1 ]
+
+The following bug was triggered on a system built with
+CONFIG_DEBUG_PREEMPT=y:
+
+ # echo p > /proc/sysrq-trigger
+
+ BUG: using smp_processor_id() in preemptible [00000000] code: sh/117
+ caller is perf_event_print_debug+0x1a/0x4c0
+ CPU: 3 UID: 0 PID: 117 Comm: sh Not tainted 6.11.0-rc1 #109
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x4f/0x60
+ check_preemption_disabled+0xc8/0xd0
+ perf_event_print_debug+0x1a/0x4c0
+ __handle_sysrq+0x140/0x180
+ write_sysrq_trigger+0x61/0x70
+ proc_reg_write+0x4e/0x70
+ vfs_write+0xd0/0x430
+ ? handle_mm_fault+0xc8/0x240
+ ksys_write+0x9c/0xd0
+ do_syscall_64+0x96/0x190
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+This is because the commit d4b294bf84db ("perf/x86: Hybrid PMU support
+for counters") took smp_processor_id() outside the irq critical section.
+If a preemption occurs in perf_event_print_debug() and the task is
+migrated to another cpu, we may get incorrect pmu debug information.
+Move smp_processor_id() back inside the irq critical section to fix this
+issue.
+
+Fixes: d4b294bf84db ("perf/x86: Hybrid PMU support for counters")
+Signed-off-by: Li Huafei <lihuafei1@huawei.com>
+Reviewed-and-tested-by: K Prateek Nayak <kprateek.nayak@amd.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240729220928.325449-1-lihuafei1@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/core.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index 0c51cfdf76092..83d12dd3f831a 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -1521,20 +1521,23 @@ static void x86_pmu_start(struct perf_event *event, int flags)
+ void perf_event_print_debug(void)
+ {
+ u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
++ unsigned long *cntr_mask, *fixed_cntr_mask;
++ struct event_constraint *pebs_constraints;
++ struct cpu_hw_events *cpuc;
+ u64 pebs, debugctl;
+- int cpu = smp_processor_id();
+- struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+- unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
+- unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+- struct event_constraint *pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+- unsigned long flags;
+- int idx;
++ int cpu, idx;
++
++ guard(irqsave)();
++
++ cpu = smp_processor_id();
++ cpuc = &per_cpu(cpu_hw_events, cpu);
++ cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++ fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
++ pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+
+ if (!*(u64 *)cntr_mask)
+ return;
+
+- local_irq_save(flags);
+-
+ if (x86_pmu.version >= 2) {
+ rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
+ rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+@@ -1578,7 +1581,6 @@ void perf_event_print_debug(void)
+ pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
+ cpu, idx, pmc_count);
+ }
+- local_irq_restore(flags);
+ }
+
+ void x86_pmu_stop(struct perf_event *event, int flags)
+--
+2.43.0
+
--- /dev/null
+From d7646c3bd205da17c72cbe83eb093cfb2a46cf06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jun 2024 11:17:57 +0800
+Subject: perf/x86/intel/cstate: Add Arrowlake support
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit a31000753d41305d2fb7faa8cc80a8edaeb7b56b ]
+
+Like Alderlake, Arrowlake supports CC1/CC6/CC7 and PC2/PC3/PC6/PC8/PC10.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240628031758.43103-3-rui.zhang@intel.com
+Stable-dep-of: b1d0e15c8725 ("perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index dd18320558914..cb165af1a1bfd 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -41,7 +41,7 @@
+ * MSR_CORE_C1_RES: CORE C1 Residency Counter
+ * perf code: 0x00
+ * Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
+- * MTL,SRF,GRR
++ * MTL,SRF,GRR,ARL
+ * Scope: Core (each processor core has a MSR)
+ * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
+ * perf code: 0x01
+@@ -53,30 +53,31 @@
+ * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+ * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+ * TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- * GRR
++ * GRR,ARL
+ * Scope: Core
+ * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
+ * perf code: 0x03
+ * Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
+- * ICL,TGL,RKL,ADL,RPL,MTL
++ * ICL,TGL,RKL,ADL,RPL,MTL,ARL
+ * Scope: Core
+ * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter.
+ * perf code: 0x00
+ * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+ * KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- * RPL,SPR,MTL
++ * RPL,SPR,MTL,ARL
+ * Scope: Package (physical package)
+ * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter.
+ * perf code: 0x01
+ * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
+ * GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
+- * ADL,RPL,MTL
++ * ADL,RPL,MTL,ARL
+ * Scope: Package (physical package)
+ * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter.
+ * perf code: 0x02
+ * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+ * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+- * TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF
++ * TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
++ * ARL
+ * Scope: Package (physical package)
+ * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter.
+ * perf code: 0x03
+@@ -86,7 +87,7 @@
+ * MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter.
+ * perf code: 0x04
+ * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL,RKL,
+- * ADL,RPL,MTL
++ * ADL,RPL,MTL,ARL
+ * Scope: Package (physical package)
+ * MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter.
+ * perf code: 0x05
+@@ -95,7 +96,7 @@
+ * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
+ * perf code: 0x06
+ * Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
+- * TNT,RKL,ADL,RPL,MTL
++ * TNT,RKL,ADL,RPL,MTL,ARL
+ * Scope: Package (physical package)
+ * MSR_MODULE_C6_RES_MS: Module C6 Residency Counter.
+ * perf code: 0x00
+@@ -760,6 +761,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
+ X86_MATCH_VFM(INTEL_RAPTORLAKE_S, &adl_cstates),
+ X86_MATCH_VFM(INTEL_METEORLAKE, &adl_cstates),
+ X86_MATCH_VFM(INTEL_METEORLAKE_L, &adl_cstates),
++ X86_MATCH_VFM(INTEL_ARROWLAKE, &adl_cstates),
++ X86_MATCH_VFM(INTEL_ARROWLAKE_H, &adl_cstates),
++ X86_MATCH_VFM(INTEL_ARROWLAKE_U, &adl_cstates),
+ { },
+ };
+ MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
+--
+2.43.0
+
--- /dev/null
+From 2628b6f24b07d5d5fc198874a932a5f046ff60ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jun 2024 11:17:58 +0800
+Subject: perf/x86/intel/cstate: Add Lunarlake support
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit 26579860fbd5129e18de9d6fa0751a48420b26b7 ]
+
+Compared with previous client platforms, PC8 is removed from Lunarlake.
+It supports CC1/CC6/CC7 and PC2/PC3/PC6/PC10 residency counters.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20240628031758.43103-4-rui.zhang@intel.com
+Stable-dep-of: b1d0e15c8725 ("perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index cb165af1a1bfd..be58cfb012dd1 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -41,7 +41,7 @@
+ * MSR_CORE_C1_RES: CORE C1 Residency Counter
+ * perf code: 0x00
+ * Available model: SLM,AMT,GLM,CNL,ICX,TNT,ADL,RPL
+- * MTL,SRF,GRR,ARL
++ * MTL,SRF,GRR,ARL,LNL
+ * Scope: Core (each processor core has a MSR)
+ * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
+ * perf code: 0x01
+@@ -53,31 +53,31 @@
+ * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+ * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+ * TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- * GRR,ARL
++ * GRR,ARL,LNL
+ * Scope: Core
+ * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
+ * perf code: 0x03
+ * Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
+- * ICL,TGL,RKL,ADL,RPL,MTL,ARL
++ * ICL,TGL,RKL,ADL,RPL,MTL,ARL,LNL
+ * Scope: Core
+ * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter.
+ * perf code: 0x00
+ * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+ * KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- * RPL,SPR,MTL,ARL
++ * RPL,SPR,MTL,ARL,LNL
+ * Scope: Package (physical package)
+ * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter.
+ * perf code: 0x01
+ * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
+ * GLM,CNL,KBL,CML,ICL,TGL,TNT,RKL,
+- * ADL,RPL,MTL,ARL
++ * ADL,RPL,MTL,ARL,LNL
+ * Scope: Package (physical package)
+ * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter.
+ * perf code: 0x02
+ * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+ * SKL,KNL,GLM,CNL,KBL,CML,ICL,ICX,
+ * TGL,TNT,RKL,ADL,RPL,SPR,MTL,SRF,
+- * ARL
++ * ARL,LNL
+ * Scope: Package (physical package)
+ * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter.
+ * perf code: 0x03
+@@ -96,7 +96,7 @@
+ * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
+ * perf code: 0x06
+ * Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
+- * TNT,RKL,ADL,RPL,MTL,ARL
++ * TNT,RKL,ADL,RPL,MTL,ARL,LNL
+ * Scope: Package (physical package)
+ * MSR_MODULE_C6_RES_MS: Module C6 Residency Counter.
+ * perf code: 0x00
+@@ -641,6 +641,17 @@ static const struct cstate_model adl_cstates __initconst = {
+ BIT(PERF_CSTATE_PKG_C10_RES),
+ };
+
++static const struct cstate_model lnl_cstates __initconst = {
++ .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
++ BIT(PERF_CSTATE_CORE_C6_RES) |
++ BIT(PERF_CSTATE_CORE_C7_RES),
++
++ .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
++ BIT(PERF_CSTATE_PKG_C3_RES) |
++ BIT(PERF_CSTATE_PKG_C6_RES) |
++ BIT(PERF_CSTATE_PKG_C10_RES),
++};
++
+ static const struct cstate_model slm_cstates __initconst = {
+ .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
+ BIT(PERF_CSTATE_CORE_C6_RES),
+@@ -764,6 +775,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
+ X86_MATCH_VFM(INTEL_ARROWLAKE, &adl_cstates),
+ X86_MATCH_VFM(INTEL_ARROWLAKE_H, &adl_cstates),
+ X86_MATCH_VFM(INTEL_ARROWLAKE_U, &adl_cstates),
++ X86_MATCH_VFM(INTEL_LUNARLAKE_M, &lnl_cstates),
+ { },
+ };
+ MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
+--
+2.43.0
+
--- /dev/null
+From 30b9430ff2763c3d7e3b4af439b883fe560abdc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 11:16:09 +0800
+Subject: perf/x86/intel/cstate: Add pkg C2 residency counter for Sierra Forest
+
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+
+[ Upstream commit b1d0e15c8725d21a73c22c099418a63940261041 ]
+
+Package C2 residency counter is also available on Sierra Forest.
+So add it support in srf_cstates.
+
+Fixes: 3877d55a0db2 ("perf/x86/intel/cstate: Add Sierra Forest support")
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
+Tested-by: Wendy Wang <wendy.wang@intel.com>
+Link: https://lore.kernel.org/r/20240717031609.74513-1-zhenyuw@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/cstate.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
+index be58cfb012dd1..9f116dfc47284 100644
+--- a/arch/x86/events/intel/cstate.c
++++ b/arch/x86/events/intel/cstate.c
+@@ -64,7 +64,7 @@
+ * perf code: 0x00
+ * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
+ * KBL,CML,ICL,ICX,TGL,TNT,RKL,ADL,
+- * RPL,SPR,MTL,ARL,LNL
++ * RPL,SPR,MTL,ARL,LNL,SRF
+ * Scope: Package (physical package)
+ * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter.
+ * perf code: 0x01
+@@ -693,7 +693,8 @@ static const struct cstate_model srf_cstates __initconst = {
+ .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
+ BIT(PERF_CSTATE_CORE_C6_RES),
+
+- .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES),
++ .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
++ BIT(PERF_CSTATE_PKG_C6_RES),
+
+ .module_events = BIT(PERF_CSTATE_MODULE_C6_RES),
+ };
+--
+2.43.0
+
--- /dev/null
+From 34d459e35c1ad1e14de2d13bcae9cebe8a72f8cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 07:35:33 -0700
+Subject: perf/x86/intel: Support the PEBS event mask
+
+From: Kan Liang <kan.liang@linux.intel.com>
+
+[ Upstream commit a23eb2fc1d818cdac9b31f032842d55483a6a040 ]
+
+The current perf assumes that the counters that support PEBS are
+contiguous. But it's not guaranteed with the new leaf 0x23 introduced.
+The counters are enumerated with a counter mask. There may be holes in
+the counter mask for future platforms or in a virtualization
+environment.
+
+Store the PEBS event mask rather than the maximum number of PEBS
+counters in the x86 PMU structures.
+
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Andi Kleen <ak@linux.intel.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Link: https://lkml.kernel.org/r/20240626143545.480761-2-kan.liang@linux.intel.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/core.c | 8 ++++----
+ arch/x86/events/intel/ds.c | 15 ++++++++-------
+ arch/x86/events/perf_event.h | 15 +++++++++++++--
+ arch/x86/include/asm/intel_ds.h | 1 +
+ 4 files changed, 26 insertions(+), 13 deletions(-)
+
+diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
+index 101a21fe9c213..2175ca2fdba47 100644
+--- a/arch/x86/events/intel/core.c
++++ b/arch/x86/events/intel/core.c
+@@ -4728,7 +4728,7 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+ {
+ intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
+ &pmu->intel_ctrl, (1ULL << pmu->num_counters_fixed) - 1);
+- pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+ pmu->unconstrained = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+ 0, pmu->num_counters, 0, 0);
+@@ -6070,7 +6070,7 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
+
+ pmu->num_counters = x86_pmu.num_counters;
+ pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+- pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+ pmu->unconstrained = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+ 0, pmu->num_counters, 0, 0);
+@@ -6193,7 +6193,7 @@ __init int intel_pmu_init(void)
+ x86_pmu.events_maskl = ebx.full;
+ x86_pmu.events_mask_len = eax.split.mask_length;
+
+- x86_pmu.max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
++ x86_pmu.pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(x86_pmu.num_counters - 1, 0));
+ x86_pmu.pebs_capable = PEBS_COUNTER_MASK;
+
+ /*
+@@ -6826,7 +6826,7 @@ __init int intel_pmu_init(void)
+ pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+ }
+
+- pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters);
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
+ pmu->unconstrained = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+ 0, pmu->num_counters, 0, 0);
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index 80a4f712217b7..87d3feb9f8fe8 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1137,7 +1137,7 @@ void intel_pmu_pebs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sche
+ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+ {
+ struct debug_store *ds = cpuc->ds;
+- int max_pebs_events = hybrid(cpuc->pmu, max_pebs_events);
++ int max_pebs_events = intel_pmu_max_num_pebs(cpuc->pmu);
+ int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+ u64 threshold;
+ int reserved;
+@@ -2161,6 +2161,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+ void *base, *at, *top;
+ short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+ short error[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
++ int max_pebs_events = intel_pmu_max_num_pebs(NULL);
+ int bit, i, size;
+ u64 mask;
+
+@@ -2172,8 +2173,8 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+
+ ds->pebs_index = ds->pebs_buffer_base;
+
+- mask = (1ULL << x86_pmu.max_pebs_events) - 1;
+- size = x86_pmu.max_pebs_events;
++ mask = x86_pmu.pebs_events_mask;
++ size = max_pebs_events;
+ if (x86_pmu.flags & PMU_FL_PEBS_ALL) {
+ mask |= ((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED;
+ size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed;
+@@ -2212,8 +2213,9 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+ pebs_status = p->status = cpuc->pebs_enabled;
+
+ bit = find_first_bit((unsigned long *)&pebs_status,
+- x86_pmu.max_pebs_events);
+- if (bit >= x86_pmu.max_pebs_events)
++ max_pebs_events);
++
++ if (!(x86_pmu.pebs_events_mask & (1 << bit)))
+ continue;
+
+ /*
+@@ -2271,7 +2273,6 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ {
+ short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+- int max_pebs_events = hybrid(cpuc->pmu, max_pebs_events);
+ int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+ struct debug_store *ds = cpuc->ds;
+ struct perf_event *event;
+@@ -2287,7 +2288,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+
+ ds->pebs_index = ds->pebs_buffer_base;
+
+- mask = ((1ULL << max_pebs_events) - 1) |
++ mask = hybrid(cpuc->pmu, pebs_events_mask) |
+ (((1ULL << num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED);
+ size = INTEL_PMC_IDX_FIXED + num_counters_fixed;
+
+diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
+index 72b022a1e16c5..a7ba2868018ca 100644
+--- a/arch/x86/events/perf_event.h
++++ b/arch/x86/events/perf_event.h
+@@ -684,7 +684,7 @@ struct x86_hybrid_pmu {
+ cpumask_t supported_cpus;
+ union perf_capabilities intel_cap;
+ u64 intel_ctrl;
+- int max_pebs_events;
++ u64 pebs_events_mask;
+ int num_counters;
+ int num_counters_fixed;
+ struct event_constraint unconstrained;
+@@ -852,7 +852,7 @@ struct x86_pmu {
+ pebs_ept :1;
+ int pebs_record_size;
+ int pebs_buffer_size;
+- int max_pebs_events;
++ u64 pebs_events_mask;
+ void (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data);
+ struct event_constraint *pebs_constraints;
+ void (*pebs_aliases)(struct perf_event *event);
+@@ -1661,6 +1661,17 @@ static inline int is_ht_workaround_enabled(void)
+ return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
+ }
+
++static inline u64 intel_pmu_pebs_mask(u64 cntr_mask)
++{
++ return MAX_PEBS_EVENTS_MASK & cntr_mask;
++}
++
++static inline int intel_pmu_max_num_pebs(struct pmu *pmu)
++{
++ static_assert(MAX_PEBS_EVENTS == 32);
++ return fls((u32)hybrid(pmu, pebs_events_mask));
++}
++
+ #else /* CONFIG_CPU_SUP_INTEL */
+
+ static inline void reserve_ds_buffers(void)
+diff --git a/arch/x86/include/asm/intel_ds.h b/arch/x86/include/asm/intel_ds.h
+index 2f9eeb5c3069a..5dbeac48a5b93 100644
+--- a/arch/x86/include/asm/intel_ds.h
++++ b/arch/x86/include/asm/intel_ds.h
+@@ -9,6 +9,7 @@
+ /* The maximal number of PEBS events: */
+ #define MAX_PEBS_EVENTS_FMT4 8
+ #define MAX_PEBS_EVENTS 32
++#define MAX_PEBS_EVENTS_MASK GENMASK_ULL(MAX_PEBS_EVENTS - 1, 0)
+ #define MAX_FIXED_PEBS_EVENTS 16
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 83cdd752bf447ef52d3f5d3936f02912070d4c7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jun 2024 07:35:34 -0700
+Subject: perf/x86: Support counter mask
+
+From: Kan Liang <kan.liang@linux.intel.com>
+
+[ Upstream commit 722e42e45c2f1c6d1adec7813651dba5139f52f4 ]
+
+The current perf assumes that both GP and fixed counters are contiguous.
+But it's not guaranteed on newer Intel platforms or in a virtualization
+environment.
+
+Use the counter mask to replace the number of counters for both GP and
+the fixed counters. For the other ARCHs or old platforms which don't
+support a counter mask, using GENMASK_ULL(num_counter - 1, 0) to
+replace. There is no functional change for them.
+
+The interface to KVM is not changed. The number of counters still be
+passed to KVM. It can be updated later separately.
+
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Andi Kleen <ak@linux.intel.com>
+Reviewed-by: Ian Rogers <irogers@google.com>
+Link: https://lkml.kernel.org/r/20240626143545.480761-3-kan.liang@linux.intel.com
+Stable-dep-of: f73cefa3b72e ("perf/x86: Fix smp_processor_id()-in-preemptible warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/amd/core.c | 24 ++---
+ arch/x86/events/core.c | 98 ++++++++++----------
+ arch/x86/events/intel/core.c | 164 ++++++++++++++++-----------------
+ arch/x86/events/intel/ds.c | 19 ++--
+ arch/x86/events/intel/knc.c | 2 +-
+ arch/x86/events/intel/p4.c | 10 +-
+ arch/x86/events/intel/p6.c | 2 +-
+ arch/x86/events/perf_event.h | 47 ++++++++--
+ arch/x86/events/zhaoxin/core.c | 12 +--
+ 9 files changed, 199 insertions(+), 179 deletions(-)
+
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 18bfe3451f3aa..920e3a640cadd 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -432,7 +432,7 @@ static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+ * be removed on one CPU at a time AND PMU is disabled
+ * when we come here
+ */
+- for (i = 0; i < x86_pmu.num_counters; i++) {
++ for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct perf_event *tmp = event;
+
+ if (try_cmpxchg(nb->owners + i, &tmp, NULL))
+@@ -501,7 +501,7 @@ __amd_get_nb_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *ev
+ * because of successive calls to x86_schedule_events() from
+ * hw_perf_group_sched_in() without hw_perf_enable()
+ */
+- for_each_set_bit(idx, c->idxmsk, x86_pmu.num_counters) {
++ for_each_set_bit(idx, c->idxmsk, x86_pmu_max_num_counters(NULL)) {
+ if (new == -1 || hwc->idx == idx)
+ /* assign free slot, prefer hwc->idx */
+ old = cmpxchg(nb->owners + idx, NULL, event);
+@@ -544,7 +544,7 @@ static struct amd_nb *amd_alloc_nb(int cpu)
+ /*
+ * initialize all possible NB constraints
+ */
+- for (i = 0; i < x86_pmu.num_counters; i++) {
++ for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ __set_bit(i, nb->event_constraints[i].idxmsk);
+ nb->event_constraints[i].weight = 1;
+ }
+@@ -737,7 +737,7 @@ static void amd_pmu_check_overflow(void)
+ * counters are always enabled when this function is called and
+ * ARCH_PERFMON_EVENTSEL_INT is always set.
+ */
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+
+@@ -757,7 +757,7 @@ static void amd_pmu_enable_all(int added)
+
+ amd_brs_enable_all();
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ /* only activate events which are marked as active */
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+@@ -980,7 +980,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
+ /* Clear any reserved bits set by buggy microcode */
+ status &= amd_pmu_global_cntr_mask;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+
+@@ -1315,7 +1315,7 @@ static __initconst const struct x86_pmu amd_pmu = {
+ .addr_offset = amd_pmu_addr_offset,
+ .event_map = amd_pmu_event_map,
+ .max_events = ARRAY_SIZE(amd_perfmon_event_map),
+- .num_counters = AMD64_NUM_COUNTERS,
++ .cntr_mask64 = GENMASK_ULL(AMD64_NUM_COUNTERS - 1, 0),
+ .add = amd_pmu_add_event,
+ .del = amd_pmu_del_event,
+ .cntval_bits = 48,
+@@ -1414,7 +1414,7 @@ static int __init amd_core_pmu_init(void)
+ */
+ x86_pmu.eventsel = MSR_F15H_PERF_CTL;
+ x86_pmu.perfctr = MSR_F15H_PERF_CTR;
+- x86_pmu.num_counters = AMD64_NUM_COUNTERS_CORE;
++ x86_pmu.cntr_mask64 = GENMASK_ULL(AMD64_NUM_COUNTERS_CORE - 1, 0);
+
+ /* Check for Performance Monitoring v2 support */
+ if (boot_cpu_has(X86_FEATURE_PERFMON_V2)) {
+@@ -1424,9 +1424,9 @@ static int __init amd_core_pmu_init(void)
+ x86_pmu.version = 2;
+
+ /* Find the number of available Core PMCs */
+- x86_pmu.num_counters = ebx.split.num_core_pmc;
++ x86_pmu.cntr_mask64 = GENMASK_ULL(ebx.split.num_core_pmc - 1, 0);
+
+- amd_pmu_global_cntr_mask = (1ULL << x86_pmu.num_counters) - 1;
++ amd_pmu_global_cntr_mask = x86_pmu.cntr_mask64;
+
+ /* Update PMC handling functions */
+ x86_pmu.enable_all = amd_pmu_v2_enable_all;
+@@ -1454,12 +1454,12 @@ static int __init amd_core_pmu_init(void)
+ * even numbered counter that has a consecutive adjacent odd
+ * numbered counter following it.
+ */
+- for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
++ for (i = 0; i < x86_pmu_max_num_counters(NULL) - 1; i += 2)
+ even_ctr_mask |= BIT_ULL(i);
+
+ pair_constraint = (struct event_constraint)
+ __EVENT_CONSTRAINT(0, even_ctr_mask, 0,
+- x86_pmu.num_counters / 2, 0,
++ x86_pmu_max_num_counters(NULL) / 2, 0,
+ PERF_X86_EVENT_PAIR);
+
+ x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index acd367c453341..0c51cfdf76092 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -189,29 +189,31 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
+
+ #ifdef CONFIG_X86_LOCAL_APIC
+
+-static inline int get_possible_num_counters(void)
++static inline u64 get_possible_counter_mask(void)
+ {
+- int i, num_counters = x86_pmu.num_counters;
++ u64 cntr_mask = x86_pmu.cntr_mask64;
++ int i;
+
+ if (!is_hybrid())
+- return num_counters;
++ return cntr_mask;
+
+ for (i = 0; i < x86_pmu.num_hybrid_pmus; i++)
+- num_counters = max_t(int, num_counters, x86_pmu.hybrid_pmu[i].num_counters);
++ cntr_mask |= x86_pmu.hybrid_pmu[i].cntr_mask64;
+
+- return num_counters;
++ return cntr_mask;
+ }
+
+ static bool reserve_pmc_hardware(void)
+ {
+- int i, num_counters = get_possible_num_counters();
++ u64 cntr_mask = get_possible_counter_mask();
++ int i, end;
+
+- for (i = 0; i < num_counters; i++) {
++ for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+ if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
+ goto perfctr_fail;
+ }
+
+- for (i = 0; i < num_counters; i++) {
++ for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+ if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
+ goto eventsel_fail;
+ }
+@@ -219,13 +221,14 @@ static bool reserve_pmc_hardware(void)
+ return true;
+
+ eventsel_fail:
+- for (i--; i >= 0; i--)
++ end = i;
++ for_each_set_bit(i, (unsigned long *)&cntr_mask, end)
+ release_evntsel_nmi(x86_pmu_config_addr(i));
+-
+- i = num_counters;
++ i = X86_PMC_IDX_MAX;
+
+ perfctr_fail:
+- for (i--; i >= 0; i--)
++ end = i;
++ for_each_set_bit(i, (unsigned long *)&cntr_mask, end)
+ release_perfctr_nmi(x86_pmu_event_addr(i));
+
+ return false;
+@@ -233,9 +236,10 @@ static bool reserve_pmc_hardware(void)
+
+ static void release_pmc_hardware(void)
+ {
+- int i, num_counters = get_possible_num_counters();
++ u64 cntr_mask = get_possible_counter_mask();
++ int i;
+
+- for (i = 0; i < num_counters; i++) {
++ for_each_set_bit(i, (unsigned long *)&cntr_mask, X86_PMC_IDX_MAX) {
+ release_perfctr_nmi(x86_pmu_event_addr(i));
+ release_evntsel_nmi(x86_pmu_config_addr(i));
+ }
+@@ -248,7 +252,8 @@ static void release_pmc_hardware(void) {}
+
+ #endif
+
+-bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
++bool check_hw_exists(struct pmu *pmu, unsigned long *cntr_mask,
++ unsigned long *fixed_cntr_mask)
+ {
+ u64 val, val_fail = -1, val_new= ~0;
+ int i, reg, reg_fail = -1, ret = 0;
+@@ -259,7 +264,7 @@ bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
+ * Check to see if the BIOS enabled any of the counters, if so
+ * complain and bail.
+ */
+- for (i = 0; i < num_counters; i++) {
++ for_each_set_bit(i, cntr_mask, X86_PMC_IDX_MAX) {
+ reg = x86_pmu_config_addr(i);
+ ret = rdmsrl_safe(reg, &val);
+ if (ret)
+@@ -273,12 +278,12 @@ bool check_hw_exists(struct pmu *pmu, int num_counters, int num_counters_fixed)
+ }
+ }
+
+- if (num_counters_fixed) {
++ if (*(u64 *)fixed_cntr_mask) {
+ reg = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+ ret = rdmsrl_safe(reg, &val);
+ if (ret)
+ goto msr_fail;
+- for (i = 0; i < num_counters_fixed; i++) {
++ for_each_set_bit(i, fixed_cntr_mask, X86_PMC_IDX_MAX) {
+ if (fixed_counter_disabled(i, pmu))
+ continue;
+ if (val & (0x03ULL << i*4)) {
+@@ -679,7 +684,7 @@ void x86_pmu_disable_all(void)
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+ u64 val;
+
+@@ -736,7 +741,7 @@ void x86_pmu_enable_all(int added)
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+ if (!test_bit(idx, cpuc->active_mask))
+@@ -975,7 +980,6 @@ EXPORT_SYMBOL_GPL(perf_assign_events);
+
+ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+ {
+- int num_counters = hybrid(cpuc->pmu, num_counters);
+ struct event_constraint *c;
+ struct perf_event *e;
+ int n0, i, wmin, wmax, unsched = 0;
+@@ -1051,7 +1055,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+
+ /* slow path */
+ if (i != n) {
+- int gpmax = num_counters;
++ int gpmax = x86_pmu_max_num_counters(cpuc->pmu);
+
+ /*
+ * Do not allow scheduling of more than half the available
+@@ -1072,7 +1076,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+ * the extra Merge events needed by large increment events.
+ */
+ if (x86_pmu.flags & PMU_FL_PAIR) {
+- gpmax = num_counters - cpuc->n_pair;
++ gpmax -= cpuc->n_pair;
+ WARN_ON(gpmax <= 0);
+ }
+
+@@ -1157,12 +1161,10 @@ static int collect_event(struct cpu_hw_events *cpuc, struct perf_event *event,
+ */
+ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, bool dogrp)
+ {
+- int num_counters = hybrid(cpuc->pmu, num_counters);
+- int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+ struct perf_event *event;
+ int n, max_count;
+
+- max_count = num_counters + num_counters_fixed;
++ max_count = x86_pmu_num_counters(cpuc->pmu) + x86_pmu_num_counters_fixed(cpuc->pmu);
+
+ /* current number of events already accepted */
+ n = cpuc->n_events;
+@@ -1522,13 +1524,13 @@ void perf_event_print_debug(void)
+ u64 pebs, debugctl;
+ int cpu = smp_processor_id();
+ struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+- int num_counters = hybrid(cpuc->pmu, num_counters);
+- int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
++ unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++ unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+ struct event_constraint *pebs_constraints = hybrid(cpuc->pmu, pebs_constraints);
+ unsigned long flags;
+ int idx;
+
+- if (!num_counters)
++ if (!*(u64 *)cntr_mask)
+ return;
+
+ local_irq_save(flags);
+@@ -1555,7 +1557,7 @@ void perf_event_print_debug(void)
+ }
+ pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask);
+
+- for (idx = 0; idx < num_counters; idx++) {
++ for_each_set_bit(idx, cntr_mask, X86_PMC_IDX_MAX) {
+ rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
+ rdmsrl(x86_pmu_event_addr(idx), pmc_count);
+
+@@ -1568,7 +1570,7 @@ void perf_event_print_debug(void)
+ pr_info("CPU#%d: gen-PMC%d left: %016llx\n",
+ cpu, idx, prev_left);
+ }
+- for (idx = 0; idx < num_counters_fixed; idx++) {
++ for_each_set_bit(idx, fixed_cntr_mask, X86_PMC_IDX_MAX) {
+ if (fixed_counter_disabled(idx, cpuc->pmu))
+ continue;
+ rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
+@@ -1682,7 +1684,7 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
+ */
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+
+@@ -2038,18 +2040,15 @@ static void _x86_pmu_read(struct perf_event *event)
+ static_call(x86_pmu_update)(event);
+ }
+
+-void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
+- u64 intel_ctrl)
++void x86_pmu_show_pmu_cap(struct pmu *pmu)
+ {
+ pr_info("... version: %d\n", x86_pmu.version);
+ pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
+- pr_info("... generic registers: %d\n", num_counters);
++ pr_info("... generic registers: %d\n", x86_pmu_num_counters(pmu));
+ pr_info("... value mask: %016Lx\n", x86_pmu.cntval_mask);
+ pr_info("... max period: %016Lx\n", x86_pmu.max_period);
+- pr_info("... fixed-purpose events: %lu\n",
+- hweight64((((1ULL << num_counters_fixed) - 1)
+- << INTEL_PMC_IDX_FIXED) & intel_ctrl));
+- pr_info("... event mask: %016Lx\n", intel_ctrl);
++ pr_info("... fixed-purpose events: %d\n", x86_pmu_num_counters_fixed(pmu));
++ pr_info("... event mask: %016Lx\n", hybrid(pmu, intel_ctrl));
+ }
+
+ static int __init init_hw_perf_events(void)
+@@ -2086,7 +2085,7 @@ static int __init init_hw_perf_events(void)
+ pmu_check_apic();
+
+ /* sanity check that the hardware exists or is emulated */
+- if (!check_hw_exists(&pmu, x86_pmu.num_counters, x86_pmu.num_counters_fixed))
++ if (!check_hw_exists(&pmu, x86_pmu.cntr_mask, x86_pmu.fixed_cntr_mask))
+ goto out_bad_pmu;
+
+ pr_cont("%s PMU driver.\n", x86_pmu.name);
+@@ -2097,14 +2096,14 @@ static int __init init_hw_perf_events(void)
+ quirk->func();
+
+ if (!x86_pmu.intel_ctrl)
+- x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
++ x86_pmu.intel_ctrl = x86_pmu.cntr_mask64;
+
+ perf_events_lapic_init();
+ register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
+
+ unconstrained = (struct event_constraint)
+- __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
+- 0, x86_pmu.num_counters, 0, 0);
++ __EVENT_CONSTRAINT(0, x86_pmu.cntr_mask64,
++ 0, x86_pmu_num_counters(NULL), 0, 0);
+
+ x86_pmu_format_group.attrs = x86_pmu.format_attrs;
+
+@@ -2113,11 +2112,8 @@ static int __init init_hw_perf_events(void)
+
+ pmu.attr_update = x86_pmu.attr_update;
+
+- if (!is_hybrid()) {
+- x86_pmu_show_pmu_cap(x86_pmu.num_counters,
+- x86_pmu.num_counters_fixed,
+- x86_pmu.intel_ctrl);
+- }
++ if (!is_hybrid())
++ x86_pmu_show_pmu_cap(NULL);
+
+ if (!x86_pmu.read)
+ x86_pmu.read = _x86_pmu_read;
+@@ -2481,7 +2477,7 @@ void perf_clear_dirty_counters(void)
+ for_each_set_bit(i, cpuc->dirty, X86_PMC_IDX_MAX) {
+ if (i >= INTEL_PMC_IDX_FIXED) {
+ /* Metrics and fake events don't have corresponding HW counters. */
+- if ((i - INTEL_PMC_IDX_FIXED) >= hybrid(cpuc->pmu, num_counters_fixed))
++ if (!test_bit(i - INTEL_PMC_IDX_FIXED, hybrid(cpuc->pmu, fixed_cntr_mask)))
+ continue;
+
+ wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + (i - INTEL_PMC_IDX_FIXED), 0);
+@@ -2986,8 +2982,8 @@ void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
+ * base PMU holds the correct number of counters for P-cores.
+ */
+ cap->version = x86_pmu.version;
+- cap->num_counters_gp = x86_pmu.num_counters;
+- cap->num_counters_fixed = x86_pmu.num_counters_fixed;
++ cap->num_counters_gp = x86_pmu_num_counters(NULL);
++ cap->num_counters_fixed = x86_pmu_num_counters_fixed(NULL);
+ cap->bit_width_gp = x86_pmu.cntval_bits;
+ cap->bit_width_fixed = x86_pmu.cntval_bits;
+ cap->events_mask = (unsigned int)x86_pmu.events_maskl;
+diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
+index 2175ca2fdba47..f25205d047e83 100644
+--- a/arch/x86/events/intel/core.c
++++ b/arch/x86/events/intel/core.c
+@@ -2874,23 +2874,23 @@ static void intel_pmu_reset(void)
+ {
+ struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+- int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+- int num_counters = hybrid(cpuc->pmu, num_counters);
++ unsigned long *cntr_mask = hybrid(cpuc->pmu, cntr_mask);
++ unsigned long *fixed_cntr_mask = hybrid(cpuc->pmu, fixed_cntr_mask);
+ unsigned long flags;
+ int idx;
+
+- if (!num_counters)
++ if (!*(u64 *)cntr_mask)
+ return;
+
+ local_irq_save(flags);
+
+ pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
+
+- for (idx = 0; idx < num_counters; idx++) {
++ for_each_set_bit(idx, cntr_mask, INTEL_PMC_MAX_GENERIC) {
+ wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
+ wrmsrl_safe(x86_pmu_event_addr(idx), 0ull);
+ }
+- for (idx = 0; idx < num_counters_fixed; idx++) {
++ for_each_set_bit(idx, fixed_cntr_mask, INTEL_PMC_MAX_FIXED) {
+ if (fixed_counter_disabled(idx, cpuc->pmu))
+ continue;
+ wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+@@ -2940,8 +2940,7 @@ static void x86_pmu_handle_guest_pebs(struct pt_regs *regs,
+ !guest_pebs_idxs)
+ return;
+
+- for_each_set_bit(bit, (unsigned long *)&guest_pebs_idxs,
+- INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed) {
++ for_each_set_bit(bit, (unsigned long *)&guest_pebs_idxs, X86_PMC_IDX_MAX) {
+ event = cpuc->events[bit];
+ if (!event->attr.precise_ip)
+ continue;
+@@ -4199,7 +4198,7 @@ static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr, void *data)
+ struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct perf_event *event = cpuc->events[idx];
+
+ arr[idx].msr = x86_pmu_config_addr(idx);
+@@ -4217,7 +4216,7 @@ static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr, void *data)
+ arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+ }
+
+- *nr = x86_pmu.num_counters;
++ *nr = x86_pmu_max_num_counters(cpuc->pmu);
+ return arr;
+ }
+
+@@ -4232,7 +4231,7 @@ static void core_pmu_enable_all(int added)
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+ if (!test_bit(idx, cpuc->active_mask) ||
+@@ -4684,13 +4683,33 @@ static void flip_smm_bit(void *data)
+ }
+ }
+
+-static void intel_pmu_check_num_counters(int *num_counters,
+- int *num_counters_fixed,
+- u64 *intel_ctrl, u64 fixed_mask);
++static void intel_pmu_check_counters_mask(u64 *cntr_mask,
++ u64 *fixed_cntr_mask,
++ u64 *intel_ctrl)
++{
++ unsigned int bit;
++
++ bit = fls64(*cntr_mask);
++ if (bit > INTEL_PMC_MAX_GENERIC) {
++ WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
++ bit, INTEL_PMC_MAX_GENERIC);
++ *cntr_mask &= GENMASK_ULL(INTEL_PMC_MAX_GENERIC - 1, 0);
++ }
++ *intel_ctrl = *cntr_mask;
++
++ bit = fls64(*fixed_cntr_mask);
++ if (bit > INTEL_PMC_MAX_FIXED) {
++ WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
++ bit, INTEL_PMC_MAX_FIXED);
++ *fixed_cntr_mask &= GENMASK_ULL(INTEL_PMC_MAX_FIXED - 1, 0);
++ }
++
++ *intel_ctrl |= *fixed_cntr_mask << INTEL_PMC_IDX_FIXED;
++}
+
+ static void intel_pmu_check_event_constraints(struct event_constraint *event_constraints,
+- int num_counters,
+- int num_counters_fixed,
++ u64 cntr_mask,
++ u64 fixed_cntr_mask,
+ u64 intel_ctrl);
+
+ static void intel_pmu_check_extra_regs(struct extra_reg *extra_regs);
+@@ -4713,11 +4732,10 @@ static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
+ if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
+ cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
+ &eax, &ebx, &ecx, &edx);
+- pmu->num_counters = fls(eax);
+- pmu->num_counters_fixed = fls(ebx);
++ pmu->cntr_mask64 = eax;
++ pmu->fixed_cntr_mask64 = ebx;
+ }
+
+-
+ if (!intel_pmu_broken_perf_cap()) {
+ /* Perf Metric (Bit 15) and PEBS via PT (Bit 16) are hybrid enumeration */
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, pmu->intel_cap.capabilities);
+@@ -4726,12 +4744,12 @@ static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
+
+ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+ {
+- intel_pmu_check_num_counters(&pmu->num_counters, &pmu->num_counters_fixed,
+- &pmu->intel_ctrl, (1ULL << pmu->num_counters_fixed) - 1);
+- pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++ intel_pmu_check_counters_mask(&pmu->cntr_mask64, &pmu->fixed_cntr_mask64,
++ &pmu->intel_ctrl);
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+ pmu->unconstrained = (struct event_constraint)
+- __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+- 0, pmu->num_counters, 0, 0);
++ __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++ 0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
+
+ if (pmu->intel_cap.perf_metrics)
+ pmu->intel_ctrl |= 1ULL << GLOBAL_CTRL_EN_PERF_METRICS;
+@@ -4744,8 +4762,8 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
+ pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT;
+
+ intel_pmu_check_event_constraints(pmu->event_constraints,
+- pmu->num_counters,
+- pmu->num_counters_fixed,
++ pmu->cntr_mask64,
++ pmu->fixed_cntr_mask64,
+ pmu->intel_ctrl);
+
+ intel_pmu_check_extra_regs(pmu->extra_regs);
+@@ -4806,7 +4824,7 @@ static bool init_hybrid_pmu(int cpu)
+
+ intel_pmu_check_hybrid_pmus(pmu);
+
+- if (!check_hw_exists(&pmu->pmu, pmu->num_counters, pmu->num_counters_fixed))
++ if (!check_hw_exists(&pmu->pmu, pmu->cntr_mask, pmu->fixed_cntr_mask))
+ return false;
+
+ pr_info("%s PMU driver: ", pmu->name);
+@@ -4816,8 +4834,7 @@ static bool init_hybrid_pmu(int cpu)
+
+ pr_cont("\n");
+
+- x86_pmu_show_pmu_cap(pmu->num_counters, pmu->num_counters_fixed,
+- pmu->intel_ctrl);
++ x86_pmu_show_pmu_cap(&pmu->pmu);
+
+ end:
+ cpumask_set_cpu(cpu, &pmu->supported_cpus);
+@@ -5955,29 +5972,9 @@ static const struct attribute_group *hybrid_attr_update[] = {
+
+ static struct attribute *empty_attrs;
+
+-static void intel_pmu_check_num_counters(int *num_counters,
+- int *num_counters_fixed,
+- u64 *intel_ctrl, u64 fixed_mask)
+-{
+- if (*num_counters > INTEL_PMC_MAX_GENERIC) {
+- WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
+- *num_counters, INTEL_PMC_MAX_GENERIC);
+- *num_counters = INTEL_PMC_MAX_GENERIC;
+- }
+- *intel_ctrl = (1ULL << *num_counters) - 1;
+-
+- if (*num_counters_fixed > INTEL_PMC_MAX_FIXED) {
+- WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
+- *num_counters_fixed, INTEL_PMC_MAX_FIXED);
+- *num_counters_fixed = INTEL_PMC_MAX_FIXED;
+- }
+-
+- *intel_ctrl |= fixed_mask << INTEL_PMC_IDX_FIXED;
+-}
+-
+ static void intel_pmu_check_event_constraints(struct event_constraint *event_constraints,
+- int num_counters,
+- int num_counters_fixed,
++ u64 cntr_mask,
++ u64 fixed_cntr_mask,
+ u64 intel_ctrl)
+ {
+ struct event_constraint *c;
+@@ -6014,10 +6011,9 @@ static void intel_pmu_check_event_constraints(struct event_constraint *event_con
+ * generic counters
+ */
+ if (!use_fixed_pseudo_encoding(c->code))
+- c->idxmsk64 |= (1ULL << num_counters) - 1;
++ c->idxmsk64 |= cntr_mask;
+ }
+- c->idxmsk64 &=
+- ~(~0ULL << (INTEL_PMC_IDX_FIXED + num_counters_fixed));
++ c->idxmsk64 &= cntr_mask | (fixed_cntr_mask << INTEL_PMC_IDX_FIXED);
+ c->weight = hweight64(c->idxmsk64);
+ }
+ }
+@@ -6068,12 +6064,12 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus)
+ pmu->pmu_type = intel_hybrid_pmu_type_map[bit].id;
+ pmu->name = intel_hybrid_pmu_type_map[bit].name;
+
+- pmu->num_counters = x86_pmu.num_counters;
+- pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
+- pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++ pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++ pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+ pmu->unconstrained = (struct event_constraint)
+- __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+- 0, pmu->num_counters, 0, 0);
++ __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++ 0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
+
+ pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities;
+ if (pmu->pmu_type & hybrid_small) {
+@@ -6186,14 +6182,14 @@ __init int intel_pmu_init(void)
+ x86_pmu = intel_pmu;
+
+ x86_pmu.version = version;
+- x86_pmu.num_counters = eax.split.num_counters;
++ x86_pmu.cntr_mask64 = GENMASK_ULL(eax.split.num_counters - 1, 0);
+ x86_pmu.cntval_bits = eax.split.bit_width;
+ x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1;
+
+ x86_pmu.events_maskl = ebx.full;
+ x86_pmu.events_mask_len = eax.split.mask_length;
+
+- x86_pmu.pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(x86_pmu.num_counters - 1, 0));
++ x86_pmu.pebs_events_mask = intel_pmu_pebs_mask(x86_pmu.cntr_mask64);
+ x86_pmu.pebs_capable = PEBS_COUNTER_MASK;
+
+ /*
+@@ -6203,12 +6199,10 @@ __init int intel_pmu_init(void)
+ if (version > 1 && version < 5) {
+ int assume = 3 * !boot_cpu_has(X86_FEATURE_HYPERVISOR);
+
+- x86_pmu.num_counters_fixed =
+- max((int)edx.split.num_counters_fixed, assume);
+-
+- fixed_mask = (1L << x86_pmu.num_counters_fixed) - 1;
++ x86_pmu.fixed_cntr_mask64 =
++ GENMASK_ULL(max((int)edx.split.num_counters_fixed, assume) - 1, 0);
+ } else if (version >= 5)
+- x86_pmu.num_counters_fixed = fls(fixed_mask);
++ x86_pmu.fixed_cntr_mask64 = fixed_mask;
+
+ if (boot_cpu_has(X86_FEATURE_PDCM)) {
+ u64 capabilities;
+@@ -6807,11 +6801,13 @@ __init int intel_pmu_init(void)
+ pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
+ intel_pmu_init_glc(&pmu->pmu);
+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
+- pmu->num_counters = x86_pmu.num_counters + 2;
+- pmu->num_counters_fixed = x86_pmu.num_counters_fixed + 1;
++ pmu->cntr_mask64 <<= 2;
++ pmu->cntr_mask64 |= 0x3;
++ pmu->fixed_cntr_mask64 <<= 1;
++ pmu->fixed_cntr_mask64 |= 0x1;
+ } else {
+- pmu->num_counters = x86_pmu.num_counters;
+- pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
++ pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++ pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
+ }
+
+ /*
+@@ -6821,15 +6817,16 @@ __init int intel_pmu_init(void)
+ * mistakenly add extra counters for P-cores. Correct the number of
+ * counters here.
+ */
+- if ((pmu->num_counters > 8) || (pmu->num_counters_fixed > 4)) {
+- pmu->num_counters = x86_pmu.num_counters;
+- pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
++ if ((x86_pmu_num_counters(&pmu->pmu) > 8) || (x86_pmu_num_counters_fixed(&pmu->pmu) > 4)) {
++ pmu->cntr_mask64 = x86_pmu.cntr_mask64;
++ pmu->fixed_cntr_mask64 = x86_pmu.fixed_cntr_mask64;
+ }
+
+- pmu->pebs_events_mask = intel_pmu_pebs_mask(GENMASK_ULL(pmu->num_counters - 1, 0));
++ pmu->pebs_events_mask = intel_pmu_pebs_mask(pmu->cntr_mask64);
+ pmu->unconstrained = (struct event_constraint)
+- __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1,
+- 0, pmu->num_counters, 0, 0);
++ __EVENT_CONSTRAINT(0, pmu->cntr_mask64,
++ 0, x86_pmu_num_counters(&pmu->pmu), 0, 0);
++
+ pmu->extra_regs = intel_glc_extra_regs;
+
+ /* Initialize Atom core specific PerfMon capabilities.*/
+@@ -6896,9 +6893,9 @@ __init int intel_pmu_init(void)
+ * The constraints may be cut according to the CPUID enumeration
+ * by inserting the EVENT_CONSTRAINT_END.
+ */
+- if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED)
+- x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
+- intel_v5_gen_event_constraints[x86_pmu.num_counters_fixed].weight = -1;
++ if (fls64(x86_pmu.fixed_cntr_mask64) > INTEL_PMC_MAX_FIXED)
++ x86_pmu.fixed_cntr_mask64 &= GENMASK_ULL(INTEL_PMC_MAX_FIXED - 1, 0);
++ intel_v5_gen_event_constraints[fls64(x86_pmu.fixed_cntr_mask64)].weight = -1;
+ x86_pmu.event_constraints = intel_v5_gen_event_constraints;
+ pr_cont("generic architected perfmon, ");
+ name = "generic_arch_v5+";
+@@ -6925,18 +6922,17 @@ __init int intel_pmu_init(void)
+ x86_pmu.attr_update = hybrid_attr_update;
+ }
+
+- intel_pmu_check_num_counters(&x86_pmu.num_counters,
+- &x86_pmu.num_counters_fixed,
+- &x86_pmu.intel_ctrl,
+- (u64)fixed_mask);
++ intel_pmu_check_counters_mask(&x86_pmu.cntr_mask64,
++ &x86_pmu.fixed_cntr_mask64,
++ &x86_pmu.intel_ctrl);
+
+ /* AnyThread may be deprecated on arch perfmon v5 or later */
+ if (x86_pmu.intel_cap.anythread_deprecated)
+ x86_pmu.format_attrs = intel_arch_formats_attr;
+
+ intel_pmu_check_event_constraints(x86_pmu.event_constraints,
+- x86_pmu.num_counters,
+- x86_pmu.num_counters_fixed,
++ x86_pmu.cntr_mask64,
++ x86_pmu.fixed_cntr_mask64,
+ x86_pmu.intel_ctrl);
+ /*
+ * Access LBR MSR may cause #GP under certain circumstances.
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index 87d3feb9f8fe8..9212053f6f1d6 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1138,7 +1138,6 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+ {
+ struct debug_store *ds = cpuc->ds;
+ int max_pebs_events = intel_pmu_max_num_pebs(cpuc->pmu);
+- int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+ u64 threshold;
+ int reserved;
+
+@@ -1146,7 +1145,7 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
+ return;
+
+ if (x86_pmu.flags & PMU_FL_PEBS_ALL)
+- reserved = max_pebs_events + num_counters_fixed;
++ reserved = max_pebs_events + x86_pmu_max_num_counters_fixed(cpuc->pmu);
+ else
+ reserved = max_pebs_events;
+
+@@ -2176,8 +2175,8 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
+ mask = x86_pmu.pebs_events_mask;
+ size = max_pebs_events;
+ if (x86_pmu.flags & PMU_FL_PEBS_ALL) {
+- mask |= ((1ULL << x86_pmu.num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED;
+- size = INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed;
++ mask |= x86_pmu.fixed_cntr_mask64 << INTEL_PMC_IDX_FIXED;
++ size = INTEL_PMC_IDX_FIXED + x86_pmu_max_num_counters_fixed(NULL);
+ }
+
+ if (unlikely(base >= top)) {
+@@ -2273,11 +2272,10 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ {
+ short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+- int num_counters_fixed = hybrid(cpuc->pmu, num_counters_fixed);
+ struct debug_store *ds = cpuc->ds;
+ struct perf_event *event;
+ void *base, *at, *top;
+- int bit, size;
++ int bit;
+ u64 mask;
+
+ if (!x86_pmu.pebs_active)
+@@ -2289,11 +2287,10 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ ds->pebs_index = ds->pebs_buffer_base;
+
+ mask = hybrid(cpuc->pmu, pebs_events_mask) |
+- (((1ULL << num_counters_fixed) - 1) << INTEL_PMC_IDX_FIXED);
+- size = INTEL_PMC_IDX_FIXED + num_counters_fixed;
++ (hybrid(cpuc->pmu, fixed_cntr_mask64) << INTEL_PMC_IDX_FIXED);
+
+ if (unlikely(base >= top)) {
+- intel_pmu_pebs_event_update_no_drain(cpuc, size);
++ intel_pmu_pebs_event_update_no_drain(cpuc, X86_PMC_IDX_MAX);
+ return;
+ }
+
+@@ -2303,11 +2300,11 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_d
+ pebs_status = get_pebs_status(at) & cpuc->pebs_enabled;
+ pebs_status &= mask;
+
+- for_each_set_bit(bit, (unsigned long *)&pebs_status, size)
++ for_each_set_bit(bit, (unsigned long *)&pebs_status, X86_PMC_IDX_MAX)
+ counts[bit]++;
+ }
+
+- for_each_set_bit(bit, (unsigned long *)&mask, size) {
++ for_each_set_bit(bit, (unsigned long *)&mask, X86_PMC_IDX_MAX) {
+ if (counts[bit] == 0)
+ continue;
+
+diff --git a/arch/x86/events/intel/knc.c b/arch/x86/events/intel/knc.c
+index 618001c208e81..034a1f6a457c6 100644
+--- a/arch/x86/events/intel/knc.c
++++ b/arch/x86/events/intel/knc.c
+@@ -303,7 +303,7 @@ static const struct x86_pmu knc_pmu __initconst = {
+ .apic = 1,
+ .max_period = (1ULL << 39) - 1,
+ .version = 0,
+- .num_counters = 2,
++ .cntr_mask64 = 0x3,
+ .cntval_bits = 40,
+ .cntval_mask = (1ULL << 40) - 1,
+ .get_event_constraints = x86_get_event_constraints,
+diff --git a/arch/x86/events/intel/p4.c b/arch/x86/events/intel/p4.c
+index 35936188db01b..844bc4fc4724d 100644
+--- a/arch/x86/events/intel/p4.c
++++ b/arch/x86/events/intel/p4.c
+@@ -919,7 +919,7 @@ static void p4_pmu_disable_all(void)
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct perf_event *event = cpuc->events[idx];
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+@@ -998,7 +998,7 @@ static void p4_pmu_enable_all(int added)
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int idx;
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ struct perf_event *event = cpuc->events[idx];
+ if (!test_bit(idx, cpuc->active_mask))
+ continue;
+@@ -1040,7 +1040,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
+
+ cpuc = this_cpu_ptr(&cpu_hw_events);
+
+- for (idx = 0; idx < x86_pmu.num_counters; idx++) {
++ for_each_set_bit(idx, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ int overflow;
+
+ if (!test_bit(idx, cpuc->active_mask)) {
+@@ -1353,7 +1353,7 @@ static __initconst const struct x86_pmu p4_pmu = {
+ * though leave it restricted at moment assuming
+ * HT is on
+ */
+- .num_counters = ARCH_P4_MAX_CCCR,
++ .cntr_mask64 = GENMASK_ULL(ARCH_P4_MAX_CCCR - 1, 0),
+ .apic = 1,
+ .cntval_bits = ARCH_P4_CNTRVAL_BITS,
+ .cntval_mask = ARCH_P4_CNTRVAL_MASK,
+@@ -1395,7 +1395,7 @@ __init int p4_pmu_init(void)
+ *
+ * Solve this by zero'ing out the registers to mimic a reset.
+ */
+- for (i = 0; i < x86_pmu.num_counters; i++) {
++ for_each_set_bit(i, x86_pmu.cntr_mask, X86_PMC_IDX_MAX) {
+ reg = x86_pmu_config_addr(i);
+ wrmsrl_safe(reg, 0ULL);
+ }
+diff --git a/arch/x86/events/intel/p6.c b/arch/x86/events/intel/p6.c
+index 408879b0c0d4e..a6cffb4f4ef52 100644
+--- a/arch/x86/events/intel/p6.c
++++ b/arch/x86/events/intel/p6.c
+@@ -214,7 +214,7 @@ static __initconst const struct x86_pmu p6_pmu = {
+ .apic = 1,
+ .max_period = (1ULL << 31) - 1,
+ .version = 0,
+- .num_counters = 2,
++ .cntr_mask64 = 0x3,
+ /*
+ * Events have 40 bits implemented. However they are designed such
+ * that bits [32-39] are sign extensions of bit 31. As such the
+diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
+index a7ba2868018ca..745c174fc8809 100644
+--- a/arch/x86/events/perf_event.h
++++ b/arch/x86/events/perf_event.h
+@@ -685,8 +685,14 @@ struct x86_hybrid_pmu {
+ union perf_capabilities intel_cap;
+ u64 intel_ctrl;
+ u64 pebs_events_mask;
+- int num_counters;
+- int num_counters_fixed;
++ union {
++ u64 cntr_mask64;
++ unsigned long cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++ };
++ union {
++ u64 fixed_cntr_mask64;
++ unsigned long fixed_cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++ };
+ struct event_constraint unconstrained;
+
+ u64 hw_cache_event_ids
+@@ -774,8 +780,14 @@ struct x86_pmu {
+ int (*rdpmc_index)(int index);
+ u64 (*event_map)(int);
+ int max_events;
+- int num_counters;
+- int num_counters_fixed;
++ union {
++ u64 cntr_mask64;
++ unsigned long cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++ };
++ union {
++ u64 fixed_cntr_mask64;
++ unsigned long fixed_cntr_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
++ };
+ int cntval_bits;
+ u64 cntval_mask;
+ union {
+@@ -1125,8 +1137,8 @@ static inline int x86_pmu_rdpmc_index(int index)
+ return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
+ }
+
+-bool check_hw_exists(struct pmu *pmu, int num_counters,
+- int num_counters_fixed);
++bool check_hw_exists(struct pmu *pmu, unsigned long *cntr_mask,
++ unsigned long *fixed_cntr_mask);
+
+ int x86_add_exclusive(unsigned int what);
+
+@@ -1197,8 +1209,27 @@ void x86_pmu_enable_event(struct perf_event *event);
+
+ int x86_pmu_handle_irq(struct pt_regs *regs);
+
+-void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
+- u64 intel_ctrl);
++void x86_pmu_show_pmu_cap(struct pmu *pmu);
++
++static inline int x86_pmu_num_counters(struct pmu *pmu)
++{
++ return hweight64(hybrid(pmu, cntr_mask64));
++}
++
++static inline int x86_pmu_max_num_counters(struct pmu *pmu)
++{
++ return fls64(hybrid(pmu, cntr_mask64));
++}
++
++static inline int x86_pmu_num_counters_fixed(struct pmu *pmu)
++{
++ return hweight64(hybrid(pmu, fixed_cntr_mask64));
++}
++
++static inline int x86_pmu_max_num_counters_fixed(struct pmu *pmu)
++{
++ return fls64(hybrid(pmu, fixed_cntr_mask64));
++}
+
+ extern struct event_constraint emptyconstraint;
+
+diff --git a/arch/x86/events/zhaoxin/core.c b/arch/x86/events/zhaoxin/core.c
+index 3e9acdaeed1ec..2fd9b0cf9a5e5 100644
+--- a/arch/x86/events/zhaoxin/core.c
++++ b/arch/x86/events/zhaoxin/core.c
+@@ -530,13 +530,13 @@ __init int zhaoxin_pmu_init(void)
+ pr_info("Version check pass!\n");
+
+ x86_pmu.version = version;
+- x86_pmu.num_counters = eax.split.num_counters;
++ x86_pmu.cntr_mask64 = GENMASK_ULL(eax.split.num_counters - 1, 0);
+ x86_pmu.cntval_bits = eax.split.bit_width;
+ x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1;
+ x86_pmu.events_maskl = ebx.full;
+ x86_pmu.events_mask_len = eax.split.mask_length;
+
+- x86_pmu.num_counters_fixed = edx.split.num_counters_fixed;
++ x86_pmu.fixed_cntr_mask64 = GENMASK_ULL(edx.split.num_counters_fixed - 1, 0);
+ x86_add_quirk(zhaoxin_arch_events_quirk);
+
+ switch (boot_cpu_data.x86) {
+@@ -604,13 +604,13 @@ __init int zhaoxin_pmu_init(void)
+ return -ENODEV;
+ }
+
+- x86_pmu.intel_ctrl = (1 << (x86_pmu.num_counters)) - 1;
+- x86_pmu.intel_ctrl |= ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
++ x86_pmu.intel_ctrl = x86_pmu.cntr_mask64;
++ x86_pmu.intel_ctrl |= x86_pmu.fixed_cntr_mask64 << INTEL_PMC_IDX_FIXED;
+
+ if (x86_pmu.event_constraints) {
+ for_each_event_constraint(c, x86_pmu.event_constraints) {
+- c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
+- c->weight += x86_pmu.num_counters;
++ c->idxmsk64 |= x86_pmu.cntr_mask64;
++ c->weight += x86_pmu_num_counters(NULL);
+ }
+ }
+
+--
+2.43.0
+
--- /dev/null
+From d95e53db9dc2db9cb26f741797e8dabefd0fe374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 07:33:49 +0100
+Subject: platform/chrome: cros_ec_lpc: Add a new quirk for ACPI id
+
+From: Ben Walsh <ben@jubnut.com>
+
+[ Upstream commit 040159e0912c31fe959d8671f9700bda105ab63a ]
+
+Framework Laptops' ACPI exposes the EC with id "PNP0C09". But
+"PNP0C09" is part of the ACPI standard; there are lots of computers
+with EC chips with this id, and most of them don't support the cros_ec
+protocol.
+
+The driver could find the ACPI device by having "PNP0C09" in the
+acpi_match_table, but this would match devices which don't support the
+cros_ec protocol. Instead, add a new quirk "CROS_EC_LPC_QUIRK_ACPI_ID"
+which allows the id to be specified. This quirk is applied after the
+DMI check shows that the device is supported.
+
+Tested-by: Dustin L. Howett <dustin@howett.net>
+Signed-off-by: Ben Walsh <ben@jubnut.com>
+Link: https://lore.kernel.org/r/20240605063351.14836-4-ben@jubnut.com
+Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/chrome/cros_ec_lpc.c | 50 ++++++++++++++++++++-------
+ 1 file changed, 38 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
+index ddfbfec44f4cc..43e0914256a3c 100644
+--- a/drivers/platform/chrome/cros_ec_lpc.c
++++ b/drivers/platform/chrome/cros_ec_lpc.c
+@@ -39,6 +39,11 @@ static bool cros_ec_lpc_acpi_device_found;
+ * be used as the base port for EC mapped memory.
+ */
+ #define CROS_EC_LPC_QUIRK_REMAP_MEMORY BIT(0)
++/*
++ * Indicates that lpc_driver_data.quirk_acpi_id should be used to find
++ * the ACPI device.
++ */
++#define CROS_EC_LPC_QUIRK_ACPI_ID BIT(1)
+
+ /**
+ * struct lpc_driver_data - driver data attached to a DMI device ID to indicate
+@@ -46,10 +51,12 @@ static bool cros_ec_lpc_acpi_device_found;
+ * @quirks: a bitfield composed of quirks from CROS_EC_LPC_QUIRK_*
+ * @quirk_mmio_memory_base: The first I/O port addressing EC mapped memory (used
+ * when quirk ...REMAP_MEMORY is set.)
++ * @quirk_acpi_id: An ACPI HID to be used to find the ACPI device.
+ */
+ struct lpc_driver_data {
+ u32 quirks;
+ u16 quirk_mmio_memory_base;
++ const char *quirk_acpi_id;
+ };
+
+ /**
+@@ -374,6 +381,26 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
+ pm_system_wakeup();
+ }
+
++static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
++ void *context, void **retval)
++{
++ *(struct acpi_device **)context = acpi_fetch_acpi_dev(handle);
++ return AE_CTRL_TERMINATE;
++}
++
++static struct acpi_device *cros_ec_lpc_get_device(const char *id)
++{
++ struct acpi_device *adev = NULL;
++ acpi_status status = acpi_get_devices(id, cros_ec_lpc_parse_device,
++ &adev, NULL);
++ if (ACPI_FAILURE(status)) {
++ pr_warn(DRV_NAME ": Looking for %s failed\n", id);
++ return NULL;
++ }
++
++ return adev;
++}
++
+ static int cros_ec_lpc_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -401,6 +428,16 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
+
+ if (quirks & CROS_EC_LPC_QUIRK_REMAP_MEMORY)
+ ec_lpc->mmio_memory_base = driver_data->quirk_mmio_memory_base;
++
++ if (quirks & CROS_EC_LPC_QUIRK_ACPI_ID) {
++ adev = cros_ec_lpc_get_device(driver_data->quirk_acpi_id);
++ if (!adev) {
++ dev_err(dev, "failed to get ACPI device '%s'",
++ driver_data->quirk_acpi_id);
++ return -ENODEV;
++ }
++ ACPI_COMPANION_SET(dev, adev);
++ }
+ }
+
+ /*
+@@ -661,23 +698,12 @@ static struct platform_device cros_ec_lpc_device = {
+ .name = DRV_NAME
+ };
+
+-static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
+- void *context, void **retval)
+-{
+- *(bool *)context = true;
+- return AE_CTRL_TERMINATE;
+-}
+-
+ static int __init cros_ec_lpc_init(void)
+ {
+ int ret;
+- acpi_status status;
+ const struct dmi_system_id *dmi_match;
+
+- status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
+- &cros_ec_lpc_acpi_device_found, NULL);
+- if (ACPI_FAILURE(status))
+- pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
++ cros_ec_lpc_acpi_device_found = !!cros_ec_lpc_get_device(ACPI_DRV_NAME);
+
+ dmi_match = dmi_first_match(cros_ec_lpc_dmi_table);
+
+--
+2.43.0
+
--- /dev/null
+From c59d4f8d1068a600dda81b5c20d4391e622eb1fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 15:59:30 +0000
+Subject: platform/x86/intel/ifs: Initialize union ifs_status to zero
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+
+[ Upstream commit 3114f77e9453daa292ec0906f313a715c69b5943 ]
+
+If the IFS scan test exits prematurely due to a timeout before
+completing a single run, the union ifs_status remains uninitialized,
+leading to incorrect test status reporting. To prevent this, always
+initialize the union ifs_status to zero.
+
+Fixes: 2b40e654b73a ("platform/x86/intel/ifs: Add scan test support")
+Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Reviewed-by: Jithu Joseph <jithu.joseph@intel.com>
+Reviewed-by: Ashok Raj <ashok.raj@intel.com>
+Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Link: https://lore.kernel.org/r/20240730155930.1754744-1-sathyanarayanan.kuppuswamy@linux.intel.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/ifs/runtest.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c
+index 282e4bfe30da3..be3d51ed0e474 100644
+--- a/drivers/platform/x86/intel/ifs/runtest.c
++++ b/drivers/platform/x86/intel/ifs/runtest.c
+@@ -221,8 +221,8 @@ static int doscan(void *data)
+ */
+ static void ifs_test_core(int cpu, struct device *dev)
+ {
++ union ifs_status status = {};
+ union ifs_scan activate;
+- union ifs_status status;
+ unsigned long timeout;
+ struct ifs_data *ifsd;
+ int to_start, to_stop;
+--
+2.43.0
+
--- /dev/null
+From 75caffd4f52c38007990781d90e01b59c0a0b3ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jul 2024 14:04:43 +0200
+Subject: platform/x86: intel-vbtn: Protect ACPI notify handler against
+ recursion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit e075c3b13a0a142dcd3151b25d29a24f31b7b640 ]
+
+Since commit e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on
+all CPUs") ACPI notify handlers like the intel-vbtn notify_handler() may
+run on multiple CPU cores racing with themselves.
+
+This race gets hit on Dell Venue 7140 tablets when undocking from
+the keyboard, causing the handler to try and register priv->switches_dev
+twice, as can be seen from the dev_info() message getting logged twice:
+
+[ 83.861800] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event
+[ 83.861858] input: Intel Virtual Switches as /devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17
+[ 83.861865] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event
+
+After which things go seriously wrong:
+[ 83.861872] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17'
+...
+[ 83.861967] kobject: kobject_add_internal failed for input17 with -EEXIST, don't try to register things with the same name in the same directory.
+[ 83.877338] BUG: kernel NULL pointer dereference, address: 0000000000000018
+...
+
+Protect intel-vbtn notify_handler() from racing with itself with a mutex
+to fix this.
+
+Fixes: e2ffcda16290 ("ACPI: OSL: Allow Notify () handlers to run on all CPUs")
+Reported-by: En-Wei Wu <en-wei.wu@canonical.com>
+Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2073001
+Tested-by: Kostadin Stoilov <kmstoilov@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240729120443.14779-1-hdegoede@redhat.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/vbtn.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c
+index 9b7ce03ba085c..a353e830b65fd 100644
+--- a/drivers/platform/x86/intel/vbtn.c
++++ b/drivers/platform/x86/intel/vbtn.c
+@@ -7,11 +7,13 @@
+ */
+
+ #include <linux/acpi.h>
++#include <linux/cleanup.h>
+ #include <linux/dmi.h>
+ #include <linux/input.h>
+ #include <linux/input/sparse-keymap.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mutex.h>
+ #include <linux/platform_device.h>
+ #include <linux/suspend.h>
+ #include "../dual_accel_detect.h"
+@@ -66,6 +68,7 @@ static const struct key_entry intel_vbtn_switchmap[] = {
+ };
+
+ struct intel_vbtn_priv {
++ struct mutex mutex; /* Avoid notify_handler() racing with itself */
+ struct input_dev *buttons_dev;
+ struct input_dev *switches_dev;
+ bool dual_accel;
+@@ -155,6 +158,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
+ bool autorelease;
+ int ret;
+
++ guard(mutex)(&priv->mutex);
++
+ if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) {
+ if (!priv->has_buttons) {
+ dev_warn(&device->dev, "Warning: received 0x%02x button event on a device without buttons, please report this.\n",
+@@ -290,6 +295,10 @@ static int intel_vbtn_probe(struct platform_device *device)
+ return -ENOMEM;
+ dev_set_drvdata(&device->dev, priv);
+
++ err = devm_mutex_init(&device->dev, &priv->mutex);
++ if (err)
++ return err;
++
+ priv->dual_accel = dual_accel;
+ priv->has_buttons = has_buttons;
+ priv->has_switches = has_switches;
+--
+2.43.0
+
--- /dev/null
+From df8ea4860eda6b9d624193269506702028ff9a33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 18:53:27 +0500
+Subject: power: supply: rt5033: Bring back i2c_set_clientdata
+
+From: Nikita Travkin <nikita@trvn.ru>
+
+[ Upstream commit d3911f1639e67fc7b12aae0efa5a540976d7443b ]
+
+Commit 3a93da231c12 ("power: supply: rt5033: Use devm_power_supply_register() helper")
+reworked the driver to use devm. While at it, the i2c_set_clientdata
+was dropped along with the remove callback. Unfortunately other parts
+of the driver also rely on i2c clientdata so this causes kernel oops.
+
+Bring the call back to fix the driver.
+
+Fixes: 3a93da231c12 ("power: supply: rt5033: Use devm_power_supply_register() helper")
+Tested-by: Raymond Hackley <raymondhackley@protonmail.com>
+Signed-off-by: Nikita Travkin <nikita@trvn.ru>
+Link: https://lore.kernel.org/r/20240605-rt5033-null-clientdata-v1-1-558d710eeb4d@trvn.ru
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/rt5033_battery.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c
+index 32eafe2c00af5..7a27b262fb84a 100644
+--- a/drivers/power/supply/rt5033_battery.c
++++ b/drivers/power/supply/rt5033_battery.c
+@@ -159,6 +159,7 @@ static int rt5033_battery_probe(struct i2c_client *client)
+ return -EINVAL;
+ }
+
++ i2c_set_clientdata(client, battery);
+ psy_cfg.of_node = client->dev.of_node;
+ psy_cfg.drv_data = battery;
+
+--
+2.43.0
+
--- /dev/null
+From c95d51f2944b26eb1d7db90295af840770ed150c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 21:20:16 +0200
+Subject: r8169: remove detection of chip version 11 (early RTL8168b)
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 982300c115d229565d7af8e8b38aa1ee7bb1f5bd ]
+
+This early RTL8168b version was the first PCIe chip version, and it's
+quite quirky. Last sign of life is from more than 15 yrs ago.
+Let's remove detection of this chip version, we'll see whether anybody
+complains. If not, support for this chip version can be removed a few
+kernel versions later.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/875cdcf4-843c-420a-ad5d-417447b68572@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index b6e89fc5a4ae7..e5f883a66f47a 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2274,7 +2274,9 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
+
+ /* 8168B family. */
+ { 0x7c8, 0x380, RTL_GIGA_MAC_VER_17 },
+- { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 },
++ /* This one is very old and rare, let's see if anybody complains.
++ * { 0x7c8, 0x300, RTL_GIGA_MAC_VER_11 },
++ */
+
+ /* 8101 family. */
+ { 0x7c8, 0x448, RTL_GIGA_MAC_VER_39 },
+--
+2.43.0
+
--- /dev/null
+From 87be42b489031f336fd6306b38dac82246e01748 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 16:05:24 +0200
+Subject: rcu: Fix rcu_barrier() VS post CPUHP_TEARDOWN_CPU invocation
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit 55d4669ef1b76823083caecfab12a8bd2ccdcf64 ]
+
+When rcu_barrier() calls rcu_rdp_cpu_online() and observes a CPU off
+rnp->qsmaskinitnext, it means that all accesses from the offline CPU
+preceding the CPUHP_TEARDOWN_CPU are visible to RCU barrier, including
+callbacks expiration and counter updates.
+
+However interrupts can still fire after stop_machine() re-enables
+interrupts and before rcutree_report_cpu_dead(). The related accesses
+happening between CPUHP_TEARDOWN_CPU and rnp->qsmaskinitnext clearing
+are _NOT_ guaranteed to be seen by rcu_barrier() without proper
+ordering, especially when callbacks are invoked there to the end, making
+rcutree_migrate_callback() bypass barrier_lock.
+
+The following theoretical race example can make rcu_barrier() hang:
+
+CPU 0 CPU 1
+----- -----
+//cpu_down()
+smpboot_park_threads()
+//ksoftirqd is parked now
+<IRQ>
+rcu_sched_clock_irq()
+ invoke_rcu_core()
+do_softirq()
+ rcu_core()
+ rcu_do_batch()
+ // callback storm
+ // rcu_do_batch() returns
+ // before completing all
+ // of them
+ // do_softirq also returns early because of
+ // timeout. It defers to ksoftirqd but
+ // it's parked
+</IRQ>
+stop_machine()
+ take_cpu_down()
+ rcu_barrier()
+ spin_lock(barrier_lock)
+ // observes rcu_segcblist_n_cbs(&rdp->cblist) != 0
+<IRQ>
+do_softirq()
+ rcu_core()
+ rcu_do_batch()
+ //completes all pending callbacks
+ //smp_mb() implied _after_ callback number dec
+</IRQ>
+
+rcutree_report_cpu_dead()
+ rnp->qsmaskinitnext &= ~rdp->grpmask;
+
+rcutree_migrate_callback()
+ // no callback, early return without locking
+ // barrier_lock
+ //observes !rcu_rdp_cpu_online(rdp)
+ rcu_barrier_entrain()
+ rcu_segcblist_entrain()
+ // Observe rcu_segcblist_n_cbs(rsclp) == 0
+ // because no barrier between reading
+ // rnp->qsmaskinitnext and rsclp->len
+ rcu_segcblist_add_len()
+ smp_mb__before_atomic()
+ // will now observe the 0 count and empty
+ // list, but too late, we enqueue regardless
+ WRITE_ONCE(rsclp->len, rsclp->len + v);
+ // ignored barrier callback
+ // rcu barrier stall...
+
+This could be solved with a read memory barrier, enforcing the message
+passing between rnp->qsmaskinitnext and rsclp->len, matching the full
+memory barrier after rsclp->len addition in rcu_segcblist_add_len()
+performed at the end of rcu_do_batch().
+
+However the rcu_barrier() is complicated enough and probably doesn't
+need too many more subtleties. CPU down is a slowpath and the
+barrier_lock seldom contended. Solve the issue with unconditionally
+locking the barrier_lock on rcutree_migrate_callbacks(). This makes sure
+that either rcu_barrier() sees the empty queue or its entrained
+callback will be migrated.
+
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/tree.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index 28c7031711a3f..63fb007beeaf5 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -5110,11 +5110,15 @@ void rcutree_migrate_callbacks(int cpu)
+ struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu);
+ bool needwake;
+
+- if (rcu_rdp_is_offloaded(rdp) ||
+- rcu_segcblist_empty(&rdp->cblist))
+- return; /* No callbacks to migrate. */
++ if (rcu_rdp_is_offloaded(rdp))
++ return;
+
+ raw_spin_lock_irqsave(&rcu_state.barrier_lock, flags);
++ if (rcu_segcblist_empty(&rdp->cblist)) {
++ raw_spin_unlock_irqrestore(&rcu_state.barrier_lock, flags);
++ return; /* No callbacks to migrate. */
++ }
++
+ WARN_ON_ONCE(rcu_rdp_cpu_online(rdp));
+ rcu_barrier_entrain(rdp);
+ my_rdp = this_cpu_ptr(&rcu_data);
+--
+2.43.0
+
--- /dev/null
+From 979bb844576dfc17e70114e5e6cd38e05ba19815 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Apr 2024 12:02:11 -0700
+Subject: rcutorture: Fix rcu_torture_fwd_cb_cr() data race
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 6040072f4774a575fa67b912efe7722874be337b ]
+
+On powerpc systems, spinlock acquisition does not order prior stores
+against later loads. This means that this statement:
+
+ rfcp->rfc_next = NULL;
+
+Can be reordered to follow this statement:
+
+ WRITE_ONCE(*rfcpp, rfcp);
+
+Which is then a data race with rcu_torture_fwd_prog_cr(), specifically,
+this statement:
+
+ rfcpn = READ_ONCE(rfcp->rfc_next)
+
+KCSAN located this data race, which represents a real failure on powerpc.
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Acked-by: Marco Elver <elver@google.com>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: <kasan-dev@googlegroups.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcutorture.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
+index 807fbf6123a77..251cead744603 100644
+--- a/kernel/rcu/rcutorture.c
++++ b/kernel/rcu/rcutorture.c
+@@ -2626,7 +2626,7 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
+ spin_lock_irqsave(&rfp->rcu_fwd_lock, flags);
+ rfcpp = rfp->rcu_fwd_cb_tail;
+ rfp->rcu_fwd_cb_tail = &rfcp->rfc_next;
+- WRITE_ONCE(*rfcpp, rfcp);
++ smp_store_release(rfcpp, rfcp);
+ WRITE_ONCE(rfp->n_launders_cb, rfp->n_launders_cb + 1);
+ i = ((jiffies - rfp->rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
+ if (i >= ARRAY_SIZE(rfp->n_launders_hist))
+--
+2.43.0
+
--- /dev/null
+From 115d098e4b21deb2d3a85f86b1fc8ee34e9f8895 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 11:37:24 +0100
+Subject: regmap: kunit: Fix memory leaks in gen_regmap() and gen_raw_regmap()
+
+From: Richard Fitzgerald <rf@opensource.cirrus.com>
+
+[ Upstream commit c3820641da87442251e0c00b6874ef1022da8f58 ]
+
+- Use kunit_kcalloc() to allocate the defaults table so that it will be
+ freed when the test case ends.
+- kfree() the buf and *data buffers on the error paths.
+- Use kunit_add_action_or_reset() instead of kunit_add_action() so that
+ if it fails it will call regmap_exit().
+
+Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Link: https://msgid.link/r/20240411103724.54063-1-rf@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap-kunit.c | 72 +++++++++++++++++++-----------
+ 1 file changed, 45 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c
+index be32cd4e84da4..292e86f601978 100644
+--- a/drivers/base/regmap/regmap-kunit.c
++++ b/drivers/base/regmap/regmap-kunit.c
+@@ -145,9 +145,9 @@ static struct regmap *gen_regmap(struct kunit *test,
+ const struct regmap_test_param *param = test->param_value;
+ struct regmap_test_priv *priv = test->priv;
+ unsigned int *buf;
+- struct regmap *ret;
++ struct regmap *ret = ERR_PTR(-ENOMEM);
+ size_t size;
+- int i;
++ int i, error;
+ struct reg_default *defaults;
+
+ config->cache_type = param->cache;
+@@ -172,15 +172,17 @@ static struct regmap *gen_regmap(struct kunit *test,
+
+ *data = kzalloc(sizeof(**data), GFP_KERNEL);
+ if (!(*data))
+- return ERR_PTR(-ENOMEM);
++ goto out_free;
+ (*data)->vals = buf;
+
+ if (config->num_reg_defaults) {
+- defaults = kcalloc(config->num_reg_defaults,
+- sizeof(struct reg_default),
+- GFP_KERNEL);
++ defaults = kunit_kcalloc(test,
++ config->num_reg_defaults,
++ sizeof(struct reg_default),
++ GFP_KERNEL);
+ if (!defaults)
+- return ERR_PTR(-ENOMEM);
++ goto out_free;
++
+ config->reg_defaults = defaults;
+
+ for (i = 0; i < config->num_reg_defaults; i++) {
+@@ -190,12 +192,19 @@ static struct regmap *gen_regmap(struct kunit *test,
+ }
+
+ ret = regmap_init_ram(priv->dev, config, *data);
+- if (IS_ERR(ret)) {
+- kfree(buf);
+- kfree(*data);
+- } else {
+- kunit_add_action(test, regmap_exit_action, ret);
+- }
++ if (IS_ERR(ret))
++ goto out_free;
++
++ /* This calls regmap_exit() on failure, which frees buf and *data */
++ error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
++ if (error)
++ ret = ERR_PTR(error);
++
++ return ret;
++
++out_free:
++ kfree(buf);
++ kfree(*data);
+
+ return ret;
+ }
+@@ -1497,9 +1506,9 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+ struct regmap_test_priv *priv = test->priv;
+ const struct regmap_test_param *param = test->param_value;
+ u16 *buf;
+- struct regmap *ret;
++ struct regmap *ret = ERR_PTR(-ENOMEM);
+ size_t size = (config->max_register + 1) * config->reg_bits / 8;
+- int i;
++ int i, error;
+ struct reg_default *defaults;
+
+ config->cache_type = param->cache;
+@@ -1515,15 +1524,16 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+
+ *data = kzalloc(sizeof(**data), GFP_KERNEL);
+ if (!(*data))
+- return ERR_PTR(-ENOMEM);
++ goto out_free;
+ (*data)->vals = (void *)buf;
+
+ config->num_reg_defaults = config->max_register + 1;
+- defaults = kcalloc(config->num_reg_defaults,
+- sizeof(struct reg_default),
+- GFP_KERNEL);
++ defaults = kunit_kcalloc(test,
++ config->num_reg_defaults,
++ sizeof(struct reg_default),
++ GFP_KERNEL);
+ if (!defaults)
+- return ERR_PTR(-ENOMEM);
++ goto out_free;
+ config->reg_defaults = defaults;
+
+ for (i = 0; i < config->num_reg_defaults; i++) {
+@@ -1536,7 +1546,8 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+ defaults[i].def = be16_to_cpu(buf[i]);
+ break;
+ default:
+- return ERR_PTR(-EINVAL);
++ ret = ERR_PTR(-EINVAL);
++ goto out_free;
+ }
+ }
+
+@@ -1548,12 +1559,19 @@ static struct regmap *gen_raw_regmap(struct kunit *test,
+ config->num_reg_defaults = 0;
+
+ ret = regmap_init_raw_ram(priv->dev, config, *data);
+- if (IS_ERR(ret)) {
+- kfree(buf);
+- kfree(*data);
+- } else {
+- kunit_add_action(test, regmap_exit_action, ret);
+- }
++ if (IS_ERR(ret))
++ goto out_free;
++
++ /* This calls regmap_exit() on failure, which frees buf and *data */
++ error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
++ if (error)
++ ret = ERR_PTR(error);
++
++ return ret;
++
++out_free:
++ kfree(buf);
++ kfree(*data);
+
+ return ret;
+ }
+--
+2.43.0
+
--- /dev/null
+From c7ef3842aaf54bb8a367f6a94b90e86066a7e5cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Apr 2024 16:24:04 +0200
+Subject: Revert "rcu-tasks: Fix synchronize_rcu_tasks() VS
+ zap_pid_ns_processes()"
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit 9855c37edf0009cc276cecfee09f7e76e2380212 ]
+
+This reverts commit 28319d6dc5e2ffefa452c2377dd0f71621b5bff0. The race
+it fixed was subject to conditions that don't exist anymore since:
+
+ 1612160b9127 ("rcu-tasks: Eliminate deadlocks involving do_exit() and RCU tasks")
+
+This latter commit removes the use of SRCU that used to cover the
+RCU-tasks blind spot on exit between the tasklist's removal and the
+final preemption disabling. The task is now placed instead into a
+temporary list inside which voluntary sleeps are accounted as RCU-tasks
+quiescent states. This would disarm the deadlock initially reported
+against PID namespace exit.
+
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/rcupdate.h | 2 --
+ kernel/pid_namespace.c | 17 -----------------
+ kernel/rcu/tasks.h | 16 +++-------------
+ 3 files changed, 3 insertions(+), 32 deletions(-)
+
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index dfd2399f2cde0..61cb3de236af1 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -209,7 +209,6 @@ void synchronize_rcu_tasks_rude(void);
+
+ #define rcu_note_voluntary_context_switch(t) rcu_tasks_qs(t, false)
+ void exit_tasks_rcu_start(void);
+-void exit_tasks_rcu_stop(void);
+ void exit_tasks_rcu_finish(void);
+ #else /* #ifdef CONFIG_TASKS_RCU_GENERIC */
+ #define rcu_tasks_classic_qs(t, preempt) do { } while (0)
+@@ -218,7 +217,6 @@ void exit_tasks_rcu_finish(void);
+ #define call_rcu_tasks call_rcu
+ #define synchronize_rcu_tasks synchronize_rcu
+ static inline void exit_tasks_rcu_start(void) { }
+-static inline void exit_tasks_rcu_stop(void) { }
+ static inline void exit_tasks_rcu_finish(void) { }
+ #endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */
+
+diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
+index 25f3cf679b358..bdf0087d64423 100644
+--- a/kernel/pid_namespace.c
++++ b/kernel/pid_namespace.c
+@@ -249,24 +249,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (pid_ns->pid_allocated == init_pids)
+ break;
+- /*
+- * Release tasks_rcu_exit_srcu to avoid following deadlock:
+- *
+- * 1) TASK A unshare(CLONE_NEWPID)
+- * 2) TASK A fork() twice -> TASK B (child reaper for new ns)
+- * and TASK C
+- * 3) TASK B exits, kills TASK C, waits for TASK A to reap it
+- * 4) TASK A calls synchronize_rcu_tasks()
+- * -> synchronize_srcu(tasks_rcu_exit_srcu)
+- * 5) *DEADLOCK*
+- *
+- * It is considered safe to release tasks_rcu_exit_srcu here
+- * because we assume the current task can not be concurrently
+- * reaped at this point.
+- */
+- exit_tasks_rcu_stop();
+ schedule();
+- exit_tasks_rcu_start();
+ }
+ __set_current_state(TASK_RUNNING);
+
+diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
+index 098e82bcc427f..ba3440a45b6dd 100644
+--- a/kernel/rcu/tasks.h
++++ b/kernel/rcu/tasks.h
+@@ -858,7 +858,7 @@ static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
+ // not know to synchronize with this RCU Tasks grace period) have
+ // completed exiting. The synchronize_rcu() in rcu_tasks_postgp()
+ // will take care of any tasks stuck in the non-preemptible region
+-// of do_exit() following its call to exit_tasks_rcu_stop().
++// of do_exit() following its call to exit_tasks_rcu_finish().
+ // check_all_holdout_tasks(), repeatedly until holdout list is empty:
+ // Scans the holdout list, attempting to identify a quiescent state
+ // for each task on the list. If there is a quiescent state, the
+@@ -1220,7 +1220,7 @@ void exit_tasks_rcu_start(void)
+ * Remove the task from the "yet another list" because do_exit() is now
+ * non-preemptible, allowing synchronize_rcu() to wait beyond this point.
+ */
+-void exit_tasks_rcu_stop(void)
++void exit_tasks_rcu_finish(void)
+ {
+ unsigned long flags;
+ struct rcu_tasks_percpu *rtpcp;
+@@ -1231,22 +1231,12 @@ void exit_tasks_rcu_stop(void)
+ raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
+ list_del_init(&t->rcu_tasks_exit_list);
+ raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
+-}
+
+-/*
+- * Contribute to protect against tasklist scan blind spot while the
+- * task is exiting and may be removed from the tasklist. See
+- * corresponding synchronize_srcu() for further details.
+- */
+-void exit_tasks_rcu_finish(void)
+-{
+- exit_tasks_rcu_stop();
+- exit_tasks_rcu_finish_trace(current);
++ exit_tasks_rcu_finish_trace(t);
+ }
+
+ #else /* #ifdef CONFIG_TASKS_RCU */
+ void exit_tasks_rcu_start(void) { }
+-void exit_tasks_rcu_stop(void) { }
+ void exit_tasks_rcu_finish(void) { exit_tasks_rcu_finish_trace(current); }
+ #endif /* #else #ifdef CONFIG_TASKS_RCU */
+
+--
+2.43.0
+
--- /dev/null
+From f55180327012f0f847d9cd05ce4662c3e3d56e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jun 2024 12:29:05 -0700
+Subject: rtnetlink: move rtnl_lock handling out of af_netlink
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 5380d64f8d766576ac5c0f627418b2d0e1d2641f ]
+
+Now that we have an intermediate layer of code for handling
+rtnl-level netlink dump quirks, we can move the rtnl_lock
+taking there.
+
+For dump handlers with RTNL_FLAG_DUMP_SPLIT_NLM_DONE we can
+avoid taking rtnl_lock just to generate NLM_DONE, once again.
+
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/rtnetlink.c | 9 +++++++--
+ net/netlink/af_netlink.c | 2 --
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 5e589f0a62bc5..cb8792800cee8 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -6486,6 +6486,7 @@ static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
+
+ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++ const bool needs_lock = !(cb->flags & RTNL_FLAG_DUMP_UNLOCKED);
+ rtnl_dumpit_func dumpit = cb->data;
+ int err;
+
+@@ -6495,7 +6496,11 @@ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ if (!dumpit)
+ return 0;
+
++ if (needs_lock)
++ rtnl_lock();
+ err = dumpit(skb, cb);
++ if (needs_lock)
++ rtnl_unlock();
+
+ /* Old dump handlers used to send NLM_DONE as in a separate recvmsg().
+ * Some applications which parse netlink manually depend on this.
+@@ -6515,7 +6520,8 @@ static int rtnetlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ struct netlink_dump_control *control)
+ {
+- if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE) {
++ if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE ||
++ !(control->flags & RTNL_FLAG_DUMP_UNLOCKED)) {
+ WARN_ON(control->data);
+ control->data = control->dump;
+ control->dump = rtnl_dumpit;
+@@ -6703,7 +6709,6 @@ static int __net_init rtnetlink_net_init(struct net *net)
+ struct netlink_kernel_cfg cfg = {
+ .groups = RTNLGRP_MAX,
+ .input = rtnetlink_rcv,
+- .cb_mutex = &rtnl_mutex,
+ .flags = NL_CFG_F_NONROOT_RECV,
+ .bind = rtnetlink_bind,
+ };
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index fa9c090cf629e..8bbbe75e75dbe 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -2330,8 +2330,6 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
+
+ cb->extack = &extack;
+
+- if (cb->flags & RTNL_FLAG_DUMP_UNLOCKED)
+- extra_mutex = NULL;
+ if (extra_mutex)
+ mutex_lock(extra_mutex);
+ nlk->dump_done_errno = cb->dump(skb, cb);
+--
+2.43.0
+
--- /dev/null
+From 3abb325358c8ba00fd9fdcdf21bcb33da7e2252e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 14:20:27 +0200
+Subject: s390/sclp: Prevent release of buffer in I/O
+
+From: Peter Oberparleiter <oberpar@linux.ibm.com>
+
+[ Upstream commit bf365071ea92b9579d5a272679b74052a5643e35 ]
+
+When a task waiting for completion of a Store Data operation is
+interrupted, an attempt is made to halt this operation. If this attempt
+fails due to a hardware or firmware problem, there is a chance that the
+SCLP facility might store data into buffers referenced by the original
+operation at a later time.
+
+Handle this situation by not releasing the referenced data buffers if
+the halt attempt fails. For current use cases, this might result in a
+leak of few pages of memory in case of a rare hardware/firmware
+malfunction.
+
+Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/char/sclp_sd.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c
+index f9e164be7568f..944e75beb160c 100644
+--- a/drivers/s390/char/sclp_sd.c
++++ b/drivers/s390/char/sclp_sd.c
+@@ -320,8 +320,14 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di)
+ &esize);
+ if (rc) {
+ /* Cancel running request if interrupted */
+- if (rc == -ERESTARTSYS)
+- sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL);
++ if (rc == -ERESTARTSYS) {
++ if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) {
++ pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n",
++ (size_t)dsize * PAGE_SIZE);
++ data = NULL;
++ asce = 0;
++ }
++ }
+ vfree(data);
+ goto out;
+ }
+--
+2.43.0
+
--- /dev/null
+From 9ae4a4f48a9ec79154e3f499ba5468050ba5a9e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 16:46:24 -0700
+Subject: sctp: Fix null-ptr-deref in reuseport_add_sock().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 9ab0faa7f9ffe31296dbb9bbe6f76c72c14eea18 ]
+
+syzbot reported a null-ptr-deref while accessing sk2->sk_reuseport_cb in
+reuseport_add_sock(). [0]
+
+The repro first creates a listener with SO_REUSEPORT. Then, it creates
+another listener on the same port and concurrently closes the first
+listener.
+
+The second listen() calls reuseport_add_sock() with the first listener as
+sk2, where sk2->sk_reuseport_cb is not expected to be cleared concurrently,
+but the close() does clear it by reuseport_detach_sock().
+
+The problem is SCTP does not properly synchronise reuseport_alloc(),
+reuseport_add_sock(), and reuseport_detach_sock().
+
+The caller of reuseport_alloc() and reuseport_{add,detach}_sock() must
+provide synchronisation for sockets that are classified into the same
+reuseport group.
+
+Otherwise, such sockets form multiple identical reuseport groups, and
+all groups except one would be silently dead.
+
+ 1. Two sockets call listen() concurrently
+ 2. No socket in the same group found in sctp_ep_hashtable[]
+ 3. Two sockets call reuseport_alloc() and form two reuseport groups
+ 4. Only one group hit first in __sctp_rcv_lookup_endpoint() receives
+ incoming packets
+
+Also, the reported null-ptr-deref could occur.
+
+TCP/UDP guarantees that would not happen by holding the hash bucket lock.
+
+Let's apply the locking strategy to __sctp_hash_endpoint() and
+__sctp_unhash_endpoint().
+
+[0]:
+Oops: general protection fault, probably for non-canonical address 0xdffffc0000000002: 0000 [#1] PREEMPT SMP KASAN PTI
+KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
+CPU: 1 UID: 0 PID: 10230 Comm: syz-executor119 Not tainted 6.10.0-syzkaller-12585-g301927d2d2eb #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024
+RIP: 0010:reuseport_add_sock+0x27e/0x5e0 net/core/sock_reuseport.c:350
+Code: 00 0f b7 5d 00 bf 01 00 00 00 89 de e8 1b a4 ff f7 83 fb 01 0f 85 a3 01 00 00 e8 6d a0 ff f7 49 8d 7e 12 48 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 4b 02 00 00 41 0f b7 5e 12 49 8d 7e 14
+RSP: 0018:ffffc9000b947c98 EFLAGS: 00010202
+RAX: 0000000000000002 RBX: ffff8880252ddf98 RCX: ffff888079478000
+RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000012
+RBP: 0000000000000001 R08: ffffffff8993e18d R09: 1ffffffff1fef385
+R10: dffffc0000000000 R11: fffffbfff1fef386 R12: ffff8880252ddac0
+R13: dffffc0000000000 R14: 0000000000000000 R15: 0000000000000000
+FS: 00007f24e45b96c0(0000) GS:ffff8880b9300000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007ffcced5f7b8 CR3: 00000000241be000 CR4: 00000000003506f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+ DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ __sctp_hash_endpoint net/sctp/input.c:762 [inline]
+ sctp_hash_endpoint+0x52a/0x600 net/sctp/input.c:790
+ sctp_listen_start net/sctp/socket.c:8570 [inline]
+ sctp_inet_listen+0x767/0xa20 net/sctp/socket.c:8625
+ __sys_listen_socket net/socket.c:1883 [inline]
+ __sys_listen+0x1b7/0x230 net/socket.c:1894
+ __do_sys_listen net/socket.c:1902 [inline]
+ __se_sys_listen net/socket.c:1900 [inline]
+ __x64_sys_listen+0x5a/0x70 net/socket.c:1900
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f24e46039b9
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 91 1a 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f24e45b9228 EFLAGS: 00000246 ORIG_RAX: 0000000000000032
+RAX: ffffffffffffffda RBX: 00007f24e468e428 RCX: 00007f24e46039b9
+RDX: 00007f24e46039b9 RSI: 0000000000000003 RDI: 0000000000000004
+RBP: 00007f24e468e420 R08: 00007f24e45b96c0 R09: 00007f24e45b96c0
+R10: 00007f24e45b96c0 R11: 0000000000000246 R12: 00007f24e468e42c
+R13: 00007f24e465a5dc R14: 0020000000000001 R15: 00007ffcced5f7d8
+ </TASK>
+Modules linked in:
+
+Fixes: 6ba845740267 ("sctp: process sk_reuseport in sctp_get_port_local")
+Reported-by: syzbot+e6979a5d2f10ecb700e4@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=e6979a5d2f10ecb700e4
+Tested-by: syzbot+e6979a5d2f10ecb700e4@syzkaller.appspotmail.com
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20240731234624.94055-1-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/input.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/net/sctp/input.c b/net/sctp/input.c
+index 17fcaa9b0df94..a8a254a5008e5 100644
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -735,15 +735,19 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
+ struct sock *sk = ep->base.sk;
+ struct net *net = sock_net(sk);
+ struct sctp_hashbucket *head;
++ int err = 0;
+
+ ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port);
+ head = &sctp_ep_hashtable[ep->hashent];
+
++ write_lock(&head->lock);
+ if (sk->sk_reuseport) {
+ bool any = sctp_is_ep_boundall(sk);
+ struct sctp_endpoint *ep2;
+ struct list_head *list;
+- int cnt = 0, err = 1;
++ int cnt = 0;
++
++ err = 1;
+
+ list_for_each(list, &ep->base.bind_addr.address_list)
+ cnt++;
+@@ -761,24 +765,24 @@ static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
+ if (!err) {
+ err = reuseport_add_sock(sk, sk2, any);
+ if (err)
+- return err;
++ goto out;
+ break;
+ } else if (err < 0) {
+- return err;
++ goto out;
+ }
+ }
+
+ if (err) {
+ err = reuseport_alloc(sk, any);
+ if (err)
+- return err;
++ goto out;
+ }
+ }
+
+- write_lock(&head->lock);
+ hlist_add_head(&ep->node, &head->chain);
++out:
+ write_unlock(&head->lock);
+- return 0;
++ return err;
+ }
+
+ /* Add an endpoint to the hash. Local BH-safe. */
+@@ -803,10 +807,9 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
+
+ head = &sctp_ep_hashtable[ep->hashent];
+
++ write_lock(&head->lock);
+ if (rcu_access_pointer(sk->sk_reuseport_cb))
+ reuseport_detach_sock(sk);
+-
+- write_lock(&head->lock);
+ hlist_del_init(&ep->node);
+ write_unlock(&head->lock);
+ }
+--
+2.43.0
+
--- /dev/null
+From f6ca913a5be30cea9b776bdfbdd426d33f0f5367 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 13:12:03 -0700
+Subject: selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+[ Upstream commit 7015843afcaf68c132784c89528dfddc0005e483 ]
+
+Alexei reported that send_signal test may fail with nested CONFIG_PARAVIRT
+configs. In this particular case, the base VM is AMD with 166 cpus, and I
+run selftests with regular qemu on top of that and indeed send_signal test
+failed. I also tried with an Intel box with 80 cpus and there is no issue.
+
+The main qemu command line includes:
+
+ -enable-kvm -smp 16 -cpu host
+
+The failure log looks like:
+
+ $ ./test_progs -t send_signal
+ [ 48.501588] watchdog: BUG: soft lockup - CPU#9 stuck for 26s! [test_progs:2225]
+ [ 48.503622] Modules linked in: bpf_testmod(O)
+ [ 48.503622] CPU: 9 PID: 2225 Comm: test_progs Tainted: G O 6.9.0-08561-g2c1713a8f1c9-dirty #69
+ [ 48.507629] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
+ [ 48.511635] RIP: 0010:handle_softirqs+0x71/0x290
+ [ 48.511635] Code: [...] 10 0a 00 00 00 31 c0 65 66 89 05 d5 f4 fa 7e fb bb ff ff ff ff <49> c7 c2 cb
+ [ 48.518527] RSP: 0018:ffffc90000310fa0 EFLAGS: 00000246
+ [ 48.519579] RAX: 0000000000000000 RBX: 00000000ffffffff RCX: 00000000000006e0
+ [ 48.522526] RDX: 0000000000000006 RSI: ffff88810791ae80 RDI: 0000000000000000
+ [ 48.523587] RBP: ffffc90000fabc88 R08: 00000005a0af4f7f R09: 0000000000000000
+ [ 48.525525] R10: 0000000561d2f29c R11: 0000000000006534 R12: 0000000000000280
+ [ 48.528525] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+ [ 48.528525] FS: 00007f2f2885cd00(0000) GS:ffff888237c40000(0000) knlGS:0000000000000000
+ [ 48.531600] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ [ 48.535520] CR2: 00007f2f287059f0 CR3: 0000000106a28002 CR4: 00000000003706f0
+ [ 48.537538] Call Trace:
+ [ 48.537538] <IRQ>
+ [ 48.537538] ? watchdog_timer_fn+0x1cd/0x250
+ [ 48.539590] ? lockup_detector_update_enable+0x50/0x50
+ [ 48.539590] ? __hrtimer_run_queues+0xff/0x280
+ [ 48.542520] ? hrtimer_interrupt+0x103/0x230
+ [ 48.544524] ? __sysvec_apic_timer_interrupt+0x4f/0x140
+ [ 48.545522] ? sysvec_apic_timer_interrupt+0x3a/0x90
+ [ 48.547612] ? asm_sysvec_apic_timer_interrupt+0x1a/0x20
+ [ 48.547612] ? handle_softirqs+0x71/0x290
+ [ 48.547612] irq_exit_rcu+0x63/0x80
+ [ 48.551585] sysvec_apic_timer_interrupt+0x75/0x90
+ [ 48.552521] </IRQ>
+ [ 48.553529] <TASK>
+ [ 48.553529] asm_sysvec_apic_timer_interrupt+0x1a/0x20
+ [ 48.555609] RIP: 0010:finish_task_switch.isra.0+0x90/0x260
+ [ 48.556526] Code: [...] 9f 58 0a 00 00 48 85 db 0f 85 89 01 00 00 4c 89 ff e8 53 d9 bd 00 fb 66 90 <4d> 85 ed 74
+ [ 48.562524] RSP: 0018:ffffc90000fabd38 EFLAGS: 00000282
+ [ 48.563589] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff83385620
+ [ 48.563589] RDX: ffff888237c73ae4 RSI: 0000000000000000 RDI: ffff888237c6fd00
+ [ 48.568521] RBP: ffffc90000fabd68 R08: 0000000000000000 R09: 0000000000000000
+ [ 48.569528] R10: 0000000000000001 R11: 0000000000000000 R12: ffff8881009d0000
+ [ 48.573525] R13: ffff8881024e5400 R14: ffff88810791ae80 R15: ffff888237c6fd00
+ [ 48.575614] ? finish_task_switch.isra.0+0x8d/0x260
+ [ 48.576523] __schedule+0x364/0xac0
+ [ 48.577535] schedule+0x2e/0x110
+ [ 48.578555] pipe_read+0x301/0x400
+ [ 48.579589] ? destroy_sched_domains_rcu+0x30/0x30
+ [ 48.579589] vfs_read+0x2b3/0x2f0
+ [ 48.579589] ksys_read+0x8b/0xc0
+ [ 48.583590] do_syscall_64+0x3d/0xc0
+ [ 48.583590] entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ [ 48.586525] RIP: 0033:0x7f2f28703fa1
+ [ 48.587592] Code: [...] 00 00 00 0f 1f 44 00 00 f3 0f 1e fa 80 3d c5 23 14 00 00 74 13 31 c0 0f 05 <48> 3d 00 f0
+ [ 48.593534] RSP: 002b:00007ffd90f8cf88 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
+ [ 48.595589] RAX: ffffffffffffffda RBX: 00007ffd90f8d5e8 RCX: 00007f2f28703fa1
+ [ 48.595589] RDX: 0000000000000001 RSI: 00007ffd90f8cfb0 RDI: 0000000000000006
+ [ 48.599592] RBP: 00007ffd90f8d2f0 R08: 0000000000000064 R09: 0000000000000000
+ [ 48.602527] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+ [ 48.603589] R13: 00007ffd90f8d608 R14: 00007f2f288d8000 R15: 0000000000f6bdb0
+ [ 48.605527] </TASK>
+
+In the test, two processes are communicating through pipe. Further debugging
+with strace found that the above splat is triggered as read() syscall could
+not receive the data even if the corresponding write() syscall in another
+process successfully wrote data into the pipe.
+
+The failed subtest is "send_signal_perf". The corresponding perf event has
+sample_period 1 and config PERF_COUNT_SW_CPU_CLOCK. sample_period 1 means every
+overflow event will trigger a call to the BPF program. So I suspect this may
+overwhelm the system. So I increased the sample_period to 100,000 and the test
+passed. The sample_period 10,000 still has the test failed.
+
+In other parts of selftest, e.g., [1], sample_freq is used instead. So I
+decided to use sample_freq = 1,000 since the test can pass as well.
+
+ [1] https://lore.kernel.org/bpf/20240604070700.3032142-1-song@kernel.org/
+
+Reported-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20240605201203.2603846-1-yonghong.song@linux.dev
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/prog_tests/send_signal.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
+index 920aee41bd58c..6cc69900b3106 100644
+--- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
++++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
+@@ -156,7 +156,8 @@ static void test_send_signal_tracepoint(bool signal_thread)
+ static void test_send_signal_perf(bool signal_thread)
+ {
+ struct perf_event_attr attr = {
+- .sample_period = 1,
++ .freq = 1,
++ .sample_freq = 1000,
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ };
+--
+2.43.0
+
--- /dev/null
+From d9b11444b59d3863a586715d1b6e7adef7d12781 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 12:29:28 +0200
+Subject: selftests: ksft: Fix finished() helper exit code on skipped tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Laura Nao <laura.nao@collabora.com>
+
+[ Upstream commit 170c966cbe274e664288cfc12ee919d5e706dc50 ]
+
+The Python finished() helper currently exits with KSFT_FAIL when there
+are only passed and skipped tests. Fix the logic to exit with KSFT_PASS
+instead, making it consistent with its C and bash counterparts
+(ksft_finished() and ktap_finished() respectively).
+
+Reviewed-by: NÃcolas F. R. A. Prado <nfraprado@collabora.com>
+Fixes: dacf1d7a78bf ("kselftest: Add test to verify probe of devices from discoverable buses")
+Signed-off-by: Laura Nao <laura.nao@collabora.com>
+Reviewed-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/devices/ksft.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/devices/ksft.py b/tools/testing/selftests/devices/ksft.py
+index cd89fb2bc10e7..bf215790a89d7 100644
+--- a/tools/testing/selftests/devices/ksft.py
++++ b/tools/testing/selftests/devices/ksft.py
+@@ -70,7 +70,7 @@ def test_result(condition, description=""):
+
+
+ def finished():
+- if ksft_cnt["pass"] == ksft_num_tests:
++ if ksft_cnt["pass"] + ksft_cnt["skip"] == ksft_num_tests:
+ exit_code = KSFT_PASS
+ else:
+ exit_code = KSFT_FAIL
+--
+2.43.0
+
--- /dev/null
+From 469e6fe99988649029b7f136218d5c3d8854e705 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:05:58 +0200
+Subject: selftests: mptcp: join: ability to invert ADD_ADDR check
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit bec1f3b119ebc613d08dfbcdbaef01a79aa7de92 ]
+
+In the following commit, the client will initiate the ADD_ADDR, instead
+of the server. We need to way to verify the ADD_ADDR have been correctly
+sent.
+
+Note: the default expected counters for when the port number is given
+are never changed by the caller, no need to accept them as parameter
+then.
+
+The 'Fixes' tag here below is the same as the one from the previous
+commit: this patch here is not fixing anything wrong in the selftests,
+but it validates the previous fix for an issue introduced by this commit
+ID.
+
+Fixes: 86e39e04482b ("mptcp: keep track of local endpoint still available for each msk")
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-6-c8a9b036493b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../testing/selftests/net/mptcp/mptcp_join.sh | 40 ++++++++++++-------
+ 1 file changed, 26 insertions(+), 14 deletions(-)
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index 7043984b7e74a..8ab350059ce10 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -1415,18 +1415,28 @@ chk_add_nr()
+ local add_nr=$1
+ local echo_nr=$2
+ local port_nr=${3:-0}
+- local syn_nr=${4:-$port_nr}
+- local syn_ack_nr=${5:-$port_nr}
+- local ack_nr=${6:-$port_nr}
+- local mis_syn_nr=${7:-0}
+- local mis_ack_nr=${8:-0}
++ local ns_invert=${4:-""}
++ local syn_nr=$port_nr
++ local syn_ack_nr=$port_nr
++ local ack_nr=$port_nr
++ local mis_syn_nr=0
++ local mis_ack_nr=0
++ local ns_tx=$ns1
++ local ns_rx=$ns2
++ local extra_msg=""
+ local count
+ local timeout
+
+- timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
++ if [[ $ns_invert = "invert" ]]; then
++ ns_tx=$ns2
++ ns_rx=$ns1
++ extra_msg="invert"
++ fi
++
++ timeout=$(ip netns exec ${ns_tx} sysctl -n net.mptcp.add_addr_timeout)
+
+ print_check "add"
+- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtAddAddr")
++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr")
+ if [ -z "$count" ]; then
+ print_skip
+ # if the test configured a short timeout tolerate greater then expected
+@@ -1438,7 +1448,7 @@ chk_add_nr()
+ fi
+
+ print_check "echo"
+- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtEchoAdd")
++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$echo_nr" ]; then
+@@ -1449,7 +1459,7 @@ chk_add_nr()
+
+ if [ $port_nr -gt 0 ]; then
+ print_check "pt"
+- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtPortAdd")
++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$port_nr" ]; then
+@@ -1459,7 +1469,7 @@ chk_add_nr()
+ fi
+
+ print_check "syn"
+- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortSynRx")
++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$syn_nr" ]; then
+@@ -1470,7 +1480,7 @@ chk_add_nr()
+ fi
+
+ print_check "synack"
+- count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinPortSynAckRx")
++ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$syn_ack_nr" ]; then
+@@ -1481,7 +1491,7 @@ chk_add_nr()
+ fi
+
+ print_check "ack"
+- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinPortAckRx")
++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$ack_nr" ]; then
+@@ -1492,7 +1502,7 @@ chk_add_nr()
+ fi
+
+ print_check "syn"
+- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortSynRx")
++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$mis_syn_nr" ]; then
+@@ -1503,7 +1513,7 @@ chk_add_nr()
+ fi
+
+ print_check "ack"
+- count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMismatchPortAckRx")
++ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx")
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$mis_ack_nr" ]; then
+@@ -1513,6 +1523,8 @@ chk_add_nr()
+ print_ok
+ fi
+ fi
++
++ print_info "$extra_msg"
+ }
+
+ chk_add_tx_nr()
+--
+2.43.0
+
--- /dev/null
+From 3cc461a175266db86d3e3918e915988108c8953c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 13:05:59 +0200
+Subject: selftests: mptcp: join: test both signal & subflow
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit 4d2868b5d191c74262f7407972d68d1bf3245d6a ]
+
+It should be quite uncommon to set both the subflow and the signal
+flags: the initiator of the connection is typically the one creating new
+subflows, not the other peer, then no need to announce additional local
+addresses, and use it to create subflows.
+
+But some people might be confused about the flags, and set both "just to
+be sure at least the right one is set". To verify the previous fix, and
+avoid future regressions, this specific case is now validated: the
+client announces a new address, and initiates a new subflow from the
+same address.
+
+While working on this, another bug has been noticed, where the client
+reset the new subflow because an ADD_ADDR echo got received as the 3rd
+ACK: this new test also explicitly checks that no RST have been sent by
+the client and server.
+
+The 'Fixes' tag here below is the same as the one from the previous
+commit: this patch here is not fixing anything wrong in the selftests,
+but it validates the previous fix for an issue introduced by this commit
+ID.
+
+Fixes: 86e39e04482b ("mptcp: keep track of local endpoint still available for each msk")
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-7-c8a9b036493b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/mptcp_join.sh | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index 8ab350059ce10..a3293043c85dd 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -1989,6 +1989,21 @@ signal_address_tests()
+ chk_add_nr 1 1
+ fi
+
++ # uncommon: subflow and signal flags on the same endpoint
++ # or because the user wrongly picked both, but still expects the client
++ # to create additional subflows
++ if reset "subflow and signal together"; then
++ pm_nl_set_limits $ns1 0 2
++ pm_nl_set_limits $ns2 0 2
++ pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow
++ run_tests $ns1 $ns2 10.0.1.1
++ chk_join_nr 1 1 1
++ chk_add_nr 1 1 0 invert # only initiated by ns2
++ chk_add_nr 0 0 0 # none initiated by ns1
++ chk_rst_nr 0 0 invert # no RST sent by the client
++ chk_rst_nr 0 0 # no RST sent by the server
++ fi
++
+ # accept and use add_addr with additional subflows
+ if reset "multiple subflows and signal"; then
+ pm_nl_set_limits $ns1 0 3
+--
+2.43.0
+
drm-amd-display-refactor-function-dm_dp_mst_is_port_support_mode.patch
+locking-pvqspinlock-correct-the-type-of-old-variable.patch
+perf-x86-intel-cstate-add-arrowlake-support.patch
+perf-x86-intel-cstate-add-lunarlake-support.patch
+perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch
+platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch
+irqchip-mbigen-fix-mbigen-node-address-layout.patch
+platform-x86-intel-ifs-initialize-union-ifs_status-t.patch
+jump_label-fix-the-fix-brown-paper-bags-galore.patch
+perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch
+perf-x86-intel-support-the-pebs-event-mask.patch
+perf-x86-support-counter-mask.patch
+perf-x86-fix-smp_processor_id-in-preemptible-warning.patch
+selftests-ksft-fix-finished-helper-exit-code-on-skip.patch
+x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch
+x86-mm-fix-pti_clone_entry_text-for-i386.patch
+smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch
+power-supply-rt5033-bring-back-i2c_set_clientdata.patch
+selftests-mptcp-join-ability-to-invert-add_addr-chec.patch
+selftests-mptcp-join-test-both-signal-subflow.patch
+sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch
+net-pse-pd-tps23881-fix-the-device-id-check.patch
+gve-fix-use-of-netif_carrier_ok.patch
+virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch
+net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch
+net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch
+net-linkwatch-use-system_unbound_wq.patch
+net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch
+ice-fix-reset-handler.patch
+bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch
+bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch
+net-smc-add-the-max-value-of-fallback-reason-count.patch
+net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch
+bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch
+idpf-fix-memory-leaks-and-crashes-while-performing-a.patch
+idpf-fix-uafs-when-destroying-the-queues.patch
+l2tp-fix-lockdep-splat.patch
+net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch
+net-fec-stop-pps-on-driver-remove.patch
+net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch
+net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch
+regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch
+gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch
+hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch
+revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch
+platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch
+rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch
+md-do-not-delete-safemode_timer-in-mddev_suspend.patch
+md-change-the-return-value-type-of-md_write_start-to.patch
+md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch
+debugobjects-annotate-racy-debug-variables.patch
+nvme-apple-fix-device-reference-counting.patch
+block-change-rq_integrity_vec-to-respect-the-iterato.patch
+irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch
+rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch
+clocksource-drivers-sh_cmt-address-race-condition-fo.patch
+acpi-battery-create-alarm-sysfs-attribute-atomically.patch
+acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch
+cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch
+cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch
+soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch
+xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch
+acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch
+acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833
+thermal-intel-hfi-give-hfi-instances-package-scope.patch
+wifi-nl80211-disallow-setting-special-ap-channel-wid.patch
+wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch
+r8169-remove-detection-of-chip-version-11-early-rtl8.patch
+wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch
+wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch
+net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch
+selftests-bpf-fix-send_signal-test-with-nested-confi.patch
+rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch
+wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch
+net-reference-bpf_redirect_info-via-task_struct-on-p.patch
+af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch
+pci-add-edimax-vendor-id-to-pci_ids.h.patch
+wifi-mac80211-fix-null-dereference-at-band-check-in-.patch
+udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch
+bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch
+wifi-nl80211-don-t-give-key-data-to-userspace.patch
+can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch
+can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch
+net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch
+mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch
+btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch
+btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch
+btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch
+btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch
+btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch
+bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch
+drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch
+drm-amd-display-handle-hpd_irq-for-internal-link.patch
+drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch
+drm-amdgpu-fix-potential-resource-leak-warning.patch
+drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch
+drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch
+drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch
+drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch
+drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch
+drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch
+drm-admgpu-fix-dereferencing-null-pointer-context.patch
+drm-amdgpu-add-lock-around-vf-rlcg-interface.patch
+drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch
+drm-amd-display-add-null-checks-for-stream-and-plane.patch
+media-amphion-remove-lock-in-s_ctrl-callback.patch
+drm-amd-display-add-null-check-for-afb-before-derefe.patch
+drm-amd-display-wake-dmcub-before-sending-a-command-.patch
+drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch
+drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch
+drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch
+drm-amd-display-add-null-checker-before-passing-vari.patch
+media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch
+media-uvcvideo-ignore-empty-ts-packets.patch
+media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch
+drm-amd-display-fix-null-pointer-dereference-for-dtn.patch
+media-xc2028-avoid-use-after-free-in-load_firmware_c.patch
+ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch
+jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch
+drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch
+s390-sclp-prevent-release-of-buffer-in-i-o.patch
+ext4-sanity-check-for-null-pointer-after-ext4_force_.patch
+sunrpc-fix-a-race-to-wake-a-sync-task.patch
--- /dev/null
+From 9a7075723424ef12129d1a1b93d081871fa45c80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 10:23:39 -0300
+Subject: smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+[ Upstream commit 4b96024ef2296b1d323af327cae5e52809b61420 ]
+
+As per MS-FSA 2.1.5.10.14, support for FSCTL_GET_REPARSE_POINT is
+optional and if the server doesn't support it,
+STATUS_INVALID_DEVICE_REQUEST must be returned for the operation.
+
+If we find files with reparse points and we can't read them due to
+lack of client or server support, just ignore it and then treat them
+as regular files or junctions.
+
+Fixes: 5f71ebc41294 ("smb: client: parse reparse point flag in create response")
+Reported-by: Sebastian Steinbeisser <Sebastian.Steinbeisser@lrz.de>
+Tested-by: Sebastian Steinbeisser <Sebastian.Steinbeisser@lrz.de>
+Acked-by: Tom Talpey <tom@talpey.com>
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/inode.c | 17 +++++++++++++++--
+ fs/smb/client/reparse.c | 4 ++++
+ fs/smb/client/reparse.h | 19 +++++++++++++++++--
+ fs/smb/client/smb2inode.c | 2 ++
+ 4 files changed, 38 insertions(+), 4 deletions(-)
+
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index 4a8aa1de95223..dd0afa23734c8 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -1042,13 +1042,26 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
+ }
+
+ rc = -EOPNOTSUPP;
+- switch ((data->reparse.tag = tag)) {
+- case 0: /* SMB1 symlink */
++ data->reparse.tag = tag;
++ if (!data->reparse.tag) {
+ if (server->ops->query_symlink) {
+ rc = server->ops->query_symlink(xid, tcon,
+ cifs_sb, full_path,
+ &data->symlink_target);
+ }
++ if (rc == -EOPNOTSUPP)
++ data->reparse.tag = IO_REPARSE_TAG_INTERNAL;
++ }
++
++ switch (data->reparse.tag) {
++ case 0: /* SMB1 symlink */
++ break;
++ case IO_REPARSE_TAG_INTERNAL:
++ rc = 0;
++ if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
++ cifs_create_junction_fattr(fattr, sb);
++ goto out;
++ }
+ break;
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ cifs_create_junction_fattr(fattr, sb);
+diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
+index a0ffbda907331..689d8a506d459 100644
+--- a/fs/smb/client/reparse.c
++++ b/fs/smb/client/reparse.c
+@@ -505,6 +505,10 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
+ }
+
+ switch (tag) {
++ case IO_REPARSE_TAG_INTERNAL:
++ if (!(fattr->cf_cifsattrs & ATTR_DIRECTORY))
++ return false;
++ fallthrough;
+ case IO_REPARSE_TAG_DFS:
+ case IO_REPARSE_TAG_DFSR:
+ case IO_REPARSE_TAG_MOUNT_POINT:
+diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
+index 6b55d1df9e2f8..2c0644bc4e65a 100644
+--- a/fs/smb/client/reparse.h
++++ b/fs/smb/client/reparse.h
+@@ -12,6 +12,12 @@
+ #include "fs_context.h"
+ #include "cifsglob.h"
+
++/*
++ * Used only by cifs.ko to ignore reparse points from files when client or
++ * server doesn't support FSCTL_GET_REPARSE_POINT.
++ */
++#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U)
++
+ static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
+ {
+ u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
+@@ -78,10 +84,19 @@ static inline u32 reparse_mode_wsl_tag(mode_t mode)
+ static inline bool reparse_inode_match(struct inode *inode,
+ struct cifs_fattr *fattr)
+ {
++ struct cifsInodeInfo *cinode = CIFS_I(inode);
+ struct timespec64 ctime = inode_get_ctime(inode);
+
+- return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) &&
+- CIFS_I(inode)->reparse_tag == fattr->cf_cifstag &&
++ /*
++ * Do not match reparse tags when client or server doesn't support
++ * FSCTL_GET_REPARSE_POINT. @fattr->cf_cifstag should contain correct
++ * reparse tag from query dir response but the client won't be able to
++ * read the reparse point data anyway. This spares us a revalidation.
++ */
++ if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
++ cinode->reparse_tag != fattr->cf_cifstag)
++ return false;
++ return (cinode->cifsAttrs & ATTR_REPARSE) &&
+ timespec64_equal(&ctime, &fattr->cf_ctime);
+ }
+
+diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
+index 5c02a12251c84..062b86a4936fd 100644
+--- a/fs/smb/client/smb2inode.c
++++ b/fs/smb/client/smb2inode.c
+@@ -930,6 +930,8 @@ int smb2_query_path_info(const unsigned int xid,
+
+ switch (rc) {
+ case 0:
++ rc = parse_create_response(data, cifs_sb, &out_iov[0]);
++ break;
+ case -EOPNOTSUPP:
+ /*
+ * BB TODO: When support for special files added to Samba
+--
+2.43.0
+
--- /dev/null
+From c0664fb300408b27a12b709a39a168c2e3c3cd07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jun 2024 14:52:13 +0530
+Subject: soc: qcom: icc-bwmon: Allow for interrupts to be shared across
+ instances
+
+From: Sibi Sankar <quic_sibis@quicinc.com>
+
+[ Upstream commit dc18836435e7f8dda019db2c618c69194933157f ]
+
+The multiple BWMONv4 instances available on the X1E80100 SoC use the
+same interrupt number. Mark them are shared to allow for re-use across
+instances.
+
+Using IRQF_SHARED coupled with devm_request_threaded_irq implies that
+the irq can still trigger during/after bwmon_remove due to other active
+bwmon instances. Handle this race by relying on bwmon_disable to disable
+the interrupt and coupled with explicit request/free irqs.
+
+Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20240624092214.146935-4-quic_sibis@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/icc-bwmon.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
+index ecddb60bd6650..e7851974084b6 100644
+--- a/drivers/soc/qcom/icc-bwmon.c
++++ b/drivers/soc/qcom/icc-bwmon.c
+@@ -783,9 +783,14 @@ static int bwmon_probe(struct platform_device *pdev)
+ bwmon->dev = dev;
+
+ bwmon_disable(bwmon);
+- ret = devm_request_threaded_irq(dev, bwmon->irq, bwmon_intr,
+- bwmon_intr_thread,
+- IRQF_ONESHOT, dev_name(dev), bwmon);
++
++ /*
++ * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt
++ * line. Using the devm_ variant might result in the IRQ handler being executed
++ * after bwmon_disable in bwmon_remove()
++ */
++ ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread,
++ IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), bwmon);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to request IRQ\n");
+
+@@ -800,6 +805,7 @@ static void bwmon_remove(struct platform_device *pdev)
+ struct icc_bwmon *bwmon = platform_get_drvdata(pdev);
+
+ bwmon_disable(bwmon);
++ free_irq(bwmon->irq, bwmon);
+ }
+
+ static const struct icc_bwmon_data msm8998_bwmon_data = {
+--
+2.43.0
+
--- /dev/null
+From ac69c54756981d59319f63c63598c30005cf18d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jul 2024 10:49:33 -0400
+Subject: SUNRPC: Fix a race to wake a sync task
+
+From: Benjamin Coddington <bcodding@redhat.com>
+
+[ Upstream commit ed0172af5d6fc07d1b40ca82f5ca3979300369f7 ]
+
+We've observed NFS clients with sync tasks sleeping in __rpc_execute
+waiting on RPC_TASK_QUEUED that have not responded to a wake-up from
+rpc_make_runnable(). I suspect this problem usually goes unnoticed,
+because on a busy client the task will eventually be re-awoken by another
+task completion or xprt event. However, if the state manager is draining
+the slot table, a sync task missing a wake-up can result in a hung client.
+
+We've been able to prove that the waker in rpc_make_runnable() successfully
+calls wake_up_bit() (ie- there's no race to tk_runstate), but the
+wake_up_bit() call fails to wake the waiter. I suspect the waker is
+missing the load of the bit's wait_queue_head, so waitqueue_active() is
+false. There are some very helpful comments about this problem above
+wake_up_bit(), prepare_to_wait(), and waitqueue_active().
+
+Fix this by inserting smp_mb__after_atomic() before the wake_up_bit(),
+which pairs with prepare_to_wait() calling set_current_state().
+
+Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sunrpc/sched.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 6debf4fd42d4e..cef623ea15060 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -369,8 +369,10 @@ static void rpc_make_runnable(struct workqueue_struct *wq,
+ if (RPC_IS_ASYNC(task)) {
+ INIT_WORK(&task->u.tk_work, rpc_async_schedule);
+ queue_work(wq, &task->u.tk_work);
+- } else
++ } else {
++ smp_mb__after_atomic();
+ wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED);
++ }
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 2ec2adabc97a9bdb14c023d44ce6706c8265be4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jul 2024 13:54:45 +0800
+Subject: thermal: intel: hfi: Give HFI instances package scope
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit b755367602d70deade956cbe0b8a3f5a12f569dc ]
+
+The Intel Software Developer's Manual defines the scope of HFI (registers
+and memory buffer) as a package. Use package scope(*) in the software
+representation of an HFI instance.
+
+Using die scope in HFI instances has the effect of creating multiple
+conflicting instances for the same package: each instance allocates its
+own memory buffer and configures the same package-level registers.
+Specifically, only one of the allocated memory buffers can be set in the
+MSR_IA32_HW_FEEDBACK_PTR register. CPUs get incorrect HFI data from the
+table.
+
+The problem does not affect current HFI-capable platforms because they
+all have single-die processors.
+
+(*) We used die scope for HFI instances because there had been
+ processors with packages enumerated as dies. None of those systems
+ supported HFI, though. If such a system emerged, it would need to
+ be quirked.
+
+Co-developed-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Reviewed-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+Link: https://patch.msgid.link/20240703055445.125362-1-rui.zhang@intel.com
+[ rjw: Changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/intel/intel_hfi.c | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c
+index a180a98bb9f15..5b18a46a10b06 100644
+--- a/drivers/thermal/intel/intel_hfi.c
++++ b/drivers/thermal/intel/intel_hfi.c
+@@ -401,10 +401,10 @@ static void hfi_disable(void)
+ * intel_hfi_online() - Enable HFI on @cpu
+ * @cpu: CPU in which the HFI will be enabled
+ *
+- * Enable the HFI to be used in @cpu. The HFI is enabled at the die/package
+- * level. The first CPU in the die/package to come online does the full HFI
++ * Enable the HFI to be used in @cpu. The HFI is enabled at the package
++ * level. The first CPU in the package to come online does the full HFI
+ * initialization. Subsequent CPUs will just link themselves to the HFI
+- * instance of their die/package.
++ * instance of their package.
+ *
+ * This function is called before enabling the thermal vector in the local APIC
+ * in order to ensure that @cpu has an associated HFI instance when it receives
+@@ -414,31 +414,31 @@ void intel_hfi_online(unsigned int cpu)
+ {
+ struct hfi_instance *hfi_instance;
+ struct hfi_cpu_info *info;
+- u16 die_id;
++ u16 pkg_id;
+
+ /* Nothing to do if hfi_instances are missing. */
+ if (!hfi_instances)
+ return;
+
+ /*
+- * Link @cpu to the HFI instance of its package/die. It does not
++ * Link @cpu to the HFI instance of its package. It does not
+ * matter whether the instance has been initialized.
+ */
+ info = &per_cpu(hfi_cpu_info, cpu);
+- die_id = topology_logical_die_id(cpu);
++ pkg_id = topology_logical_package_id(cpu);
+ hfi_instance = info->hfi_instance;
+ if (!hfi_instance) {
+- if (die_id >= max_hfi_instances)
++ if (pkg_id >= max_hfi_instances)
+ return;
+
+- hfi_instance = &hfi_instances[die_id];
++ hfi_instance = &hfi_instances[pkg_id];
+ info->hfi_instance = hfi_instance;
+ }
+
+ init_hfi_cpu_index(info);
+
+ /*
+- * Now check if the HFI instance of the package/die of @cpu has been
++ * Now check if the HFI instance of the package of @cpu has been
+ * initialized (by checking its header). In such case, all we have to
+ * do is to add @cpu to this instance's cpumask and enable the instance
+ * if needed.
+@@ -504,7 +504,7 @@ void intel_hfi_online(unsigned int cpu)
+ *
+ * On some processors, hardware remembers previous programming settings even
+ * after being reprogrammed. Thus, keep HFI enabled even if all CPUs in the
+- * die/package of @cpu are offline. See note in intel_hfi_online().
++ * package of @cpu are offline. See note in intel_hfi_online().
+ */
+ void intel_hfi_offline(unsigned int cpu)
+ {
+@@ -674,9 +674,13 @@ void __init intel_hfi_init(void)
+ if (hfi_parse_features())
+ return;
+
+- /* There is one HFI instance per die/package. */
+- max_hfi_instances = topology_max_packages() *
+- topology_max_dies_per_package();
++ /*
++ * Note: HFI resources are managed at the physical package scope.
++ * There could be platforms that enumerate packages as Linux dies.
++ * Special handling would be needed if this happens on an HFI-capable
++ * platform.
++ */
++ max_hfi_instances = topology_max_packages();
+
+ /*
+ * This allocation may fail. CPU hotplug callbacks must check
+--
+2.43.0
+
--- /dev/null
+From 7037c8e9ddb173ac89ddeef484fccf17f5d15bde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jun 2024 10:24:13 +0300
+Subject: udf: prevent integer overflow in udf_bitmap_free_blocks()
+
+From: Roman Smirnov <r.smirnov@omp.ru>
+
+[ Upstream commit 56e69e59751d20993f243fb7dd6991c4e522424c ]
+
+An overflow may occur if the function is called with the last
+block and an offset greater than zero. It is necessary to add
+a check to avoid this.
+
+Found by Linux Verification Center (linuxtesting.org) with Svace.
+
+[JK: Make test cover also unalloc table freeing]
+
+Link: https://patch.msgid.link/20240620072413.7448-1-r.smirnov@omp.ru
+Suggested-by: Jan Kara <jack@suse.com>
+Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/udf/balloc.c | 36 +++++++++++++-----------------------
+ 1 file changed, 13 insertions(+), 23 deletions(-)
+
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index 558ad046972ad..bb471ec364046 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -18,6 +18,7 @@
+ #include "udfdecl.h"
+
+ #include <linux/bitops.h>
++#include <linux/overflow.h>
+
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -140,7 +141,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
+ {
+ struct udf_sb_info *sbi = UDF_SB(sb);
+ struct buffer_head *bh = NULL;
+- struct udf_part_map *partmap;
+ unsigned long block;
+ unsigned long block_group;
+ unsigned long bit;
+@@ -149,19 +149,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
+ unsigned long overflow;
+
+ mutex_lock(&sbi->s_alloc_mutex);
+- partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
+- if (bloc->logicalBlockNum + count < count ||
+- (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
+- udf_debug("%u < %d || %u + %u > %u\n",
+- bloc->logicalBlockNum, 0,
+- bloc->logicalBlockNum, count,
+- partmap->s_partition_len);
+- goto error_return;
+- }
+-
++ /* We make sure this cannot overflow when mounting the filesystem */
+ block = bloc->logicalBlockNum + offset +
+ (sizeof(struct spaceBitmapDesc) << 3);
+-
+ do {
+ overflow = 0;
+ block_group = block >> (sb->s_blocksize_bits + 3);
+@@ -391,7 +381,6 @@ static void udf_table_free_blocks(struct super_block *sb,
+ uint32_t count)
+ {
+ struct udf_sb_info *sbi = UDF_SB(sb);
+- struct udf_part_map *partmap;
+ uint32_t start, end;
+ uint32_t elen;
+ struct kernel_lb_addr eloc;
+@@ -400,16 +389,6 @@ static void udf_table_free_blocks(struct super_block *sb,
+ struct udf_inode_info *iinfo;
+
+ mutex_lock(&sbi->s_alloc_mutex);
+- partmap = &sbi->s_partmaps[bloc->partitionReferenceNum];
+- if (bloc->logicalBlockNum + count < count ||
+- (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
+- udf_debug("%u < %d || %u + %u > %u\n",
+- bloc->logicalBlockNum, 0,
+- bloc->logicalBlockNum, count,
+- partmap->s_partition_len);
+- goto error_return;
+- }
+-
+ iinfo = UDF_I(table);
+ udf_add_free_space(sb, sbi->s_partition, count);
+
+@@ -684,6 +663,17 @@ void udf_free_blocks(struct super_block *sb, struct inode *inode,
+ {
+ uint16_t partition = bloc->partitionReferenceNum;
+ struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
++ uint32_t blk;
++
++ if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) ||
++ check_add_overflow(blk, count, &blk) ||
++ bloc->logicalBlockNum + count > map->s_partition_len) {
++ udf_debug("Invalid request to free blocks: (%d, %u), off %u, "
++ "len %u, partition len %u\n",
++ partition, bloc->logicalBlockNum, offset, count,
++ map->s_partition_len);
++ return;
++ }
+
+ if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
+ udf_bitmap_free_blocks(sb, map->s_uspace.s_bitmap,
+--
+2.43.0
+
--- /dev/null
+From 7f6adfb3e6f58e0744f80dec409f7dac7a881e4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 21:23:38 +0800
+Subject: virtio-net: unbreak vq resizing when coalescing is not negotiated
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heng Qi <hengqi@linux.alibaba.com>
+
+[ Upstream commit 4ba8d97083707409822264fd1776aad7233f353e ]
+
+Don't break the resize action if the vq coalescing feature
+named VIRTIO_NET_F_VQ_NOTF_COAL is not negotiated.
+
+Fixes: f61fe5f081cf ("virtio-net: fix the vq coalescing setting for vq resize")
+Signed-off-by: Heng Qi <hengqi@linux.alibaba.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Acked-by: Eugenio Pé rez <eperezma@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/virtio_net.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 5161e7efda2cb..f32e017b62e9b 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3257,7 +3257,11 @@ static int virtnet_set_ringparam(struct net_device *dev,
+ err = virtnet_send_tx_ctrl_coal_vq_cmd(vi, i,
+ vi->intr_coal_tx.max_usecs,
+ vi->intr_coal_tx.max_packets);
+- if (err)
++
++ /* Don't break the tx resize action if the vq coalescing is not
++ * supported. The same is true for rx resize below.
++ */
++ if (err && err != -EOPNOTSUPP)
+ return err;
+ }
+
+@@ -3272,7 +3276,7 @@ static int virtnet_set_ringparam(struct net_device *dev,
+ vi->intr_coal_rx.max_usecs,
+ vi->intr_coal_rx.max_packets);
+ mutex_unlock(&vi->rq[i].dim_lock);
+- if (err)
++ if (err && err != -EOPNOTSUPP)
+ return err;
+ }
+ }
+--
+2.43.0
+
--- /dev/null
+From ff178d8b532a407e5ef2a9c4c5b6636a28ffb4f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 May 2024 20:42:26 +0800
+Subject: wifi: ath12k: fix memory leak in ath12k_dp_rx_peer_frag_setup()
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 3d60041543189438cd1b03a1fa40ff6681c77970 ]
+
+Currently the resource allocated by crypto_alloc_shash() is not
+freed in case ath12k_peer_find() fails, resulting in memory leak.
+
+Add crypto_free_shash() to fix it.
+
+This is found during code review, compile tested only.
+
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://msgid.link/20240526124226.24661-1-quic_bqiang@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp_rx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
+index 121f27284be59..1d287ed25a949 100644
+--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
+@@ -2793,6 +2793,7 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
+ peer = ath12k_peer_find(ab, vdev_id, peer_mac);
+ if (!peer) {
+ spin_unlock_bh(&ab->base_lock);
++ crypto_free_shash(tfm);
+ ath12k_warn(ab, "failed to find the peer to set up fragment info\n");
+ return -ENOENT;
+ }
+--
+2.43.0
+
--- /dev/null
+From 0fc79574406532ac31165c556c8cc8365bcabb53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 10:36:42 +0800
+Subject: wifi: ath12k: fix race due to setting ATH12K_FLAG_EXT_IRQ_ENABLED too
+ early
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 0a993772e0f0934d730c0d451622c80e03a40ab1 ]
+
+Commit 5082b3e3027e ("wifi: ath11k: fix race due to setting
+ATH11K_FLAG_EXT_IRQ_ENABLED too early") fixes a race in ath11k
+driver. Since ath12k shares the same logic as ath11k, currently
+the race also exists in ath12k: in ath12k_pci_ext_irq_enable(),
+ATH12K_FLAG_EXT_IRQ_ENABLED is set before NAPI is enabled.
+In cases where only one MSI vector is allocated, this results
+in a race condition: after ATH12K_FLAG_EXT_IRQ_ENABLED is set
+but before NAPI enabled, CE interrupt breaks in. Since IRQ is
+shared by CE and data path, ath12k_pci_ext_interrupt_handler()
+is also called where we call disable_irq_nosync() to disable
+IRQ. Then napi_schedule() is called but it does nothing because
+NAPI is not enabled at that time, meaning that
+ath12k_pci_ext_grp_napi_poll() will never run, so we have
+no chance to call enable_irq() to enable IRQ back. Since IRQ
+is shared, all interrupts are disabled and we would finally
+get no response from target.
+
+So port ath11k fix here, this is done by setting
+ATH12K_FLAG_EXT_IRQ_ENABLED after all NAPI and IRQ work are
+done. With the fix, we are sure that by the time
+ATH12K_FLAG_EXT_IRQ_ENABLED is set, NAPI is enabled.
+
+Note that the fix above also introduce some side effects:
+if ath12k_pci_ext_interrupt_handler() breaks in after NAPI
+enabled but before ATH12K_FLAG_EXT_IRQ_ENABLED set, nothing
+will be done by the handler this time, the work will be
+postponed till the next time the IRQ fires.
+
+This is found during code review.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
+
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://msgid.link/20240524023642.37030-1-quic_bqiang@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/pci.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index 55fde0d33183c..f92b4ce49dfd4 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -1091,14 +1091,14 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab)
+ {
+ int i;
+
+- set_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
+-
+ for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
+ struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
+
+ napi_enable(&irq_grp->napi);
+ ath12k_pci_ext_grp_enable(irq_grp);
+ }
++
++ set_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
+ }
+
+ void ath12k_pci_ext_irq_disable(struct ath12k_base *ab)
+--
+2.43.0
+
--- /dev/null
+From 3d948b9ac5f1492d6a0cc4165c3c33f8139e1bfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 19:52:17 +0800
+Subject: wifi: mac80211: fix NULL dereference at band check in starting tx ba
+ session
+
+From: Zong-Zhe Yang <kevin_yang@realtek.com>
+
+[ Upstream commit 021d53a3d87eeb9dbba524ac515651242a2a7e3b ]
+
+In MLD connection, link_data/link_conf are dynamically allocated. They
+don't point to vif->bss_conf. So, there will be no chanreq assigned to
+vif->bss_conf and then the chan will be NULL. Tweak the code to check
+ht_supported/vht_supported/has_he/has_eht on sta deflink.
+
+Crash log (with rtw89 version under MLO development):
+[ 9890.526087] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[ 9890.526102] #PF: supervisor read access in kernel mode
+[ 9890.526105] #PF: error_code(0x0000) - not-present page
+[ 9890.526109] PGD 0 P4D 0
+[ 9890.526114] Oops: 0000 [#1] PREEMPT SMP PTI
+[ 9890.526119] CPU: 2 PID: 6367 Comm: kworker/u16:2 Kdump: loaded Tainted: G OE 6.9.0 #1
+[ 9890.526123] Hardware name: LENOVO 2356AD1/2356AD1, BIOS G7ETB3WW (2.73 ) 11/28/2018
+[ 9890.526126] Workqueue: phy2 rtw89_core_ba_work [rtw89_core]
+[ 9890.526203] RIP: 0010:ieee80211_start_tx_ba_session (net/mac80211/agg-tx.c:618 (discriminator 1)) mac80211
+[ 9890.526279] Code: f7 e8 d5 93 3e ea 48 83 c4 28 89 d8 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 49 8b 84 24 e0 f1 ff ff 48 8b 80 90 1b 00 00 <83> 38 03 0f 84 37 fe ff ff bb ea ff ff ff eb cc 49 8b 84 24 10 f3
+All code
+========
+ 0: f7 e8 imul %eax
+ 2: d5 (bad)
+ 3: 93 xchg %eax,%ebx
+ 4: 3e ea ds (bad)
+ 6: 48 83 c4 28 add $0x28,%rsp
+ a: 89 d8 mov %ebx,%eax
+ c: 5b pop %rbx
+ d: 41 5c pop %r12
+ f: 41 5d pop %r13
+ 11: 41 5e pop %r14
+ 13: 41 5f pop %r15
+ 15: 5d pop %rbp
+ 16: c3 retq
+ 17: cc int3
+ 18: cc int3
+ 19: cc int3
+ 1a: cc int3
+ 1b: 49 8b 84 24 e0 f1 ff mov -0xe20(%r12),%rax
+ 22: ff
+ 23: 48 8b 80 90 1b 00 00 mov 0x1b90(%rax),%rax
+ 2a:* 83 38 03 cmpl $0x3,(%rax) <-- trapping instruction
+ 2d: 0f 84 37 fe ff ff je 0xfffffffffffffe6a
+ 33: bb ea ff ff ff mov $0xffffffea,%ebx
+ 38: eb cc jmp 0x6
+ 3a: 49 rex.WB
+ 3b: 8b .byte 0x8b
+ 3c: 84 24 10 test %ah,(%rax,%rdx,1)
+ 3f: f3 repz
+
+Code starting with the faulting instruction
+===========================================
+ 0: 83 38 03 cmpl $0x3,(%rax)
+ 3: 0f 84 37 fe ff ff je 0xfffffffffffffe40
+ 9: bb ea ff ff ff mov $0xffffffea,%ebx
+ e: eb cc jmp 0xffffffffffffffdc
+ 10: 49 rex.WB
+ 11: 8b .byte 0x8b
+ 12: 84 24 10 test %ah,(%rax,%rdx,1)
+ 15: f3 repz
+[ 9890.526285] RSP: 0018:ffffb8db09013d68 EFLAGS: 00010246
+[ 9890.526291] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff9308e0d656c8
+[ 9890.526295] RDX: 0000000000000000 RSI: ffffffffab99460b RDI: ffffffffab9a7685
+[ 9890.526300] RBP: ffffb8db09013db8 R08: 0000000000000000 R09: 0000000000000873
+[ 9890.526304] R10: ffff9308e0d64800 R11: 0000000000000002 R12: ffff9308e5ff6e70
+[ 9890.526308] R13: ffff930952500e20 R14: ffff9309192a8c00 R15: 0000000000000000
+[ 9890.526313] FS: 0000000000000000(0000) GS:ffff930b4e700000(0000) knlGS:0000000000000000
+[ 9890.526316] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 9890.526318] CR2: 0000000000000000 CR3: 0000000391c58005 CR4: 00000000001706f0
+[ 9890.526321] Call Trace:
+[ 9890.526324] <TASK>
+[ 9890.526327] ? show_regs (arch/x86/kernel/dumpstack.c:479)
+[ 9890.526335] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434)
+[ 9890.526340] ? page_fault_oops (arch/x86/mm/fault.c:713)
+[ 9890.526347] ? search_module_extables (kernel/module/main.c:3256 (discriminator 3))
+[ 9890.526353] ? ieee80211_start_tx_ba_session (net/mac80211/agg-tx.c:618 (discriminator 1)) mac80211
+
+Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
+Link: https://patch.msgid.link/20240617115217.22344-1-kevin_yang@realtek.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/agg-tx.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index 21d55dc539f6c..677bbbac9f169 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -616,7 +616,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
+ return -EINVAL;
+
+ if (!pubsta->deflink.ht_cap.ht_supported &&
+- sta->sdata->vif.bss_conf.chanreq.oper.chan->band != NL80211_BAND_6GHZ)
++ !pubsta->deflink.vht_cap.vht_supported &&
++ !pubsta->deflink.he_cap.has_he &&
++ !pubsta->deflink.eht_cap.has_eht)
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(!local->ops->ampdu_action))
+--
+2.43.0
+
--- /dev/null
+From 128d3b9c21d94b6bce2f537c77f5cbc686cef97d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 14:16:00 +0200
+Subject: wifi: nl80211: disallow setting special AP channel widths
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 23daf1b4c91db9b26f8425cc7039cf96d22ccbfe ]
+
+Setting the AP channel width is meant for use with the normal
+20/40/... MHz channel width progression, and switching around
+in S1G or narrow channels isn't supported. Disallow that.
+
+Reported-by: syzbot+bc0f5b92cc7091f45fb6@syzkaller.appspotmail.com
+Link: https://msgid.link/20240515141600.d4a9590bfe32.I19a32d60097e81b527eafe6b0924f6c5fbb2dc45@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 0fd075238fc74..07538be6805ef 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3422,6 +3422,33 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
+ if (chandef.chan != cur_chan)
+ return -EBUSY;
+
++ /* only allow this for regular channel widths */
++ switch (wdev->links[link_id].ap.chandef.width) {
++ case NL80211_CHAN_WIDTH_20_NOHT:
++ case NL80211_CHAN_WIDTH_20:
++ case NL80211_CHAN_WIDTH_40:
++ case NL80211_CHAN_WIDTH_80:
++ case NL80211_CHAN_WIDTH_80P80:
++ case NL80211_CHAN_WIDTH_160:
++ case NL80211_CHAN_WIDTH_320:
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (chandef.width) {
++ case NL80211_CHAN_WIDTH_20_NOHT:
++ case NL80211_CHAN_WIDTH_20:
++ case NL80211_CHAN_WIDTH_40:
++ case NL80211_CHAN_WIDTH_80:
++ case NL80211_CHAN_WIDTH_80P80:
++ case NL80211_CHAN_WIDTH_160:
++ case NL80211_CHAN_WIDTH_320:
++ break;
++ default:
++ return -EINVAL;
++ }
++
+ result = rdev_set_ap_chanwidth(rdev, dev, link_id,
+ &chandef);
+ if (result)
+--
+2.43.0
+
--- /dev/null
+From 9a5a3f985f453310f4d4782f0bd4320f38f66d91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 10:44:11 +0200
+Subject: wifi: nl80211: don't give key data to userspace
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit a7e5793035792cc46a1a4b0a783655ffa897dfe9 ]
+
+When a key is requested by userspace, there's really no need
+to include the key data, the sequence counter is really what
+userspace needs in this case. The fact that it's included is
+just a historic quirk.
+
+Remove the key data.
+
+Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240627104411.b6a4f097e4ea.I7e6cc976cb9e8a80ef25a3351330f313373b4578@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/nl80211.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 07538be6805ef..c2829d673bc76 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4485,10 +4485,7 @@ static void get_key_callback(void *c, struct key_params *params)
+ struct nlattr *key;
+ struct get_key_cookie *cookie = c;
+
+- if ((params->key &&
+- nla_put(cookie->msg, NL80211_ATTR_KEY_DATA,
+- params->key_len, params->key)) ||
+- (params->seq &&
++ if ((params->seq &&
+ nla_put(cookie->msg, NL80211_ATTR_KEY_SEQ,
+ params->seq_len, params->seq)) ||
+ (params->cipher &&
+@@ -4500,10 +4497,7 @@ static void get_key_callback(void *c, struct key_params *params)
+ if (!key)
+ goto nla_put_failure;
+
+- if ((params->key &&
+- nla_put(cookie->msg, NL80211_KEY_DATA,
+- params->key_len, params->key)) ||
+- (params->seq &&
++ if ((params->seq &&
+ nla_put(cookie->msg, NL80211_KEY_SEQ,
+ params->seq_len, params->seq)) ||
+ (params->cipher &&
+--
+2.43.0
+
--- /dev/null
+From bfebd03fbda839faa4cb55256add3d525b7db80a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 May 2024 08:32:48 +0800
+Subject: wifi: rtlwifi: handle return value of usb init TX/RX
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 9c4fde42cce05719120cf892a44b76ff61d908c7 ]
+
+Handle error code to cause failed to USB probe result from unexpected
+USB EP number, otherwise when USB disconnect skb_dequeue() an uninitialized
+skb list and cause warnings below.
+
+usb 2-1: USB disconnect, device number 76
+INFO: trying to register non-static key.
+The code is fine but needs lockdep annotation, or maybe
+you didn't initialize this object before use?
+turning off the locking correctness validator.
+CPU: 0 PID: 54060 Comm: kworker/0:1 Not tainted 6.9.0-rc7 #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014
+Workqueue: usb_hub_wq hub_event
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x116/0x1b0 lib/dump_stack.c:114
+ assign_lock_key kernel/locking/lockdep.c:976 [inline]
+ register_lock_class+0xc18/0xfa0 kernel/locking/lockdep.c:1289
+ __lock_acquire+0x108/0x3bc0 kernel/locking/lockdep.c:5014
+ lock_acquire kernel/locking/lockdep.c:5754 [inline]
+ lock_acquire+0x1b0/0x550 kernel/locking/lockdep.c:5719
+ __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline]
+ _raw_spin_lock_irqsave+0x3d/0x60 kernel/locking/spinlock.c:162
+ skb_dequeue+0x20/0x180 net/core/skbuff.c:3846
+ rtl_usb_cleanup drivers/net/wireless/realtek/rtlwifi/usb.c:706 [inline]
+ rtl_usb_deinit drivers/net/wireless/realtek/rtlwifi/usb.c:721 [inline]
+ rtl_usb_disconnect+0x4a4/0x850 drivers/net/wireless/realtek/rtlwifi/usb.c:1051
+ usb_unbind_interface+0x1e8/0x980 drivers/usb/core/driver.c:461
+ device_remove drivers/base/dd.c:568 [inline]
+ device_remove+0x122/0x170 drivers/base/dd.c:560
+ __device_release_driver drivers/base/dd.c:1270 [inline]
+ device_release_driver_internal+0x443/0x620 drivers/base/dd.c:1293
+ bus_remove_device+0x22f/0x420 drivers/base/bus.c:574
+ device_del+0x395/0x9f0 drivers/base/core.c:3909
+ usb_disable_device+0x360/0x7b0 drivers/usb/core/message.c:1418
+ usb_disconnect+0x2db/0x930 drivers/usb/core/hub.c:2305
+ hub_port_connect drivers/usb/core/hub.c:5362 [inline]
+ hub_port_connect_change drivers/usb/core/hub.c:5662 [inline]
+ port_event drivers/usb/core/hub.c:5822 [inline]
+ hub_event+0x1e39/0x4ce0 drivers/usb/core/hub.c:5904
+ process_one_work+0x97b/0x1a90 kernel/workqueue.c:3267
+ process_scheduled_works kernel/workqueue.c:3348 [inline]
+ worker_thread+0x680/0xf00 kernel/workqueue.c:3429
+ kthread+0x2c7/0x3b0 kernel/kthread.c:388
+ ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+ </TASK>
+
+Reported-by: Shichao Lai <shichaorai@gmail.com>
+Closes: https://lore.kernel.org/linux-wireless/CAEk6kZuuezkH1dVRJf3EAVZK-83=OpTz62qCugkpTkswj8JF6w@mail.gmail.com/T/#u
+Tested-by: Shichao Lai <shichaorai@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://msgid.link/20240524003248.5952-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtlwifi/usb.c | 34 +++++++++++++++++-----
+ 1 file changed, 26 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
+index 2ea72d9e39577..4d2931e544278 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
+@@ -23,6 +23,8 @@ MODULE_DESCRIPTION("USB basic driver for rtlwifi");
+
+ #define MAX_USBCTRL_VENDORREQ_TIMES 10
+
++static void _rtl_usb_cleanup_tx(struct ieee80211_hw *hw);
++
+ static void _usbctrl_vendorreq_sync(struct usb_device *udev, u8 reqtype,
+ u16 value, void *pdata, u16 len)
+ {
+@@ -285,9 +287,23 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
+ }
+ /* usb endpoint mapping */
+ err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
+- rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
+- _rtl_usb_init_tx(hw);
+- _rtl_usb_init_rx(hw);
++ if (err)
++ return err;
++
++ rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
++
++ err = _rtl_usb_init_tx(hw);
++ if (err)
++ return err;
++
++ err = _rtl_usb_init_rx(hw);
++ if (err)
++ goto err_out;
++
++ return 0;
++
++err_out:
++ _rtl_usb_cleanup_tx(hw);
+ return err;
+ }
+
+@@ -691,17 +707,13 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
+ }
+
+ /*======================= tx =========================================*/
+-static void rtl_usb_cleanup(struct ieee80211_hw *hw)
++static void _rtl_usb_cleanup_tx(struct ieee80211_hw *hw)
+ {
+ u32 i;
+ struct sk_buff *_skb;
+ struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+ struct ieee80211_tx_info *txinfo;
+
+- /* clean up rx stuff. */
+- _rtl_usb_cleanup_rx(hw);
+-
+- /* clean up tx stuff */
+ for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+ while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) {
+ rtlusb->usb_tx_cleanup(hw, _skb);
+@@ -715,6 +727,12 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+ usb_kill_anchored_urbs(&rtlusb->tx_submitted);
+ }
+
++static void rtl_usb_cleanup(struct ieee80211_hw *hw)
++{
++ _rtl_usb_cleanup_rx(hw);
++ _rtl_usb_cleanup_tx(hw);
++}
++
+ /* We may add some struct into struct rtl_usb later. Do deinit here. */
+ static void rtl_usb_deinit(struct ieee80211_hw *hw)
+ {
+--
+2.43.0
+
--- /dev/null
+From 7677d35617d23618b64bdd3b3017b4113c92887b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 10:19:01 +0800
+Subject: wifi: rtw89: pci: fix RX tag race condition resulting in wrong RX
+ length
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit 94298477f81a1701fc4e1b5a0ce9672acab5dcb2 ]
+
+Read 32 bits RX info to a local variable to fix race condition between
+reading RX length and RX tag.
+
+Another solution is to get RX tag at first statement, but adopted solution
+can save some memory read, and also save 15 bytes binary code.
+
+RX tag, a sequence number, is used to ensure that RX data has been DMA to
+memory completely, so driver must check sequence number is expected before
+reading other data.
+
+This potential problem happens only after enabling 36-bit DMA.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://msgid.link/20240611021901.26394-2-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/pci.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
+index b36aa9a6bb3fc..312b57d7da642 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.c
++++ b/drivers/net/wireless/realtek/rtw89/pci.c
+@@ -183,14 +183,17 @@ static void rtw89_pci_sync_skb_for_device(struct rtw89_dev *rtwdev,
+ static void rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
+ struct sk_buff *skb)
+ {
+- struct rtw89_pci_rxbd_info *rxbd_info;
+ struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
++ struct rtw89_pci_rxbd_info *rxbd_info;
++ __le32 info;
+
+ rxbd_info = (struct rtw89_pci_rxbd_info *)skb->data;
+- rx_info->fs = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_FS);
+- rx_info->ls = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_LS);
+- rx_info->len = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_WRITE_SIZE);
+- rx_info->tag = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_TAG);
++ info = rxbd_info->dword;
++
++ rx_info->fs = le32_get_bits(info, RTW89_PCI_RXBD_FS);
++ rx_info->ls = le32_get_bits(info, RTW89_PCI_RXBD_LS);
++ rx_info->len = le32_get_bits(info, RTW89_PCI_RXBD_WRITE_SIZE);
++ rx_info->tag = le32_get_bits(info, RTW89_PCI_RXBD_TAG);
+ }
+
+ static int rtw89_pci_validate_rx_tag(struct rtw89_dev *rtwdev,
+--
+2.43.0
+
--- /dev/null
+From 7b2dbb7688f8b5a467236a644510e7bb7317c5cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Aug 2024 12:42:25 +0200
+Subject: x86/mm: Fix pti_clone_entry_text() for i386
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 3db03fb4995ef85fc41e86262ead7b4852f4bcf0 ]
+
+While x86_64 has PMD aligned text sections, i386 does not have this
+luxery. Notably ALIGN_ENTRY_TEXT_END is empty and _etext has PAGE
+alignment.
+
+This means that text on i386 can be page granular at the tail end,
+which in turn means that the PTI text clones should consistently
+account for this.
+
+Make pti_clone_entry_text() consistent with pti_clone_kernel_text().
+
+Fixes: 16a3fe634f6a ("x86/mm/pti: Clone kernel-image on PTE level for 32 bit")
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/pti.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 48c503208c794..bfdf5f45b1370 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -496,7 +496,7 @@ static void pti_clone_entry_text(void)
+ {
+ pti_clone_pgtable((unsigned long) __entry_text_start,
+ (unsigned long) __entry_text_end,
+- PTI_CLONE_PMD);
++ PTI_LEVEL_KERNEL_IMAGE);
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 77c77e2f8adae016f5e842e959c4aef7e51eddff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 18:31:05 +0200
+Subject: x86/mm: Fix pti_clone_pgtable() alignment assumption
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 41e71dbb0e0a0fe214545fe64af031303a08524c ]
+
+Guenter reported dodgy crashes on an i386-nosmp build using GCC-11
+that had the form of endless traps until entry stack exhaust and then
+#DF from the stack guard.
+
+It turned out that pti_clone_pgtable() had alignment assumptions on
+the start address, notably it hard assumes start is PMD aligned. This
+is true on x86_64, but very much not true on i386.
+
+These assumptions can cause the end condition to malfunction, leading
+to a 'short' clone. Guess what happens when the user mapping has a
+short copy of the entry text?
+
+Use the correct increment form for addr to avoid alignment
+assumptions.
+
+Fixes: 16a3fe634f6a ("x86/mm/pti: Clone kernel-image on PTE level for 32 bit")
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Tested-by: Guenter Roeck <linux@roeck-us.net>
+Suggested-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20240731163105.GG33588@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/pti.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 2e69abf4f852a..48c503208c794 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -374,14 +374,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
+ */
+ *target_pmd = *pmd;
+
+- addr += PMD_SIZE;
++ addr = round_up(addr + 1, PMD_SIZE);
+
+ } else if (level == PTI_CLONE_PTE) {
+
+ /* Walk the page-table down to the pte level */
+ pte = pte_offset_kernel(pmd, addr);
+ if (pte_none(*pte)) {
+- addr += PAGE_SIZE;
++ addr = round_up(addr + 1, PAGE_SIZE);
+ continue;
+ }
+
+@@ -401,7 +401,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
+ /* Clone the PTE */
+ *target_pte = *pte;
+
+- addr += PAGE_SIZE;
++ addr = round_up(addr + 1, PAGE_SIZE);
+
+ } else {
+ BUG();
+--
+2.43.0
+
--- /dev/null
+From e4857f0c15cc1227c949f2bdb69f932018283206 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 15:12:28 +0530
+Subject: xen: privcmd: Switch from mutex to spinlock for irqfds
+
+From: Viresh Kumar <viresh.kumar@linaro.org>
+
+[ Upstream commit 1c682593096a487fd9aebc079a307ff7a6d054a3 ]
+
+irqfd_wakeup() gets EPOLLHUP, when it is called by
+eventfd_release() by way of wake_up_poll(&ctx->wqh, EPOLLHUP), which
+gets called under spin_lock_irqsave(). We can't use a mutex here as it
+will lead to a deadlock.
+
+Fix it by switching over to a spin lock.
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/a66d7a7a9001424d432f52a9fc3931a1f345464f.1718703669.git.viresh.kumar@linaro.org
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/privcmd.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
+index 67dfa47788649..c9c620e32fa8b 100644
+--- a/drivers/xen/privcmd.c
++++ b/drivers/xen/privcmd.c
+@@ -845,7 +845,7 @@ static long privcmd_ioctl_mmap_resource(struct file *file,
+ #ifdef CONFIG_XEN_PRIVCMD_EVENTFD
+ /* Irqfd support */
+ static struct workqueue_struct *irqfd_cleanup_wq;
+-static DEFINE_MUTEX(irqfds_lock);
++static DEFINE_SPINLOCK(irqfds_lock);
+ static LIST_HEAD(irqfds_list);
+
+ struct privcmd_kernel_irqfd {
+@@ -909,9 +909,11 @@ irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
+ irqfd_inject(kirqfd);
+
+ if (flags & EPOLLHUP) {
+- mutex_lock(&irqfds_lock);
++ unsigned long flags;
++
++ spin_lock_irqsave(&irqfds_lock, flags);
+ irqfd_deactivate(kirqfd);
+- mutex_unlock(&irqfds_lock);
++ spin_unlock_irqrestore(&irqfds_lock, flags);
+ }
+
+ return 0;
+@@ -929,6 +931,7 @@ irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt)
+ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
+ {
+ struct privcmd_kernel_irqfd *kirqfd, *tmp;
++ unsigned long flags;
+ __poll_t events;
+ struct fd f;
+ void *dm_op;
+@@ -968,18 +971,18 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
+ init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup);
+ init_poll_funcptr(&kirqfd->pt, irqfd_poll_func);
+
+- mutex_lock(&irqfds_lock);
++ spin_lock_irqsave(&irqfds_lock, flags);
+
+ list_for_each_entry(tmp, &irqfds_list, list) {
+ if (kirqfd->eventfd == tmp->eventfd) {
+ ret = -EBUSY;
+- mutex_unlock(&irqfds_lock);
++ spin_unlock_irqrestore(&irqfds_lock, flags);
+ goto error_eventfd;
+ }
+ }
+
+ list_add_tail(&kirqfd->list, &irqfds_list);
+- mutex_unlock(&irqfds_lock);
++ spin_unlock_irqrestore(&irqfds_lock, flags);
+
+ /*
+ * Check if there was an event already pending on the eventfd before we
+@@ -1011,12 +1014,13 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
+ {
+ struct privcmd_kernel_irqfd *kirqfd;
+ struct eventfd_ctx *eventfd;
++ unsigned long flags;
+
+ eventfd = eventfd_ctx_fdget(irqfd->fd);
+ if (IS_ERR(eventfd))
+ return PTR_ERR(eventfd);
+
+- mutex_lock(&irqfds_lock);
++ spin_lock_irqsave(&irqfds_lock, flags);
+
+ list_for_each_entry(kirqfd, &irqfds_list, list) {
+ if (kirqfd->eventfd == eventfd) {
+@@ -1025,7 +1029,7 @@ static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd)
+ }
+ }
+
+- mutex_unlock(&irqfds_lock);
++ spin_unlock_irqrestore(&irqfds_lock, flags);
+
+ eventfd_ctx_put(eventfd);
+
+@@ -1073,13 +1077,14 @@ static int privcmd_irqfd_init(void)
+ static void privcmd_irqfd_exit(void)
+ {
+ struct privcmd_kernel_irqfd *kirqfd, *tmp;
++ unsigned long flags;
+
+- mutex_lock(&irqfds_lock);
++ spin_lock_irqsave(&irqfds_lock, flags);
+
+ list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list)
+ irqfd_deactivate(kirqfd);
+
+- mutex_unlock(&irqfds_lock);
++ spin_unlock_irqrestore(&irqfds_lock, flags);
+
+ destroy_workqueue(irqfd_cleanup_wq);
+ }
+--
+2.43.0
+