From: Sasha Levin Date: Sun, 11 Aug 2024 12:55:08 +0000 (-0400) Subject: Fixes for 6.10 X-Git-Tag: v6.1.105~121 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6a221328778fef823fb1a24e7e1e87629651fa13;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.10 Signed-off-by: Sasha Levin --- diff --git a/queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch b/queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch new file mode 100644 index 00000000000..620a72abd35 --- /dev/null +++ b/queue-6.10/acpi-battery-create-alarm-sysfs-attribute-atomically.patch @@ -0,0 +1,79 @@ +From 9839095f50202ea752d4ed6d18e4b358ba2c952e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch new file mode 100644 index 00000000000..b4c0518a331 --- /dev/null +++ b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch @@ -0,0 +1,46 @@ +From 523d65eb01f501ea407c1d38b8916cb31d08ce72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jul 2024 08:58:06 -0400 +Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MU + +From: Tamim Khan + +[ 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 +Signed-off-by: Tamim Khan +Link: https://patch.msgid.link/20240702125918.34683-1-tamim@fusetak.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833 b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833 new file mode 100644 index 00000000000..2fff75e16e0 --- /dev/null +++ b/queue-6.10/acpi-resource-skip-irq-override-on-asus-vivobook-pro.patch-7833 @@ -0,0 +1,46 @@ +From 441a4585d061c956fa28eaa5862b4992960abc6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Jul 2024 20:05:50 -0400 +Subject: ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MJ + +From: Tamim Khan + +[ 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 +Signed-off-by: Tamim Khan +Link: https://patch.msgid.link/20240708000557.83539-1-tamim@fusetak.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch b/queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch new file mode 100644 index 00000000000..dc21b326a7b --- /dev/null +++ b/queue-6.10/acpi-sbs-manage-alarm-sysfs-attribute-through-psy-co.patch @@ -0,0 +1,95 @@ +From 33ae8199c3dc00979ee1548fc374e2da87180c68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch b/queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch new file mode 100644 index 00000000000..7263ce79e53 --- /dev/null +++ b/queue-6.10/af_unix-don-t-retry-after-unix_state_lock_nested-in-.patch @@ -0,0 +1,139 @@ +From ba95fd74d89f45c1ec46ec9e17e76c1b97f8f778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch b/queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch new file mode 100644 index 00000000000..27f5faa69e6 --- /dev/null +++ b/queue-6.10/block-change-rq_integrity_vec-to-respect-the-iterato.patch @@ -0,0 +1,106 @@ +From 4925f571ef20bb3170a2c62cef6c8f55573d1fe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 May 2024 17:40:10 +0200 +Subject: block: change rq_integrity_vec to respect the iterator + +From: Mikulas Patocka + +[ 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 +Reviewed-by: Anuj Gupta +Reviewed-by: Kanchan Joshi +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/49d1afaa-f934-6ed2-a678-e0d428c63a65@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch b/queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch new file mode 100644 index 00000000000..5b90be74694 --- /dev/null +++ b/queue-6.10/bluetooth-btnxpuart-shutdown-timer-and-prevent-rearm.patch @@ -0,0 +1,70 @@ +From d48078439a68d507c4b74415591eb46c8a316afa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 19:15:35 +0800 +Subject: Bluetooth: btnxpuart: Shutdown timer and prevent rearming when driver + unloading + +From: Luke Wang + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch b/queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch new file mode 100644 index 00000000000..dfc43161259 --- /dev/null +++ b/queue-6.10/bluetooth-hci_sync-avoid-dup-filtering-when-passive-.patch @@ -0,0 +1,53 @@ +From 87f2a3176664f2cd87893bd0384841827205f52f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch b/queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch new file mode 100644 index 00000000000..d1cd4fe082f --- /dev/null +++ b/queue-6.10/bluetooth-l2cap-always-unlock-channel-in-l2cap_conle.patch @@ -0,0 +1,37 @@ +From 96cd656b241ef33c9bdbc9d4621d6c92ceb9c111 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 12:19:36 +0300 +Subject: Bluetooth: l2cap: always unlock channel in l2cap_conless_channel() + +From: Dmitry Antipov + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch b/queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch new file mode 100644 index 00000000000..371f3025aca --- /dev/null +++ b/queue-6.10/bnxt_en-fix-memory-out-of-bounds-in-bnxt_fill_hw_rss.patch @@ -0,0 +1,97 @@ +From 6168307f0f39543f5d6cc0a0674beacb2d78a82b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/netdev/ZrC6jpghA3PWVWSB@gmail.com/ +Fixes: 98ba1d931f61 ("bnxt_en: Fix RSS logic in __bnxt_reserve_rings()") +Reviewed-by: Pavan Chebbi +Reviewed-by: Kalesh AP +Reviewed-by: Somnath Kotur +Signed-off-by: Michael Chan +Tested-by: Breno Leitao +Link: https://patch.msgid.link/20240806053742.140304-1-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch b/queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch new file mode 100644 index 00000000000..66e3192de95 --- /dev/null +++ b/queue-6.10/bpf-add-missing-check_func_arg_reg_off-to-prevent-ou.patch @@ -0,0 +1,113 @@ +From 48ece36104ccd87af1864d784b95b920e99a6b3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +[ 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] + +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 +Acked-by: Kumar Kartikeya Dwivedi +Acked-by: Eduard Zingerman +Signed-off-by: Matt Bobrowski +Link: https://lore.kernel.org/r/20240625062857.92760-1-mattbobrowski@google.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch b/queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch new file mode 100644 index 00000000000..9b90d620001 --- /dev/null +++ b/queue-6.10/btrfs-do-not-bug_on-when-freeing-tree-block-after-er.patch @@ -0,0 +1,308 @@ +From f209ea9ea6d1f8a2351aa30d4b7b23d4a98486ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jun 2024 14:50:47 +0100 +Subject: btrfs: do not BUG_ON() when freeing tree block after error + +From: Filipe Manana + +[ 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 +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch b/queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch new file mode 100644 index 00000000000..e079a665ad1 --- /dev/null +++ b/queue-6.10/btrfs-do-not-clear-page-dirty-inside-extent_write_lo.patch @@ -0,0 +1,201 @@ +From b324b0d12a6f5cfb3dd5c6bec6171e73782ebf03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Mar 2024 08:21:54 +1030 +Subject: btrfs: do not clear page dirty inside extent_write_locked_range() + +From: Qu Wenruo + +[ 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 +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch b/queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch new file mode 100644 index 00000000000..bcf104c176f --- /dev/null +++ b/queue-6.10/btrfs-fix-bitmap-leak-when-loading-free-space-cache-.patch @@ -0,0 +1,39 @@ +From 88797b3ae2188e7c474bbf49ff51949478a26db2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch b/queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch new file mode 100644 index 00000000000..67e354d967a --- /dev/null +++ b/queue-6.10/btrfs-fix-data-race-when-accessing-the-last_trans-fi.patch @@ -0,0 +1,228 @@ +From eecc72d6ce5b65bd37c4112bb1e9a401c51fac93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch b/queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch new file mode 100644 index 00000000000..f125576eaf4 --- /dev/null +++ b/queue-6.10/btrfs-reduce-nesting-for-extent-processing-at-btrfs_.patch @@ -0,0 +1,77 @@ +From 5a0873e18421183cf695cc5f2c851aac4e1d832c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jun 2024 11:52:19 +0100 +Subject: btrfs: reduce nesting for extent processing at + btrfs_lookup_extent_info() + +From: Filipe Manana + +[ 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 +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch b/queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch new file mode 100644 index 00000000000..4f28036aaa7 --- /dev/null +++ b/queue-6.10/can-mcp251xfd-tef-prepare-to-workaround-broken-tef-f.patch @@ -0,0 +1,211 @@ +From 55b694b7967c21c8bf443c4a0eecf4136161a8fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Thomas Kopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + .../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 + // + // 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 + diff --git a/queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch b/queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch new file mode 100644 index 00000000000..f1c06ae2b76 --- /dev/null +++ b/queue-6.10/can-mcp251xfd-tef-update-workaround-for-erratum-ds80.patch @@ -0,0 +1,151 @@ +From 1809c96bd0c5a7fe492d4a8e60840da50642ecc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Thomas Kopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch b/queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch new file mode 100644 index 00000000000..b3f447a527d --- /dev/null +++ b/queue-6.10/clocksource-drivers-sh_cmt-address-race-condition-fo.patch @@ -0,0 +1,144 @@ +From 0952ac7e4caa804c44d3e373719c10c5e566a0b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20240702190230.3825292-1-niklas.soderlund+renesas@ragnatech.se +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch b/queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch new file mode 100644 index 00000000000..67c1f4d3ef3 --- /dev/null +++ b/queue-6.10/cpufreq-amd-pstate-allow-users-to-write-default-epp-.patch @@ -0,0 +1,67 @@ +From b949cff9e9a86ae2343320d9045a38da5fbae431 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 09:20:49 -0500 +Subject: cpufreq: amd-pstate: Allow users to write 'default' EPP string + +From: Mario Limonciello + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217931#c61 +Reviewed-by: Perry Yuan +Signed-off-by: Mario Limonciello +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch b/queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch new file mode 100644 index 00000000000..d6e1caaf660 --- /dev/null +++ b/queue-6.10/cpufreq-amd-pstate-auto-load-pstate-driver-by-defaul.patch @@ -0,0 +1,92 @@ +From 6b48e8f74e1ba147eb68634476b85012f1386776 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Jun 2024 23:40:19 +0800 +Subject: cpufreq: amd-pstate: auto-load pstate driver by default + +From: Perry Yuan + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218705 +Signed-off-by: Perry Yuan +Reviewed-by: Mario Limonciello +Link: https://lore.kernel.org/r/83301c4cea4f92fb19e14b23f2bac7facfd8bdbb.1718811234.git.perry.yuan@amd.com +Signed-off-by: Mario Limonciello +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/debugobjects-annotate-racy-debug-variables.patch b/queue-6.10/debugobjects-annotate-racy-debug-variables.patch new file mode 100644 index 00000000000..809b652a3e7 --- /dev/null +++ b/queue-6.10/debugobjects-annotate-racy-debug-variables.patch @@ -0,0 +1,79 @@ +From 2914c33c3aba36a09f17f7d6d1b0305db31c2e7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jun 2024 02:18:12 -0700 +Subject: debugobjects: Annotate racy debug variables + +From: Breno Leitao + +[ 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 +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20240611091813.1189860-1-leitao@debian.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch b/queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch new file mode 100644 index 00000000000..137ba09e499 --- /dev/null +++ b/queue-6.10/drm-admgpu-fix-dereferencing-null-pointer-context.patch @@ -0,0 +1,37 @@ +From 964d2008dd63f9d6bb493c452c4663fc96447d5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 10:57:04 +0800 +Subject: drm/admgpu: fix dereferencing null pointer context + +From: Jesse Zhang + +[ 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 +Suggested-by: Tim Huang +Reviewed-by: Tim Huang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch b/queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch new file mode 100644 index 00000000000..87faa6a8633 --- /dev/null +++ b/queue-6.10/drm-amd-amdkfd-fix-a-resource-leak-in-svm_range_vali.patch @@ -0,0 +1,51 @@ +From aba2f0eef21c63e0287c2047a788e849cc57ded2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch b/queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch new file mode 100644 index 00000000000..1da870ef370 --- /dev/null +++ b/queue-6.10/drm-amd-display-add-delay-to-improve-lttpr-uhbr-inte.patch @@ -0,0 +1,45 @@ +From dd0e44e843b878e839f6ae5379f413c37bf30a44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Apr 2024 12:00:34 -0400 +Subject: drm/amd/display: Add delay to improve LTTPR UHBR interop + +From: Michael Strauss + +[ 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 +Acked-by: Aurabindo Pillai +Signed-off-by: Michael Strauss +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch b/queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch new file mode 100644 index 00000000000..43fd440ed3a --- /dev/null +++ b/queue-6.10/drm-amd-display-add-null-check-for-afb-before-derefe.patch @@ -0,0 +1,67 @@ +From 2a26e9c9acd06183ee0c1c13acce22ec926243ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Rodrigo Siqueira +Cc: Roman Li +Cc: Hersen Wu +Cc: Alex Hung +Cc: Aurabindo Pillai +Cc: Harry Wentland +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch b/queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch new file mode 100644 index 00000000000..191bbae98ab --- /dev/null +++ b/queue-6.10/drm-amd-display-add-null-checker-before-passing-vari.patch @@ -0,0 +1,59 @@ +From 579cb49b6beebcd3b45775f9848614e7110d888d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 16:33:18 -0600 +Subject: drm/amd/display: Add null checker before passing variables + +From: Alex Hung + +[ Upstream commit 8092aa3ab8f7b737a34b71f91492c676a843043a ] + +Checks null pointer before passing variables to functions. + +This fixes 3 NULL_RETURNS issues reported by Coverity. + +Reviewed-by: Harry Wentland +Acked-by: Hamza Mahfooz +Signed-off-by: Alex Hung +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch b/queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch new file mode 100644 index 00000000000..1ae879afe52 --- /dev/null +++ b/queue-6.10/drm-amd-display-add-null-checks-for-stream-and-plane.patch @@ -0,0 +1,57 @@ +From 867f093dea3e42437521b9dd2c3c9dddf17d07de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Nicholas Kazlauskas +Cc: Bhawanpreet Lakha +Cc: Rodrigo Siqueira +Cc: Roman Li +Cc: Hersen Wu +Cc: Alex Hung +Cc: Aurabindo Pillai +Cc: Harry Wentland +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Aurabindo Pillai +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch b/queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch new file mode 100644 index 00000000000..aacebaad02a --- /dev/null +++ b/queue-6.10/drm-amd-display-don-t-refer-to-dc_sink-in-is_dsc_nee.patch @@ -0,0 +1,70 @@ +From cb0c1a81dfd1ac47ece50a420d61e102df1eac95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Zaeem Mohamed +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch b/queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch new file mode 100644 index 00000000000..91f454f9623 --- /dev/null +++ b/queue-6.10/drm-amd-display-fix-null-pointer-deref-in-dcn20_reso.patch @@ -0,0 +1,83 @@ +From 379467002e520422ebc323a6a68552741ad8b0f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Jun 2024 13:13:57 -0400 +Subject: drm/amd/display: Fix null pointer deref in dcn20_resource.c + +From: Aurabindo Pillai + +[ 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] +[ 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 +Reviewed-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch b/queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch new file mode 100644 index 00000000000..cf3421ef5b3 --- /dev/null +++ b/queue-6.10/drm-amd-display-fix-null-pointer-dereference-for-dtn.patch @@ -0,0 +1,157 @@ +From 81599e460038b57347811bc8d3d5a8879c8acf61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +[ +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 +Acked-by: Hamza Mahfooz +Signed-off-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch b/queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch new file mode 100644 index 00000000000..41267cc0991 --- /dev/null +++ b/queue-6.10/drm-amd-display-handle-hpd_irq-for-internal-link.patch @@ -0,0 +1,94 @@ +From ccc1ac5cd979220dd3625dcdf773aec5e68997c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 14:40:32 +0800 +Subject: drm/amd/display: Handle HPD_IRQ for internal link + +From: Sung-huai Wang + +[ 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 +Acked-by: Aurabindo Pillai +Signed-off-by: Sung-huai Wang +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch b/queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch new file mode 100644 index 00000000000..c632983d60c --- /dev/null +++ b/queue-6.10/drm-amd-display-reduce-odm-slice-count-to-initial-ne.patch @@ -0,0 +1,235 @@ +From 757d529cb7d14863eea92bc0754ace8f1e0626c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Zaeem Mohamed +Signed-off-by: Wenjing Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch b/queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch new file mode 100644 index 00000000000..f3571a56d77 --- /dev/null +++ b/queue-6.10/drm-amd-display-remove-dpp-pipes-on-failure-to-updat.patch @@ -0,0 +1,66 @@ +From c023cd7163dd6984148c259b8048d987cd6fa8d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Zaeem Mohamed +Signed-off-by: Wenjing Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch b/queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch new file mode 100644 index 00000000000..7e6d30a9cb2 --- /dev/null +++ b/queue-6.10/drm-amd-display-wake-dmcub-before-sending-a-command-.patch @@ -0,0 +1,69 @@ +From 7df4a098a4fe0480fd292647816550d4d176cfd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Nicholas Kazlauskas +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch b/queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch new file mode 100644 index 00000000000..dba204d9bb2 --- /dev/null +++ b/queue-6.10/drm-amd-pm-fix-the-null-pointer-dereference-for-vega.patch @@ -0,0 +1,114 @@ +From 3debc8183b07e5eb1494d60687490d81b00e42fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 15:01:22 +0800 +Subject: drm/amd/pm: Fix the null pointer dereference for vega10_hwmgr + +From: Bob Zhou + +[ Upstream commit 50151b7f1c79a09117837eb95b76c2de76841dab ] + +Check return value and conduct null pointer handling to avoid null pointer dereference. + +Signed-off-by: Bob Zhou +Reviewed-by: Tim Huang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch b/queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch new file mode 100644 index 00000000000..996b7e525b1 --- /dev/null +++ b/queue-6.10/drm-amdgpu-add-lock-around-vf-rlcg-interface.patch @@ -0,0 +1,78 @@ +From cc1128f2104fda9f2e9e1ed13407fa7017242ff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 May 2024 16:10:43 -0400 +Subject: drm/amdgpu: Add lock around VF RLCG interface + +From: Victor Skvortsov + +[ 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 +Reviewed-by: Zhigang Luo +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch b/queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch new file mode 100644 index 00000000000..42187e85b29 --- /dev/null +++ b/queue-6.10/drm-amdgpu-fix-potential-resource-leak-warning.patch @@ -0,0 +1,42 @@ +From 257f1201243d672e09b0728c33db390a06232c81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch b/queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch new file mode 100644 index 00000000000..f8143f17be0 --- /dev/null +++ b/queue-6.10/drm-amdgpu-fix-the-null-pointer-dereference-to-ras_m.patch @@ -0,0 +1,44 @@ +From ac585cb8a2f143e114b9deeb29b8030200d36b76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 May 2024 15:48:02 +0800 +Subject: drm/amdgpu: Fix the null pointer dereference to ras_manager + +From: Ma Jun + +[ Upstream commit 4c11d30c95576937c6c35e6f29884761f2dddb43 ] + +Check ras_manager before using it + +Signed-off-by: Ma Jun +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch new file mode 100644 index 00000000000..aee43a04589 --- /dev/null +++ b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-for-s.patch @@ -0,0 +1,99 @@ +From ab9b20b8a7b373daa083ef37d79c719d918552a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 15:01:59 +0800 +Subject: drm/amdgpu/pm: Fix the null pointer dereference for smu7 + +From: Ma Jun + +[ 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 +Reviewed-by: Yang Wang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch new file mode 100644 index 00000000000..0b823a6d488 --- /dev/null +++ b/queue-6.10/drm-amdgpu-pm-fix-the-null-pointer-dereference-in-ap.patch @@ -0,0 +1,105 @@ +From e27959baf16e47ed93ddbfb86cb622554af866cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit d19fb10085a49b77578314f69fff21562f7cd054 ] + +Check the pointer value to fix potential null pointer +dereference + +Acked-by: Yang Wang +Signed-off-by: Ma Jun +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch b/queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch new file mode 100644 index 00000000000..dcf4511e903 --- /dev/null +++ b/queue-6.10/drm-amdgpu-pm-fix-the-param-type-of-set_power_profil.patch @@ -0,0 +1,151 @@ +From d6949fe3402e882edaff83a660883e4d83c296ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Alex Deucher +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch b/queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch new file mode 100644 index 00000000000..0d025ba28ed --- /dev/null +++ b/queue-6.10/drm-xe-preempt_fence-enlarge-the-fence-critical-sect.patch @@ -0,0 +1,58 @@ +From 01d5e852b29741df41afd95b2a1e478f1003046b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Apr 2024 15:46:31 +0100 +Subject: drm/xe/preempt_fence: enlarge the fence critical section + +From: Matthew Auld + +[ 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 +Cc: Matthew Brost +Reviewed-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20240418144630.299531-2-matthew.auld@intel.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch b/queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch new file mode 100644 index 00000000000..4dda89f40d8 --- /dev/null +++ b/queue-6.10/drm-xe-xe_guc_submit-fix-exec-queue-stop-race-condit.patch @@ -0,0 +1,43 @@ +From 631e1848172aa763280eb4fe20ba9db6779a7829 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 May 2024 12:45:38 -0700 +Subject: drm/xe/xe_guc_submit: Fix exec queue stop race condition + +From: Jonathan Cavitt + +[ 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 +Signed-off-by: Jonathan Cavitt +Reviewed-by: Matthew Brost +Reviewed-by: Stuart Summers +Signed-off-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20240510194540.3246991-1-jonathan.cavitt@intel.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch b/queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch new file mode 100644 index 00000000000..84c33b2f6f2 --- /dev/null +++ b/queue-6.10/ext4-fix-uninitialized-variable-in-ext4_inlinedir_to.patch @@ -0,0 +1,48 @@ +From 938069bddcc6d7de73703b002f19c47de12aa14b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Apr 2024 20:30:17 -0700 +Subject: ext4: fix uninitialized variable in ext4_inlinedir_to_tree + +From: Xiaxi Shen + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch b/queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch new file mode 100644 index 00000000000..06b30c40c04 --- /dev/null +++ b/queue-6.10/ext4-sanity-check-for-null-pointer-after-ext4_force_.patch @@ -0,0 +1,135 @@ +From 19bd2510608703f6f8c0ac7639edb98a16d3cf45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/20240703070112.10235-1-wojciech.gladysz@infogain.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch b/queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch new file mode 100644 index 00000000000..e99090da9d6 --- /dev/null +++ b/queue-6.10/gpio-prevent-potential-speculation-leaks-in-gpio_dev.patch @@ -0,0 +1,54 @@ +From 326813cd370e4a615d144750cc76857c60105b7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 May 2024 08:53:32 +0000 +Subject: gpio: prevent potential speculation leaks in gpio_device_get_desc() + +From: Hagar Hemdan + +[ 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 +Link: https://lore.kernel.org/r/20240523085332.1801-1-hagarhem@amazon.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-6.10/gve-fix-use-of-netif_carrier_ok.patch b/queue-6.10/gve-fix-use-of-netif_carrier_ok.patch new file mode 100644 index 00000000000..0ca5c202521 --- /dev/null +++ b/queue-6.10/gve-fix-use-of-netif_carrier_ok.patch @@ -0,0 +1,105 @@ +From 280dfdbc195fd9e86fdd021104ef7fce411313d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Aug 2024 13:56:19 -0700 +Subject: gve: Fix use of netif_carrier_ok() + +From: Praveen Kaligineedi + +[ 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 +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 +Reviewed-by: Shailend Chand +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20240801205619.987396-1-pkaligineedi@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch b/queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch new file mode 100644 index 00000000000..cae51a79da9 --- /dev/null +++ b/queue-6.10/hwmon-corsair-psu-add-usb-id-of-hx1200i-series-2023-.patch @@ -0,0 +1,69 @@ +From 6193b8c2c40664cb3fba9b9e6a35f8ed53e6bead Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 May 2024 04:38:11 +0000 +Subject: hwmon: corsair-psu: add USB id of HX1200i Series 2023 psu + +From: Wilken Gottwalt + +[ 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 +Link: https://lore.kernel.org/r/ZlAZs4u0dU7JxtDf@monster.localdomain +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/ice-fix-reset-handler.patch b/queue-6.10/ice-fix-reset-handler.patch new file mode 100644 index 00000000000..73decf8e4f1 --- /dev/null +++ b/queue-6.10/ice-fix-reset-handler.patch @@ -0,0 +1,39 @@ +From 9f00e4f8b752d687416d233e2a16915ac6c6c2e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jul 2024 17:39:10 +0200 +Subject: ice: Fix reset handler + +From: Grzegorz Nitka + +[ 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 +Signed-off-by: Sergey Temerkhanov +Reviewed-by: Przemek Kitszel +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch b/queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch new file mode 100644 index 00000000000..eb3194aa999 --- /dev/null +++ b/queue-6.10/idpf-fix-memory-leaks-and-crashes-while-performing-a.patch @@ -0,0 +1,134 @@ +From 48d1b9ca863052b0adc33c883a25f95c6bf51f26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 15:09:20 -0700 +Subject: idpf: fix memory leaks and crashes while performing a soft reset + +From: Alexander Lobakin + +[ 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 +Reviewed-by: Simon Horman +Tested-by: Krishneil Singh +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240806220923.3359860-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch b/queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch new file mode 100644 index 00000000000..e2888eab634 --- /dev/null +++ b/queue-6.10/idpf-fix-uafs-when-destroying-the-queues.patch @@ -0,0 +1,167 @@ +From 1af8bab4a3f2749b1597ae7f8ef4daaac1130494 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 15:09:22 -0700 +Subject: idpf: fix UAFs when destroying the queues + +From: Alexander Lobakin + +[ 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 +Signed-off-by: Alexander Lobakin +Reviewed-by: Simon Horman +Tested-by: Krishneil Singh +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20240806220923.3359860-4-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch b/queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch new file mode 100644 index 00000000000..ab36f54d9f8 --- /dev/null +++ b/queue-6.10/irqchip-gic-v3-don-t-return-errors-from-gic_acpi_mat.patch @@ -0,0 +1,72 @@ +From cb6803bff3500e0963d27f0ba8b9808ceb7f47bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Gavin Shan +Tested-by: Miguel Luis +Signed-off-by: Russell King (Oracle) +Reviewed-by: Jonathan Cameron +Signed-off-by: Jonathan Cameron +Reviewed-by: Marc Zyngier +Link: https://lore.kernel.org/r/20240529133446.28446-14-Jonathan.Cameron@huawei.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch b/queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch new file mode 100644 index 00000000000..ac7957aa04d --- /dev/null +++ b/queue-6.10/irqchip-mbigen-fix-mbigen-node-address-layout.patch @@ -0,0 +1,89 @@ +From 5f106f43bb5fce672ba9267df68be411bd460179 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jul 2024 09:44:00 +0800 +Subject: irqchip/mbigen: Fix mbigen node address layout + +From: Yipeng Zou + +[ 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 +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20240730014400.1751530-1-zouyipeng@huawei.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch b/queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch new file mode 100644 index 00000000000..ac01638112d --- /dev/null +++ b/queue-6.10/jbd2-avoid-memleak-in-jbd2_journal_write_metadata_bu.patch @@ -0,0 +1,37 @@ +From 2a7f4000bc674db6d88b0dcc7ef33f06f3dabda5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 May 2024 19:24:30 +0800 +Subject: jbd2: avoid memleak in jbd2_journal_write_metadata_buffer + +From: Kemeng Shi + +[ 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 +Reviewed-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20240514112438.1269037-2-shikemeng@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch b/queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch new file mode 100644 index 00000000000..5e8b9855bb9 --- /dev/null +++ b/queue-6.10/jump_label-fix-the-fix-brown-paper-bags-galore.patch @@ -0,0 +1,62 @@ +From 5f26cebd62e22fd6022ca20f0ac44ecad8b381cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 12:43:21 +0200 +Subject: jump_label: Fix the fix, brown paper bags galore + +From: Peter Zijlstra + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +Tested-by: Darrick J. Wong +Link: https://lkml.kernel.org/r/20240731105557.GY33588@noisy.programming.kicks-ass.net +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/l2tp-fix-lockdep-splat.patch b/queue-6.10/l2tp-fix-lockdep-splat.patch new file mode 100644 index 00000000000..a2f5941a048 --- /dev/null +++ b/queue-6.10/l2tp-fix-lockdep-splat.patch @@ -0,0 +1,216 @@ +From eb851d4bba57158911fe10573dbd59bd358f7fed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 17:06:26 +0100 +Subject: l2tp: fix lockdep splat + +From: James Chapman + +[ 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: + + 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 + + + __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 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 + + +Fixes: 0b2c59720e65 ("l2tp: close all race conditions in l2tp_tunnel_register()") +Suggested-by: Eric Dumazet +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 +Signed-off-by: Tom Parkin +Link: https://patch.msgid.link/20240806160626.1248317-1-jchapman@katalix.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch b/queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch new file mode 100644 index 00000000000..a03431d3b73 --- /dev/null +++ b/queue-6.10/locking-pvqspinlock-correct-the-type-of-old-variable.patch @@ -0,0 +1,45 @@ +From fed28319395deb213e9ffec499733460f57640c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Uros Bizjak +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Waiman Long +Link: https://lore.kernel.org/r/20240721164552.50175-1-ubizjak@gmail.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch b/queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch new file mode 100644 index 00000000000..0c451992e9c --- /dev/null +++ b/queue-6.10/md-change-the-return-value-type-of-md_write_start-to.patch @@ -0,0 +1,125 @@ +From 1c475a309fe6d4cf4dab2a21d8bf742e4f7d95b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Yu Kuai +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20240525185257.3896201-2-linan666@huaweicloud.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch b/queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch new file mode 100644 index 00000000000..0374031db6f --- /dev/null +++ b/queue-6.10/md-do-not-delete-safemode_timer-in-mddev_suspend.patch @@ -0,0 +1,48 @@ +From b44ae01194d94f931c56978e6000e1674ea25cf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 May 2024 17:20:53 +0800 +Subject: md: do not delete safemode_timer in mddev_suspend + +From: Li Nan + +[ 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 +Reviewed-by: Yu Kuai +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20240508092053.1447930-1-linan666@huaweicloud.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch b/queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch new file mode 100644 index 00000000000..6d6b2a13495 --- /dev/null +++ b/queue-6.10/md-raid5-avoid-bug_on-while-continue-reshape-after-r.patch @@ -0,0 +1,93 @@ +From d60b757a4fd882e728f3fda3bc803ba357d9bb5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jun 2024 21:22:51 +0800 +Subject: md/raid5: avoid BUG_ON() while continue reshape after reassembling + +From: Yu Kuai + +[ 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: + + 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 + + +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 +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20240611132251.1967786-13-yukuai1@huaweicloud.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch b/queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch new file mode 100644 index 00000000000..0bd1ca971eb --- /dev/null +++ b/queue-6.10/media-amphion-remove-lock-in-s_ctrl-callback.patch @@ -0,0 +1,65 @@ +From 8aa23f4e314d0dd9f62062228ae18c02fdcd89f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 May 2024 17:49:17 +0900 +Subject: media: amphion: Remove lock in s_ctrl callback + +From: Ming Qian + +[ 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 +Signed-off-by: Sebastian Fricke +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch b/queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch new file mode 100644 index 00000000000..7d3df4facff --- /dev/null +++ b/queue-6.10/media-i2c-ov5647-replacing-of_node_put-with-__free-d.patch @@ -0,0 +1,58 @@ +From eef42813941642af47101e5524f80d8824ad39c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 06:51:58 -0400 +Subject: media: i2c: ov5647: replacing of_node_put with __free(device_node) + +From: Abdulrasaq Lawani + +[ 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 +Acked-by: Dave Stevenson +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch b/queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch new file mode 100644 index 00000000000..4c52579cfa6 --- /dev/null +++ b/queue-6.10/media-uvcvideo-fix-the-bandwdith-quirk-on-usb-3.x.patch @@ -0,0 +1,52 @@ +From 21532cf722d3213bd830a52ca71e6f316e3141e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Apr 2024 19:00:40 +0200 +Subject: media: uvcvideo: Fix the bandwdith quirk on USB 3.x + +From: Michal Pecio + +[ 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 +Reviewed-by: Ricardo Ribalda +Reviewed-by: Laurent Pinchart +Link: https://lore.kernel.org/r/20240414190040.2255a0bc@foxbook +Signed-off-by: Laurent Pinchart +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch b/queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch new file mode 100644 index 00000000000..abb26d4f293 --- /dev/null +++ b/queue-6.10/media-uvcvideo-ignore-empty-ts-packets.patch @@ -0,0 +1,129 @@ +From e05394917945485e8c7b7f986e3fe7bc17d5a9e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Mar 2024 10:48:03 +0000 +Subject: media: uvcvideo: Ignore empty TS packets + +From: Ricardo Ribalda + +[ 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 +Reviewed-by: Sergey Senozhatsky +Reviewed-by: Laurent Pinchart +Signed-off-by: Ricardo Ribalda +Reviewed-by: Tomasz Figa +Link: https://lore.kernel.org/r/20240323-resend-hwtimestamp-v10-2-b08e590d97c7@chromium.org +Signed-off-by: Laurent Pinchart +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch b/queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch new file mode 100644 index 00000000000..203092648c8 --- /dev/null +++ b/queue-6.10/media-xc2028-avoid-use-after-free-in-load_firmware_c.patch @@ -0,0 +1,129 @@ +From f4afc234a5ac4ee3af59108a4e74abb8da0d3af6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jun 2024 08:22:25 -0700 +Subject: media: xc2028: avoid use-after-free in load_firmware_cb() + +From: Chi Zhiling + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch b/queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch new file mode 100644 index 00000000000..082cab6ae51 --- /dev/null +++ b/queue-6.10/mlxsw-pci-lock-configuration-space-of-upstream-bridg.patch @@ -0,0 +1,70 @@ +From 54c51fb53554f5c2a50bd288002f8407f33ff2aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Jul 2024 16:23:42 +0200 +Subject: mlxsw: pci: Lock configuration space of upstream bridge during reset + +From: Ido Schimmel + +[ 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 +Signed-off-by: Petr Machata +Reviewed-by: Przemek Kitszel +Link: https://patch.msgid.link/9937b0afdb50f2f2825945393c94c093c04a5897.1720447210.git.petrm@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch b/queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch new file mode 100644 index 00000000000..dda84dc9299 --- /dev/null +++ b/queue-6.10/net-bcmgenet-properly-overlay-phy-and-mac-wake-on-la.patch @@ -0,0 +1,55 @@ +From fe3cc5d6e1596c945a8d0c3d4a383f3bd16b1864 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 10:56:59 -0700 +Subject: net: bcmgenet: Properly overlay PHY and MAC Wake-on-LAN capabilities + +From: Florian Fainelli + +[ 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 +Link: https://patch.msgid.link/20240806175659.3232204-1-florian.fainelli@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch b/queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch new file mode 100644 index 00000000000..530663e4186 --- /dev/null +++ b/queue-6.10/net-bridge-mcast-wait-for-previous-gc-cycles-when-re.patch @@ -0,0 +1,82 @@ +From 2c2fcaa66479fa8e5132b282b9d8ddca68cf4ce8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Aug 2024 11:07:30 +0300 +Subject: net: bridge: mcast: wait for previous gc cycles when removing port + +From: Nikolay Aleksandrov + +[ 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: + + __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 +Link: https://patch.msgid.link/20240802080730.3206303-1-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch b/queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch new file mode 100644 index 00000000000..f18472cd153 --- /dev/null +++ b/queue-6.10/net-dsa-bcm_sf2-fix-a-possible-memory-leak-in-bcm_sf.patch @@ -0,0 +1,50 @@ +From 0a021dbaf4b0a8000aeb7c742070e461b17e0821 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Florian Fainelli +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20240806011327.3817861-1-joe@pf.is.s.u-tokyo.ac.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch b/queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch new file mode 100644 index 00000000000..2fbfb8c0930 --- /dev/null +++ b/queue-6.10/net-dsa-microchip-disable-eee-for-ksz8567-ksz9567-ks.patch @@ -0,0 +1,72 @@ +From 38765944c6c8500c34eee8c1514f3701656032e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Aug 2024 21:52:09 +0100 +Subject: net: dsa: microchip: disable EEE for KSZ8567/KSZ9567/KSZ9896/KSZ9897. + +From: Martin Whitaker + +[ 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 +Acked-by: Arun Ramadoss +Reviewed-by: Oleksij Rempel +Reviewed-by: Lukasz Majewski +Link: https://patch.msgid.link/20240807205209.21464-1-foss@martin-whitaker.me.uk +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch b/queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch new file mode 100644 index 00000000000..58c4f275638 --- /dev/null +++ b/queue-6.10/net-dsa-microchip-fix-wake-on-lan-check-to-not-retur.patch @@ -0,0 +1,44 @@ +From 881f1d5fb207a51add1fd66cf2aabf4c58f6ae8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Oleksij Rempel +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20240805235200.24982-1-Tristram.Ha@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-fec-stop-pps-on-driver-remove.patch b/queue-6.10/net-fec-stop-pps-on-driver-remove.patch new file mode 100644 index 00000000000..b526d64efd5 --- /dev/null +++ b/queue-6.10/net-fec-stop-pps-on-driver-remove.patch @@ -0,0 +1,46 @@ +From 3cc8f38bc5dd1f1dfbf076ba3441e413537e79c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/netdev/CAOMZO5BzcZR8PwKKwBssQq_wAGzVgf1ffwe_nhpQJjviTdxy-w@mail.gmail.com/T/#m01dcb810bfc451a492140f6797ca77443d0cb79f +Signed-off-by: Csókás, Bence +Reviewed-by: Andrew Lunn +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20240807080956.2556602-1-csokas.bence@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-linkwatch-use-system_unbound_wq.patch b/queue-6.10/net-linkwatch-use-system_unbound_wq.patch new file mode 100644 index 00000000000..25427a76ae8 --- /dev/null +++ b/queue-6.10/net-linkwatch-use-system_unbound_wq.patch @@ -0,0 +1,52 @@ +From 9c8f913bb330d9a6562b9335958ccbb3413ab95d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Aug 2024 08:58:21 +0000 +Subject: net: linkwatch: use system_unbound_wq + +From: Eric Dumazet + +[ 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 +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20240805085821.1616528-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch b/queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch new file mode 100644 index 00000000000..7848470a541 --- /dev/null +++ b/queue-6.10/net-mlx5e-shampo-fix-invalid-wq-linked-list-unlink.patch @@ -0,0 +1,44 @@ +From 249809b1f8b24bf6aec02e7ce3d455bb954958d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 00:22:08 +0300 +Subject: net/mlx5e: SHAMPO, Fix invalid WQ linked list unlink + +From: Dragos Tatulea + +[ 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 +Signed-off-by: Tariq Toukan +Link: https://lore.kernel.org/r/20240603212219.1037656-4-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch b/queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch new file mode 100644 index 00000000000..6d5e797899e --- /dev/null +++ b/queue-6.10/net-pse-pd-tps23881-fix-the-device-id-check.patch @@ -0,0 +1,50 @@ +From 8e55abe94209a3f0f393ba56da6f21124dbbe2dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 15:42:14 +0000 +Subject: net: pse-pd: tps23881: Fix the device ID check + +From: Kyle Swenson + +[ 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 +Reviewed-by: Thomas Petazzoni +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20240731154152.4020668-1-kyle.swenson@est.tech +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch b/queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch new file mode 100644 index 00000000000..002db223956 --- /dev/null +++ b/queue-6.10/net-pse-pd-tps23881-include-missing-bitfield.h-heade.patch @@ -0,0 +1,42 @@ +From 05c3d118aef4464fad29d0171d84e21b2b3e6dbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Aug 2024 09:54:22 +0200 +Subject: net: pse-pd: tps23881: include missing bitfield.h header + +From: Arnd Bergmann + +[ 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 +Acked-by: Oleksij Rempel +Link: https://patch.msgid.link/20240807075455.2055224-1-arnd@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + */ + ++#include + #include + #include + #include +-- +2.43.0 + diff --git a/queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch b/queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch new file mode 100644 index 00000000000..336e0d3d9c9 --- /dev/null +++ b/queue-6.10/net-reference-bpf_redirect_info-via-task_struct-on-p.patch @@ -0,0 +1,681 @@ +From 12b7a3a48179413fe2ed1554c15a9fdd40c7faae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Eduard Zingerman +Cc: Hao Luo +Cc: Jiri Olsa +Cc: John Fastabend +Cc: KP Singh +Cc: Martin KaFai Lau +Cc: Song Liu +Cc: Stanislav Fomichev +Cc: Yonghong Song +Acked-by: Alexei Starovoitov +Acked-by: Jesper Dangaard Brouer +Reviewed-by: Toke Høiland-Jørgensen +Signed-off-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/20240620132727.660738-15-bigeasy@linutronix.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch b/queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch new file mode 100644 index 00000000000..468cf9a98d9 --- /dev/null +++ b/queue-6.10/net-smc-add-the-max-value-of-fallback-reason-count.patch @@ -0,0 +1,42 @@ +From aa4bc1c51cd7d1ddf365ba2035b0b3df1c672833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Aug 2024 12:38:56 +0800 +Subject: net/smc: add the max value of fallback reason count + +From: Zhengchao Shao + +[ 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 +Reviewed-by: Wenjia Zhang +Reviewed-by: D. Wythe +Link: https://patch.msgid.link/20240805043856.565677-1-shaozhengchao@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch b/queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch new file mode 100644 index 00000000000..a4b4be5fee0 --- /dev/null +++ b/queue-6.10/net-stmmac-qcom-ethqos-enable-sgmii-loopback-during-.patch @@ -0,0 +1,120 @@ +From 517a8082696b6dc917e704b8aaa5fe512ef1924f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20240703181500.28491-3-brgl@bgdev.pl +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch b/queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch new file mode 100644 index 00000000000..d4462271e1f --- /dev/null +++ b/queue-6.10/net-usb-qmi_wwan-fix-memory-leak-for-not-ip-packets.patch @@ -0,0 +1,38 @@ +From 9bd3cba08d7a9f2686e4c4b80a515d8ce29946ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/nvme-apple-fix-device-reference-counting.patch b/queue-6.10/nvme-apple-fix-device-reference-counting.patch new file mode 100644 index 00000000000..0c2ea437aa2 --- /dev/null +++ b/queue-6.10/nvme-apple-fix-device-reference-counting.patch @@ -0,0 +1,87 @@ +From 88109c7f7caabe4f2a816e8918b2bacc920ddf76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 11:59:04 -0700 +Subject: nvme: apple: fix device reference counting + +From: Keith Busch + +[ 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 +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch b/queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch new file mode 100644 index 00000000000..1849dd7587d --- /dev/null +++ b/queue-6.10/pci-add-edimax-vendor-id-to-pci_ids.h.patch @@ -0,0 +1,38 @@ +From cb4eaff98e9f6c9bb7b03ac27c7e4561423684e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Jun 2024 08:55:01 +0900 +Subject: PCI: Add Edimax Vendor ID to pci_ids.h + +From: FUJITA Tomonori + +[ 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 +Acked-by: Bjorn Helgaas +Link: https://patch.msgid.link/20240623235507.108147-2-fujita.tomonori@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch b/queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch new file mode 100644 index 00000000000..87658803f8f --- /dev/null +++ b/queue-6.10/perf-x86-amd-use-try_cmpxchg-in-events-amd-un-core.c.patch @@ -0,0 +1,76 @@ +From 7aea1d980841c78c46186af0ade988b6db7de3ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Ingo Molnar +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 +--- + 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 + diff --git a/queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch b/queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch new file mode 100644 index 00000000000..ac512872da8 --- /dev/null +++ b/queue-6.10/perf-x86-fix-smp_processor_id-in-preemptible-warning.patch @@ -0,0 +1,98 @@ +From ade587b6d2d92bc9bed6cb7147eb464f4066b969 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jul 2024 06:09:28 +0800 +Subject: perf/x86: Fix smp_processor_id()-in-preemptible warnings + +From: Li Huafei + +[ 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: + + 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 +Reviewed-and-tested-by: K Prateek Nayak +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20240729220928.325449-1-lihuafei1@huawei.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch b/queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch new file mode 100644 index 00000000000..510412e130d --- /dev/null +++ b/queue-6.10/perf-x86-intel-cstate-add-arrowlake-support.patch @@ -0,0 +1,102 @@ +From d7646c3bd205da17c72cbe83eb093cfb2a46cf06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Jun 2024 11:17:57 +0800 +Subject: perf/x86/intel/cstate: Add Arrowlake support + +From: Zhang Rui + +[ Upstream commit a31000753d41305d2fb7faa8cc80a8edaeb7b56b ] + +Like Alderlake, Arrowlake supports CC1/CC6/CC7 and PC2/PC3/PC6/PC8/PC10. + +Signed-off-by: Zhang Rui +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +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 +--- + 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 + diff --git a/queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch b/queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch new file mode 100644 index 00000000000..83a90c02f41 --- /dev/null +++ b/queue-6.10/perf-x86-intel-cstate-add-lunarlake-support.patch @@ -0,0 +1,110 @@ +From 2628b6f24b07d5d5fc198874a932a5f046ff60ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Jun 2024 11:17:58 +0800 +Subject: perf/x86/intel/cstate: Add Lunarlake support + +From: Zhang Rui + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +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 +--- + 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 + diff --git a/queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch b/queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch new file mode 100644 index 00000000000..56cda371508 --- /dev/null +++ b/queue-6.10/perf-x86-intel-cstate-add-pkg-c2-residency-counter-f.patch @@ -0,0 +1,49 @@ +From 30b9430ff2763c3d7e3b4af439b883fe560abdc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Tested-by: Wendy Wang +Link: https://lore.kernel.org/r/20240717031609.74513-1-zhenyuw@linux.intel.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch b/queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch new file mode 100644 index 00000000000..9effcd795b1 --- /dev/null +++ b/queue-6.10/perf-x86-intel-support-the-pebs-event-mask.patch @@ -0,0 +1,188 @@ +From 34d459e35c1ad1e14de2d13bcae9cebe8a72f8cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Jun 2024 07:35:33 -0700 +Subject: perf/x86/intel: Support the PEBS event mask + +From: Kan Liang + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Andi Kleen +Reviewed-by: Ian Rogers +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 +--- + 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 + diff --git a/queue-6.10/perf-x86-support-counter-mask.patch b/queue-6.10/perf-x86-support-counter-mask.patch new file mode 100644 index 00000000000..cac41262dd6 --- /dev/null +++ b/queue-6.10/perf-x86-support-counter-mask.patch @@ -0,0 +1,1052 @@ +From 83cdd752bf447ef52d3f5d3936f02912070d4c7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Jun 2024 07:35:34 -0700 +Subject: perf/x86: Support counter mask + +From: Kan Liang + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Andi Kleen +Reviewed-by: Ian Rogers +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 +--- + 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 + diff --git a/queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch b/queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch new file mode 100644 index 00000000000..607cbe94b70 --- /dev/null +++ b/queue-6.10/platform-chrome-cros_ec_lpc-add-a-new-quirk-for-acpi.patch @@ -0,0 +1,130 @@ +From d95e53db9dc2db9cb26f741797e8dabefd0fe374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Ben Walsh +Link: https://lore.kernel.org/r/20240605063351.14836-4-ben@jubnut.com +Signed-off-by: Tzung-Bi Shih +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch b/queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch new file mode 100644 index 00000000000..322e955f3a7 --- /dev/null +++ b/queue-6.10/platform-x86-intel-ifs-initialize-union-ifs_status-t.patch @@ -0,0 +1,47 @@ +From c59d4f8d1068a600dda81b5c20d4391e622eb1fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jithu Joseph +Reviewed-by: Ashok Raj +Signed-off-by: Kuppuswamy Sathyanarayanan +Link: https://lore.kernel.org/r/20240730155930.1754744-1-sathyanarayanan.kuppuswamy@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch b/queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch new file mode 100644 index 00000000000..03681381d32 --- /dev/null +++ b/queue-6.10/platform-x86-intel-vbtn-protect-acpi-notify-handler-.patch @@ -0,0 +1,97 @@ +From 75caffd4f52c38007990781d90e01b59c0a0b3ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2073001 +Tested-by: Kostadin Stoilov +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20240729120443.14779-1-hdegoede@redhat.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + 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 ++#include + #include + #include + #include + #include + #include ++#include + #include + #include + #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 + diff --git a/queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch b/queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch new file mode 100644 index 00000000000..1e1fcb229fe --- /dev/null +++ b/queue-6.10/power-supply-rt5033-bring-back-i2c_set_clientdata.patch @@ -0,0 +1,41 @@ +From df8ea4860eda6b9d624193269506702028ff9a33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 18:53:27 +0500 +Subject: power: supply: rt5033: Bring back i2c_set_clientdata + +From: Nikita Travkin + +[ 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 +Signed-off-by: Nikita Travkin +Link: https://lore.kernel.org/r/20240605-rt5033-null-clientdata-v1-1-558d710eeb4d@trvn.ru +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch b/queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch new file mode 100644 index 00000000000..61a00aada40 --- /dev/null +++ b/queue-6.10/r8169-remove-detection-of-chip-version-11-early-rtl8.patch @@ -0,0 +1,41 @@ +From c95d51f2944b26eb1d7db90295af840770ed150c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 May 2024 21:20:16 +0200 +Subject: r8169: remove detection of chip version 11 (early RTL8168b) + +From: Heiner Kallweit + +[ 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 +Link: https://lore.kernel.org/r/875cdcf4-843c-420a-ad5d-417447b68572@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch b/queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch new file mode 100644 index 00000000000..4f9dd89ee75 --- /dev/null +++ b/queue-6.10/rcu-fix-rcu_barrier-vs-post-cpuhp_teardown_cpu-invoc.patch @@ -0,0 +1,120 @@ +From 87be42b489031f336fd6306b38dac82246e01748 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 May 2024 16:05:24 +0200 +Subject: rcu: Fix rcu_barrier() VS post CPUHP_TEARDOWN_CPU invocation + +From: Frederic Weisbecker + +[ 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 + +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 + +stop_machine() + take_cpu_down() + rcu_barrier() + spin_lock(barrier_lock) + // observes rcu_segcblist_n_cbs(&rdp->cblist) != 0 + +do_softirq() + rcu_core() + rcu_do_batch() + //completes all pending callbacks + //smp_mb() implied _after_ callback number dec + + +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 +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch b/queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch new file mode 100644 index 00000000000..40c79130b98 --- /dev/null +++ b/queue-6.10/rcutorture-fix-rcu_torture_fwd_cb_cr-data-race.patch @@ -0,0 +1,50 @@ +From 979bb844576dfc17e70114e5e6cd38e05ba19815 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Apr 2024 12:02:11 -0700 +Subject: rcutorture: Fix rcu_torture_fwd_cb_cr() data race + +From: Paul E. McKenney + +[ 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 +Acked-by: Marco Elver +Cc: Andrey Konovalov +Cc: +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch b/queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch new file mode 100644 index 00000000000..13156ba5a66 --- /dev/null +++ b/queue-6.10/regmap-kunit-fix-memory-leaks-in-gen_regmap-and-gen_.patch @@ -0,0 +1,161 @@ +From 115d098e4b21deb2d3a85f86b1fc8ee34e9f8895 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://msgid.link/r/20240411103724.54063-1-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch b/queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch new file mode 100644 index 00000000000..46d3a7ba5f7 --- /dev/null +++ b/queue-6.10/revert-rcu-tasks-fix-synchronize_rcu_tasks-vs-zap_pi.patch @@ -0,0 +1,130 @@ +From c7ef3842aaf54bb8a367f6a94b90e86066a7e5cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Oleg Nesterov +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch b/queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch new file mode 100644 index 00000000000..b249ef24ef9 --- /dev/null +++ b/queue-6.10/rtnetlink-move-rtnl_lock-handling-out-of-af_netlink.patch @@ -0,0 +1,84 @@ +From f55180327012f0f847d9cd05ce4662c3e3d56e38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 12:29:05 -0700 +Subject: rtnetlink: move rtnl_lock handling out of af_netlink + +From: Jakub Kicinski + +[ 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 +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch b/queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch new file mode 100644 index 00000000000..296e9029ccc --- /dev/null +++ b/queue-6.10/s390-sclp-prevent-release-of-buffer-in-i-o.patch @@ -0,0 +1,52 @@ +From 3abb325358c8ba00fd9fdcdf21bcb33da7e2252e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jun 2024 14:20:27 +0200 +Subject: s390/sclp: Prevent release of buffer in I/O + +From: Peter Oberparleiter + +[ 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 +Signed-off-by: Peter Oberparleiter +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch b/queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch new file mode 100644 index 00000000000..0d35c441904 --- /dev/null +++ b/queue-6.10/sctp-fix-null-ptr-deref-in-reuseport_add_sock.patch @@ -0,0 +1,169 @@ +From 9ae4a4f48a9ec79154e3f499ba5468050ba5a9e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 16:46:24 -0700 +Subject: sctp: Fix null-ptr-deref in reuseport_add_sock(). + +From: Kuniyuki Iwashima + +[ 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: + + __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 + +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 +Acked-by: Xin Long +Link: https://patch.msgid.link/20240731234624.94055-1-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch b/queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch new file mode 100644 index 00000000000..9f1694eb31e --- /dev/null +++ b/queue-6.10/selftests-bpf-fix-send_signal-test-with-nested-confi.patch @@ -0,0 +1,120 @@ +From f6ca913a5be30cea9b776bdfbdd426d33f0f5367 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 13:12:03 -0700 +Subject: selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT + +From: Yonghong Song + +[ 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] + [ 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] + [ 48.553529] + [ 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] + +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 +Signed-off-by: Yonghong Song +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20240605201203.2603846-1-yonghong.song@linux.dev +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch b/queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch new file mode 100644 index 00000000000..ef12b7ffbb4 --- /dev/null +++ b/queue-6.10/selftests-ksft-fix-finished-helper-exit-code-on-skip.patch @@ -0,0 +1,43 @@ +From d9b11444b59d3863a586715d1b6e7adef7d12781 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: dacf1d7a78bf ("kselftest: Add test to verify probe of devices from discoverable buses") +Signed-off-by: Laura Nao +Reviewed-by: Muhammad Usama Anjum +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch b/queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch new file mode 100644 index 00000000000..5ed26d7c3ff --- /dev/null +++ b/queue-6.10/selftests-mptcp-join-ability-to-invert-add_addr-chec.patch @@ -0,0 +1,147 @@ +From 469e6fe99988649029b7f136218d5c3d8854e705 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 13:05:58 +0200 +Subject: selftests: mptcp: join: ability to invert ADD_ADDR check + +From: Matthieu Baerts (NGI0) + +[ 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 +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-6-c8a9b036493b@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch b/queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch new file mode 100644 index 00000000000..7c32aa07e20 --- /dev/null +++ b/queue-6.10/selftests-mptcp-join-test-both-signal-subflow.patch @@ -0,0 +1,69 @@ +From 3cc461a175266db86d3e3918e915988108c8953c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 13:05:59 +0200 +Subject: selftests: mptcp: join: test both signal & subflow + +From: Matthieu Baerts (NGI0) + +[ 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 +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-7-c8a9b036493b@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/series b/queue-6.10/series index 058ef66d012..879710093d9 100644 --- a/queue-6.10/series +++ b/queue-6.10/series @@ -1 +1,123 @@ 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 diff --git a/queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch b/queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch new file mode 100644 index 00000000000..7528140aabf --- /dev/null +++ b/queue-6.10/smb-client-handle-lack-of-fsctl_get_reparse_point-su.patch @@ -0,0 +1,134 @@ +From 9a7075723424ef12129d1a1b93d081871fa45c80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 10:23:39 -0300 +Subject: smb: client: handle lack of FSCTL_GET_REPARSE_POINT support + +From: Paulo Alcantara + +[ 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 +Tested-by: Sebastian Steinbeisser +Acked-by: Tom Talpey +Signed-off-by: Paulo Alcantara (Red Hat) +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch b/queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch new file mode 100644 index 00000000000..dcf363104f6 --- /dev/null +++ b/queue-6.10/soc-qcom-icc-bwmon-allow-for-interrupts-to-be-shared.patch @@ -0,0 +1,61 @@ +From c0664fb300408b27a12b709a39a168c2e3c3cd07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20240624092214.146935-4-quic_sibis@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch b/queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch new file mode 100644 index 00000000000..f81efa55921 --- /dev/null +++ b/queue-6.10/sunrpc-fix-a-race-to-wake-a-sync-task.patch @@ -0,0 +1,53 @@ +From ac69c54756981d59319f63c63598c30005cf18d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Jul 2024 10:49:33 -0400 +Subject: SUNRPC: Fix a race to wake a sync task + +From: Benjamin Coddington + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch b/queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch new file mode 100644 index 00000000000..32a323ae319 --- /dev/null +++ b/queue-6.10/thermal-intel-hfi-give-hfi-instances-package-scope.patch @@ -0,0 +1,125 @@ +From 2ec2adabc97a9bdb14c023d44ce6706c8265be4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jul 2024 13:54:45 +0800 +Subject: thermal: intel: hfi: Give HFI instances package scope + +From: Zhang Rui + +[ 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 +Signed-off-by: Chen Yu +Signed-off-by: Zhang Rui +Reviewed-by: Ricardo Neri +Link: https://patch.msgid.link/20240703055445.125362-1-rui.zhang@intel.com +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch b/queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch new file mode 100644 index 00000000000..3948be6f24a --- /dev/null +++ b/queue-6.10/udf-prevent-integer-overflow-in-udf_bitmap_free_bloc.patch @@ -0,0 +1,113 @@ +From 7037c8e9ddb173ac89ddeef484fccf17f5d15bde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jun 2024 10:24:13 +0300 +Subject: udf: prevent integer overflow in udf_bitmap_free_blocks() + +From: Roman Smirnov + +[ 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 +Signed-off-by: Roman Smirnov +Signed-off-by: Jan Kara +Signed-off-by: Sasha Levin +--- + 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 ++#include + + #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 + diff --git a/queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch b/queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch new file mode 100644 index 00000000000..a12c736b9f8 --- /dev/null +++ b/queue-6.10/virtio-net-unbreak-vq-resizing-when-coalescing-is-no.patch @@ -0,0 +1,55 @@ +From 7f6adfb3e6f58e0744f80dec409f7dac7a881e4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Xuan Zhuo +Acked-by: Eugenio Pé rez +Acked-by: Jason Wang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch b/queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch new file mode 100644 index 00000000000..7a2cef36cc0 --- /dev/null +++ b/queue-6.10/wifi-ath12k-fix-memory-leak-in-ath12k_dp_rx_peer_fra.patch @@ -0,0 +1,40 @@ +From ff178d8b532a407e5ef2a9c4c5b6636a28ffb4f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240526124226.24661-1-quic_bqiang@quicinc.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch b/queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch new file mode 100644 index 00000000000..0ab444ddca0 --- /dev/null +++ b/queue-6.10/wifi-ath12k-fix-race-due-to-setting-ath12k_flag_ext_.patch @@ -0,0 +1,75 @@ +From 0fc79574406532ac31165c556c8cc8365bcabb53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://msgid.link/20240524023642.37030-1-quic_bqiang@quicinc.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch b/queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch new file mode 100644 index 00000000000..d832fee55ab --- /dev/null +++ b/queue-6.10/wifi-mac80211-fix-null-dereference-at-band-check-in-.patch @@ -0,0 +1,110 @@ +From 3d948b9ac5f1492d6a0cc4165c3c33f8139e1bfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +[ 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 +Link: https://patch.msgid.link/20240617115217.22344-1-kevin_yang@realtek.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch b/queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch new file mode 100644 index 00000000000..8e8d05ab614 --- /dev/null +++ b/queue-6.10/wifi-nl80211-disallow-setting-special-ap-channel-wid.patch @@ -0,0 +1,62 @@ +From 128d3b9c21d94b6bce2f537c77f5cbc686cef97d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 14:16:00 +0200 +Subject: wifi: nl80211: disallow setting special AP channel widths + +From: Johannes Berg + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch b/queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch new file mode 100644 index 00000000000..90e44ef79af --- /dev/null +++ b/queue-6.10/wifi-nl80211-don-t-give-key-data-to-userspace.patch @@ -0,0 +1,55 @@ +From 9a5a3f985f453310f4d4782f0bd4320f38f66d91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Jun 2024 10:44:11 +0200 +Subject: wifi: nl80211: don't give key data to userspace + +From: Johannes Berg + +[ 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 +Link: https://patch.msgid.link/20240627104411.b6a4f097e4ea.I7e6cc976cb9e8a80ef25a3351330f313373b4578@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch b/queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch new file mode 100644 index 00000000000..ee0531cc502 --- /dev/null +++ b/queue-6.10/wifi-rtlwifi-handle-return-value-of-usb-init-tx-rx.patch @@ -0,0 +1,142 @@ +From bfebd03fbda839faa4cb55256add3d525b7db80a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 May 2024 08:32:48 +0800 +Subject: wifi: rtlwifi: handle return value of usb init TX/RX + +From: Ping-Ke Shih + +[ 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: + + __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 + + +Reported-by: Shichao Lai +Closes: https://lore.kernel.org/linux-wireless/CAEk6kZuuezkH1dVRJf3EAVZK-83=OpTz62qCugkpTkswj8JF6w@mail.gmail.com/T/#u +Tested-by: Shichao Lai +Signed-off-by: Ping-Ke Shih +Link: https://msgid.link/20240524003248.5952-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch b/queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch new file mode 100644 index 00000000000..33791ca0c38 --- /dev/null +++ b/queue-6.10/wifi-rtw89-pci-fix-rx-tag-race-condition-resulting-i.patch @@ -0,0 +1,59 @@ +From 7677d35617d23618b64bdd3b3017b4113c92887b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://msgid.link/20240611021901.26394-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch b/queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch new file mode 100644 index 00000000000..f2e81e762a2 --- /dev/null +++ b/queue-6.10/x86-mm-fix-pti_clone_entry_text-for-i386.patch @@ -0,0 +1,42 @@ +From 7b2dbb7688f8b5a467236a644510e7bb7317c5cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Aug 2024 12:42:25 +0200 +Subject: x86/mm: Fix pti_clone_entry_text() for i386 + +From: Peter Zijlstra + +[ 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) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch b/queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch new file mode 100644 index 00000000000..1390e9a79a9 --- /dev/null +++ b/queue-6.10/x86-mm-fix-pti_clone_pgtable-alignment-assumption.patch @@ -0,0 +1,68 @@ +From 77c77e2f8adae016f5e842e959c4aef7e51eddff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jul 2024 18:31:05 +0200 +Subject: x86/mm: Fix pti_clone_pgtable() alignment assumption + +From: Peter Zijlstra + +[ 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 +Tested-by: Guenter Roeck +Suggested-by: Thomas Gleixner +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20240731163105.GG33588@noisy.programming.kicks-ass.net +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch b/queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch new file mode 100644 index 00000000000..44997b177c8 --- /dev/null +++ b/queue-6.10/xen-privcmd-switch-from-mutex-to-spinlock-for-irqfds.patch @@ -0,0 +1,127 @@ +From e4857f0c15cc1227c949f2bdb69f932018283206 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jun 2024 15:12:28 +0530 +Subject: xen: privcmd: Switch from mutex to spinlock for irqfds + +From: Viresh Kumar + +[ 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 +Signed-off-by: Viresh Kumar +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/r/a66d7a7a9001424d432f52a9fc3931a1f345464f.1718703669.git.viresh.kumar@linaro.org +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + 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 +