6.10.7-rc1 review
Subsystems (11)
Greg Kroah-Hartman
maintainerPATCH 132/273 cpu/SMT: Enable SMT only if a core is online
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nysal Jan K.A <[email protected]>
[ Upstream commit 6c17ea1f3eaa330d445ac14a9428402ce4e3055e ]
If a core is offline then enabling SMT should not online CPUs of this core. By enabling SMT, what is intended is either changing the SMT value from "off" to "on" or setting the SMT level (threads per core) from a lower to higher value.
On PowerPC the ppc64_cpu utility can be used, among other things, to perform the following functions:
ppc64_cpu --cores-on # Get the number of online coresppc64_cpu --cores-on=X # Put exactly X cores onlineppc64_cpu --offline-cores=X[,Y,...] # Put specified cores offlineppc64_cpu --smt={on|off|value} # Enable, disable or change SMT level
If the user has decided to offline certain cores, enabling SMT should not online CPUs in those cores. This patch fixes the issue and changes the behaviour as described, by introducing an arch specific function topology_is_core_online(). It is currently implemented only for PowerPC.
--- Documentation/ABI/testing/sysfs-devices-system-cpu | 3 ++- kernel/cpu.c | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-)
Documentation/ABI/testing/sysfs-devices-system-cpu +2 -1
@@ -562,7 +562,8 @@ Description: Control Symmetric Multi Threading (SMT) ================ ========================================= If control status is "forceoff" or "notsupported" writes - are rejected. + are rejected. Note that enabling SMT on PowerPC skips + offline cores. What: /sys/devices/system/cpu/cpuX/power/energy_perf_bias Date: March 2019
kernel/cpu.c +11 -1
@@ -2679,6 +2679,16 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)return ret; } +/** +* Check if the core a CPU belongs to is online +*/ +#if !defined(topology_is_core_online) +static inline bool topology_is_core_online (unsigned int cpu) +{ +return true; +} +#endif +int cpuhp_smt_enable (void ) {int cpu, ret =0 ;
@@ -2689,7 +2699,7 @@ int cpuhp_smt_enable(void)/* Skip online CPUs and CPUs on offline nodes */ if (cpu_online (cpu) || !node_online (cpu_to_node (cpu)))continue ; -if (!cpu_smt_thread_allowed (cpu)) +if (!cpu_smt_thread_allowed (cpu) || !topology_is_core_online (cpu))continue ; ret =_cpu_up (cpu,0 ,CPUHP_ONLINE );if (ret)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 133/273 powerpc/topology: Check if a core is online
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nysal Jan K.A <[email protected]>
[ Upstream commit 227bbaabe64b6f9cd98aa051454c1d4a194a8c6a ]
topology_is_core_online() checks if the core a CPU belongs to is online. The core is online if at least one of the sibling CPUs is online. The first CPU of an online core is also online in the common case, so this should be fairly quick.
--- arch/powerpc/include/asm/topology.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/powerpc/include/asm/topology.h +13 -0
@@ -145,6 +145,7 @@ static inline int cpu_to_coregroup_id(int cpu)#ifdef CONFIG_HOTPLUG_SMT #include <linux/cpu_smt.h> +#include <linux/cpumask.h> #include <asm/cputhreads.h> static inline bool topology_is_primary_thread (unsigned int cpu)
@@ -156,6 +157,18 @@ static inline bool topology_smt_thread_allowed(unsigned int cpu) {return cpu_thread_in_core (cpu) < cpu_smt_num_threads; } + +#define topology_is_core_online topology_is_core_online +static inline bool topology_is_core_online (unsigned int cpu) +{ +int i, first_cpu =cpu_first_thread_sibling (cpu); + +for (i = first_cpu; i < first_cpu + threads_per_core; ++i) { +if (cpu_online (i)) +return true; + } +return false; +}#endif #endif /* __KERNEL__ */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 134/273 printk/panic: Allow cpu backtraces to be written into ringbuffer during panic
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryo Takakura <[email protected]>
[ Upstream commit bcc954c6caba01fca143162d5fbb90e46aa1ad80 ]
commit 779dbc2e78d7 ("printk: Avoid non-panic CPUs writing to ringbuffer") disabled non-panic CPUs to further write messages to ringbuffer after panicked.
Since the commit, non-panicked CPU's are not allowed to write to ring buffer after panicked and CPU backtrace which is triggered after panicked to sample non-panicked CPUs' backtrace no longer serves its function as it has nothing to print.
Fix the issue by allowing non-panicked CPUs to write into ringbuffer while CPU backtrace is in flight.
--- include/linux/panic.h | 1 + kernel/panic.c | 8 +++++++- kernel/printk/printk.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-)
include/linux/panic.h +1 -0
@@ -16,6 +16,7 @@ extern void oops_enter(void);extern void oops_exit (void );extern bool oops_may_print (void ); +extern bool panic_triggering_all_cpu_backtrace;extern int panic_timeout;extern unsigned long panic_print;extern int panic_on_oops;
kernel/panic.c +7 -1
@@ -63,6 +63,8 @@ unsigned long panic_on_taint;bool panic_on_taint_nousertaint = false;static unsigned int warn_limit__read_mostly ; +bool panic_triggering_all_cpu_backtrace; +int panic_timeout =CONFIG_PANIC_TIMEOUT ;EXPORT_SYMBOL_GPL (panic_timeout);
@@ -252,8 +254,12 @@ void check_panic_on_warn(const char *origin)*/ static void panic_other_cpus_shutdown (bool crash_kexec) { -if (panic_print &PANIC_PRINT_ALL_CPU_BT ) +if (panic_print &PANIC_PRINT_ALL_CPU_BT ) { +/* Temporary allow non-panic CPUs to write their backtraces. */ + panic_triggering_all_cpu_backtrace = true;trigger_all_cpu_backtrace (); + panic_triggering_all_cpu_backtrace = false; + }/* * Note that smp_send_stop() is the usual SMP shutdown function,
kernel/printk/printk.c +1 -1
@@ -2316,7 +2316,7 @@ asmlinkage int vprintk_emit(int facility, int level,* non-panic CPUs are generating any messages, they will be * silently dropped. */ -if (other_cpu_in_panic ()) +if (other_cpu_in_panic () && !panic_triggering_all_cpu_backtrace)return 0 ;if (level ==LOGLEVEL_SCHED ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 135/273 arm64: Fix KASAN random tag seed initialization
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <[email protected]>
[ Upstream commit f75c235565f90c4a17b125e47f1c68ef6b8c2bce ]
Currently, kasan_init_sw_tags() is called before setup_per_cpu_areas(), so per_cpu(prng_state, cpu) accesses the same address regardless of the value of "cpu", and the same seed value gets copied to the percpu area for every CPU. Fix this by moving the call to smp_prepare_boot_cpu(), which is the first architecture hook after setup_per_cpu_areas().
--- arch/arm64/kernel/setup.c | 3 --- arch/arm64/kernel/smp.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-)
arch/arm64/kernel/setup.c +0 -3
@@ -355,9 +355,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)smp_init_cpus ();smp_build_mpidr_hash (); -/* Init percpu seeds for random tags after cpus are set up. */ -kasan_init_sw_tags (); -#ifdef CONFIG_ARM64_SW_TTBR0_PAN /* * Make sure init_thread_info.ttbr0 always generates translation
arch/arm64/kernel/smp.c +2 -0
@@ -469,6 +469,8 @@ void __init smp_prepare_boot_cpu(void)init_gic_priority_masking ();kasan_init_hw_tags (); +/* Init percpu seeds for random tags after cpus are set up. */ +kasan_init_sw_tags (); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 136/273 block: Fix lockdep warning in blk_mq_mark_tag_wait
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Lingfeng <[email protected]>
[ Upstream commit b313a8c835516bdda85025500be866ac8a74e022 ]
Lockdep reported a warning in Linux version 6.6:
[ 414.344659] ================================
[ 414.345155] WARNING: inconsistent lock state
[ 414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
[ 414.346221] --------------------------------
[ 414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
[ 414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.351204] {IN-SOFTIRQ-W} state was registered at:
[ 414.351751] lock_acquire+0x18d/0x460
[ 414.352218] _raw_spin_lock_irqsave+0x39/0x60
[ 414.352769] __wake_up_common_lock+0x22/0x60
[ 414.353289] sbitmap_queue_wake_up+0x375/0x4f0
[ 414.353829] sbitmap_queue_clear+0xdd/0x270
[ 414.354338] blk_mq_put_tag+0xdf/0x170
[ 414.354807] __blk_mq_free_request+0x381/0x4d0
[ 414.355335] blk_mq_free_request+0x28b/0x3e0
[ 414.355847] __blk_mq_end_request+0x242/0xc30
[ 414.356367] scsi_end_request+0x2c1/0x830
[ 414.345155] WARNING: inconsistent lock state
[ 414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
[ 414.346221] --------------------------------
[ 414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
[ 414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.351204] {IN-SOFTIRQ-W} state was registered at:
[ 414.351751] lock_acquire+0x18d/0x460
[ 414.352218] _raw_spin_lock_irqsave+0x39/0x60
[ 414.352769] __wake_up_common_lock+0x22/0x60
[ 414.353289] sbitmap_queue_wake_up+0x375/0x4f0
[ 414.353829] sbitmap_queue_clear+0xdd/0x270
[ 414.354338] blk_mq_put_tag+0xdf/0x170
[ 414.354807] __blk_mq_free_request+0x381/0x4d0
[ 414.355335] blk_mq_free_request+0x28b/0x3e0
[ 414.355847] __blk_mq_end_request+0x242/0xc30
[ 414.356367] scsi_end_request+0x2c1/0x830
[ 414.356863] scsi_io_completion+0x177/0x1610
[ 414.357379] scsi_complete+0x12f/0x260
[ 414.357856] blk_complete_reqs+0xba/0xf0
[ 414.358338] __do_softirq+0x1b0/0x7a2
[ 414.358796] irq_exit_rcu+0x14b/0x1a0
[ 414.359262] sysvec_call_function_single+0xaf/0xc0
[ 414.359828] asm_sysvec_call_function_single+0x1a/0x20
[ 414.360426] default_idle+0x1e/0x30
[ 414.360873] default_idle_call+0x9b/0x1f0
[ 414.361390] do_idle+0x2d2/0x3e0
[ 414.361819] cpu_startup_entry+0x55/0x60
[ 414.362314] start_secondary+0x235/0x2b0
[ 414.362809] secondary_startup_64_no_verify+0x18f/0x19b
[ 414.363413] irq event stamp: 428794
[ 414.363825] hardirqs last enabled at (428793): [<ffffffff816bfd1c>] ktime_get+0x1dc/0x200
[ 414.364694] hardirqs last disabled at (428794): [<ffffffff85470177>] _raw_spin_lock_irq+0x47/0x50
[ 414.365629] softirqs last enabled at (428444): [<ffffffff85474780>] __do_softirq+0x540/0x7a2
[ 414.366522] softirqs last disabled at (428419): [<ffffffff813f65ab>] irq_exit_rcu+0x14b/0x1a0
[ 414.367425]
other info that might help us debug this:
[ 414.368194] Possible unsafe locking scenario:
[ 414.368900] CPU0
[ 414.369225] ----
[ 414.369548] lock(&sbq->ws[i].wait);
[ 414.370000] <Interrupt>
[ 414.370342] lock(&sbq->ws[i].wait);
[ 414.370802]
*** DEADLOCK ***
[ 414.371569] 5 locks held by kworker/u10:3/1152:
[ 414.372088] #0: ffff88810130e938 ((wq_completion)writeback){+.+.}-{0:0}, at: process_scheduled_works+0x357/0x13f0
[ 414.373180] #1: ffff88810201fdb8 ((work_completion)(&(&wb->dwork)->work)){+.+.}-{0:0}, at: process_scheduled_works+0x3a3/0x13f0
[ 414.374384] #2: ffffffff86ffbdc0 (rcu_read_lock){....}-{1:2}, at: blk_mq_run_hw_queue+0x637/0xa00
[ 414.375342] #3: ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
[ 414.376377] #4: ffff888106205a08 (&hctx->dispatch_wait_lock){+.-.}-{2:2}, at: blk_mq_dispatch_rq_list+0x1337/0x1ee0
[ 414.378607]
stack backtrace:
[ 414.379177] CPU: 0 PID: 1152 Comm: kworker/u10:3 Not tainted 6.6.0-07439-gba2303cacfda #6
[ 414.380032] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[ 414.381177] Workqueue: writeback wb_workfn (flush-253:0)
[ 414.381805] Call Trace:
[ 414.382136] <TASK>
[ 414.382429] dump_stack_lvl+0x91/0xf0
[ 414.382884] mark_lock_irq+0xb3b/0x1260
[ 414.383367] ? __pfx_mark_lock_irq+0x10/0x10
[ 414.383889] ? stack_trace_save+0x8e/0xc0
[ 414.384373] ? __pfx_stack_trace_save+0x10/0x10
[ 414.384903] ? graph_lock+0xcf/0x410
[ 414.385350] ? save_trace+0x3d/0xc70
[ 414.385808] mark_lock.part.20+0x56d/0xa90
[ 414.386317] mark_held_locks+0xb0/0x110
[ 414.386791] ? __pfx_do_raw_spin_lock+0x10/0x10
[ 414.387320] lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.387901] ? _raw_spin_unlock_irq+0x28/0x50
[ 414.388422] trace_hardirqs_on+0x58/0x100
[ 414.388917] _raw_spin_unlock_irq+0x28/0x50
[ 414.389422] __blk_mq_tag_busy+0x1d6/0x2a0
[ 414.389920] __blk_mq_get_driver_tag+0x761/0x9f0
[ 414.390899] blk_mq_dispatch_rq_list+0x1780/0x1ee0
[ 414.391473] ? __pfx_blk_mq_dispatch_rq_list+0x10/0x10
[ 414.392070] ? sbitmap_get+0x2b8/0x450
[ 414.392533] ? __blk_mq_get_driver_tag+0x210/0x9f0
[ 414.393095] __blk_mq_sched_dispatch_requests+0xd99/0x1690
[ 414.393730] ? elv_attempt_insert_merge+0x1b1/0x420
[ 414.394302] ? __pfx___blk_mq_sched_dispatch_requests+0x10/0x10
[ 414.394970] ? lock_acquire+0x18d/0x460
[ 414.395456] ? blk_mq_run_hw_queue+0x637/0xa00
[ 414.395986] ? __pfx_lock_acquire+0x10/0x10
[ 414.396499] blk_mq_sched_dispatch_requests+0x109/0x190
[ 414.397100] blk_mq_run_hw_queue+0x66e/0xa00
[ 414.397616] blk_mq_flush_plug_list.part.17+0x614/0x2030
[ 414.398244] ? __pfx_blk_mq_flush_plug_list.part.17+0x10/0x10
[ 414.398897] ? writeback_sb_inodes+0x241/0xcc0
[ 414.399429] blk_mq_flush_plug_list+0x65/0x80
[ 414.399957] __blk_flush_plug+0x2f1/0x530
[ 414.400458] ? __pfx___blk_flush_plug+0x10/0x10
[ 414.400999] blk_finish_plug+0x59/0xa0
[ 414.401467] wb_writeback+0x7cc/0x920
[ 414.401935] ? __pfx_wb_writeback+0x10/0x10
[ 414.402442] ? mark_held_locks+0xb0/0x110
[ 414.402931] ? __pfx_do_raw_spin_lock+0x10/0x10
[ 414.403462] ? lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.404062] wb_workfn+0x2b3/0xcf0
[ 414.404500] ? __pfx_wb_workfn+0x10/0x10
[ 414.404989] process_scheduled_works+0x432/0x13f0
[ 414.405546] ? __pfx_process_scheduled_works+0x10/0x10
[ 414.406139] ? do_raw_spin_lock+0x101/0x2a0
[ 414.406641] ? assign_work+0x19b/0x240
[ 414.407106] ? lock_is_held_type+0x9d/0x110
[ 414.407604] worker_thread+0x6f2/0x1160
[ 414.408075] ? __kthread_parkme+0x62/0x210
[ 414.408572] ? lockdep_hardirqs_on_prepare+0x297/0x3f0
[ 414.409168] ? __kthread_parkme+0x13c/0x210
[ 414.409678] ? __pfx_worker_thread+0x10/0x10
[ 414.410191] kthread+0x33c/0x440
[ 414.410602] ? __pfx_kthread+0x10/0x10
[ 414.411068] ret_from_fork+0x4d/0x80
[ 414.411526] ? __pfx_kthread+0x10/0x10
[ 414.411993] ret_from_fork_asm+0x1b/0x30
[ 414.412489] </TASK>When interrupt is turned on while a lock holding by spin_lock_irq it throws a warning because of potential deadlock.
blk_mq_prep_dispatch_rq
blk_mq_get_driver_tag
__blk_mq_get_driver_tag
__blk_mq_alloc_driver_tag
blk_mq_tag_busy -> tag is already busy
// failed to get driver tag blk_mq_mark_tag_wait
spin_lock_irq(&wq->lock) -> lock A (&sbq->ws[i].wait) __add_wait_queue(wq, wait) -> wait queue active blk_mq_get_driver_tag
__blk_mq_tag_busy
-> 1) tag must be idle, which means there can't be inflight IO
spin_lock_irq(&tags->lock) -> lock B (hctx->tags) spin_unlock_irq(&tags->lock) -> unlock B, turn on interrupt accidentally
-> 2) context must be preempt by IO interrupt to trigger deadlock.
As shown above, the deadlock is not possible in theory, but the warning still need to be fixed.
Fix it by using spin_lock_irqsave to get lockB instead of spin_lock_irq.
--- block/blk-mq-tag.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
block/blk-mq-tag.c +3 -2
@@ -38,6 +38,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags,void __blk_mq_tag_busy (struct blk_mq_hw_ctx *hctx) {unsigned int users; +unsigned long flags;struct blk_mq_tags *tags = hctx->tags;/*
@@ -56,11 +57,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)return ; } -spin_lock_irq (&tags->lock); +spin_lock_irqsave (&tags->lock, flags); users = tags->active_queues +1 ;WRITE_ONCE (tags->active_queues, users);blk_mq_update_wake_batch (tags, users); -spin_unlock_irq (&tags->lock); +spin_unlock_irqrestore (&tags->lock, flags); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 137/273 drm/amd/display: Dont register panel_power_savings on OLED panels
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
commit 76cb763e6ea62e838ccc8f7a1ea4246d690fccc9 upstream.
OLED panels don't support the ABM, they shouldn't offer the panel_power_savings attribute to the user. Check whether aux BL control support was enabled to decide whether to offer it.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +25 -4
@@ -6562,12 +6562,34 @@ static const struct attribute_group amdg .attrs = amdgpu_attrs }; +static bool +amdgpu_dm_should_create_sysfs (struct amdgpu_dm_connector *amdgpu_dm_connector) +{ +if (amdgpu_dm_abm_level >=0 ) +return false; + +if (amdgpu_dm_connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) +return false; + +/* check for OLED panels */ +if (amdgpu_dm_connector->bl_idx >=0 ) { +struct drm_device *drm = amdgpu_dm_connector->base.dev; +struct amdgpu_display_manager *dm = &drm_to_adev (drm)->dm; +struct amdgpu_dm_backlight_caps *caps; + + caps = &dm->backlight_caps[amdgpu_dm_connector->bl_idx]; +if (caps->aux_support) +return false; + } + +return true; +} +static void amdgpu_dm_connector_unregister (struct drm_connector *connector) {struct amdgpu_dm_connector *amdgpu_dm_connector =to_amdgpu_dm_connector (connector); -if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - amdgpu_dm_abm_level <0 ) +if (amdgpu_dm_should_create_sysfs (amdgpu_dm_connector))sysfs_remove_group (&connector->kdev->kobj, &amdgpu_group);drm_dp_aux_unregister (&amdgpu_dm_connector->dm_dp_aux.aux);
@@ -6674,8 +6696,7 @@ amdgpu_dm_connector_late_register(structto_amdgpu_dm_connector (connector);int r; -if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - amdgpu_dm_abm_level <0 ) { +if (amdgpu_dm_should_create_sysfs (amdgpu_dm_connector)) { r =sysfs_create_group (&connector->kdev->kobj, &amdgpu_group);if (r)
Greg Kroah-Hartman
maintainerPATCH 138/273 thermal: gov_bang_bang: Drop unnecessary cooling device target state checks
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 2c637af8a74d9a2a52ee5456a75dd29c8cb52da5 ]
Some cooling device target state checks in bang_bang_control() done before setting the new target state are not necessary after recent changes, so drop them.
Also avoid updating the target state before checking it for unexpected values.
Stable-dep-of: 84248e35d9b6 ("thermal: gov_bang_bang: Split bang_bang_control()")
--- drivers/thermal/gov_bang_bang.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
drivers/thermal/gov_bang_bang.c +3 -11
@@ -57,24 +57,16 @@ static void bang_bang_control(struct thermal_zone_device *tz,if (instance->trip != trip)continue ; -if (instance->target ==THERMAL_NO_TARGET ) - instance->target =0 ; - -if (instance->target !=0 && instance->target !=1 ) { +if (instance->target !=0 && instance->target !=1 && + instance->target !=THERMAL_NO_TARGET )pr_debug ("Unexpected state %ld of thermal instance %s in bang-bang\n" , instance->target, instance->name); - instance->target =1 ; - } -/* * Enable the fan when the trip is crossed on the way up and * disable it when the trip is crossed on the way down. */ -if (instance->target ==0 && crossed_up) - instance->target =1 ; -else if (instance->target ==1 && !crossed_up) - instance->target =0 ; + instance->target = crossed_up;dev_dbg (&instance->cdev->device,"target=%ld\n" , instance->target);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 139/273 thermal: gov_bang_bang: Split bang_bang_control()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 84248e35d9b60e03df7276627e4e91fbaf80f73d ]
Move the setting of the thermal instance target state from bang_bang_control() into a separate function that will be also called in a different place going forward.
No intentional functional impact.
--- drivers/thermal/gov_bang_bang.c | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-)
drivers/thermal/gov_bang_bang.c +23 -19
@@ -13,6 +13,27 @@#include "thermal_core.h" +static void bang_bang_set_instance_target (struct thermal_instance *instance, +unsigned int target) +{ +if (instance->target !=0 && instance->target !=1 && + instance->target !=THERMAL_NO_TARGET ) +pr_debug ("Unexpected state %ld of thermal instance %s in bang-bang\n" , + instance->target, instance->name); + +/* +* Enable the fan when the trip is crossed on the way up and disable it +* when the trip is crossed on the way down. +*/ + instance->target = target; + +dev_dbg (&instance->cdev->device,"target=%ld\n" , instance->target); + +mutex_lock (&instance->cdev->lock); +__thermal_cdev_update (instance->cdev); +mutex_unlock (&instance->cdev->lock); +} +/** * bang_bang_control - controls devices associated with the given zone * @tz: thermal_zone_device
@@ -54,25 +75,8 @@ static void bang_bang_control(struct thermal_zone_device *tz, tz->temperature, trip->hysteresis);list_for_each_entry (instance, &tz->thermal_instances, tz_node) { -if (instance->trip != trip) -continue ; - -if (instance->target !=0 && instance->target !=1 && - instance->target !=THERMAL_NO_TARGET ) -pr_debug ("Unexpected state %ld of thermal instance %s in bang-bang\n" , - instance->target, instance->name); - -/* -* Enable the fan when the trip is crossed on the way up and -* disable it when the trip is crossed on the way down. -*/ - instance->target = crossed_up; - -dev_dbg (&instance->cdev->device,"target=%ld\n" , instance->target); - -mutex_lock (&instance->cdev->lock); -__thermal_cdev_update (instance->cdev); -mutex_unlock (&instance->cdev->lock); +if (instance->trip == trip) +bang_bang_set_instance_target (instance, crossed_up); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 140/273 thermal: gov_bang_bang: Add .manage() callback
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 5f64b4a1ab1b0412446d42e1fc2964c2cdb60b27 ]
After recent changes, the Bang-bang governor may not adjust the initial configuration of cooling devices to the actual situation.
Namely, if a cooling device bound to a certain trip point starts in the "on" state and the thermal zone temperature is below the threshold of that trip point, the trip point may never be crossed on the way up in which case the state of the cooling device will never be adjusted because the thermal core will never invoke the governor's .trip_crossed() callback. [Note that there is no issue if the zone temperature is at the trip threshold or above it to start with because .trip_crossed() will be invoked then to indicate the start of thermal mitigation for the given trip.]
To address this, add a .manage() callback to the Bang-bang governor and use it to ensure that all of the thermal instances managed by the governor have been initialized properly and the states of all of the cooling devices involved have been adjusted to the current zone temperature as appropriate.
--- drivers/thermal/gov_bang_bang.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/thermal/gov_bang_bang.c +30 -0
@@ -26,6 +26,7 @@ static void bang_bang_set_instance_target(struct thermal_instance *instance,* when the trip is crossed on the way down. */ instance->target = target; + instance->initialized = true;dev_dbg (&instance->cdev->device,"target=%ld\n" , instance->target);
@@ -80,8 +81,37 @@ static void bang_bang_control(struct thermal_zone_device *tz, } } +static void bang_bang_manage (struct thermal_zone_device *tz) +{ +const struct thermal_trip_desc *td; +struct thermal_instance *instance; + +for_each_trip_desc (tz, td) { +const struct thermal_trip *trip = &td->trip; + +if (tz->temperature >= td->threshold || + trip->temperature ==THERMAL_TEMP_INVALID || + trip->type ==THERMAL_TRIP_CRITICAL || + trip->type ==THERMAL_TRIP_HOT ) +continue ; + +/* +* If the initial cooling device state is "on", but the zone +* temperature is not above the trip point, the core will not +* call bang_bang_control() until the zone temperature reaches +* the trip point temperature which may be never. In those +* cases, set the initial state of the cooling device to 0. +*/ +list_for_each_entry (instance, &tz->thermal_instances, tz_node) { +if (!instance->initialized && instance->trip == trip) +bang_bang_set_instance_target (instance,0 ); + } + } +} +static struct thermal_governor thermal_gov_bang_bang = { .name ="bang_bang" , .trip_crossed = bang_bang_control, + .manage = bang_bang_manage, };THERMAL_GOVERNOR_DECLARE (thermal_gov_bang_bang);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 141/273 thermal: gov_bang_bang: Use governor_data to reduce overhead
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 6e6f58a170ea98e44075b761f2da42a5aec47dfb ]
After running once, the for_each_trip_desc() loop in bang_bang_manage() is pure needless overhead because it is not going to make any changes unless a new cooling device has been bound to one of the trips in the thermal zone or the system is resuming from sleep.
For this reason, make bang_bang_manage() set governor_data for the thermal zone and check it upfront to decide whether or not it needs to do anything.
However, governor_data needs to be reset in some cases to let bang_bang_manage() know that it should walk the trips again, so add an .update_tz() callback to the governor and make the core additionally invoke it during system resume.
To avoid affecting the other users of that callback unnecessarily, add a special notification reason for system resume, THERMAL_TZ_RESUME, and also pass it to __thermal_zone_device_update() called during system resume for consistency.
--- drivers/thermal/gov_bang_bang.c | 18 ++++++++++++++++++ drivers/thermal/thermal_core.c | 3 ++- include/linux/thermal.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-)
drivers/thermal/gov_bang_bang.c +18 -0
@@ -86,6 +86,10 @@ static void bang_bang_manage(struct thermal_zone_device *tz)const struct thermal_trip_desc *td;struct thermal_instance *instance; +/* If the code below has run already, nothing needs to be done. */ +if (tz->governor_data) +return ; +for_each_trip_desc (tz, td) {const struct thermal_trip *trip = &td->trip;
@@ -107,11 +111,25 @@ static void bang_bang_manage(struct thermal_zone_device *tz)bang_bang_set_instance_target (instance,0 ); } } + + tz->governor_data = (void *)true; +} + +static void bang_bang_update_tz (struct thermal_zone_device *tz, +enum thermal_notify_event reason) +{ +/* +* Let bang_bang_manage() know that it needs to walk trips after binding +* a new cdev and after system resume. +*/ +if (reason ==THERMAL_TZ_BIND_CDEV || reason ==THERMAL_TZ_RESUME ) + tz->governor_data =NULL ; }static struct thermal_governor thermal_gov_bang_bang = { .name ="bang_bang" , .trip_crossed = bang_bang_control, .manage = bang_bang_manage, + .update_tz = bang_bang_update_tz, };THERMAL_GOVERNOR_DECLARE (thermal_gov_bang_bang);
drivers/thermal/thermal_core.c +2 -1
@@ -1715,7 +1715,8 @@ static void thermal_zone_device_resume(struct work_struct *work) tz->suspended = false;thermal_zone_device_init (tz); -__thermal_zone_device_update (tz,THERMAL_EVENT_UNSPECIFIED ); +thermal_governor_update_tz (tz,THERMAL_TZ_RESUME ); +__thermal_zone_device_update (tz,THERMAL_TZ_RESUME );complete (&tz->resume); tz->resuming = false;
include/linux/thermal.h +1 -0
@@ -55,6 +55,7 @@ enum thermal_notify_event {THERMAL_TZ_BIND_CDEV ,/* Cooling dev is bind to the thermal zone */ THERMAL_TZ_UNBIND_CDEV ,/* Cooling dev is unbind from the thermal zone */ THERMAL_INSTANCE_WEIGHT_CHANGED ,/* Thermal instance weight changed */ + THERMAL_TZ_RESUME, /* Thermal zone is resuming after system sleep */ };/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 142/273 cifs: Add a tracepoint to track credits involved in R/W requests
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit 519be989717c5bffaed1dc14a439e3872cb4bb8d ]
Add a tracepoint to track the credit changes and server in_flight value involved in the lifetime of a R/W request, logging it against the request/subreq debugging ID. This requires the debugging IDs to be recorded in the cifs_credits struct.
The tracepoint can be enabled with:
echo 1 >/sys/kernel/debug/tracing/events/cifs/smb3_rw_credits/enable
Also add a three-state flag to struct cifs_credits to note if we're interested in determining when the in_flight contribution ends and, if so, to track whether we've decremented the contribution yet.
Stable-dep-of: 74c2ab6d653b ("smb/client: avoid possible NULL dereference in cifs_free_subrequest()")
--- fs/smb/client/cifsglob.h | 17 +++++++----- fs/smb/client/file.c | 32 ++++++++++++++++++++++- fs/smb/client/smb1ops.c | 2 +- fs/smb/client/smb2ops.c | 42 ++++++++++++++++++++++++++---- fs/smb/client/smb2pdu.c | 40 +++++++++++++++++++++++++--- fs/smb/client/trace.h | 55 ++++++++++++++++++++++++++++++++++++++- fs/smb/client/transport.c | 8 +++--- 7 files changed, 173 insertions(+), 23 deletions(-)
fs/smb/client/cifsglob.h +10 -7
@@ -290,7 +290,7 @@ struct smb_version_operations {int (*check_receive)(struct mid_q_entry *,struct TCP_Server_Info *,bool );void (*add_credits)(struct TCP_Server_Info *server, -const struct cifs_credits *credits, +struct cifs_credits *credits,const int optype);void (*set_credits)(struct TCP_Server_Info *,const int );int * (*get_credits_field)(struct TCP_Server_Info *,const int );
@@ -550,8 +550,8 @@ struct smb_version_operations { size_t *, struct cifs_credits *);/* adjust previously taken mtu credits to request size */ int (*adjust_credits)(struct TCP_Server_Info *server, -struct cifs_credits *credits, -const unsigned int payload_size); +struct cifs_io_subrequest *subreq, +unsigned int /*enum smb3_rw_credits_trace*/ trace);/* check if we need to issue closedir */ bool (*dir_needs_close)(struct cifsFileInfo *); long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
@@ -848,6 +848,9 @@ static inline void cifs_server_unlock(struct TCP_Server_Info *server)struct cifs_credits {unsigned int value;unsigned int instance; +unsigned int in_flight_check; +unsigned int rreq_debug_id; +unsigned int rreq_debug_index; }; static inline unsigned int
@@ -873,7 +876,7 @@ has_credits(struct TCP_Server_Info *server, int *credits, int num_credits) }static inline void -add_credits (struct TCP_Server_Info *server,const struct cifs_credits *credits, +add_credits (struct TCP_Server_Info *server,struct cifs_credits *credits,const int optype) { server->ops->add_credits (server, credits, optype);
@@ -897,11 +900,11 @@ set_credits(struct TCP_Server_Info *server, const int val) }static inline int -adjust_credits (struct TCP_Server_Info *server,struct cifs_credits *credits, -const unsigned int payload_size) +adjust_credits (struct TCP_Server_Info *server,struct cifs_io_subrequest *subreq, +unsigned int /* enum smb3_rw_credits_trace */ trace) {return server->ops->adjust_credits ? - server->ops->adjust_credits (server, credits, payload_size) :0 ; + server->ops->adjust_credits (server, subreq, trace) :0 ; } static inline __le64
fs/smb/client/file.c +31 -1
@@ -80,6 +80,16 @@ static void cifs_prepare_write(struct netfs_io_subrequest *subreq)return netfs_prepare_write_failed (subreq); } + wdata->credits.rreq_debug_id = subreq->rreq->debug_id; + wdata->credits.rreq_debug_index = subreq->debug_index; + wdata->credits.in_flight_check =1 ; +trace_smb3_rw_credits (wdata->rreq->debug_id, + wdata->subreq.debug_index, + wdata->credits.value, + server->credits, server->in_flight, + wdata->credits.value, + cifs_trace_rw_credits_write_prepare); +#ifdef CONFIG_CIFS_SMB_DIRECT if (server->smbd_conn) subreq->max_nr_segs = server->smbd_conn->max_frmr_depth;
@@ -101,7 +111,7 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq) goto fail; } - rc =adjust_credits (wdata->server, &wdata->credits, wdata->subreq.len); + rc =adjust_credits (wdata->server, wdata, cifs_trace_rw_credits_issue_write_adjust);if (rc) goto fail;
@@ -163,7 +173,18 @@ static bool cifs_clamp_length(struct netfs_io_subrequest *subreq)return false; } + rdata->credits.in_flight_check =1 ; + rdata->credits.rreq_debug_id = rreq->debug_id; + rdata->credits.rreq_debug_index = subreq->debug_index; + +trace_smb3_rw_credits (rdata->rreq->debug_id, + rdata->subreq.debug_index, + rdata->credits.value, + server->credits, server->in_flight,0 , + cifs_trace_rw_credits_read_submit); + subreq->len =min_t (size_t, subreq->len, rsize); +#ifdef CONFIG_CIFS_SMB_DIRECT if (server->smbd_conn) subreq->max_nr_segs = server->smbd_conn->max_frmr_depth;
@@ -295,6 +316,15 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq)#endif } +if (rdata->credits.value !=0 ) +trace_smb3_rw_credits (rdata->rreq->debug_id, + rdata->subreq.debug_index, + rdata->credits.value, + rdata->server ? rdata->server->credits :0 , + rdata->server ? rdata->server->in_flight :0 , + -rdata->credits.value, + cifs_trace_rw_credits_free_subreq); +add_credits_and_wake_if (rdata->server, &rdata->credits,0 );if (rdata->have_xid)free_xid (rdata->xid);
fs/smb/client/smb1ops.c +1 -1
@@ -108,7 +108,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)static void cifs_add_credits (struct TCP_Server_Info *server, -const struct cifs_credits *credits,const int optype) +struct cifs_credits *credits,const int optype) {spin_lock (&server->req_lock); server->credits += credits->value;
fs/smb/client/smb2ops.c +37 -5
79 lines not on this page · raw message
fs/smb/client/smb2pdu.c +36 -4
@@ -4505,8 +4505,15 @@ smb2_readv_callback(struct mid_q_entry *mid)struct TCP_Server_Info *server = rdata->server;struct smb2_hdr *shdr = (struct smb2_hdr *)rdata->iov[0 ].iov_base; -struct cifs_credits credits = { .value =0 , .instance =0 }; +struct cifs_credits credits = { + .value =0 , + .instance =0 , + .rreq_debug_id = rdata->rreq->debug_id, + .rreq_debug_index = rdata->subreq.debug_index, + };struct smb_rqst rqst = { .rq_iov = &rdata->iov[1 ], .rq_nvec =1 }; +unsigned int rreq_debug_id = rdata->rreq->debug_id; +unsigned int subreq_debug_index = rdata->subreq.debug_index;if (rdata->got_bytes) { rqst.rq_iter = rdata->subreq.io_iter;
@@ -4590,10 +4597,16 @@ smb2_readv_callback(struct mid_q_entry *mid)if (rdata->subreq.start < rdata->subreq.rreq->i_size) rdata->result =0 ; } +trace_smb3_rw_credits (rreq_debug_id, subreq_debug_index, rdata->credits.value, + server->credits, server->in_flight, +0 , cifs_trace_rw_credits_read_response_clear); rdata->credits.value =0 ;INIT_WORK (&rdata->subreq.work, smb2_readv_worker);queue_work (cifsiod_wq, &rdata->subreq.work);release_mid (mid); +trace_smb3_rw_credits (rreq_debug_id, subreq_debug_index,0 , + server->credits, server->in_flight, + credits.value, cifs_trace_rw_credits_read_response_add);add_credits (server, &credits,0 ); }
@@ -4650,7 +4663,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)min_t (int, server->max_credits - server->credits, credit_request)); - rc =adjust_credits (server, &rdata->credits, rdata->subreq.len); + rc =adjust_credits (server, rdata, cifs_trace_rw_credits_call_readv_adjust);if (rc) goto async_readv_out;
@@ -4769,7 +4782,14 @@ smb2_writev_callback(struct mid_q_entry *mid)struct cifs_tcon *tcon =tlink_tcon (wdata->req->cfile->tlink);struct TCP_Server_Info *server = wdata->server;struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; -struct cifs_credits credits = { .value =0 , .instance =0 }; +struct cifs_credits credits = { + .value =0 , + .instance =0 , + .rreq_debug_id = wdata->rreq->debug_id, + .rreq_debug_index = wdata->subreq.debug_index, + }; +unsigned int rreq_debug_id = wdata->rreq->debug_id; +unsigned int subreq_debug_index = wdata->subreq.debug_index;ssize_t result =0 ;size_t written;
@@ -4840,9 +4860,15 @@ smb2_writev_callback(struct mid_q_entry *mid) tcon->tid, tcon->ses->Suid, wdata->subreq.start, wdata->subreq.len); +trace_smb3_rw_credits (rreq_debug_id, subreq_debug_index, wdata->credits.value, + server->credits, server->in_flight, +0 , cifs_trace_rw_credits_write_response_clear); wdata->credits.value =0 ;cifs_write_subrequest_terminated (wdata, result ?: written, true);release_mid (mid); +trace_smb3_rw_credits (rreq_debug_id, subreq_debug_index,0 , + server->credits, server->in_flight, + credits.value, cifs_trace_rw_credits_write_response_add);add_credits (server, &credits,0 ); }
@@ -4972,7 +4998,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)min_t (int, server->max_credits - server->credits, credit_request)); - rc =adjust_credits (server, &wdata->credits, io_parms->length); + rc =adjust_credits (server, wdata, cifs_trace_rw_credits_call_writev_adjust);if (rc) goto async_writev_out;
@@ -4997,6 +5023,12 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)cifs_small_buf_release (req); out:if (rc) { +trace_smb3_rw_credits (wdata->rreq->debug_id, + wdata->subreq.debug_index, + wdata->credits.value, + server->credits, server->in_flight, + -(int )wdata->credits.value, + cifs_trace_rw_credits_write_response_clear);add_credits_and_wake_if (wdata->server, &wdata->credits,0 );cifs_write_subrequest_terminated (wdata, rc, true); }
fs/smb/client/trace.h +54 -1
79 lines not on this page · raw message
fs/smb/client/transport.c +4 -4
@@ -988,10 +988,10 @@ static void cifs_compound_callback(struct mid_q_entry *mid) {struct TCP_Server_Info *server = mid->server; -struct cifs_credits credits; - - credits.value = server->ops->get_credits (mid); - credits.instance = server->reconnect_instance; +struct cifs_credits credits = { + .value = server->ops->get_credits (mid), + .instance = server->reconnect_instance, + };add_credits (server, &credits, mid->optype);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 143/273 smb/client: avoid possible NULL dereference in cifs_free_subrequest()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
[ Upstream commit 74c2ab6d653b4c2354df65a7f7f2df1925a40a51 ]
Clang static checker (scan-build) warning:
cifsglob.h:line 890, column 3
Access to field 'ops' results in a dereference of a null pointer.
Commit 519be989717c ("cifs: Add a tracepoint to track credits involved in R/W requests") adds a check for 'rdata->server', and let clang throw this warning about NULL dereference.
When 'rdata->credits.value != 0 && rdata->server == NULL' happens, add_credits_and_wake_if() will call rdata->server->ops->add_credits(). This will cause NULL dereference problem. Add a check for 'rdata->server' to avoid NULL dereference.
--- fs/smb/client/file.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/smb/client/file.c +6 -2
@@ -316,7 +316,7 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq)#endif } -if (rdata->credits.value !=0 ) +if (rdata->credits.value !=0 ) { trace_smb3_rw_credits(rdata->rreq->debug_id, rdata->subreq.debug_index, rdata->credits.value,
@@ -324,8 +324,12 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq) rdata->server ? rdata->server->in_flight :0 , -rdata->credits.value, cifs_trace_rw_credits_free_subreq); +if (rdata->server) +add_credits_and_wake_if (rdata->server, &rdata->credits,0 ); +else + rdata->credits.value =0 ; + } -add_credits_and_wake_if (rdata->server, &rdata->credits,0 );if (rdata->have_xid)free_xid (rdata->xid); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 144/273 dm suspend: return -ERESTARTSYS instead of -EINTR
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
[ Upstream commit 1e1fd567d32fcf7544c6e09e0e5bc6c650da6e23 ]
This commit changes device mapper, so that it returns -ERESTARTSYS instead of -EINTR when it is interrupted by a signal (so that the ioctl can be restarted).
The manpage signal(7) says that the ioctl function should be restarted if the signal was handled with SA_RESTART.
--- drivers/md/dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/dm.c +2 -2
@@ -2594,7 +2594,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int tabreak ;if (signal_pending_state (task_state, current)) { - r = -EINTR ; + r = -ERESTARTSYS ;break ; }
@@ -2619,7 +2619,7 @@ static int dm_wait_for_completion(struct mapped_device *md, unsigned int task_stbreak ;if (signal_pending_state (task_state, current)) { - r = -EINTR ; + r = -ERESTARTSYS ;break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 145/273 wifi: ath12k: use 128 bytes aligned iova in transmit path for WCN7850
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baochen Qiang <[email protected]>
[ Upstream commit 38055789d15155109b41602ad719d770af507030 ]
In transmit path, it is likely that the iova is not aligned to PCIe TLP max payload size, which is 128 for WCN7850. Normally in such cases hardware is expected to split the packet into several parts in a manner such that they, other than the first one, have aligned iova. However due to hardware limitations, WCN7850 does not behave like that properly with some specific unaligned iova in transmit path. This easily results in target hang in a KPI transmit test: packet send/receive failure, WMI command send timeout etc. Also fatal error seen in PCIe level:
... Capabilities: ... ... DevSta: ... FatalErr+ ... ... ...
Work around this by manually moving/reallocating payload buffer such that we can map it to a 128 bytes aligned iova. The moving requires sufficient head room or tail room in skb: for the former we can do ourselves a favor by asking some extra bytes when registering with mac80211, while for the latter we can do nothing.
Moving/reallocating buffer consumes additional CPU cycles, but the good news is that an aligned iova increases PCIe efficiency. In my tests on some X86 platforms the KPI results are almost consistent.
Since this is seen only with WCN7850, add a new hardware parameter to differentiate from others.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/dp_tx.c | 72 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/hw.c | 6 +++ drivers/net/wireless/ath/ath12k/hw.h | 4 ++ drivers/net/wireless/ath/ath12k/mac.c | 1 + 4 files changed, 83 insertions(+)
drivers/net/wireless/ath/ath12k/dp_tx.c +72 -0
@@ -124,6 +124,60 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); } +static void ath12k_dp_tx_move_payload (struct sk_buff *skb, +unsigned long delta, +bool head) +{ +unsigned long len = skb->len; + +if (head) { +skb_push (skb, delta); +memmove (skb->data, skb->data + delta, len); +skb_trim (skb, len); + }else { +skb_put (skb, delta); +memmove (skb->data + delta, skb->data, len); +skb_pull (skb, delta); + } +} + +static int ath12k_dp_tx_align_payload (struct ath12k_base *ab, +struct sk_buff **pskb) +{ +u32 iova_mask = ab->hw_params->iova_mask; +unsigned long offset, delta1, delta2; +struct sk_buff *skb2, *skb = *pskb; +unsigned int headroom =skb_headroom (skb); +int tailroom =skb_tailroom (skb); +int ret =0 ; + + offset = (unsigned long )skb->data & iova_mask; + delta1 = offset; + delta2 = iova_mask - offset +1 ; + +if (headroom >= delta1) { +ath12k_dp_tx_move_payload (skb, delta1, true); + }else if (tailroom >= delta2) { +ath12k_dp_tx_move_payload (skb, delta2, false); + }else { + skb2 =skb_realloc_headroom (skb, iova_mask); +if (!skb2) { + ret = -ENOMEM ; + goto out; + } + +dev_kfree_skb_any (skb); + + offset = (unsigned long )skb2->data & iova_mask; +if (offset) +ath12k_dp_tx_move_payload (skb2, offset, true); + *pskb = skb2; + } + +out: +return ret; +} +int ath12k_dp_tx (struct ath12k *ar,struct ath12k_vif *arvif,struct sk_buff *skb) {
@@ -145,6 +199,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,u8 ring_selector, ring_map =0 ;bool tcl_ring_retry;bool msdu_ext_desc = false; +u32 iova_mask = ab->hw_params->iova_mask;if (test_bit (ATH12K_FLAG_CRASH_FLUSH , &ar->ab->dev_flags))return -ESHUTDOWN ;
@@ -240,6 +295,23 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, goto fail_remove_tx_buf; } +if (iova_mask && + (unsigned long )skb->data & iova_mask) { + ret =ath12k_dp_tx_align_payload (ab, &skb); +if (ret) { +ath12k_warn (ab,"failed to align TX buffer %d\n" , ret); +/* don't bail out, give original buffer +* a chance even unaligned. +*/ + goto map; + } + +/* hdr is pointing to a wrong place after alignment, +* so refresh it for later use. +*/ + hdr = (void *)skb->data; + } +map: ti.paddr =dma_map_single (ab->dev, skb->data, skb->len,DMA_TO_DEVICE );if (dma_mapping_error (ab->dev, ti.paddr)) {atomic_inc (&ab->soc_stats.tx_err.misc_fail);
drivers/net/wireless/ath/ath12k/hw.c +6 -0
@@ -922,6 +922,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .supports_sta_ps = false, .acpi_guid = NULL, + + .iova_mask = 0, }, { .name = "wcn7850 hw2.0",
@@ -997,6 +999,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .supports_sta_ps = true, .acpi_guid = &wcn7850_uuid, + + .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1, }, { .name = "qcn9274 hw2.0",
@@ -1067,6 +1071,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .supports_sta_ps = false, .acpi_guid = NULL, + + .iova_mask = 0, }, };
drivers/net/wireless/ath/ath12k/hw.h +4 -0
@@ -96,6 +96,8 @@#define ATH12K_M3_FILE "m3.bin"#define ATH12K_REGDB_FILE_NAME "regdb.bin" +#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128 +enum ath12k_hw_rate_cck {ATH12K_HW_RATE_CCK_LP_11M =0 ,ATH12K_HW_RATE_CCK_LP_5_5M ,
@@ -214,6 +216,8 @@ struct ath12k_hw_params {bool supports_sta_ps;const guid_t *acpi_guid; + +u32 iova_mask; };struct ath12k_hw_ops {
drivers/net/wireless/ath/ath12k/mac.c +1 -0
@@ -8737,6 +8737,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) hw->vif_data_size =sizeof (struct ath12k_vif ); hw->sta_data_size =sizeof (struct ath12k_sta ); + hw->extra_tx_headroom = ab->hw_params->iova_mask;wiphy_ext_feature_set (wiphy,NL80211_EXT_FEATURE_CQM_RSSI_LIST );wiphy_ext_feature_set (wiphy,NL80211_EXT_FEATURE_STA_TX_PWR );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 146/273 platform/surface: aggregator: Fix warning when controller is destroyed in probe
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maximilian Luz <[email protected]>
[ Upstream commit bc923d594db21bee0ead128eb4bb78f7e77467a4 ]
There is a small window in ssam_serial_hub_probe() where the controller is initialized but has not been started yet. Specifically, between ssam_controller_init() and ssam_controller_start(). Any failure in this window, for example caused by a failure of serdev_device_open(), currently results in an incorrect warning being emitted.
In particular, any failure in this window results in the controller being destroyed via ssam_controller_destroy(). This function checks the state of the controller and, in an attempt to validate that the controller has been cleanly shut down before we try and deallocate any resources, emits a warning if that state is not SSAM_CONTROLLER_STOPPED.
However, since we have only just initialized the controller and have not yet started it, its state is SSAM_CONTROLLER_INITIALIZED. Note that this is the only point at which the controller has this state, as it will change after we start the controller with ssam_controller_start() and never revert back. Further, at this point no communication has taken place and the sender and receiver threads have not been started yet (and we may not even have an open serdev device either).
Therefore, it is perfectly safe to call ssam_controller_destroy() with a state of SSAM_CONTROLLER_INITIALIZED. This, however, means that the warning currently being emitted is incorrect. Fix it by extending the check.
--- drivers/platform/surface/aggregator/controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/platform/surface/aggregator/controller.c +2 -1
@@ -1354,7 +1354,8 @@ void ssam_controller_destroy(struct ssam_controller *ctrl)if (ctrl->state ==SSAM_CONTROLLER_UNINITIALIZED )return ; -WARN_ON (ctrl->state !=SSAM_CONTROLLER_STOPPED ); +WARN_ON (ctrl->state !=SSAM_CONTROLLER_STOPPED && + ctrl->state !=SSAM_CONTROLLER_INITIALIZED );/* * Note: New events could still have been received after the previous
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 147/273 ALSA: hda/tas2781: Use correct endian conversion
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 829e2a23121fb36ee30ea5145c2a85199f68e2c8 ]
The data conversion is done rather by a wrong function. We convert to BE32, not from BE32. Although the end result must be same, this was complained by the compiler.
Fix the code again and align with another similar function tas2563_apply_calib() that does already right.
--- sound/pci/hda/tas2781_hda_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/pci/hda/tas2781_hda_i2c.c +2 -2
@@ -527,8 +527,8 @@ static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)for (i =0 ; i < tas_priv->ndev; i++) {for (j =0 ; j <CALIB_MAX ; j++) { - data =get_unaligned_be32 ( - &tas_priv->cali_data.data[offset]); + data =cpu_to_be32 ( + *(uint32_t *)&tas_priv->cali_data.data[offset]); rc =tasdevice_dev_bulk_write (tas_priv, i,TASDEVICE_REG (0 , page_array[j], rgno_array[j]), (unsigned char *)&data,4 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 148/273 Makefile: add $(srctree) to dependency of compile_commands.json target
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandre Courbot <[email protected]>
[ Upstream commit 6fc9aacad49e3fbecd270c266850d50c453d52ef ]
When trying to build compile_commands.json for an external module against the kernel built in a separate output directory, the following error is displayed:
make[1]: *** No rule to make target 'scripts/clang-tools/gen_compile_commands.py', needed by 'compile_commands.json'. Stop.
This is because gen_compile_commands.py was previously looked up using a relative path to $(srctree), but commit b1992c3772e6 ("kbuild: use $(src) instead of $(srctree)/$(src) for source directory") stopped defining VPATH for external module builds.
Prefixing gen_compile_commands.py with $(srctree) fixes the problem.
--- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Makefile +1 -1
@@ -1986,7 +1986,7 @@ nsdeps: modules quiet_cmd_gen_compile_commands = GEN $@ cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs)) -$(extmod_prefix)compile_commands.json: scripts/clang-tools/gen_compile_commands.py \ +$(extmod_prefix)compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \ $(if $(KBUILD_EXTMOD),, vmlinux.a $(KBUILD_VMLINUX_LIBS)) \ $(if $(CONFIG_MODULES), $(MODORDER)) FORCE $(call if_changed,gen_compile_commands)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 149/273 kbuild: merge temporary vmlinux for BTF and kallsyms
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit b1a9a5e04767e2a78783e19c9e55c25812ceccc3 ]
CONFIG_DEBUG_INFO_BTF=y requires one additional link step. (.tmp_vmlinux.btf)
CONFIG_KALLSYMS=y requires two additional link steps. (.tmp_vmlinux.kallsyms1 and .tmp_vmlinux.kallsyms2)
Enabling both requires three additional link steps.
When CONFIG_DEBUG_INFO_BTF=y and CONFIG_KALLSYMS=y, the current build process is as follows:
KSYMS .tmp_vmlinux.kallsyms0.S
AS .tmp_vmlinux.kallsyms0.o
LD .tmp_vmlinux.btf # temporary vmlinux for BTF
BTF .btf.vmlinux.bin.o
LD .tmp_vmlinux.kallsyms1 # temporary vmlinux for kallsyms step 1
NM .tmp_vmlinux.kallsyms1.syms
KSYMS .tmp_vmlinux.kallsyms1.S
AS .tmp_vmlinux.kallsyms1.o
LD .tmp_vmlinux.kallsyms2 # temporary vmlinux for kallsyms step 2
NM .tmp_vmlinux.kallsyms2.syms
KSYMS .tmp_vmlinux.kallsyms2.S
AS .tmp_vmlinux.kallsyms2.o
LD vmlinux # final vmlinuxThis is redundant because the BTF generation and the kallsyms step 1 can be performed against the same temporary vmlinux.
When both CONFIG_DEBUG_INFO_BTF and CONFIG_KALLSYMS are enabled, we can reduce the number of link steps by one.
This commit changes the build process as follows:
KSYMS .tmp_vmlinux0.kallsyms.S
AS .tmp_vmlinux0.kallsyms.o
LD .tmp_vmlinux1 # temporary vmlinux for BTF and kallsyms step 1
BTF .tmp_vmlinux1.btf.o
NM .tmp_vmlinux1.syms
KSYMS .tmp_vmlinux1.kallsyms.S
AS .tmp_vmlinux1.kallsyms.o
LD .tmp_vmlinux2 # temporary vmlinux for kallsyms step 2
NM .tmp_vmlinux2.syms
KSYMS .tmp_vmlinux2.kallsyms.S
AS .tmp_vmlinux2.kallsyms.o
LD vmlinux # final vmlinuxStable-dep-of: 1472464c6248 ("kbuild: avoid scripts/kallsyms parsing /dev/null")
--- scripts/link-vmlinux.sh | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-)
scripts/link-vmlinux.sh +24 -17
@@ -105,11 +105,10 @@ vmlinux_link() # generate .BTF typeinfo from DWARF debuginfo # ${1} - vmlinux image -# ${2} - file to dump raw BTF data into gen_btf() { local pahole_ver - local btf_data=${2} + local btf_data=${1}.btf.o if ! [ -x "$(command -v ${PAHOLE})" ]; then echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
@@ -122,8 +121,6 @@ gen_btf() return 1 fi - vmlinux_link ${1} - info BTF "${btf_data}" LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1}
@@ -169,15 +166,13 @@ kallsyms() kallsymso=${2}.o } -# Perform one step in kallsyms generation, including temporary linking of -# vmlinux. -kallsyms_step() +# Perform kallsyms for the given temporary vmlinux. +sysmap_and_kallsyms() { - kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1} + mksysmap "${1}" "${1}.syms" + kallsyms "${1}.syms" "${1}.kallsyms" - vmlinux_link "${kallsyms_vmlinux}" - mksysmap "${kallsyms_vmlinux}" "${kallsyms_vmlinux}.syms" - kallsyms "${kallsyms_vmlinux}.syms" "${kallsyms_vmlinux}" + kallsyms_sysmap=${1}.syms } # Create map file with all symbols from ${1}
@@ -220,11 +215,21 @@ kallsymso= strip_debug= if is_enabled CONFIG_KALLSYMS; then - kallsyms /dev/null .tmp_vmlinux.kallsyms0 + kallsyms /dev/null .tmp_vmlinux0.kallsyms +fi + +if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then + + # The kallsyms linking does not need debug symbols, but the BTF does. + if ! is_enabled CONFIG_DEBUG_INFO_BTF; then + strip_debug=1 + fi + + vmlinux_link .tmp_vmlinux1 fi if is_enabled CONFIG_DEBUG_INFO_BTF; then - if ! gen_btf .tmp_vmlinux.btf .btf.vmlinux.bin.o ; then + if ! gen_btf .tmp_vmlinux1; then echo >&2 "Failed to generate BTF for vmlinux" echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" exit 1
@@ -260,14 +265,16 @@ if is_enabled CONFIG_KALLSYMS; then # The kallsyms linking does not need debug symbols included. strip_debug=1 - kallsyms_step 1 + sysmap_and_kallsyms .tmp_vmlinux1 size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) - kallsyms_step 2 + vmlinux_link .tmp_vmlinux2 + sysmap_and_kallsyms .tmp_vmlinux2 size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then - kallsyms_step 3 + vmlinux_link .tmp_vmlinux3 + sysmap_and_kallsyms .tmp_vmlinux3 fi fi
@@ -293,7 +300,7 @@ fi # step a (see comment above) if is_enabled CONFIG_KALLSYMS; then - if ! cmp -s System.map ${kallsyms_vmlinux}.syms; then + if ! cmp -s System.map "${kallsyms_sysmap}"; then echo >&2 Inconsistent kallsyms data echo >&2 'Try "make KALLSYMS_EXTRA_PASS=1" as a workaround' exit 1
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 150/273 kbuild: avoid scripts/kallsyms parsing /dev/null
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit 1472464c6248575bf2d01c7f076b94704bb32c95 ]
On macOS, as reported by Daniel Gomez, getline() sets ENOTTY to errno if it is requested to read from /dev/null.
If this is worth fixing, I would rather pass an empty file to scripts/kallsyms instead of adding the ugly #ifdef __APPLE__.
--- scripts/link-vmlinux.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
scripts/link-vmlinux.sh +2 -1
@@ -215,7 +215,8 @@ kallsymso= strip_debug= if is_enabled CONFIG_KALLSYMS; then - kallsyms /dev/null .tmp_vmlinux0.kallsyms + truncate -s0 .tmp_vmlinux.kallsyms0.syms + kallsyms .tmp_vmlinux.kallsyms0.syms .tmp_vmlinux0.kallsyms fi if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/273 Bluetooth: HCI: Invert LE State quirk to be opt-out rather then opt-in
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit aae6b81260fd9a7224f7eb4fc440d625852245bb ]
This inverts the LE State quirk so by default we assume the controllers would report valid states rather than invalid which is how quirks normally behave, also this would result in HCI command failing it the LE States are really broken thus exposing the controllers that are really broken in this respect.
--- drivers/bluetooth/btintel.c | 10 ---------- drivers/bluetooth/btintel_pcie.c | 3 --- drivers/bluetooth/btmtksdio.c | 3 --- drivers/bluetooth/btrtl.c | 1 - drivers/bluetooth/btusb.c | 4 ++-- drivers/bluetooth/hci_qca.c | 4 ++-- drivers/bluetooth/hci_vhci.c | 2 -- include/net/bluetooth/hci.h | 17 ++++++++++------- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_event.c | 2 +- 10 files changed, 16 insertions(+), 32 deletions(-)
drivers/bluetooth/btintel.c +0 -10
@@ -2876,9 +2876,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -if (ver.hw_variant ==0x08 && ver.fw_variant ==0x22 ) -set_bit (HCI_QUIRK_VALID_LE_STATES , - &hdev->quirks); err =btintel_legacy_rom_setup (hdev, &ver);break ;
@@ -2887,7 +2884,6 @@ static int btintel_setup_combined(struct hci_dev *hdev)case 0x12 :/* ThP */ case 0x13 :/* HrP */ case 0x14 :/* CcP */ -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); fallthrough;case 0x0c :/* WsP */ /* Apply the device specific HCI quirks
@@ -2979,9 +2975,6 @@ static int btintel_setup_combined(struct hci_dev *hdev)/* These variants don't seem to support LE Coded PHY */ set_bit (HCI_QUIRK_BROKEN_LE_CODED , &hdev->quirks); -/* Set Valid LE States quirk */ -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); -/* Setup MSFT Extension support */ btintel_set_msft_opcode (hdev, ver.hw_variant);
@@ -3003,9 +2996,6 @@ static int btintel_setup_combined(struct hci_dev *hdev)*/ set_bit (HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , &hdev->quirks); -/* Apply LE States quirk from solar onwards */ -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); -/* Setup MSFT Extension support */ btintel_set_msft_opcode (hdev,INTEL_HW_VARIANT (ver_tlv.cnvi_bt));
drivers/bluetooth/btintel_pcie.c +0 -3
@@ -1182,9 +1182,6 @@ static int btintel_pcie_setup(struct hci_dev *hdev)*/ set_bit (HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , &hdev->quirks); -/* Apply LE States quirk from solar onwards */ -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); -/* Setup MSFT Extension support */ btintel_set_msft_opcode (hdev,INTEL_HW_VARIANT (ver_tlv.cnvi_bt));
drivers/bluetooth/btmtksdio.c +0 -3
@@ -1144,9 +1144,6 @@ static int btmtksdio_setup(struct hci_dev *hdev) } } -/* Valid LE States quirk for MediaTek 7921 */ -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); -break ;case 0x7663 :case 0x7668 :
drivers/bluetooth/btrtl.c +0 -1
@@ -1287,7 +1287,6 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)case CHIP_ID_8852C :case CHIP_ID_8851B :case CHIP_ID_8852BT : -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks);set_bit (HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , &hdev->quirks);/* RTL8852C needs to transmit mSBC data continuously without
drivers/bluetooth/btusb.c +2 -2
@@ -4545,8 +4545,8 @@ static int btusb_probe(struct usb_interface *intf,if (id->driver_info &BTUSB_WIDEBAND_SPEECH )set_bit (HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , &hdev->quirks); -if (id->driver_info &BTUSB_VALID_LE_STATES ) -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); +if (!(id->driver_info &BTUSB_VALID_LE_STATES )) +set_bit (HCI_QUIRK_BROKEN_LE_STATES , &hdev->quirks);if (id->driver_info &BTUSB_DIGIANSWER ) { data->cmdreq_type =USB_TYPE_VENDOR ;
drivers/bluetooth/hci_qca.c +2 -2
@@ -2408,8 +2408,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)set_bit (HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , &hdev->quirks); -if (data->capabilities &QCA_CAP_VALID_LE_STATES ) -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); +if (!(data->capabilities &QCA_CAP_VALID_LE_STATES )) +set_bit (HCI_QUIRK_BROKEN_LE_STATES , &hdev->quirks); }return 0 ;
drivers/bluetooth/hci_vhci.c +0 -2
@@ -425,8 +425,6 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)if (opcode &0x80 )set_bit (HCI_QUIRK_RAW_DEVICE , &hdev->quirks); -set_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks); -if (hci_register_dev (hdev) <0 ) {BT_ERR ("Can't register HCI device" );hci_free_dev (hdev);
include/net/bluetooth/hci.h +10 -7
@@ -206,14 +206,17 @@ enum {*/ HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED , -/* When this quirk is set, the controller has validated that -* LE states reported through the HCI_LE_READ_SUPPORTED_STATES are -* valid. This mechanism is necessary as many controllers have -* been seen has having trouble initiating a connectable -* advertisement despite the state combination being reported as -* supported. +/* When this quirk is set, the LE states reported through the +* HCI_LE_READ_SUPPORTED_STATES are invalid/broken. +* +* This mechanism is necessary as many controllers have been seen has +* having trouble initiating a connectable advertisement despite the +* state combination being reported as supported. +* +* This quirk can be set before hci_register_dev is called or +* during the hdev->setup vendor callback. */ - HCI_QUIRK_VALID_LE_STATES, + HCI_QUIRK_BROKEN_LE_STATES,/* When this quirk is set, then erroneous data reporting * is ignored. This is mainly due to the fact that the HCI
include/net/bluetooth/hci_core.h +1 -1
@@ -826,7 +826,7 @@ extern struct mutex hci_cb_list_lock; }while (0 ) #define hci_dev_le_state_simultaneous(hdev) \ - (test_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks) && \ + (!test_bit (HCI_QUIRK_BROKEN_LE_STATES , &hdev->quirks) && \ (hdev->le_states[4 ] &0x08 ) &&/* Central */ \ (hdev->le_states[4 ] &0x40 ) &&/* Peripheral */ \ (hdev->le_states[3 ] &0x10 ))/* Simultaneous */
net/bluetooth/hci_event.c +1 -1
@@ -5921,7 +5921,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,* while we have an existing one in peripheral role. */ if (hdev->conn_hash.le_num_peripheral >0 && - (!test_bit (HCI_QUIRK_VALID_LE_STATES , &hdev->quirks) || + (test_bit (HCI_QUIRK_BROKEN_LE_STATES , &hdev->quirks) || !(hdev->le_states[3 ] &0x10 )))return NULL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/273 Bluetooth: hci_core: Fix LE quote calculation
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 932021a11805b9da4bd6abf66fe233cccd59fe0e ]
Function hci_sched_le needs to update the respective counter variable inplace other the likes of hci_quote_sent would attempt to use the possible outdated value of conn->{le_cnt,acl_cnt}.
--- net/bluetooth/hci_core.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
net/bluetooth/hci_core.c +7 -12
@@ -3674,19 +3674,19 @@ static void hci_sched_le(struct hci_dev *hdev) {struct hci_chan *chan;struct sk_buff *skb; -int quote, cnt, tmp; +int quote, *cnt, tmp;BT_DBG ("%s" , hdev->name);if (!hci_conn_num (hdev,LE_LINK ))return ; - cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; + cnt = hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; -__check_timeout (hdev, cnt,LE_LINK ); +__check_timeout (hdev, *cnt,LE_LINK ); - tmp = cnt; -while (cnt && (chan =hci_chan_sent (hdev,LE_LINK , "e))) { + tmp = *cnt; +while (*cnt && (chan =hci_chan_sent (hdev,LE_LINK , "e))) {u32 priority = (skb_peek (&chan->data_q))->priority;while (quote-- && (skb =skb_peek (&chan->data_q))) { BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
@@ -3701,7 +3701,7 @@ static void hci_sched_le(struct hci_dev *hdev)hci_send_frame (hdev, skb); hdev->le_last_tx = jiffies; - cnt--; + (*cnt)--; chan->sent++; chan->conn->sent++;
@@ -3711,12 +3711,7 @@ static void hci_sched_le(struct hci_dev *hdev) } } -if (hdev->le_pkts) - hdev->le_cnt = cnt; -else - hdev->acl_cnt = cnt; - -if (cnt != tmp) +if (*cnt != tmp)hci_prio_recalculate (hdev,LE_LINK ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/273 Bluetooth: SMP: Fix assumption of Central always being Initiator
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 28cd47f75185c4818b0fb1b46f2f02faaba96376 ]
SMP initiator role shall be considered the one that initiates the pairing procedure with SMP_CMD_PAIRING_REQ:
BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part H page 1557:
Figure 2.1: LE pairing phases
Note that by sending SMP_CMD_SECURITY_REQ it doesn't change the role to be Initiator.
--- net/bluetooth/smp.c | 144 ++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 72 deletions(-)
net/bluetooth/smp.c +72 -72
@@ -914,7 +914,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,* Confirms and the responder Enters the passkey. */ if (smp->method ==OVERLAP ) { -if (hcon->role ==HCI_ROLE_MASTER ) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) smp->method =CFM_PASSKEY ;else smp->method =REQ_PASSKEY ;
@@ -964,7 +964,7 @@ static u8 smp_confirm(struct smp_chan *smp)smp_send_cmd (smp->conn,SMP_CMD_PAIRING_CONFIRM ,sizeof (cp), &cp); -if (conn->hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_CONFIRM );else SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -980,7 +980,8 @@ static u8 smp_random(struct smp_chan *smp)int ret;bt_dev_dbg (conn->hcon->hdev,"conn %p %s" , conn, - conn->hcon->out ?"initiator" :"responder" ); +test_bit (SMP_FLAG_INITIATOR , &smp->flags) ?"initiator" : +"responder" ); ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, hcon->init_addr_type, &hcon->init_addr,
@@ -994,7 +995,7 @@ static u8 smp_random(struct smp_chan *smp)return SMP_CONFIRM_FAILED ; } -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {u8 stk[16 ];__le64 rand =0 ;__le16 ediv =0 ;
@@ -1256,14 +1257,15 @@ static void smp_distribute_keys(struct smp_chan *smp) rsp = (void *) &smp->prsp[1 ];/* The responder sends its keys first */ -if (hcon->out && (smp->remote_key_dist &KEY_DIST_MASK )) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags) && + (smp->remote_key_dist &KEY_DIST_MASK )) {smp_allow_key_dist (smp);return ; } req = (void *) &smp->preq[1 ]; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { keydist = &rsp->init_key_dist; *keydist &= req->init_key_dist; }else {
@@ -1432,7 +1434,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])struct hci_conn *hcon = smp->conn->hcon;u8 *na, *nb, a[7 ], b[7 ]; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { na = smp->prnd; nb = smp->rrnd; }else {
@@ -1460,7 +1462,7 @@ static void sc_dhkey_check(struct smp_chan *smp) a[6 ] = hcon->init_addr_type; b[6 ] = hcon->resp_addr_type; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local_addr = a; remote_addr = b;memcpy (io_cap, &smp->preq[1 ],3 );
@@ -1539,7 +1541,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)/* The round is only complete when the initiator * receives pairing random. */ -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);if (smp->passkey_round ==20 )
@@ -1567,7 +1569,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM ); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);return 0 ;
@@ -1578,7 +1580,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)case SMP_CMD_PUBLIC_KEY :default :/* Initiating device starts the round */ -if (!hcon->out) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))return 0 ; bt_dev_dbg(hdev, "Starting passkey round %u",
@@ -1623,7 +1625,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) }/* Initiator sends DHKey check first */ -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {sc_dhkey_check (smp);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK ); }else if (test_and_clear_bit (SMP_FLAG_DHKEY_PENDING , &smp->flags)) {
@@ -1746,7 +1748,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)struct smp_cmd_pairing rsp, *req = (void *) skb->data;struct l2cap_chan *chan = conn->smp;struct hci_dev *hdev = conn->hcon->hdev; -struct smp_chan *smp; +struct smp_chan *smp = chan->data;u8 key_size, auth, sec_level;int ret;
@@ -1755,16 +1757,14 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)if (skb->len <sizeof (*req))return SMP_INVALID_PARAMS ; -if (conn->hcon->role !=HCI_ROLE_SLAVE ) +if (smp &&test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_CMD_NOTSUPP ; -if (!chan->data) +if (!smp) { smp =smp_chan_create (conn); -else - smp = chan->data; - -if (!smp) -return SMP_UNSPECIFIED ; +if (!smp) +return SMP_UNSPECIFIED ; + }/* We didn't start the pairing, so match remote */ auth = req->auth_req &AUTH_REQ_MASK (hdev);
@@ -1946,7 +1946,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)if (skb->len <sizeof (*rsp))return SMP_INVALID_PARAMS ; -if (conn->hcon->role !=HCI_ROLE_MASTER ) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_CMD_NOTSUPP ;skb_pull (skb,sizeof (*rsp));
@@ -2041,7 +2041,7 @@ static u8 sc_check_confirm(struct smp_chan *smp)if (smp->method ==REQ_PASSKEY || smp->method ==DSP_PASSKEY )return sc_passkey_round (smp,SMP_CMD_PAIRING_CONFIRM ); -if (conn->hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -2063,7 +2063,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp)u8 auth;/* The issue is only observed when we're in responder role */ -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))return SMP_UNSPECIFIED ;if (hci_dev_test_flag (hdev,HCI_SC_ONLY )) {
@@ -2099,7 +2099,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)struct hci_dev *hdev = hcon->hdev;bt_dev_dbg (hdev,"conn %p %s" , conn, - hcon->out ?"initiator" :"responder" ); +test_bit (SMP_FLAG_INITIATOR , &smp->flags) ?"initiator" : +"responder" );if (skb->len <sizeof (smp->pcnf))return SMP_INVALID_PARAMS ;
@@ -2121,7 +2122,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)return ret; } -if (conn->hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RANDOM );
@@ -2156,7 +2157,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)if (!test_bit (SMP_FLAG_SC , &smp->flags))return smp_random (smp); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { pkax = smp->local_pk; pkbx = smp->remote_pk; na = smp->prnd;
@@ -2169,7 +2170,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) }if (smp->method ==REQ_OOB ) { -if (!hcon->out) +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags))smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK );
@@ -2180,7 +2181,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)if (smp->method ==REQ_PASSKEY || smp->method ==DSP_PASSKEY )return sc_passkey_round (smp,SMP_CMD_PAIRING_RANDOM ); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {u8 cfm[16 ]; err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
@@ -2221,7 +2222,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)return SMP_UNSPECIFIED ;if (smp->method ==REQ_OOB ) { -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {sc_dhkey_check (smp);SMP_ALLOW_CMD (smp,SMP_CMD_DHKEY_CHECK ); }
@@ -2295,10 +2296,27 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,return false; } +static void smp_send_pairing_req (struct smp_chan *smp,__u8 auth) +{ +struct smp_cmd_pairing cp; + +if (smp->conn->hcon->type ==ACL_LINK ) +build_bredr_pairing_cmd (smp, &cp,NULL ); +else +build_pairing_cmd (smp->conn, &cp,NULL , auth); + + smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; +memcpy (&smp->preq[1 ], &cp,sizeof (cp)); + +smp_send_cmd (smp->conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); +SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); + +set_bit (SMP_FLAG_INITIATOR , &smp->flags); +} +static u8 smp_cmd_security_req (struct l2cap_conn *conn,struct sk_buff *skb) {struct smp_cmd_security_req *rp = (void *) skb->data; -struct smp_cmd_pairing cp;struct hci_conn *hcon = conn->hcon;struct hci_dev *hdev = hcon->hdev;struct smp_chan *smp;
@@ -2347,16 +2365,20 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)skb_pull (skb,sizeof (*rp)); -memset (&cp,0 ,sizeof (cp)); -build_pairing_cmd (conn, &cp,NULL , auth); +smp_send_pairing_req (smp, auth); - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &cp,sizeof (cp)); +return 0 ; +} -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); +static void smp_send_security_req (struct smp_chan *smp,__u8 auth) +{ +struct smp_cmd_security_req cp; -return 0 ; + cp.auth_req = auth; +smp_send_cmd (smp->conn,SMP_CMD_SECURITY_REQ ,sizeof (cp), &cp); +SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_REQ ); + +clear_bit (SMP_FLAG_INITIATOR , &smp->flags); }int smp_conn_security (struct hci_conn *hcon,__u8 sec_level)
@@ -2427,23 +2449,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) authreq |=SMP_AUTH_MITM ; } -if (hcon->role ==HCI_ROLE_MASTER ) { -struct smp_cmd_pairing cp; - -build_pairing_cmd (conn, &cp,NULL , authreq); - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &cp,sizeof (cp)); - -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); - }else { -struct smp_cmd_security_req cp; - cp.auth_req = authreq; -smp_send_cmd (conn,SMP_CMD_SECURITY_REQ ,sizeof (cp), &cp); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_REQ ); - } +if (hcon->role ==HCI_ROLE_MASTER ) +smp_send_pairing_req (smp, authreq); +else +smp_send_security_req (smp, authreq); -set_bit (SMP_FLAG_INITIATOR , &smp->flags); ret =0 ; unlock:
@@ -2694,8 +2704,6 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)static u8 sc_select_method (struct smp_chan *smp) { -struct l2cap_conn *conn = smp->conn; -struct hci_conn *hcon = conn->hcon;struct smp_cmd_pairing *local, *remote;u8 local_mitm, remote_mitm, local_io, remote_io, method;
@@ -2708,7 +2716,7 @@ static u8 sc_select_method(struct smp_chan *smp)* the "struct smp_cmd_pairing" from them we need to skip the * first byte which contains the opcode. */ -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local = (void *) &smp->preq[1 ]; remote = (void *) &smp->prsp[1 ]; }else {
@@ -2777,7 +2785,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)/* Non-initiating device sends its public key after receiving * the key from the initiating device. */ -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { err =sc_send_public_key (smp);if (err)return err;
@@ -2839,7 +2847,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) }if (smp->method ==REQ_OOB ) { -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))smp_send_cmd (conn,SMP_CMD_PAIRING_RANDOM ,sizeof (smp->prnd), smp->prnd);
@@ -2848,7 +2856,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)return 0 ; } -if (hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_CONFIRM );if (smp->method ==REQ_PASSKEY ) {
@@ -2863,7 +2871,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)/* The Initiating device waits for the non-initiating device to * send the confirm value. */ -if (conn->hcon->out) +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags))return 0 ; err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
@@ -2897,7 +2905,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) a[6 ] = hcon->init_addr_type; b[6 ] = hcon->resp_addr_type; -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) { local_addr = a; remote_addr = b;memcpy (io_cap, &smp->prsp[1 ],3 );
@@ -2922,7 +2930,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)if (crypto_memneq (check->e, e,16 ))return SMP_DHKEY_CHECK_FAILED ; -if (!hcon->out) { +if (!test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {if (test_bit (SMP_FLAG_WAIT_USER , &smp->flags)) {set_bit (SMP_FLAG_DHKEY_PENDING , &smp->flags);return 0 ;
@@ -2934,7 +2942,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)sc_add_ltk (smp); -if (hcon->out) { +if (test_bit (SMP_FLAG_INITIATOR , &smp->flags)) {hci_le_start_enc (hcon,0 ,0 , smp->tk, smp->enc_key_size); hcon->enc_key_size = smp->enc_key_size; }
@@ -3083,7 +3091,6 @@ static void bredr_pairing(struct l2cap_chan *chan)struct l2cap_conn *conn = chan->conn;struct hci_conn *hcon = conn->hcon;struct hci_dev *hdev = hcon->hdev; -struct smp_cmd_pairing req;struct smp_chan *smp;bt_dev_dbg (hdev,"chan %p" , chan);
@@ -3135,14 +3142,7 @@ static void bredr_pairing(struct l2cap_chan *chan)bt_dev_dbg (hdev,"starting SMP over BR/EDR" ); -/* Prepare and send the BR/EDR SMP Pairing Request */ -build_bredr_pairing_cmd (smp, &req,NULL ); - - smp->preq[0 ] =SMP_CMD_PAIRING_REQ ; -memcpy (&smp->preq[1 ], &req,sizeof (req)); - -smp_send_cmd (conn,SMP_CMD_PAIRING_REQ ,sizeof (req), &req); -SMP_ALLOW_CMD (smp,SMP_CMD_PAIRING_RSP ); +smp_send_pairing_req (smp,0x00 ); }static void smp_resume_cb (struct l2cap_chan *chan)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/273 net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit 67c3ca2c5cfe6a50772514e3349b5e7b3b0fac03 ]
Problem description
-------------------
On an NXP LS1028A (felix DSA driver) with the following configuration:
- ocelot-8021q tagging protocol
- VLAN-aware bridge (with STP) spanning at least swp0 and swp1
- 8021q VLAN upper interfaces on swp0 and swp1: swp0.700, swp1.700
- ptp4l on swp0.700 and swp1.700
we see that the ptp4l instances do not see each other's traffic, and they all go to the grand master state due to the ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES condition.
Jumping to the conclusion for the impatient
-------------------------------------------
There is a zero-day bug in the ocelot switchdev driver in the way it handles VLAN-tagged packet injection. The correct logic already exists in the source code, in function ocelot_xmit_get_vlan_info() added by commit 5ca721c54d86 ("net: dsa: tag_ocelot: set the classified VLAN during xmit"). But it is used only for normal NPI-based injection with the DSA "ocelot" tagging protocol. The other injection code paths (register-based and FDMA-based) roll their own wrong logic. This affects and was noticed on the DSA "ocelot-8021q" protocol because it uses register-based injection.
By moving ocelot_xmit_get_vlan_info() to a place that's common for both the DSA tagger and the ocelot switch library, it can also be called from ocelot_port_inject_frame() in ocelot.c.
We need to touch the lines with ocelot_ifh_port_set()'s prototype anyway, so let's rename it to something clearer regarding what it does, and add a kernel-doc. ocelot_ifh_set_basic() should do.
Investigation notes
-------------------
Debugging reveals that PTP event (aka those carrying timestamps, like Sync) frames injected into swp0.700 (but also swp1.700) hit the wire with two VLAN tags:
00000000: 01 1b 19 00 00 00 00 01 02 03 04 05 81 00 02 bc
~~~~~~~~~~~
00000010: 81 00 02 bc 88 f7 00 12 00 2c 00 00 02 00 00 00
~~~~~~~~~~~00000020: 00 00 00 00 00 00 00 00 00 00 00 01 02 ff fe 03 00000030: 04 05 00 01 00 04 00 00 00 00 00 00 00 00 00 00 00000040: 00 00
The second (unexpected) VLAN tag makes felix_check_xtr_pkt() -> ptp_classify_raw() fail to see these as PTP packets at the link partner's receiving end, and return PTP_CLASS_NONE (because the BPF classifier is not written to expect 2 VLAN tags).
The reason why packets have 2 VLAN tags is because the transmission code treats VLAN incorrectly.
Neither ocelot switchdev, nor felix DSA, declare the NETIF_F_HW_VLAN_CTAG_TX feature. Therefore, at xmit time, all VLANs should be in the skb head, and none should be in the hwaccel area. This is done by:
static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
netdev_features_t features)
{
if (skb_vlan_tag_present(skb) &&
!vlan_hw_offload_capable(features, skb->vlan_proto))
skb = __vlan_hwaccel_push_inside(skb);
return skb;
}But ocelot_port_inject_frame() handles things incorrectly:
ocelot_ifh_port_set(ifh, port, rew_op, skb_vlan_tag_get(skb));
void ocelot_ifh_port_set(struct sk_buff *skb, void *ifh, int port, u32 rew_op)
{
(...)
if (vlan_tag)
ocelot_ifh_set_vlan_tci(ifh, vlan_tag);
(...)
}The way __vlan_hwaccel_push_inside() pushes the tag inside the skb head is by calling:
static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
{
skb->vlan_present = 0;
}which does _not_ zero out skb->vlan_tci as seen by skb_vlan_tag_get(). This means that ocelot, when it calls skb_vlan_tag_get(), sees (and uses) a residual skb->vlan_tci, while the same VLAN tag is _already_ in the skb head.
The trivial fix for double VLAN headers is to replace the content of ocelot_ifh_port_set() with:
if (skb_vlan_tag_present(skb)) ocelot_ifh_set_vlan_tci(ifh, skb_vlan_tag_get(skb));
but this would not be correct either, because, as mentioned, vlan_hw_offload_capable() is false for us, so we'd be inserting dead code and we'd always transmit packets with VID=0 in the injection frame header.
I can't actually test the ocelot switchdev driver and rely exclusively on code inspection, but I don't think traffic from 8021q uppers has ever been injected properly, and not double-tagged. Thus I'm blaming the introduction of VLAN fields in the injection header - early driver code.
As hinted at in the early conclusion, what we _want_ to happen for VLAN transmission was already described once in commit 5ca721c54d86 ("net: dsa: tag_ocelot: set the classified VLAN during xmit").
ocelot_xmit_get_vlan_info() intends to ensure that if the port through which we're transmitting is under a VLAN-aware bridge, the outer VLAN tag from the skb head is stripped from there and inserted into the injection frame header (so that the packet is processed in hardware through that actual VLAN). And in all other cases, the packet is sent with VID=0 in the injection frame header, since the port is VLAN-unaware and has logic to strip this VID on egress (making it invisible to the wire).
--- drivers/net/ethernet/mscc/ocelot.c | 29 +++++++++++---- drivers/net/ethernet/mscc/ocelot_fdma.c | 2 +- include/linux/dsa/ocelot.h | 47 +++++++++++++++++++++++++ include/soc/mscc/ocelot.h | 3 +- net/dsa/tag_ocelot.c | 37 ++----------------- 5 files changed, 75 insertions(+), 43 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +23 -6
@@ -1193,17 +1193,34 @@ bool ocelot_can_inject(struct ocelot *ocelot, int grp) }EXPORT_SYMBOL (ocelot_can_inject); -void ocelot_ifh_port_set (void *ifh,int port,u32 rew_op,u32 vlan_tag) +/** +* ocelot_ifh_set_basic - Set basic information in Injection Frame Header +* @ifh: Pointer to Injection Frame Header memory +* @ocelot: Switch private data structure +* @port: Egress port number +* @rew_op: Egress rewriter operation for PTP +* @skb: Pointer to socket buffer (packet) +* +* Populate the Injection Frame Header with basic information for this skb: the +* analyzer bypass bit, destination port, VLAN info, egress rewriter info. +*/ +void ocelot_ifh_set_basic (void *ifh,struct ocelot *ocelot,int port, +u32 rew_op,struct sk_buff *skb) { +struct ocelot_port *ocelot_port = ocelot->ports[port]; +u64 vlan_tci, tag_type; + +ocelot_xmit_get_vlan_info (skb, ocelot_port->bridge, &vlan_tci, + &tag_type); +ocelot_ifh_set_bypass (ifh,1 );ocelot_ifh_set_dest (ifh,BIT_ULL (port)); -ocelot_ifh_set_tag_type (ifh,IFH_TAG_TYPE_C ); -if (vlan_tag) -ocelot_ifh_set_vlan_tci (ifh, vlan_tag); +ocelot_ifh_set_tag_type (ifh, tag_type); +ocelot_ifh_set_vlan_tci (ifh, vlan_tci);if (rew_op)ocelot_ifh_set_rew_op (ifh, rew_op); } -EXPORT_SYMBOL (ocelot_ifh_port_set); +EXPORT_SYMBOL (ocelot_ifh_set_basic);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb)
@@ -1214,7 +1231,7 @@ void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp,ocelot_write_rix (ocelot,QS_INJ_CTRL_GAP_SIZE (1 ) |QS_INJ_CTRL_SOF ,QS_INJ_CTRL , grp); -ocelot_ifh_port_set (ifh, port, rew_op,skb_vlan_tag_get (skb)); +ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);for (i =0 ; i <OCELOT_TAG_LEN /4 ; i++)ocelot_write_rix (ocelot, ifh[i],QS_INJ_WR , grp);
drivers/net/ethernet/mscc/ocelot_fdma.c +1 -1
@@ -666,7 +666,7 @@ static int ocelot_fdma_prepare_skb(struct ocelot *ocelot, int port, u32 rew_op, ifh =skb_push (skb,OCELOT_TAG_LEN );skb_put (skb,ETH_FCS_LEN );memset (ifh,0 ,OCELOT_TAG_LEN ); -ocelot_ifh_port_set (ifh, port, rew_op,skb_vlan_tag_get (skb)); +ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);return 0 ; }
include/linux/dsa/ocelot.h +47 -0
57 lines not on this page · raw message
include/soc/mscc/ocelot.h +2 -1
@@ -969,7 +969,8 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,bool ocelot_can_inject (struct ocelot *ocelot,int grp);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb); -void ocelot_ifh_port_set (void *ifh,int port,u32 rew_op,u32 vlan_tag); +void ocelot_ifh_set_basic (void *ifh,struct ocelot *ocelot,int port, +u32 rew_op,struct sk_buff *skb);int ocelot_xtr_poll_frame (struct ocelot *ocelot,int grp,struct sk_buff **skb);void ocelot_drain_cpu_queue (struct ocelot *ocelot,int grp); void ocelot_ptp_rx_timestamp(struct ocelot *ocelot, struct sk_buff *skb,
net/dsa/tag_ocelot.c +2 -35
@@ -8,40 +8,6 @@#define OCELOT_NAME "ocelot"#define SEVILLE_NAME "seville" -/* If the port is under a VLAN-aware bridge, remove the VLAN header from the -* payload and move it into the DSA tag, which will make the switch classify -* the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero, -* which is the pvid of standalone and VLAN-unaware bridge ports. -*/ -static void ocelot_xmit_get_vlan_info (struct sk_buff *skb,struct dsa_port *dp, -u64 *vlan_tci,u64 *tag_type) -{ -struct net_device *br =dsa_port_bridge_dev_get (dp); -struct vlan_ethhdr *hdr; -u16 proto, tci; - -if (!br || !br_vlan_enabled (br)) { - *vlan_tci =0 ; - *tag_type =IFH_TAG_TYPE_C ; -return ; - } - - hdr =skb_vlan_eth_hdr (skb); -br_vlan_get_proto (br, &proto); - -if (ntohs (hdr->h_vlan_proto) == proto) { -vlan_remove_tag (skb, &tci); - *vlan_tci = tci; - }else { -rcu_read_lock (); -br_vlan_get_pvid_rcu (br, &tci); -rcu_read_unlock (); - *vlan_tci = tci; - } - - *tag_type = (proto !=ETH_P_8021Q ) ?IFH_TAG_TYPE_S :IFH_TAG_TYPE_C ; -} -static void ocelot_xmit_common (struct sk_buff *skb,struct net_device *netdev,__be32 ifh_prefix,void **ifh) {
@@ -53,7 +19,8 @@ static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev,u32 rew_op =0 ;u64 qos_class; -ocelot_xmit_get_vlan_info (skb, dp, &vlan_tci, &tag_type); +ocelot_xmit_get_vlan_info (skb,dsa_port_bridge_dev_get (dp), &vlan_tci, + &tag_type); qos_class =netdev_get_num_tc (netdev) ?netdev_get_prio_tc_map (netdev, skb->priority) : skb->priority;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/273 net: mscc: ocelot: fix QoS class for injected packets with "ocelot-8021q"
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit e1b9e80236c540fa85d76e2d510d1b38e1968c5d ]
There are 2 distinct code paths (listed below) in the source code which set up an injection header for Ocelot(-like) switches. Code path (2) lacks the QoS class and source port being set correctly. Especially the improper QoS classification is a problem for the "ocelot-8021q" alternative DSA tagging protocol, because we support tc-taprio and each packet needs to be scheduled precisely through its time slot. This includes PTP, which is normally assigned to a traffic class other than 0, but would be sent through TC 0 nonetheless.
The code paths are:
(1) ocelot_xmit_common() from net/dsa/tag_ocelot.c - called only by the standard "ocelot" DSA tagging protocol which uses NPI-based injection - sets up bit fields in the tag manually to account for a small difference (destination port offset) between Ocelot and Seville. Namely, ocelot_ifh_set_dest() is omitted out of ocelot_xmit_common(), because there's also seville_ifh_set_dest().
(2) ocelot_ifh_set_basic(), called by:
- ocelot_fdma_prepare_skb() for FDMA transmission of the ocelot switchdev driver
- ocelot_port_xmit() -> ocelot_port_inject_frame() for register-based transmission of the ocelot switchdev driver
- felix_port_deferred_xmit() -> ocelot_port_inject_frame() for the DSA tagger ocelot-8021q when it must transmit PTP frames (also through register-based injection).
sets the bit fields according to its own logic.
The problem is that (2) doesn't call ocelot_ifh_set_qos_class(). Copying that logic from ocelot_xmit_common() fixes that.
Unfortunately, although desirable, it is not easily possible to de-duplicate code paths (1) and (2), and make net/dsa/tag_ocelot.c directly call ocelot_ifh_set_basic()), because of the ocelot/seville difference. This is the "minimal" fix with some logic duplicated (but at least more consolidated).
--- drivers/net/ethernet/mscc/ocelot.c | 10 +++++++++- drivers/net/ethernet/mscc/ocelot_fdma.c | 1 - 2 files changed, 9 insertions(+), 2 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +9 -1
@@ -1208,13 +1208,21 @@ void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port, u32 rew_op, struct sk_buff *skb) { struct ocelot_port *ocelot_port = ocelot->ports[port]; +struct net_device *dev = skb->dev;u64 vlan_tci, tag_type; +int qos_class;ocelot_xmit_get_vlan_info (skb, ocelot_port->bridge, &vlan_tci, &tag_type); + qos_class =netdev_get_num_tc (dev) ? +netdev_get_prio_tc_map (dev, skb->priority) : skb->priority; + +memset (ifh,0 ,OCELOT_TAG_LEN );ocelot_ifh_set_bypass (ifh,1 ); +ocelot_ifh_set_src (ifh,BIT_ULL (ocelot->num_phys_ports));ocelot_ifh_set_dest (ifh,BIT_ULL (port)); +ocelot_ifh_set_qos_class (ifh, qos_class);ocelot_ifh_set_tag_type (ifh, tag_type);ocelot_ifh_set_vlan_tci (ifh, vlan_tci);if (rew_op)
@@ -1225,7 +1233,7 @@ EXPORT_SYMBOL(ocelot_ifh_set_basic);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb) { -u32 ifh[OCELOT_TAG_LEN /4 ] = {0 }; +u32 ifh[OCELOT_TAG_LEN /4 ];unsigned int i, count, last; ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) |
drivers/net/ethernet/mscc/ocelot_fdma.c +0 -1
@@ -665,7 +665,6 @@ static int ocelot_fdma_prepare_skb(struct ocelot *ocelot, int port, u32 rew_op, ifh =skb_push (skb,OCELOT_TAG_LEN );skb_put (skb,ETH_FCS_LEN ); -memset (ifh,0 ,OCELOT_TAG_LEN );ocelot_ifh_set_basic (ifh, ocelot, port, rew_op, skb);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/273 net: mscc: ocelot: serialize access to the injection/extraction groups
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <[email protected]>
[ Upstream commit c5e12ac3beb0dd3a718296b2d8af5528e9ab728e ]
As explained by Horatiu Vultur in commit 603ead96582d ("net: sparx5: Add spinlock for frame transmission from CPU") which is for a similar hardware design, multiple CPUs can simultaneously perform injection or extraction. There are only 2 register groups for injection and 2 for extraction, and the driver only uses one of each. So we'd better serialize access using spin locks, otherwise frame corruption is possible.
Note that unlike in sparx5, FDMA in ocelot does not have this issue because struct ocelot_fdma_tx_ring already contains an xmit_lock.
I guess this is mostly a problem for NXP LS1028A, as that is dual core. I don't think VSC7514 is. So I'm blaming the commit where LS1028A (aka the felix DSA driver) started using register-based packet injection and extraction.
--- drivers/net/dsa/ocelot/felix.c | 11 +++++ drivers/net/ethernet/mscc/ocelot.c | 52 ++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 4 ++ include/soc/mscc/ocelot.h | 9 ++++ 4 files changed, 76 insertions(+)
drivers/net/dsa/ocelot/felix.c +11 -0
@@ -528,7 +528,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)* so we need to be careful that there are no extra frames to be * dequeued over MMIO, since we would never know to discard them. */ +ocelot_lock_xtr_grp_bh (ocelot,0 );ocelot_drain_cpu_queue (ocelot,0 ); +ocelot_unlock_xtr_grp_bh (ocelot,0 );return 0 ; }
@@ -1504,6 +1506,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)int port = xmit_work->dp->index;int retries =10 ; +ocelot_lock_inj_grp (ocelot,0 ); + do { if (ocelot_can_inject(ocelot, 0)) break;
@@ -1512,6 +1516,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work) }while (--retries);if (!retries) { +ocelot_unlock_inj_grp (ocelot,0 );dev_err (ocelot->dev,"port %d failed to inject skb\n" , port);ocelot_port_purge_txtstamp_skb (ocelot, port, skb);
@@ -1521,6 +1526,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)ocelot_port_inject_frame (ocelot, port,0 , rew_op, skb); +ocelot_unlock_inj_grp (ocelot,0 ); +consume_skb (skb);kfree (xmit_work); }
@@ -1671,6 +1678,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)if (!felix->info->quirk_no_xtr_irq)return false; +ocelot_lock_xtr_grp (ocelot, grp); +while (ocelot_read (ocelot,QS_XTR_DATA_PRESENT ) &BIT (grp)) {struct sk_buff *skb;unsigned int type;
@@ -1707,6 +1716,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)ocelot_drain_cpu_queue (ocelot,0 ); } +ocelot_unlock_xtr_grp (ocelot, grp); +return true; }
drivers/net/ethernet/mscc/ocelot.c +52 -0
88 lines not on this page · raw message
drivers/net/ethernet/mscc/ocelot_vsc7514.c +4 -0
@@ -51,6 +51,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)struct ocelot *ocelot = arg;int grp =0 , err; +ocelot_lock_xtr_grp (ocelot, grp); +while (ocelot_read (ocelot,QS_XTR_DATA_PRESENT ) &BIT (grp)) {struct sk_buff *skb;
@@ -69,6 +71,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)if (err <0 )ocelot_drain_cpu_queue (ocelot,0 ); +ocelot_unlock_xtr_grp (ocelot, grp); +return IRQ_HANDLED ; }
include/soc/mscc/ocelot.h +9 -0
@@ -813,6 +813,9 @@ struct ocelot {const u32 *const *map;struct list_head stats_regions; +spinlock_t inj_lock; +spinlock_t xtr_lock; +u32 pool_size[OCELOT_SB_NUM ][OCELOT_SB_POOL_NUM ];int packet_buffer_size;int num_frame_refs;
@@ -966,6 +969,12 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, u32 val, u32 reg, u32 offset);/* Packet I/O */ +void ocelot_lock_inj_grp (struct ocelot *ocelot,int grp); +void ocelot_unlock_inj_grp (struct ocelot *ocelot,int grp); +void ocelot_lock_xtr_grp (struct ocelot *ocelot,int grp); +void ocelot_unlock_xtr_grp (struct ocelot *ocelot,int grp); +void ocelot_lock_xtr_grp_bh (struct ocelot *ocelot,int grp); +void ocelot_unlock_xtr_grp_bh (struct ocelot *ocelot,int grp);bool ocelot_can_inject (struct ocelot *ocelot,int grp);void ocelot_port_inject_frame (struct ocelot *ocelot,int port,int grp,u32 rew_op,struct sk_buff *skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/273 net/mlx5e: XPS, Fix oversight of Multi-PF Netdev changes
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carolina Jubran <[email protected]>
[ Upstream commit a07e953dafe5ebd88942dc861dfb06eaf055fb07 ]
The offending commit overlooked the Multi-PF Netdev changes.
Revert mlx5e_set_default_xps_cpumasks to incorporate Multi-PF Netdev changes.
--- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +8 -5
@@ -3005,15 +3005,18 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv)static void mlx5e_set_default_xps_cpumasks (struct mlx5e_priv *priv,struct mlx5e_params *params) { -struct mlx5_core_dev *mdev = priv->mdev; -int num_comp_vectors, ix, irq; - - num_comp_vectors =mlx5_comp_vectors_max (mdev); +int ix;for (ix =0 ; ix < params->num_channels; ix++) { +int num_comp_vectors, irq, vec_ix; +struct mlx5_core_dev *mdev; + + mdev =mlx5_sd_ch_ix_get_dev (priv->mdev, ix); + num_comp_vectors =mlx5_comp_vectors_max (mdev);cpumask_clear (priv->scratchpad.cpumask); + vec_ix =mlx5_sd_ch_ix_get_vec_ix (mdev, ix); -for (irq = ix; irq < num_comp_vectors; irq += params->num_channels) { +for (irq = vec_ix; irq < num_comp_vectors; irq += params->num_channels) {int cpu =mlx5_comp_vector_get_cpu (mdev, irq);cpumask_set_cpu (cpu, priv->scratchpad.cpumask);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/273 net/mlx5: Fix IPsec RoCE MPV trace call
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 607e1df7bd47fe91cab85a97f57870a26d066137 ]
Prevent the call trace below from happening, by not allowing IPsec creation over a slave, if master device doesn't support IPsec.
WARNING: CPU: 44 PID: 16136 at kernel/locking/rwsem.c:240 down_read+0x75/0x94 Modules linked in: esp4_offload esp4 act_mirred act_vlan cls_flower sch_ingress mlx5_vdpa vringh vhost_iotlb vdpa mst_pciconf(OE) nfsv3 nfs_acl nfs lockd grace fscache netfs xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 nft_compat nft_counter nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 rfkill cuse fuse rpcrdma sunrpc rdma_ucm ib_srpt ib_isert iscsi_target_mod target_core_mod ib_umad ib_iser libiscsi scsi_transport_iscsi rdma_cm ib_ipoib iw_cm ib_cm ipmi_ssif intel_rapl_msr intel_rapl_common amd64_edac edac_mce_amd kvm_amd kvm irqbypass crct10dif_pclmul crc32_pclmul mlx5_ib ghash_clmulni_intel sha1_ssse3 dell_smbios ib_uverbs aesni_intel crypto_simd dcdbas wmi_bmof dell_wmi_descriptor cryptd pcspkr ib_core acpi_ipmi sp5100_tco ccp i2c_piix4 ipmi_si ptdma k10temp ipmi_devintf ipmi_msghandler acpi_power_meter acpi_cpufreq ext4 mbcache jbd2 sd_mod t10_pi sg mgag200 drm_kms_helper syscopyarea sysfillrect mlx5_core sysimgblt fb_sys_fops cec ahci libahci mlxfw drm pci_hyperv_intf libata tg3 sha256_ssse3 tls megaraid_sas i2c_algo_bit psample wmi dm_mirror dm_region_hash dm_log dm_mod [last unloaded: mst_pci] CPU: 44 PID: 16136 Comm: kworker/44:3 Kdump: loaded Tainted: GOE 5.15.0-20240509.el8uek.uek7_u3_update_v6.6_ipsec_bf.x86_64 #2 Hardware name: Dell Inc. PowerEdge R7525/074H08, BIOS 2.0.3 01/15/2021 Workqueue: events xfrm_state_gc_task RIP: 0010:down_read+0x75/0x94 Code: 00 48 8b 45 08 65 48 8b 14 25 80 fc 01 00 83 e0 02 48 09 d0 48 83 c8 01 48 89 45 08 5d 31 c0 89 c2 89 c6 89 c7 e9 cb 88 3b 00 <0f> 0b 48 8b 45 08 a8 01 74 b2 a8 02 75 ae 48 89 c2 48 83 ca 02 f0 RSP: 0018:ffffb26387773da8 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffffa08b658af900 RCX: 0000000000000001 RDX: 0000000000000000 RSI: ff886bc5e1366f2f RDI: 0000000000000000 RBP: ffffa08b658af940 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0a9bfb31540 R13: ffffa0a9bfb37900 R14: 0000000000000000 R15: ffffa0a9bfb37905 FS: 0000000000000000(0000) GS:ffffa0a9bfb00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055a45ed814e8 CR3: 000000109038a000 CR4: 0000000000350ee0 Call Trace: <TASK> ? show_trace_log_lvl+0x1d6/0x2f9 ? show_trace_log_lvl+0x1d6/0x2f9 ? mlx5_devcom_for_each_peer_begin+0x29/0x60 [mlx5_core] ? down_read+0x75/0x94 ? __warn+0x80/0x113 ? down_read+0x75/0x94 ? report_bug+0xa4/0x11d ? handle_bug+0x35/0x8b ? exc_invalid_op+0x14/0x75 ? asm_exc_invalid_op+0x16/0x1b ? down_read+0x75/0x94 ? down_read+0xe/0x94 mlx5_devcom_for_each_peer_begin+0x29/0x60 [mlx5_core] mlx5_ipsec_fs_roce_tx_destroy+0xb1/0x130 [mlx5_core] tx_destroy+0x1b/0xc0 [mlx5_core] tx_ft_put+0x53/0xc0 [mlx5_core] mlx5e_xfrm_free_state+0x45/0x90 [mlx5_core] ___xfrm_state_destroy+0x10f/0x1a2 xfrm_state_gc_task+0x81/0xa9 process_one_work+0x1f1/0x3c6 worker_thread+0x53/0x3e4 ? process_one_work.cold+0x46/0x3c kthread+0x127/0x144 ? set_kthread_struct+0x60/0x52 ret_from_fork+0x22/0x2d </TASK> ---[ end trace 5ef7896144d398e1 ]---
--- drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c +4 -2
@@ -386,7 +386,8 @@ static int ipsec_fs_roce_tx_mpv_create(struct mlx5_core_dev *mdev,return -EOPNOTSUPP ; peer_priv =mlx5_devcom_get_next_peer_data (*ipsec_roce->devcom, &tmp); -if (!peer_priv) { +if (!peer_priv || !peer_priv->ipsec) { +mlx5_core_err (mdev,"IPsec not supported on master device\n" ); err = -EOPNOTSUPP ; goto release_peer; }
@@ -455,7 +456,8 @@ static int ipsec_fs_roce_rx_mpv_create(struct mlx5_core_dev *mdev,return -EOPNOTSUPP ; peer_priv =mlx5_devcom_get_next_peer_data (*ipsec_roce->devcom, &tmp); -if (!peer_priv) { +if (!peer_priv || !peer_priv->ipsec) { +mlx5_core_err (mdev,"IPsec not supported on master device\n" ); err = -EOPNOTSUPP ; goto release_peer; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/273 tc-testing: dont access non-existent variable on exception
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Horman <[email protected]>
[ Upstream commit a0c9fe5eecc97680323ee83780ea3eaf440ba1b7 ]
Since commit 255c1c7279ab ("tc-testing: Allow test cases to be skipped") the variable test_ordinal doesn't exist in call_pre_case(). So it should not be accessed when an exception occurs.
This resolves the following splat:
...
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ".../tdc.py", line 1028, in <module>
main()
File ".../tdc.py", line 1022, in main
set_operation_mode(pm, parser, args, remaining)
File ".../tdc.py", line 966, in set_operation_mode
catresults = test_runner_serial(pm, args, alltests)
File ".../tdc.py", line 642, in test_runner_serial
(index, tsr) = test_runner(pm, args, alltests)
File ".../tdc.py", line 536, in test_runner
res = run_one_test(pm, args, index, tidx)
File ".../tdc.py", line 419, in run_one_test
pm.call_pre_case(tidx)
File ".../tdc.py", line 146, in call_pre_case
print('test_ordinal is {}'.format(test_ordinal)) NameError: name 'test_ordinal' is not defined
--- tools/testing/selftests/tc-testing/tdc.py | 1 - 1 file changed, 1 deletion(-)
tools/testing/selftests/tc-testing/tdc.py +0 -1
@@ -143,7 +143,6 @@ class PluginMgr: except Exception as ee: print('exception {} in call to pre_case for {} plugin'. format(ee, pgn_inst.__class__)) - print('test_ordinal is {}'.format(test_ordinal)) print('testid is {}'.format(caseinfo['id'])) raise
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/273 selftests: udpgro: report error when receive failed
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 7167395a4be7930ecac6a33b4e54d7e3dd9ee209 ]
Currently, we only check the latest senders's exit code. If the receiver report failed, it is not recoreded. Fix it by checking the exit code of all the involved processes.
Before:
bad GRO lookup ok
multiple GRO socks ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
failed
$ echo $? 0
After:
bad GRO lookup ok
multiple GRO socks ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520
failed
$ echo $? 1
--- tools/testing/selftests/net/udpgro.sh | 44 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-)
tools/testing/selftests/net/udpgro.sh +27 -17
@@ -46,17 +46,19 @@ run_one() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 cfg_veth - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \ - echo "ok" || \ - echo "failed" & + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} & + local PID1=$! wait_local_port_listen ${PEER_NS} 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - wait $(jobs -p) + check_err $? + wait ${PID1} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
@@ -73,6 +75,7 @@ run_one_nat() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 if [[ ${tx_args} = *-4* ]]; then ipt_cmd=iptables
@@ -93,16 +96,17 @@ run_one_nat() { # ... so that GRO will match the UDP_GRO enabled socket, but packets # will land on the 'plain' one ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 & - pid=$! - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \ - echo "ok" || \ - echo "failed"& + local PID1=$! + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} & + local PID2=$! wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - kill -INT $pid - wait $(jobs -p) + check_err $? + kill -INT ${PID1} + wait ${PID2} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
@@ -111,20 +115,26 @@ run_one_2sock() { local -r all="$@" local -r tx_args=${all%rx*} local -r rx_args=${all#*rx} + local ret=0 cfg_veth ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 & - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \ - echo "ok" || \ - echo "failed" & + local PID1=$! + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} & + local PID2=$! wait_local_port_listen "${PEER_NS}" 12345 udp ./udpgso_bench_tx ${tx_args} -p 12345 + check_err $? wait_local_port_listen "${PEER_NS}" 8000 udp ./udpgso_bench_tx ${tx_args} - ret=$? - wait $(jobs -p) + check_err $? + wait ${PID1} + check_err $? + wait ${PID2} + check_err $? + [ "$ret" -eq 0 ] && echo "ok" || echo "failed" return $ret }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/273 selftests: udpgro: no need to load xdp for gro
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit d7818402b1d80347c764001583f6d63fa68c2e1a ]
After commit d7db7775ea2e ("net: veth: do not manipulate GRO when using XDP"), there is no need to load XDP program to enable GRO. On the other hand, the current test is failed due to loading the XDP program. e.g.
# selftests: net: udpgro.sh
# ipv4 # no GRO ok # no GRO chk cmsg ok # GRO ./udpgso_bench_rx: recv: bad packet len, got 1472, expected 14720 # # failed
[...]
# bad GRO lookup ok # multiple GRO socks ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520 # # ./udpgso_bench_rx: recv: bad packet len, got 1452, expected 14520 # # failed ok 1 selftests: net: udpgro.sh
After fix, all the test passed.
# ./udpgro.sh ipv4 no GRO ok [...] multiple GRO socks ok
--- tools/testing/selftests/net/udpgro.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
tools/testing/selftests/net/udpgro.sh +1 -8
@@ -7,8 +7,6 @@ source net_helper.sh readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" -BPF_FILE="xdp_dummy.bpf.o" - # set global exit status, but never reset nonzero one. check_err() {
@@ -38,7 +36,7 @@ cfg_veth() { ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24 ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad ip -netns "${PEER_NS}" link set dev veth1 up - ip -n "${PEER_NS}" link set veth1 xdp object ${BPF_FILE} section xdp + ip netns exec "${PEER_NS}" ethtool -K veth1 gro on } run_one() {
@@ -206,11 +204,6 @@ run_all() { return $ret } -if [ ! -f ${BPF_FILE} ]; then - echo "Missing ${BPF_FILE}. Run 'make' first" - exit -1 -fi - if [[ $# -eq 0 ]]; then run_all elif [[ $1 == "__subprocess" ]]; then
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/273 tcp: prevent concurrent execution of tcp_sk_exit_batch
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 565d121b69980637f040eb4d84289869cdaabedf ]
Its possible that two threads call tcp_sk_exit_batch() concurrently, once from the cleanup_net workqueue, once from a task that failed to clone a new netns. In the latter case, error unwinding calls the exit handlers in reverse order for the 'failed' netns.
tcp_sk_exit_batch() calls tcp_twsk_purge().
Problem is that since commit b099ce2602d8 ("net: Batch inet_twsk_purge"), this function picks up twsk in any dying netns, not just the one passed in via exit_batch list.
This means that the error unwind of setup_net() can "steal" and destroy timewait sockets belonging to the exiting netns.
This allows the netns exit worker to proceed to call
WARN_ON_ONCE(!refcount_dec_and_test(&net->ipv4.tcp_death_row.tw_refcount));
without the expected 1 -> 0 transition, which then splats.
At same time, error unwind path that is also running inet_twsk_purge() will splat as well:
WARNING: .. at lib/refcount.c:31 refcount_warn_saturate+0x1ed/0x210
...
refcount_dec include/linux/refcount.h:351 [inline] inet_twsk_kill+0x758/0x9c0 net/ipv4/inet_timewait_sock.c:70 inet_twsk_deschedule_put net/ipv4/inet_timewait_sock.c:221 inet_twsk_purge+0x725/0x890 net/ipv4/inet_timewait_sock.c:304 tcp_sk_exit_batch+0x1c/0x170 net/ipv4/tcp_ipv4.c:3522 ops_exit_list+0x128/0x180 net/core/net_namespace.c:178 setup_net+0x714/0xb40 net/core/net_namespace.c:375 copy_net_ns+0x2f0/0x670 net/core/net_namespace.c:508 create_new_namespaces+0x3ea/0xb10 kernel/nsproxy.c:110
... because refcount_dec() of tw_refcount unexpectedly dropped to 0.
This doesn't seem like an actual bug (no tw sockets got lost and I don't see a use-after-free) but as erroneous trigger of debug check.
Add a mutex to force strict ordering: the task that calls tcp_twsk_purge() blocks other task from doing final _dec_and_test before mutex-owner has removed all tw sockets of dying netns.
--- net/ipv4/tcp_ipv4.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
net/ipv4/tcp_ipv4.c +14 -0
@@ -95,6 +95,8 @@ EXPORT_SYMBOL(tcp_hashinfo); static DEFINE_PER_CPU(struct sock *, ipv4_tcp_sk); +static DEFINE_MUTEX (tcp_exit_batch_mutex); +static u32 tcp_v4_init_seq (const struct sk_buff *skb) { return secure_tcp_seq(ip_hdr(skb)->daddr,
@@ -3509,6 +3511,16 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) {struct net *net; +/* make sure concurrent calls to tcp_sk_exit_batch from net_cleanup_work +* and failed setup_net error unwinding path are serialized. +* +* tcp_twsk_purge() handles twsk in any dead netns, not just those in +* net_exit_list, the thread that dismantles a particular twsk must +* do so without other thread progressing to refcount_dec_and_test() of +* tcp_death_row.tw_refcount. +*/ +mutex_lock (&tcp_exit_batch_mutex); +tcp_twsk_purge (net_exit_list);list_for_each_entry (net, net_exit_list, exit_list) {
@@ -3516,6 +3528,8 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)WARN_ON_ONCE (!refcount_dec_and_test (&net->ipv4.tcp_death_row.tw_refcount));tcp_fastopen_ctx_destroy (net); } + +mutex_unlock (&tcp_exit_batch_mutex); }static struct pernet_operations __net_initdata tcp_sk_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/273 net: mctp: test: Use correct skb for route input check
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Kerr <[email protected]>
[ Upstream commit ce335db0621648472f9bb4b7191eb2e13a5793cf ]
In the MCTP route input test, we're routing one skb, then (when delivery is expected) checking the resulting routed skb.
However, we're currently checking the original skb length, rather than the routed skb. Check the routed skb instead; the original will have been freed at this point.
--- net/mctp/test/route-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mctp/test/route-test.c +1 -1
@@ -366,7 +366,7 @@ static void mctp_test_route_input_sk(struct kunit *test) skb2 =skb_recv_datagram (sock->sk,MSG_DONTWAIT , &rc);KUNIT_EXPECT_NOT_ERR_OR_NULL (test, skb2); -KUNIT_EXPECT_EQ (test, skb->len,1 ); +KUNIT_EXPECT_EQ (test, skb2->len,1 );skb_free_datagram (sock->sk, skb2);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/273 kcm: Serialise kcm_sendmsg() for the same socket.
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 807067bf014d4a3ae2cc55bd3de16f22a01eb580 ]
syzkaller reported UAF in kcm_release(). [0]
The scenario is
1. Thread A builds a skb with MSG_MORE and sets kcm->seq_skb.
2. Thread A resumes building skb from kcm->seq_skb but is blocked by sk_stream_wait_memory()
3. Thread B calls sendmsg() concurrently, finishes building kcm->seq_skb and puts the skb to the write queue
4. Thread A faces an error and finally frees skb that is already in the write queue
5. kcm_release() does double-free the skb in the write queue
When a thread is building a MSG_MORE skb, another thread must not touch it.
Let's add a per-sk mutex and serialise kcm_sendmsg().
[0]:
BUG: KASAN: slab-use-after-free in __skb_unlink include/linux/skbuff.h:2366 [inline] BUG: KASAN: slab-use-after-free in __skb_dequeue include/linux/skbuff.h:2385 [inline] BUG: KASAN: slab-use-after-free in __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] BUG: KASAN: slab-use-after-free in __skb_queue_purge include/linux/skbuff.h:3181 [inline] BUG: KASAN: slab-use-after-free in kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 Read of size 8 at addr ffff0000ced0fc80 by task syz-executor329/6167 CPU: 1 PID: 6167 Comm: syz-executor329 Tainted: G B 6.8.0-rc5-syzkaller-g9abbc24128bc #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024 Call trace: dump_backtrace+0x1b8/0x1e4 arch/arm64/kernel/stacktrace.c:291 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:298 __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd0/0x124 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:377 [inline] print_report+0x178/0x518 mm/kasan/report.c:488 kasan_report+0xd8/0x138 mm/kasan/report.c:601 __asan_report_load8_noabort+0x20/0x2c mm/kasan/report_generic.c:381 __skb_unlink include/linux/skbuff.h:2366 [inline] __skb_dequeue include/linux/skbuff.h:2385 [inline] __skb_queue_purge_reason include/linux/skbuff.h:3175 [inline] __skb_queue_purge include/linux/skbuff.h:3181 [inline] kcm_release+0x170/0x4c8 net/kcm/kcmsock.c:1691 __sock_release net/socket.c:659 [inline] sock_close+0xa4/0x1e8 net/socket.c:1421 __fput+0x30c/0x738 fs/file_table.c:376 ____fput+0x20/0x30 fs/file_table.c:404 task_work_run+0x230/0x2e0 kernel/task_work.c:180 exit_task_work include/linux/task_work.h:38 [inline] do_exit+0x618/0x1f64 kernel/exit.c:871 do_group_exit+0x194/0x22c kernel/exit.c:1020 get_signal+0x1500/0x15ec kernel/signal.c:2893 do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 Allocated by task 6166: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_alloc_info+0x70/0x84 mm/kasan/generic.c:626 unpoison_slab_object mm/kasan/common.c:314 [inline] __kasan_slab_alloc+0x74/0x8c mm/kasan/common.c:340 kasan_slab_alloc include/linux/kasan.h:201 [inline] slab_post_alloc_hook mm/slub.c:3813 [inline] slab_alloc_node mm/slub.c:3860 [inline] kmem_cache_alloc_node+0x204/0x4c0 mm/slub.c:3903 __alloc_skb+0x19c/0x3d8 net/core/skbuff.c:641 alloc_skb include/linux/skbuff.h:1296 [inline] kcm_sendmsg+0x1d3c/0x2124 net/kcm/kcmsock.c:783 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg net/socket.c:745 [inline] sock_sendmsg+0x220/0x2c0 net/socket.c:768 splice_to_socket+0x7cc/0xd58 fs/splice.c:889 do_splice_from fs/splice.c:941 [inline] direct_splice_actor+0xec/0x1d8 fs/splice.c:1164 splice_direct_to_actor+0x438/0xa0c fs/splice.c:1108 do_splice_direct_actor fs/splice.c:1207 [inline] do_splice_direct+0x1e4/0x304 fs/splice.c:1233 do_sendfile+0x460/0xb3c fs/read_write.c:1295 __do_sys_sendfile64 fs/read_write.c:1362 [inline] __se_sys_sendfile64 fs/read_write.c:1348 [inline] __arm64_sys_sendfile64+0x160/0x3b4 fs/read_write.c:1348 __invoke_syscall arch/arm64/kernel/syscall.c:37 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:51 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:136 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:155 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 Freed by task 6167: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_free_info+0x5c/0x74 mm/kasan/generic.c:640 poison_slab_object+0x124/0x18c mm/kasan/common.c:241 __kasan_slab_free+0x3c/0x78 mm/kasan/common.c:257 kasan_slab_free include/linux/kasan.h:184 [inline] slab_free_hook mm/slub.c:2121 [inline] slab_free mm/slub.c:4299 [inline] kmem_cache_free+0x15c/0x3d4 mm/slub.c:4363 kfree_skbmem+0x10c/0x19c __kfree_skb net/core/skbuff.c:1109 [inline] kfree_skb_reason+0x240/0x6f4 net/core/skbuff.c:1144 kfree_skb include/linux/skbuff.h:1244 [inline] kcm_release+0x104/0x4c8 net/kcm/kcmsock.c:1685 __sock_release net/socket.c:659 [inline] sock_close+0xa4/0x1e8 net/socket.c:1421 __fput+0x30c/0x738 fs/file_table.c:376 ____fput+0x20/0x30 fs/file_table.c:404 task_work_run+0x230/0x2e0 kernel/task_work.c:180 exit_task_work include/linux/task_work.h:38 [inline] do_exit+0x618/0x1f64 kernel/exit.c:871 do_group_exit+0x194/0x22c kernel/exit.c:1020 get_signal+0x1500/0x15ec kernel/signal.c:2893 do_signal+0x23c/0x3b44 arch/arm64/kernel/signal.c:1249 do_notify_resume+0x74/0x1f4 arch/arm64/kernel/entry-common.c:148 exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:169 [inline] exit_to_user_mode arch/arm64/kernel/entry-common.c:178 [inline] el0_svc+0xac/0x168 arch/arm64/kernel/entry-common.c:713 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 The buggy address belongs to the object at ffff0000ced0fc80 which belongs to the cache skbuff_head_cache of size 240
The buggy address is located 0 bytes inside of
freed 240-byte region [ffff0000ced0fc80, ffff0000ced0fd70)
The buggy address belongs to the physical page:
page:00000000d35f4ae4 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10ed0f
flags: 0x5ffc00000000800(slab|node=0|zone=2|lastcpupid=0x7ff)
page_type: 0xffffffff()
raw: 05ffc00000000800 ffff0000c1cbf640 fffffdffc3423100 dead000000000004
raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff0000ced0fb80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff0000ced0fc00: fb fb fb fb fb fb fc fc fc fc fc fc fc fc fc fc
>ffff0000ced0fc80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff0000ced0fd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc
ffff0000ced0fd80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb--- include/net/kcm.h | 1 + net/kcm/kcmsock.c | 4 ++++ 2 files changed, 5 insertions(+)
include/net/kcm.h +1 -0
@@ -70,6 +70,7 @@ struct kcm_sock {struct work_struct tx_work;struct list_head wait_psock_list;struct sk_buff *seq_skb; +struct mutex tx_mutex; u32 tx_stopped : 1;/* Don't use bit fields here, these are set under different locks */
net/kcm/kcmsock.c +4 -0
@@ -755,6 +755,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) !(msg->msg_flags & MSG_MORE) : !!(msg->msg_flags & MSG_EOR);int err = -EPIPE ; +mutex_lock (&kcm->tx_mutex);lock_sock (sk);/* Per tcp_sendmsg this should be in poll */
@@ -926,6 +927,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)KCM_STATS_ADD (kcm->stats.tx_bytes, copied);release_sock (sk); +mutex_unlock (&kcm->tx_mutex);return copied; out_error:
@@ -951,6 +953,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) sk->sk_write_space (sk);release_sock (sk); +mutex_unlock (&kcm->tx_mutex);return err; }
@@ -1204,6 +1207,7 @@ static void init_kcm_sock(struct kcm_sock *kcm, struct kcm_mux *mux)spin_unlock_bh (&mux->lock);INIT_WORK (&kcm->tx_work, kcm_tx_work); +mutex_init (&kcm->tx_mutex);spin_lock_bh (&mux->rx_lock);kcm_rcv_ready (kcm);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/273 netfilter: nft_counter: Disable BH in nft_counter_offload_stats().
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 1eacdd71b3436b54d5fc8218c4bb0187d92a6892 ]
The sequence counter nft_counter_seq is a per-CPU counter. There is no lock associated with it. nft_counter_do_eval() is using the same counter and disables BH which suggest that it can be invoked from a softirq. This in turn means that nft_counter_offload_stats(), which disables only preemption, can be interrupted by nft_counter_do_eval() leading to two writer for one seqcount_t.
This can lead to loosing stats or reading statistics while they are updated.
Disable BH during stats update in nft_counter_offload_stats() to ensure one writer at a time.
--- net/netfilter/nft_counter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/nft_counter.c +2 -2
@@ -265,7 +265,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr,struct nft_counter *this_cpu;seqcount_t *myseq; -preempt_disable (); +local_bh_disable (); this_cpu =this_cpu_ptr (priv->counter); myseq =this_cpu_ptr (&nft_counter_seq);
@@ -273,7 +273,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, this_cpu->packets += stats->pkts; this_cpu->bytes += stats->bytes;write_seqcount_end (myseq); -preempt_enable (); +local_bh_enable (); }void nft_counter_init_seqcount (void )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/273 netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit a0b39e2dc7017ac667b70bdeee5293e410fab2fb ]
nft_counter_reset() resets the counter by subtracting the previously retrieved value from the counter. This is a write operation on the counter and as such it requires to be performed with a write sequence of nft_counter_seq to serialize against its possible reader.
Update the packets/ bytes within write-sequence of nft_counter_seq.
--- net/netfilter/nft_counter.c | 5 +++++ 1 file changed, 5 insertions(+)
net/netfilter/nft_counter.c +5 -0
@@ -107,11 +107,16 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv, struct nft_counter *total) {struct nft_counter *this_cpu; +seqcount_t *myseq;local_bh_disable (); this_cpu =this_cpu_ptr (priv->counter); + myseq =this_cpu_ptr (&nft_counter_seq); + +write_seqcount_begin (myseq); this_cpu->packets -= total->packets; this_cpu->bytes -= total->bytes; +write_seqcount_end (myseq);local_bh_enable (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/273 ip6_tunnel: Fix broken GRO
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Bogendoerfer <[email protected]>
[ Upstream commit 4b3e33fcc38f7750604b065c55a43e94c5bc3145 ]
GRO code checks for matching layer 2 headers to see, if packet belongs to the same flow and because ip6 tunnel set dev->hard_header_len this check fails in cases, where it shouldn't. To fix this don't set hard_header_len, but use needed_headroom like ipv4/ip_tunnel.c does.
--- net/ipv6/ip6_tunnel.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
net/ipv6/ip6_tunnel.c +7 -5
@@ -1507,7 +1507,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) tdev =__dev_get_by_index (t->net, p->link);if (tdev) { - dev->hard_header_len = tdev->hard_header_len + t_hlen; + dev->needed_headroom = tdev->hard_header_len + + tdev->needed_headroom + t_hlen; mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU); mtu = mtu - t_hlen;
@@ -1731,7 +1732,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr,int ip6_tnl_change_mtu (struct net_device *dev,int new_mtu) {struct ip6_tnl *tnl =netdev_priv (dev); +int t_hlen; + t_hlen = tnl->hlen +sizeof (struct ipv6hdr );if (tnl->parms.proto ==IPPROTO_IPV6 ) {if (new_mtu <IPV6_MIN_MTU )return -EINVAL ;
@@ -1740,10 +1743,10 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)return -EINVAL ; }if (tnl->parms.proto ==IPPROTO_IPV6 || tnl->parms.proto ==0 ) { -if (new_mtu >IP6_MAX_MTU - dev->hard_header_len) +if (new_mtu >IP6_MAX_MTU - dev->hard_header_len - t_hlen)return -EINVAL ; }else { -if (new_mtu >IP_MAX_MTU - dev->hard_header_len) +if (new_mtu >IP_MAX_MTU - dev->hard_header_len - t_hlen)return -EINVAL ; }WRITE_ONCE (dev->mtu, new_mtu);
@@ -1887,12 +1890,11 @@ ip6_tnl_dev_init_gen(struct net_device *dev) t_hlen = t->hlen +sizeof (struct ipv6hdr ); dev->type =ARPHRD_TUNNEL6 ; - dev->hard_header_len =LL_MAX_HEADER + t_hlen; dev->mtu =ETH_DATA_LEN - t_hlen;if (!(t->parms.flags &IP6_TNL_F_IGN_ENCAP_LIMIT )) dev->mtu -=8 ; dev->min_mtu =ETH_MIN_MTU ; - dev->max_mtu =IP6_MAX_MTU - dev->hard_header_len; + dev->max_mtu =IP6_MAX_MTU - dev->hard_header_len - t_hlen;netdev_hold (dev, &t->dev_tracker,GFP_KERNEL );netdev_lockdep_set_classes (dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/273 bonding: fix bond_ipsec_offload_ok return type
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit fc59b9a5f7201b9f7272944596113a82cc7773d5 ]
Fix the return type which should be bool.
--- drivers/net/bonding/bond_main.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-)
drivers/net/bonding/bond_main.c +6 -12
@@ -599,34 +599,28 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)struct net_device *real_dev;struct slave *curr_active;struct bonding *bond; -int err; +bool ok = false; bond =netdev_priv (bond_dev);rcu_read_lock (); curr_active =rcu_dereference (bond->curr_active_slave); real_dev = curr_active->dev; -if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP ) { - err = false; +if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP ) goto out; - } -if (!xs->xso.real_dev) { - err = false; +if (!xs->xso.real_dev) goto out; - }if (!real_dev->xfrmdev_ops || !real_dev->xfrmdev_ops->xdo_dev_offload_ok || -netif_is_bond_master (real_dev)) { - err = false; +netif_is_bond_master (real_dev)) goto out; - } - err = real_dev->xfrmdev_ops->xdo_dev_offload_ok (skb, xs); + ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok (skb, xs); out:rcu_read_unlock (); -return err; +return ok; }static const struct xfrmdev_ops bond_xfrmdev_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 169/273 bonding: fix null pointer deref in bond_ipsec_offload_ok
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 95c90e4ad89d493a7a14fa200082e466e2548f9d ]
We must check if there is an active slave before dereferencing the pointer.
--- drivers/net/bonding/bond_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/bonding/bond_main.c +2 -0
@@ -604,6 +604,8 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) bond =netdev_priv (bond_dev);rcu_read_lock (); curr_active =rcu_dereference (bond->curr_active_slave); +if (!curr_active) + goto out; real_dev = curr_active->dev;if (BOND_MODE (bond) !=BOND_MODE_ACTIVEBACKUP )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/273 bonding: fix xfrm real_dev null pointer dereference
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit f8cde9805981c50d0c029063dc7d82821806fc44 ]
We shouldn't set real_dev to NULL because packets can be in transit and xfrm might call xdo_dev_offload_ok() in parallel. All callbacks assume real_dev is set.
Example trace:
kernel: BUG: unable to handle page fault for address: 0000000000001030
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: #PF: supervisor write access in kernel mode
kernel: #PF: error_code(0x0002) - not-present page
kernel: PGD 0 P4D 0
kernel: Oops: 0002 [#1] PREEMPT SMP
kernel: CPU: 4 PID: 2237 Comm: ping Not tainted 6.7.7+ #12
kernel: Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014
kernel: RIP: 0010:nsim_ipsec_offload_ok+0xc/0x20 [netdevsim]
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: Code: e0 0f 0b 48 83 7f 38 00 74 de 0f 0b 48 8b 47 08 48 8b 37 48 8b 78 40 e9 b2 e5 9a d7 66 90 0f 1f 44 00 00 48 8b 86 80 02 00 00 <83> 80 30 10 00 00 01 b8 01 00 00 00 c3 0f 1f 80 00 00 00 00 0f 1f
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: RSP: 0018:ffffabde81553b98 EFLAGS: 00010246
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel:
kernel: RAX: 0000000000000000 RBX: ffff9eb404e74900 RCX: ffff9eb403d97c60
kernel: RDX: ffffffffc090de10 RSI: ffff9eb404e74900 RDI: ffff9eb3c5de9e00
kernel: RBP: ffff9eb3c0a42000 R08: 0000000000000010 R09: 0000000000000014
kernel: R10: 7974203030303030 R11: 3030303030303030 R12: 0000000000000000
kernel: R13: ffff9eb3c5de9e00 R14: ffffabde81553cc8 R15: ffff9eb404c53000
kernel: FS: 00007f2a77a3ad00(0000) GS:ffff9eb43bd00000(0000) knlGS:0000000000000000
kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kernel: CR2: 0000000000001030 CR3: 00000001122ab000 CR4: 0000000000350ef0
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: Call Trace:
kernel: <TASK>
kernel: ? __die+0x1f/0x60
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ? page_fault_oops+0x142/0x4c0 kernel: ? do_user_addr_fault+0x65/0x670 kernel: ? kvm_read_and_reset_apf_flags+0x3b/0x50 kernel: bond0: (slave eni0np1): making interface the new active one kernel: ? exc_page_fault+0x7b/0x180 kernel: ? asm_exc_page_fault+0x22/0x30 kernel: ? nsim_bpf_uninit+0x50/0x50 [netdevsim]
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ? nsim_ipsec_offload_ok+0xc/0x20 [netdevsim]
kernel: bond0: (slave eni0np1): making interface the new active one
kernel: bond_ipsec_offload_ok+0x7b/0x90 [bonding]
kernel: xfrm_output+0x61/0x3b0
kernel: bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
kernel: ip_push_pending_frames+0x56/0x80
--- drivers/net/bonding/bond_main.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/bonding/bond_main.c +0 -1
@@ -582,7 +582,6 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) }else { slave->dev->xfrmdev_ops->xdo_dev_state_delete (ipsec->xs); } - ipsec->xs->xso.real_dev =NULL ; }spin_unlock_bh (&bond->ipsec_lock);rcu_read_unlock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 171/273 bonding: fix xfrm state handling when clearing active slave
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit c4c5c5d2ef40a9f67a9241dc5422eac9ffe19547 ]
If the active slave is cleared manually the xfrm state is not flushed. This leads to xfrm add/del imbalance and adding the same state multiple times. For example when the device cannot handle anymore states we get:
[ 1169.884811] bond0: (slave eni0np1): bond_ipsec_add_sa_all: failed to add SA
because it's filled with the same state after multiple active slave clearings. This change also has a few nice side effects: user-space gets a notification for the change, the old device gets its mac address and promisc/mcast adjusted properly.
--- drivers/net/bonding/bond_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_options.c +1 -1
@@ -936,7 +936,7 @@ static int bond_option_active_slave_set(struct bonding *bond,/* check to see if we are clearing active */ if (!slave_dev) {netdev_dbg (bond->dev,"Clearing current active slave\n" ); -RCU_INIT_POINTER (bond->curr_active_slave,NULL ); +bond_change_active_slave (bond,NULL );bond_select_active_slave (bond); }else {struct slave *old_active =rtnl_dereference (bond->curr_active_slave);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/273 ice: fix page reuse when PAGE_SIZE is over 8k
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit 50b2143356e888777fc5bca023c39f34f404613a ]
Architectures that have PAGE_SIZE >= 8192 such as arm64 should act the same as x86 currently, meaning reuse of a page should only take place when no one else is busy with it.
Do two things independently of underlying PAGE_SIZE:
- store the page count under ice_rx_buf::pgcnt
- then act upon its value vs ice_rx_buf::pagecnt_bias when making the decision regarding page reuse
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +3 -9
@@ -837,16 +837,15 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf)if (!dev_page_is_reusable (page))return false; -#if (PAGE_SIZE <8192 )/* if we are only owner of page we can reuse it */ if (unlikely (rx_buf->pgcnt - pagecnt_bias >1 ))return false; -#else +#if (PAGE_SIZE >=8192 )#define ICE_LAST_OFFSET \ (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048)if (rx_buf->page_offset >ICE_LAST_OFFSET )return false; -#endif /* PAGE_SIZE < 8192) */ +#endif /* PAGE_SIZE >= 8192) */ /* If we have drained the page fragment pool we need to update * the pagecnt_bias and page count so that we fully restock the
@@ -949,12 +948,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,struct ice_rx_buf *rx_buf; rx_buf = &rx_ring->rx_buf[ntc]; - rx_buf->pgcnt = -#if (PAGE_SIZE <8192 ) -page_count (rx_buf->page); -#else -0 ; -#endif + rx_buf->pgcnt =page_count (rx_buf->page);prefetchw (rx_buf->page);if (!size)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 173/273 ice: fix ICE_LAST_OFFSET formula
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit b966ad832942b5a11e002f9b5ef102b08425b84a ]
For bigger PAGE_SIZE archs, ice driver works on 3k Rx buffers. Therefore, ICE_LAST_OFFSET should take into account ICE_RXBUF_3072, not ICE_RXBUF_2048.
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +1 -1
@@ -842,7 +842,7 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf)return false;#if (PAGE_SIZE >=8192 )#define ICE_LAST_OFFSET \ - (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048) + (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_3072)if (rx_buf->page_offset >ICE_LAST_OFFSET )return false;#endif /* PAGE_SIZE >= 8192) */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 174/273 ice: fix truesize operations for PAGE_SIZE >= 8192
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Fijalkowski <[email protected]>
[ Upstream commit d53d4dcce69be5773e2d0878c9899ebfbf58c393 ]
When working on multi-buffer packet on arch that has PAGE_SIZE >= 8192, truesize is calculated and stored in xdp_buff::frame_sz per each processed Rx buffer. This means that frame_sz will contain the truesize based on last received buffer, but commit 1dc1a7e7f410 ("ice:
Centrallize Rx buffer recycling") assumed this value will be constant for each buffer, which breaks the page recycling scheme and mess up the way we update the page::page_offset.
To fix this, let us work on constant truesize when PAGE_SIZE >= 8192 instead of basing this on size of a packet read from Rx descriptor. This way we can simplify the code and avoid calculating truesize per each received frame and on top of that when using xdp_update_skb_shared_info(), current formula for truesize update will be valid.
This means ice_rx_frame_truesize() can be removed altogether. Furthermore, first call to it within ice_clean_rx_irq() for 4k PAGE_SIZE was redundant as xdp_buff::frame_sz is initialized via xdp_init_buff() in ice_vsi_cfg_rxq(). This should have been removed at the point where xdp_buff struct started to be a member of ice_rx_ring and it was no longer a stack based variable.
There are two fixes tags as my understanding is that the first one exposed us to broken truesize and page_offset handling and then second introduced broken skb_shared_info update in ice_{construct,build}_skb().
--- drivers/net/ethernet/intel/ice/ice_base.c | 21 ++++++++++++++- drivers/net/ethernet/intel/ice/ice_txrx.c | 33 ----------------------- 2 files changed, 20 insertions(+), 34 deletions(-)
drivers/net/ethernet/intel/ice/ice_base.c +20 -1
@@ -512,6 +512,25 @@ static void ice_xsk_pool_fill_cb(struct ice_rx_ring *ring)xsk_pool_fill_cb (ring->xsk_pool, &desc); } +/** +* ice_get_frame_sz - calculate xdp_buff::frame_sz +* @rx_ring: the ring being configured +* +* Return frame size based on underlying PAGE_SIZE +*/ +static unsigned int ice_get_frame_sz (struct ice_rx_ring *rx_ring) +{ +unsigned int frame_sz; + +#if (PAGE_SIZE >=8192 ) + frame_sz = rx_ring->rx_buf_len; +#else + frame_sz =ice_rx_pg_size (rx_ring) /2 ; +#endif + +return frame_sz; +} +/** * ice_vsi_cfg_rxq - Configure an Rx queue * @ring: the ring being configured
@@ -576,7 +595,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) } } -xdp_init_buff (&ring->xdp,ice_rx_pg_size (ring) /2 , &ring->xdp_rxq); +xdp_init_buff (&ring->xdp,ice_get_frame_sz (ring), &ring->xdp_rxq); ring->xdp.data =NULL ; ring->xdp_ext.pkt_ctx = &ring->pkt_ctx; err =ice_setup_rx_ctx (ring);
drivers/net/ethernet/intel/ice/ice_txrx.c +0 -33
@@ -521,30 +521,6 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)return -ENOMEM ; } -/** -* ice_rx_frame_truesize -* @rx_ring: ptr to Rx ring -* @size: size -* -* calculate the truesize with taking into the account PAGE_SIZE of -* underlying arch -*/ -static unsigned int -ice_rx_frame_truesize (struct ice_rx_ring *rx_ring,const unsigned int size) -{ -unsigned int truesize; - -#if (PAGE_SIZE <8192 ) - truesize =ice_rx_pg_size (rx_ring) /2 ;/* Must be power-of-2 */ -#else - truesize = rx_ring->rx_offset ? -SKB_DATA_ALIGN (rx_ring->rx_offset + size) + -SKB_DATA_ALIGN (sizeof (struct skb_shared_info )) : -SKB_DATA_ALIGN (size); -#endif -return truesize; -} -/** * ice_run_xdp - Executes an XDP program on initialized xdp_buff * @rx_ring: Rx ring
@@ -1154,11 +1130,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)bool failure;u32 first; -/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ -#if (PAGE_SIZE <8192 ) - xdp->frame_sz =ice_rx_frame_truesize (rx_ring,0 ); -#endif - xdp_prog =READ_ONCE (rx_ring->xdp_prog);if (xdp_prog) { xdp_ring = rx_ring->xdp_ring;
@@ -1217,10 +1188,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) hard_start =page_address (rx_buf->page) + rx_buf->page_offset - offset;xdp_prepare_buff (xdp, hard_start, offset, size, !!offset); -#if (PAGE_SIZE >4096 ) -/* At larger PAGE_SIZE, frame_sz depend on len size */ - xdp->frame_sz =ice_rx_frame_truesize (rx_ring, size); -#endif xdp_buff_clear_frags_flag (xdp); }else if (ice_add_xdp_frag (rx_ring, xdp, rx_buf, size)) {break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 175/273 ice: use internal pf id instead of function number
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Swiatkowski <[email protected]>
[ Upstream commit 503ab6ee40fc103ea55cc9e50bb879e571d65aac ]
Use always the same pf id in devlink port number. When doing pass-through the PF to VM bus info func number can be any value.
--- drivers/net/ethernet/intel/ice/devlink/devlink_port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/intel/ice/devlink/devlink_port.c +2 -2
@@ -337,7 +337,7 @@ int ice_devlink_create_pf_port(struct ice_pf *pf)return -EIO ; attrs.flavour =DEVLINK_PORT_FLAVOUR_PHYSICAL ; - attrs.phys.port_number = pf->hw.bus.func; + attrs.phys.port_number = pf->hw.pf_id;/* As FW supports only port split options for whole device, * set port split options only for first PF.
@@ -399,7 +399,7 @@ int ice_devlink_create_vf_port(struct ice_vf *vf)return -EINVAL ; attrs.flavour =DEVLINK_PORT_FLAVOUR_PCI_VF ; - attrs.pci_vf.pf = pf->hw.bus.func; + attrs.pci_vf.pf = pf->hw.pf_id; attrs.pci_vf.vf = vf->vf_id;ice_devlink_set_switch_id (pf, &attrs.switch_id);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 176/273 dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit c50e7475961c36ec4d21d60af055b32f9436b431 ]
The dpaa2_switch_add_bufs() function returns the number of bufs that it was able to add. It returns BUFS_PER_CMD (7) for complete success or a smaller number if there are not enough pages available. However, the error checking is looking at the total number of bufs instead of the number which were added on this iteration. Thus the error checking only works correctly for the first iteration through the loop and subsequent iterations are always counted as a success.
Fix this by checking only the bufs added in the current iteration.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +4 -3
@@ -2638,13 +2638,14 @@ static int dpaa2_switch_refill_bp(struct ethsw_core *ethsw)static int dpaa2_switch_seed_bp (struct ethsw_core *ethsw) { -int *count, i; +int *count, ret, i;for (i =0 ; i <DPAA2_ETHSW_NUM_BUFS ; i +=BUFS_PER_CMD ) { + ret =dpaa2_switch_add_bufs (ethsw, ethsw->bpid); count = ðsw->buf_count; - *count +=dpaa2_switch_add_bufs (ethsw, ethsw->bpid); + *count += ret; -if (unlikely (*count <BUFS_PER_CMD )) +if (unlikely (ret <BUFS_PER_CMD ))return -ENOMEM ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 177/273 igb: cope with large MAX_SKB_FRAGS
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 8aba27c4a5020abdf60149239198297f88338a8d ]
Sabrina reports that the igb driver does not cope well with large MAX_SKB_FRAG values: setting MAX_SKB_FRAG to 45 causes payload corruption on TX.
An easy reproducer is to run ssh to connect to the machine. With MAX_SKB_FRAGS=17 it works, with MAX_SKB_FRAGS=45 it fails. This has been reported originally in
https://bugzilla.redhat.com/show_bug.cgi?id=2265320
The root cause of the issue is that the driver does not take into account properly the (possibly large) shared info size when selecting the ring layout, and will try to fit two packets inside the same 4K page even when the 1st fraglist will trump over the 2nd head.
Address the issue by checking if 2K buffers are insufficient.
--- drivers/net/ethernet/intel/igb/igb_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/intel/igb/igb_main.c +1 -0
@@ -4809,6 +4809,7 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter,#if (PAGE_SIZE <8192 )if (adapter->max_frame_size >IGB_MAX_FRAME_BUILD_SKB || +IGB_2K_TOO_SMALL_WITH_PADDING ||rd32 (E1000_RCTL ) &E1000_RCTL_SBP )set_ring_uses_large_buffer (rx_ring);#endif
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 178/273 net: dsa: mv88e6xxx: Fix out-of-bound access
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Huang <[email protected]>
[ Upstream commit 528876d867a23b5198022baf2e388052ca67c952 ]
If an ATU violation was caused by a CPU Load operation, the SPID could be larger than DSA_MAX_PORTS (the size of mv88e6xxx_chip.ports[] array).
--- drivers/net/dsa/mv88e6xxx/global1_atu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/dsa/mv88e6xxx/global1_atu.c +2 -1
@@ -457,7 +457,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)trace_mv88e6xxx_atu_full_violation (chip->dev, spid, entry.portvec, entry.mac, fid); - chip->ports[spid].atu_full_violation++; +if (spid <ARRAY_SIZE (chip->ports)) + chip->ports[spid].atu_full_violation++; }return IRQ_HANDLED ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 179/273 netem: fix return value if duplicate enqueue fails
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Hemminger <[email protected]>
[ Upstream commit c07ff8592d57ed258afee5a5e04991a48dbaf382 ]
There is a bug in netem_enqueue() introduced by
commit 5845f706388a ("net: netem: fix skb length BUG_ON in __skb_to_sgvec") that can lead to a use-after-free.
This commit made netem_enqueue() always return NET_XMIT_SUCCESS when a packet is duplicated, which can cause the parent qdisc's q.qlen to be mistakenly incremented. When this happens qlen_notify() may be skipped on the parent during destruction, leaving a dangling pointer for some classful qdiscs like DRR.
There are two ways for the bug happen:
- If the duplicated packet is dropped by rootq->enqueue() and then the original packet is also dropped.
- If rootq->enqueue() sends the duplicated packet to a different qdisc and the original packet is dropped.
In both cases NET_XMIT_SUCCESS is returned even though no packets are enqueued at the netem qdisc.
The fix is to defer the enqueue of the duplicate packet until after the original packet has been guaranteed to return NET_XMIT_SUCCESS.
--- net/sched/sch_netem.c | 47 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-)
net/sched/sch_netem.c +29 -18
@@ -446,12 +446,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,struct netem_sched_data *q =qdisc_priv (sch);/* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; -struct sk_buff *skb2; +struct sk_buff *skb2 =NULL ;struct sk_buff *segs =NULL ;unsigned int prev_len =qdisc_pkt_len (skb);int count =1 ; -int rc =NET_XMIT_SUCCESS ; -int rc_drop =NET_XMIT_DROP ;/* Do not fool qdisc_drop_all() */ skb->prev =NULL ;
@@ -480,19 +478,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,skb_orphan_partial (skb);/* -* If we need to duplicate packet, then re-insert at top of the -* qdisc tree, since parent queuer expects that only one -* skb will be queued. +* If we need to duplicate packet, then clone it before +* original is modified. */ -if (count >1 && (skb2 =skb_clone (skb,GFP_ATOMIC )) !=NULL ) { -struct Qdisc *rootq =qdisc_root_bh (sch); -u32 dupsave = q->duplicate;/* prevent duplicating a dup... */ - - q->duplicate =0 ; - rootq->enqueue (skb2, rootq, to_free); - q->duplicate = dupsave; - rc_drop =NET_XMIT_SUCCESS ; - } +if (count >1 ) + skb2 =skb_clone (skb,GFP_ATOMIC );/* * Randomized packet corruption.
@@ -504,7 +494,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,if (skb_is_gso (skb)) { skb =netem_segment (skb, sch, to_free);if (!skb) -return rc_drop; + goto finish_segs; + segs = skb->next;skb_mark_not_on_list (skb);qdisc_skb_cb (skb)->pkt_len = skb->len;
@@ -530,7 +521,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,/* re-link segs, so that qdisc_drop_all() frees them all */ skb->next = segs;qdisc_drop_all (skb, sch, to_free); -return rc_drop; +if (skb2) +__qdisc_drop (skb2, to_free); +return NET_XMIT_DROP ; + } + +/* +* If doing duplication then re-insert at top of the +* qdisc tree, since parent queuer expects that only one +* skb will be queued. +*/ +if (skb2) { +struct Qdisc *rootq =qdisc_root_bh (sch); +u32 dupsave = q->duplicate;/* prevent duplicating a dup... */ + + q->duplicate =0 ; + rootq->enqueue (skb2, rootq, to_free); + q->duplicate = dupsave; + skb2 =NULL ; }qdisc_qstats_backlog_inc (sch, skb);
@@ -601,9 +609,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, } finish_segs: +if (skb2) +__qdisc_drop (skb2, to_free); +if (segs) {unsigned int len, last_len; -int nb; +int rc, nb; len = skb ? skb->len :0 ; nb = skb ?1 :0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 180/273 udp: fix receiving fraglist GSO packets
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit b128ed5ab27330deeeaf51ea8bb69f1442a96f7f ]
When assembling fraglist GSO packets, udp4_gro_complete does not set skb->csum_start, which makes the extra validation in __udp_gso_segment fail.
--- net/ipv4/udp_offload.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/udp_offload.c +2 -1
@@ -279,7 +279,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,return ERR_PTR (-EINVAL );if (unlikely (skb_checksum_start (gso_skb) != -skb_transport_header (gso_skb))) +skb_transport_header (gso_skb) && + !(skb_shinfo (gso_skb)->gso_type &SKB_GSO_FRAGLIST )))return ERR_PTR (-EINVAL );if (skb_gso_ok (gso_skb, features |NETIF_F_GSO_ROBUST )) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 181/273 selftests: mlxsw: ethtool_lanes: Source ethtool lib from correct path
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit f8669d7b5f5d2d88959456ae9123d8bb6fdc1ebe ]
Source the ethtool library from the correct path and avoid the following error:
./ethtool_lanes.sh: line 14: ./../../../net/forwarding/ethtool_lib.sh: No such file or directory
--- tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh +2 -1
@@ -2,6 +2,7 @@ # SPDX-License-Identifier: GPL-2.0 lib_dir=$(dirname $0)/../../../net/forwarding +ethtool_lib_dir=$(dirname $0)/../hw ALL_TESTS=" autoneg
@@ -11,7 +12,7 @@ ALL_TESTS=" NUM_NETIFS=2 : ${TIMEOUT:=30000} # ms source $lib_dir/lib.sh -source $lib_dir/ethtool_lib.sh +source $ethtool_lib_dir/ethtool_lib.sh setup_prepare() {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 182/273 ipv6: prevent UAF in ip6_send_skb()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit faa389b2fbaaec7fd27a390b4896139f9da662e3 ]
syzbot reported an UAF in ip6_send_skb() [1]
After ip6_local_out() has returned, we no longer can safely dereference rt, unless we hold rcu_read_lock().
A similar issue has been fixed in commit a688caa34beb ("ipv6: take rcu lock in rawv6_send_hdrinc()")
Another potential issue in ip6_finish_output2() is handled in a separate patch.
[1]
BUG: KASAN: slab-use-after-free in ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 Read of size 8 at addr ffff88806dde4858 by task syz.1.380/6530 CPU: 1 UID: 0 PID: 6530 Comm: syz.1.380 Not tainted 6.11.0-rc3-syzkaller-00306-gdf6cbc62cc9b #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 Call Trace: <TASK> __dump_stack lib/dump_stack.c:93 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 ip6_send_skb+0x18d/0x230 net/ipv6/ip6_output.c:1964 rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 sock_write_iter+0x2dd/0x400 net/socket.c:1160 do_iter_readv_writev+0x60a/0x890 vfs_writev+0x37c/0xbb0 fs/read_write.c:971 do_writev+0x1b1/0x350 fs/read_write.c:1018 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:0x7f936bf79e79 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f936cd7f038 EFLAGS: 00000246 ORIG_RAX: 0000000000000014 RAX: ffffffffffffffda RBX: 00007f936c115f80 RCX: 00007f936bf79e79 RDX: 0000000000000001 RSI: 0000000020000040 RDI: 0000000000000004 RBP: 00007f936bfe7916 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f936c115f80 R15: 00007fff2860a7a8 </TASK> Allocated by task 6530: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 unpoison_slab_object mm/kasan/common.c:312 [inline] __kasan_slab_alloc+0x66/0x80 mm/kasan/common.c:338 kasan_slab_alloc include/linux/kasan.h:201 [inline] slab_post_alloc_hook mm/slub.c:3988 [inline] slab_alloc_node mm/slub.c:4037 [inline] kmem_cache_alloc_noprof+0x135/0x2a0 mm/slub.c:4044 dst_alloc+0x12b/0x190 net/core/dst.c:89 ip6_blackhole_route+0x59/0x340 net/ipv6/route.c:2670 make_blackhole net/xfrm/xfrm_policy.c:3120 [inline] xfrm_lookup_route+0xd1/0x1c0 net/xfrm/xfrm_policy.c:3313 ip6_dst_lookup_flow+0x13e/0x180 net/ipv6/ip6_output.c:1257 rawv6_sendmsg+0x1283/0x23c0 net/ipv6/raw.c:898 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 ____sys_sendmsg+0x525/0x7d0 net/socket.c:2597 ___sys_sendmsg net/socket.c:2651 [inline] __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2680 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 Freed by task 45: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:579 poison_slab_object+0xe0/0x150 mm/kasan/common.c:240 __kasan_slab_free+0x37/0x60 mm/kasan/common.c:256 kasan_slab_free include/linux/kasan.h:184 [inline] slab_free_hook mm/slub.c:2252 [inline] slab_free mm/slub.c:4473 [inline] kmem_cache_free+0x145/0x350 mm/slub.c:4548 dst_destroy+0x2ac/0x460 net/core/dst.c:124 rcu_do_batch kernel/rcu/tree.c:2569 [inline] rcu_core+0xafd/0x1830 kernel/rcu/tree.c:2843 handle_softirqs+0x2c4/0x970 kernel/softirq.c:554 __do_softirq kernel/softirq.c:588 [inline] invoke_softirq kernel/softirq.c:428 [inline] __irq_exit_rcu+0xf4/0x1c0 kernel/softirq.c:637 irq_exit_rcu+0x9/0x30 kernel/softirq.c:649 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1043 [inline] sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1043 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702 Last potentially related work creation: kasan_save_stack+0x3f/0x60 mm/kasan/common.c:47 __kasan_record_aux_stack+0xac/0xc0 mm/kasan/generic.c:541 __call_rcu_common kernel/rcu/tree.c:3106 [inline] call_rcu+0x167/0xa70 kernel/rcu/tree.c:3210 refdst_drop include/net/dst.h:263 [inline] skb_dst_drop include/net/dst.h:275 [inline] nf_ct_frag6_queue net/ipv6/netfilter/nf_conntrack_reasm.c:306 [inline] nf_ct_frag6_gather+0xb9a/0x2080 net/ipv6/netfilter/nf_conntrack_reasm.c:485 ipv6_defrag+0x2c8/0x3c0 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:67 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xc3/0x220 net/netfilter/core.c:626 nf_hook include/linux/netfilter.h:269 [inline] __ip6_local_out+0x6fa/0x800 net/ipv6/output_core.c:143 ip6_local_out+0x26/0x70 net/ipv6/output_core.c:153 ip6_send_skb+0x112/0x230 net/ipv6/ip6_output.c:1959 rawv6_push_pending_frames+0x75c/0x9e0 net/ipv6/raw.c:588 rawv6_sendmsg+0x19c7/0x23c0 net/ipv6/raw.c:926 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x1a6/0x270 net/socket.c:745 sock_write_iter+0x2dd/0x400 net/socket.c:1160 do_iter_readv_writev+0x60a/0x890
--- net/ipv6/ip6_output.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv6/ip6_output.c +2 -0
@@ -1953,6 +1953,7 @@ int ip6_send_skb(struct sk_buff *skb)struct rt6_info *rt =dst_rt6_info (skb_dst (skb));int err; +rcu_read_lock (); err =ip6_local_out (net, skb->sk, skb);if (err) {if (err >0 )
@@ -1962,6 +1963,7 @@ int ip6_send_skb(struct sk_buff *skb) IPSTATS_MIB_OUTDISCARDS); } +rcu_read_unlock ();return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 183/273 ipv6: fix possible UAF in ip6_finish_output2()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit da273b377ae0d9bd255281ed3c2adb228321687b ]
If skb_expand_head() returns NULL, skb has been freed and associated dst/idev could also have been freed.
We need to hold rcu_read_lock() to make sure the dst and associated idev are alive.
--- net/ipv6/ip6_output.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/ip6_output.c +4 -0
@@ -70,11 +70,15 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff */* Be paranoid, rather than too clever. */ if (unlikely (hh_len >skb_headroom (skb)) && dev->header_ops) { +/* Make sure idev stays alive */ +rcu_read_lock (); skb =skb_expand_head (skb, hh_len);if (!skb) {IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTDISCARDS ); +rcu_read_unlock ();return -ENOMEM ; } +rcu_read_unlock (); } hdr =ipv6_hdr (skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 184/273 ipv6: prevent possible UAF in ip6_xmit()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 2d5ff7e339d04622d8282661df36151906d0e1c7 ]
If skb_expand_head() returns NULL, skb has been freed and the associated dst/idev could also have been freed.
We must use rcu_read_lock() to prevent a possible UAF.
--- net/ipv6/ip6_output.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/ip6_output.c +4 -0
@@ -287,11 +287,15 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, head_room += opt->opt_nflen + opt->opt_flen;if (unlikely (head_room >skb_headroom (skb))) { +/* Make sure idev stays alive */ +rcu_read_lock (); skb =skb_expand_head (skb, head_room);if (!skb) {IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTDISCARDS ); +rcu_read_unlock ();return -ENOBUFS ; } +rcu_read_unlock (); }if (opt) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 185/273 bnxt_en: Fix double DMA unmapping for XDP_REDIRECT
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Somnath Kotur <[email protected]>
[ Upstream commit 8baeef7616d5194045c5a6b97fd1246b87c55b13 ]
Remove the dma_unmap_page_attrs() call in the driver's XDP_REDIRECT code path. This should have been removed when we let the page pool handle the DMA mapping. This bug causes the warning:
WARNING: CPU: 7 PID: 59 at drivers/iommu/dma-iommu.c:1198 iommu_dma_unmap_page+0xd5/0x100 CPU: 7 PID: 59 Comm: ksoftirqd/7 Tainted: G W 6.8.0-1010-gcp #11-Ubuntu Hardware name: Dell Inc. PowerEdge R7525/0PYVT1, BIOS 2.15.2 04/02/2024 RIP: 0010:iommu_dma_unmap_page+0xd5/0x100 Code: 89 ee 48 89 df e8 cb f2 69 ff 48 83 c4 08 5b 41 5c 41 5d 41 5e 41 5f 5d 31 c0 31 d2 31 c9 31 f6 31 ff 45 31 c0 e9 ab 17 71 00 <0f> 0b 48 83 c4 08 5b 41 5c 41 5d 41 5e 41 5f 5d 31 c0 31 d2 31 c9 RSP: 0018:ffffab1fc0597a48 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff99ff838280c8 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffab1fc0597a78 R08: 0000000000000002 R09: ffffab1fc0597c1c R10: ffffab1fc0597cd3 R11: ffff99ffe375acd8 R12: 00000000e65b9000 R13: 0000000000000050 R14: 0000000000001000 R15: 0000000000000002 FS: 0000000000000000(0000) GS:ffff9a06efb80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000565c34c37210 CR3: 00000005c7e3e000 CR4: 0000000000350ef0 ? show_regs+0x6d/0x80 ? __warn+0x89/0x150 ? iommu_dma_unmap_page+0xd5/0x100 ? report_bug+0x16a/0x190 ? handle_bug+0x51/0xa0 ? exc_invalid_op+0x18/0x80 ? iommu_dma_unmap_page+0xd5/0x100 ? iommu_dma_unmap_page+0x35/0x100 dma_unmap_page_attrs+0x55/0x220 ? bpf_prog_4d7e87c0d30db711_xdp_dispatcher+0x64/0x9f bnxt_rx_xdp+0x237/0x520 [bnxt_en] bnxt_rx_pkt+0x640/0xdd0 [bnxt_en] __bnxt_poll_work+0x1a1/0x3d0 [bnxt_en] bnxt_poll+0xaa/0x1e0 [bnxt_en] __napi_poll+0x33/0x1e0 net_rx_action+0x18a/0x2f0
--- drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +0 -5
@@ -297,11 +297,6 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,* redirect is coming from a frame received by the * bnxt_en driver. */ - rx_buf = &rxr->rx_buf_ring[cons]; - mapping = rx_buf->mapping - bp->rx_dma_offset; -dma_unmap_page_attrs (&pdev->dev, mapping, -BNXT_RX_PAGE_SIZE , bp->rx_dir, -DMA_ATTR_WEAK_ORDERING );/* if we are unable to allocate a new buffer, abort and reuse */ if (bnxt_alloc_rx_data (bp, rxr, rxr->rx_prod,GFP_ATOMIC )) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 186/273 netfilter: flowtable: validate vlan header
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 6ea14ccb60c8ab829349979b22b58a941ec4a3ee ]
Ensure there is sufficient room to access the protocol field of the VLAN header, validate it once before the flowtable lookup.
=====================================================
BUG: KMSAN: uninit-value in nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 nf_flow_offload_inet_hook+0x45a/0x5f0 net/netfilter/nf_flow_table_inet.c:32 nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] nf_hook_slow+0xf4/0x400 net/netfilter/core.c:626 nf_hook_ingress include/linux/netfilter_netdev.h:34 [inline] nf_ingress net/core/dev.c:5440 [inline]
--- net/netfilter/nf_flow_table_inet.c | 3 +++ net/netfilter/nf_flow_table_ip.c | 3 +++ 2 files changed, 6 insertions(+)
net/netfilter/nf_flow_table_inet.c +3 -0
@@ -17,6 +17,9 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,switch (skb->protocol) {case htons (ETH_P_8021Q ): +if (!pskb_may_pull (skb,skb_mac_offset (skb) +sizeof (*veth))) +return NF_ACCEPT ; + veth = (struct vlan_ethhdr *)skb_mac_header (skb); proto = veth->h_vlan_encapsulated_proto;break ;
net/netfilter/nf_flow_table_ip.c +3 -0
@@ -281,6 +281,9 @@ static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,switch (skb->protocol) {case htons (ETH_P_8021Q ): +if (!pskb_may_pull (skb,skb_mac_offset (skb) +sizeof (*veth))) +return false; + veth = (struct vlan_ethhdr *)skb_mac_header (skb);if (veth->h_vlan_encapsulated_proto == proto) { *offset +=VLAN_HLEN ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 187/273 octeontx2-af: Fix CPT AF register offset calculation
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bharat Bhushan <[email protected]>
[ Upstream commit af688a99eb1fc7ef69774665d61e6be51cea627a ]
Some CPT AF registers are per LF and others are global. Translation of PF/VF local LF slot number to actual LF slot number is required only for accessing perf LF registers. CPT AF global registers access do not require any LF slot number. Also, there is no reason CPT PF/VF to know actual lf's register offset.
Without this fix microcode loading will fail, VFs cannot be created and hardware is not usable.
--- .../ethernet/marvell/octeontx2/af/rvu_cpt.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +11 -12
@@ -632,7 +632,9 @@ int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu,return ret; } -static bool is_valid_offset (struct rvu *rvu,struct cpt_rd_wr_reg_msg *req) +static bool validate_and_update_reg_offset (struct rvu *rvu, +struct cpt_rd_wr_reg_msg *req, +u64 *reg_offset) {u64 offset = req->reg_offset;int blkaddr, num_lfs, lf;
@@ -663,6 +665,11 @@ static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req)if (lf <0 )return false; +/* Translate local LF's offset to global CPT LF's offset to +* access LFX register. +*/ + *reg_offset = (req->reg_offset &0xFF000 ) + (lf <<3 ); +return true; }else if (!(req->hdr.pcifunc &RVU_PFVF_FUNC_MASK )) {/* Registers that can be accessed from PF */
@@ -697,7 +704,7 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, struct cpt_rd_wr_reg_msg *rsp) {u64 offset = req->reg_offset; -int blkaddr, lf; +int blkaddr; blkaddr =validate_and_get_cpt_blkaddr (req->blkaddr);if (blkaddr <0 )
@@ -708,18 +715,10 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, !is_cpt_vf(rvu, req->hdr.pcifunc))return CPT_AF_ERR_ACCESS_DENIED ; -if (!is_valid_offset (rvu, req)) +if (!validate_and_update_reg_offset (rvu, req, &offset))return CPT_AF_ERR_ACCESS_DENIED ; -/* Translate local LF used by VFs to global CPT LF */ - lf =rvu_get_lf (rvu, &rvu->hw->block[blkaddr], req->hdr.pcifunc, - (offset &0xFFF ) >>3 ); - -/* Translate local LF's offset to global CPT LF's offset */ - offset &=0xFF000 ; - offset += lf <<3 ; - - rsp->reg_offset = offset; + rsp->reg_offset = req->reg_offset; rsp->ret_val = req->ret_val; rsp->is_write = req->is_write;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 188/273 net: xilinx: axienet: Always disable promiscuous mode
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Anderson <[email protected]>
[ Upstream commit 4ae738dfef2c0323752ab81786e2d298c9939321 ]
If promiscuous mode is disabled when there are fewer than four multicast addresses, then it will not be reflected in the hardware. Fix this by always clearing the promiscuous mode flag even when we program multicast addresses.
--- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +4 -0
@@ -450,6 +450,10 @@ static void axienet_set_multicast_list(struct net_device *ndev) }else if (!netdev_mc_empty (ndev)) {struct netdev_hw_addr *ha; + reg =axienet_ior (lp,XAE_FMI_OFFSET ); + reg &= ~XAE_FMI_PM_MASK ; +axienet_iow (lp,XAE_FMI_OFFSET , reg); + i =0 ;netdev_for_each_mc_addr (ha, ndev) {if (i >=XAE_MULTICAST_CAM_TABLE_NUM )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 189/273 net: xilinx: axienet: Fix dangling multicast addresses
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Anderson <[email protected]>
[ Upstream commit 797a68c9de0f5a5447baf4bd3bb9c10a3993435b ]
If a multicast address is removed but there are still some multicast addresses, that address would remain programmed into the frame filter. Fix this by explicitly setting the enable bit for each filter.
--- drivers/net/ethernet/xilinx/xilinx_axienet.h | 1 + .../net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-)
drivers/net/ethernet/xilinx/xilinx_axienet.h +1 -0
@@ -170,6 +170,7 @@#define XAE_UAW0_OFFSET 0x00000700/* Unicast address word 0 */ #define XAE_UAW1_OFFSET 0x00000704/* Unicast address word 1 */ #define XAE_FMI_OFFSET 0x00000708/* Frame Filter Control */ +#define XAE_FFE_OFFSET 0x0000070C/* Frame Filter Enable */ #define XAE_AF0_OFFSET 0x00000710/* Address Filter 0 */ #define XAE_AF1_OFFSET 0x00000714/* Address Filter 1 */
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +9 -12
@@ -432,7 +432,7 @@ static int netdev_set_mac_address(struct net_device *ndev, void *p)*/ static void axienet_set_multicast_list (struct net_device *ndev) { -int i; +int i =0 ;u32 reg, af0reg, af1reg;struct axienet_local *lp =netdev_priv (ndev);
@@ -454,7 +454,6 @@ static void axienet_set_multicast_list(struct net_device *ndev) reg &= ~XAE_FMI_PM_MASK ;axienet_iow (lp,XAE_FMI_OFFSET , reg); - i =0 ;netdev_for_each_mc_addr (ha, ndev) {if (i >=XAE_MULTICAST_CAM_TABLE_NUM )break ;
@@ -473,6 +472,7 @@ static void axienet_set_multicast_list(struct net_device *ndev)axienet_iow (lp,XAE_FMI_OFFSET , reg);axienet_iow (lp,XAE_AF0_OFFSET , af0reg);axienet_iow (lp,XAE_AF1_OFFSET , af1reg); +axienet_iow (lp,XAE_FFE_OFFSET ,1 ); i++; } }else {
@@ -480,18 +480,15 @@ static void axienet_set_multicast_list(struct net_device *ndev) reg &= ~XAE_FMI_PM_MASK ;axienet_iow (lp,XAE_FMI_OFFSET , reg); - -for (i =0 ; i <XAE_MULTICAST_CAM_TABLE_NUM ; i++) { - reg =axienet_ior (lp,XAE_FMI_OFFSET ) &0xFFFFFF00 ; - reg |= i; - -axienet_iow (lp,XAE_FMI_OFFSET , reg); -axienet_iow (lp,XAE_AF0_OFFSET ,0 ); -axienet_iow (lp,XAE_AF1_OFFSET ,0 ); - } -dev_info (&ndev->dev,"Promiscuous mode disabled.\n" ); } + +for (; i <XAE_MULTICAST_CAM_TABLE_NUM ; i++) { + reg =axienet_ior (lp,XAE_FMI_OFFSET ) &0xFFFFFF00 ; + reg |= i; +axienet_iow (lp,XAE_FMI_OFFSET , reg); +axienet_iow (lp,XAE_FFE_OFFSET ,0 ); + } }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 190/273 net: ovs: fix ovs_drop_reasons error
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Menglong Dong <[email protected]>
[ Upstream commit 57fb67783c4011581882f32e656d738da1f82042 ]
There is something wrong with ovs_drop_reasons. ovs_drop_reasons[0] is "OVS_DROP_LAST_ACTION", but OVS_DROP_LAST_ACTION == __OVS_DROP_REASON + 1, which means that ovs_drop_reasons[1] should be "OVS_DROP_LAST_ACTION".
And as Adrian tested, without the patch, adding flow to drop packets results in:
drop at: do_execute_actions+0x197/0xb20 [openvsw (0xffffffffc0db6f97)
origin: software
input port ifindex: 8
timestamp: Tue Aug 20 10:19:17 2024 859853461 nsec
protocol: 0x800
length: 98
original length: 98
drop reason: OVS_DROP_ACTION_ERROR
With the patch, the same results in:
drop at: do_execute_actions+0x197/0xb20 [openvsw (0xffffffffc0db6f97)
origin: software
input port ifindex: 8
timestamp: Tue Aug 20 10:16:13 2024 475856608 nsec
protocol: 0x800
length: 98
original length: 98
drop reason: OVS_DROP_LAST_ACTION
Fix this by initializing ovs_drop_reasons with index.
--- net/openvswitch/datapath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/openvswitch/datapath.c +1 -1
@@ -2706,7 +2706,7 @@ static struct pernet_operations ovs_net_ops = { };static const char *const ovs_drop_reasons[] = { -#define S(x) (#x), +#define S(x) [(x) & ~SKB_DROP_REASON_SUBSYS_MASK] = (#x), OVS_DROP_REASONS(S) #undef S };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 191/273 s390/iucv: Fix vargs handling in iucv_alloc_device()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandra Winter <[email protected]>
[ Upstream commit 0124fb0ebf3b0ef89892d42147c9387be3105318 ]
iucv_alloc_device() gets a format string and a varying number of arguments. This is incorrectly forwarded by calling dev_set_name() with the format string and a va_list, while dev_set_name() expects also a varying number of arguments.
Symptoms:
Corrupted iucv device names, which can result in log messages like:
sysfs: cannot create duplicate filename '/devices/iucv/hvc_iucv1827699952'
--- net/iucv/iucv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/iucv/iucv.c +3 -1
@@ -86,13 +86,15 @@ struct device *iucv_alloc_device(const struct attribute_group **attrs, {struct device *dev;va_list vargs; +char buf[20 ];int rc; dev =kzalloc (sizeof (*dev),GFP_KERNEL );if (!dev) goto out_error;va_start (vargs, fmt); - rc =dev_set_name (dev, fmt, vargs); +vsnprintf (buf,sizeof (buf), fmt, vargs); + rc =dev_set_name (dev,"%s" , buf);va_end (vargs);if (rc) goto out_error;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 192/273 drm/msm/dpu: dont play tricks with debug macros
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit df24373435f5899a2a98b7d377479c8d4376613b ]
DPU debugging macros need to be converted to a proper drm_debug_* macros, however this is a going an intrusive patch, not suitable for a fix. Wire DPU_DEBUG and DPU_DEBUG_DRIVER to always use DRM_DEBUG_DRIVER to make sure that DPU debugging messages always end up in the drm debug messages and are controlled via the usual drm.debug mask.
I don't think that it is a good idea for a generic DPU_DEBUG macro to be tied to DRM_UT_KMS. It is used to report a debug message from driver, so by default it should go to the DRM_UT_DRIVER channel. While refactoring debug macros later on we might end up with particular messages going to ATOMIC or KMS, but DRIVER should be the default.
Patchwork: https://patchwork.freedesktop.org/patch/606932/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +2 -12
@@ -31,24 +31,14 @@* @fmt: Pointer to format string */ #define DPU_DEBUG (fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_KMS)) \ - DRM_DEBUG(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)/** * DPU_DEBUG_DRIVER - macro for hardware driver logging * @fmt: Pointer to format string */ #define DPU_DEBUG_DRIVER (fmt, ...) \ - do { \ - if (drm_debug_enabled(DRM_UT_DRIVER)) \ - DRM_ERROR(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)#define DPU_ERROR (fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)#define DPU_ERROR_RATELIMITED (fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 193/273 drm/msm/dp: fix the max supported bpp logic
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit d19d5b8d8f6dab942ce5ddbcf34bf7275e778250 ]
Fix the dp_panel_get_supported_bpp() API to return the minimum supported bpp correctly for relevant cases and use this API to correct the behavior of DP driver which hard-codes the max supported bpp to 30.
This is incorrect because the number of lanes and max data rate supported by the lanes need to be taken into account.
Replace the hardcoded limit with the appropriate math which accounts for the accurate number of lanes and max data rate.
changes in v2:
- Fix the dp_panel_get_supported_bpp() and use it
- Drop the max_t usage as dp_panel_get_supported_bpp() already returns the min_bpp correctly now
changes in v3:
- replace min_t with just min as all params are u32
Patchwork: https://patchwork.freedesktop.org/patch/607073/
--- drivers/gpu/drm/msm/dp/dp_panel.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/dp/dp_panel.c +10 -9
@@ -90,22 +90,22 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)static u32 dp_panel_get_supported_bpp (struct dp_panel *dp_panel,u32 mode_edid_bpp,u32 mode_pclk_khz) { -struct dp_link_info *link_info; +const struct dp_link_info *link_info;const u32 max_supported_bpp =30 , min_supported_bpp =18 ; -u32 bpp =0 , data_rate_khz =0 ; +u32 bpp, data_rate_khz; - bpp =min_t (u32, mode_edid_bpp, max_supported_bpp); + bpp =min (mode_edid_bpp, max_supported_bpp); link_info = &dp_panel->link_info; data_rate_khz = link_info->num_lanes * link_info->rate *8 ; -while (bpp > min_supported_bpp) { +do {if (mode_pclk_khz * bpp <= data_rate_khz) -break ; +return bpp; bpp -=6 ; - } + }while (bpp > min_supported_bpp); -return bpp; +return min_supported_bpp; } static int dp_panel_update_modes(struct drm_connector *connector,
@@ -442,8 +442,9 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel) drm_mode->clock);drm_dbg_dp (panel->drm_dev,"bpp = %d\n" , dp_panel->dp_mode.bpp); - dp_panel->dp_mode.bpp =max_t (u32,18 , -min_t (u32, dp_panel->dp_mode.bpp,30 )); + dp_panel->dp_mode.bpp =dp_panel_get_mode_bpp (dp_panel, dp_panel->dp_mode.bpp, + dp_panel->dp_mode.drm_mode.clock); +drm_dbg_dp (panel->drm_dev,"updated bpp = %d\n" , dp_panel->dp_mode.bpp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 194/273 drm/msm/dpu: move dpu_encoders connector assignment to atomic_enable()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit aedf02e46eb549dac8db4821a6b9f0c6bf6e3990 ]
For cases where the crtc's connectors_changed was set without enable/active getting toggled , there is an atomic_enable() call followed by an atomic_disable() but without an atomic_mode_set().
This results in a NULL ptr access for the dpu_encoder_get_drm_fmt() call in the atomic_enable() as the dpu_encoder's connector was cleared in the atomic_disable() but not re-assigned as there was no atomic_mode_set() call.
Fix the NULL ptr access by moving the assignment for atomic_enable() and also use drm_atomic_get_new_connector_for_encoder() to get the connector from the atomic_state.
Patchwork: https://patchwork.freedesktop.org/patch/606729/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +2 -2
@@ -1179,8 +1179,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, cstate->num_mixers = num_lm; - dpu_enc->connector = conn_state->connector; -for (i =0 ; i < dpu_enc->num_phys_encs; i++) {struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
@@ -1277,6 +1275,8 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, dpu_enc->commit_done_timedout = false; + dpu_enc->connector =drm_atomic_get_new_connector_for_encoder (state, drm_enc); + cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; dpu_enc->wide_bus_en =dpu_encoder_is_widebus_enabled (drm_enc);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 195/273 drm/msm/dp: reset the link phy params before link training
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit 319aca883bfa1b85ee08411541b51b9a934ac858 ]
Before re-starting link training reset the link phy params namely the pre-emphasis and voltage swing levels otherwise the next link training begins at the previously cached levels which can result in link training failures.
Patchwork: https://patchwork.freedesktop.org/patch/605946/
--- drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/msm/dp/dp_ctrl.c +2 -0
@@ -1286,6 +1286,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, link_info.rate = ctrl->link->link_params.rate; link_info.capabilities =DP_LINK_CAP_ENHANCED_FRAMING ; +dp_link_reset_phy_params_vx_px (ctrl->link); +dp_aux_link_configure (ctrl->aux, &link_info);if (drm_dp_max_downspread (dpcd))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 196/273 drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit bfa1a6283be390947d3649c482e5167186a37016 ]
If the dpu_format_populate_layout() fails, then FB is prepared, but not cleaned up. This ends up leaking the pin_count on the GEM object and causes a splat during DRM file closure:
msm_obj->pin_count
WARNING: CPU: 2 PID: 569 at drivers/gpu/drm/msm/msm_gem.c:121 update_lru_locked+0xc4/0xcc [...] Call trace: update_lru_locked+0xc4/0xcc put_pages+0xac/0x100 msm_gem_free_object+0x138/0x180 drm_gem_object_free+0x1c/0x30 drm_gem_object_handle_put_unlocked+0x108/0x10c drm_gem_object_release_handle+0x58/0x70 idr_for_each+0x68/0xec drm_gem_release+0x28/0x40 drm_file_free+0x174/0x234 drm_release+0xb0/0x160 __fput+0xc0/0x2c8 __fput_sync+0x50/0x5c __arm64_sys_close+0x38/0x7c invoke_syscall+0x48/0x118 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x4c/0x120 el0t_64_sync_handler+0x100/0x12c el0t_64_sync+0x190/0x194 irq event stamp: 129818 hardirqs last enabled at (129817): [<ffffa5f6d953fcc0>] console_unlock+0x118/0x124 hardirqs last disabled at (129818): [<ffffa5f6da7dcf04>] el1_dbg+0x24/0x8c softirqs last enabled at (129808): [<ffffa5f6d94afc18>] handle_softirqs+0x4c8/0x4e8 softirqs last disabled at (129785): [<ffffa5f6d94105e4>] __do_softirq+0x14/0x20
Patchwork: https://patchwork.freedesktop.org/patch/600714/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +3 -0
@@ -680,6 +680,9 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, new_state->fb, &layout);if (ret) {DPU_ERROR_PLANE (pdpu,"failed to get format layout, %d\n" , ret); +if (pstate->aspace) +msm_framebuffer_cleanup (new_state->fb, pstate->aspace, + pstate->needs_dirtyfb);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 197/273 drm/msm/dpu: limit QCM2290 to RGB formats only
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 2db13c4a631505029ada9404e09a2b06a268c1c4 ]
The QCM2290 doesn't have CSC blocks, so it can not support YUV formats even on ViG blocks. Fix the formats declared by _VIG_SBLK_NOSCALE().
Patchwork: https://patchwork.freedesktop.org/patch/601048/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +2 -2
@@ -308,8 +308,8 @@ static const u32 wb2_formats_rgb_yuv[] = { { \ .maxdwnscale = SSPP_UNITY_SCALE, \ .maxupscale = SSPP_UNITY_SCALE, \ - .format_list = plane_formats_yuv, \ - .num_formats = ARRAY_SIZE(plane_formats_yuv), \ + .format_list = plane_formats, \ + .num_formats = ARRAY_SIZE(plane_formats), \ .virt_format_list = plane_formats, \ .virt_num_formats = ARRAY_SIZE(plane_formats), \ }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 198/273 drm/msm/dpu: relax YUV requirements
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit cb18195914e353ece0e789e365a5a16872169805 ]
YUV formats require only CSC to be enabled. Even decimated formats should not require scaler. Relax the requirement and don't check for the scaler block while checking if YUV format can be enabled.
Patchwork: https://patchwork.freedesktop.org/patch/601049/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +2 -3
@@ -746,10 +746,9 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, min_src_size =MSM_FORMAT_IS_YUV (fmt) ?2 :1 ;if (MSM_FORMAT_IS_YUV (fmt) && - (!pipe->sspp->cap->sblk->scaler_blk.len || - !pipe->sspp->cap->sblk->csc_blk.len)) { + !pipe->sspp->cap->sblk->csc_blk.len) {DPU_DEBUG_PLANE (pdpu, -"plane doesn't have scaler/csc for yuv\n" ); +"plane doesn't have csc for yuv\n" );return -EINVAL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 199/273 drm/msm/dpu: take plane rotation into account for wide planes
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit d3a785e4f983f523380e023d8a05fb6d04402957 ]
Take into account the plane rotation and flipping when calculating src positions for the wide plane parts.
This is not an issue yet, because rotation is only supported for the UBWC planes and wide UBWC planes are rejected anyway because in parallel multirect case only the half of the usual width is supported for tiled formats. However it's better to fix this now rather than stumbling upon it later.
Patchwork: https://patchwork.freedesktop.org/patch/601059/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +12 -0
@@ -865,6 +865,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, max_linewidth = pdpu->catalog->caps->max_linewidth; +drm_rect_rotate (&pipe_cfg->src_rect, + new_plane_state->fb->width, new_plane_state->fb->height, + new_plane_state->rotation); +if ((drm_rect_width (&pipe_cfg->src_rect) > max_linewidth) ||_dpu_plane_calc_clk (&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {/*
@@ -914,6 +918,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; } +drm_rect_rotate_inv (&pipe_cfg->src_rect, + new_plane_state->fb->width, new_plane_state->fb->height, + new_plane_state->rotation); +if (r_pipe->sspp) +drm_rect_rotate_inv (&r_pipe_cfg->src_rect, + new_plane_state->fb->width, new_plane_state->fb->height, + new_plane_state->rotation); + ret =dpu_plane_atomic_check_pipe (pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode);if (ret)return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 200/273 workqueue: Fix UBSAN subtraction overflow error in shift_and_mask()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
[ Upstream commit 38f7e14519d39cf524ddc02d4caee9b337dad703 ]
UBSAN reports the following 'subtraction overflow' error when booting in a virtual machine on Android:
| Internal error: UBSAN: integer subtraction overflow: 00000000f2005515 [#1] PREEMPT SMP | Modules linked in: | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.10.0-00006-g3cbe9e5abd46-dirty #4 | Hardware name: linux,dummy-virt (DT) | pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) | pc : cancel_delayed_work+0x34/0x44 | lr : cancel_delayed_work+0x2c/0x44 | sp : ffff80008002ba60 | x29: ffff80008002ba60 x28: 0000000000000000 x27: 0000000000000000 | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 | x23: 0000000000000000 x22: 0000000000000000 x21: ffff1f65014cd3c0 | x20: ffffc0e84c9d0da0 x19: ffffc0e84cab3558 x18: ffff800080009058 | x17: 00000000247ee1f8 x16: 00000000247ee1f8 x15: 00000000bdcb279d | x14: 0000000000000001 x13: 0000000000000075 x12: 00000a0000000000 | x11: ffff1f6501499018 x10: 00984901651fffff x9 : ffff5e7cc35af000 | x8 : 0000000000000001 x7 : 3d4d455453595342 x6 : 000000004e514553 | x5 : ffff1f6501499265 x4 : ffff1f650ff60b10 x3 : 0000000000000620 | x2 : ffff80008002ba78 x1 : 0000000000000000 x0 : 0000000000000000 | Call trace: | cancel_delayed_work+0x34/0x44 | deferred_probe_extend_timeout+0x20/0x70 | driver_register+0xa8/0x110 | __platform_driver_register+0x28/0x3c | syscon_init+0x24/0x38 | do_one_initcall+0xe4/0x338 | do_initcall_level+0xac/0x178 | do_initcalls+0x5c/0xa0 | do_basic_setup+0x20/0x30 | kernel_init_freeable+0x8c/0xf8 | kernel_init+0x28/0x1b4 | ret_from_fork+0x10/0x20 | Code: f9000fbf 97fffa2f 39400268 37100048 (d42aa2a0) | ---[ end trace 0000000000000000 ]--- | Kernel panic - not syncing: UBSAN: integer subtraction overflow: Fatal exception
This is due to shift_and_mask() using a signed immediate to construct the mask and being called with a shift of 31 (WORK_OFFQ_POOL_SHIFT) so that it ends up decrementing from INT_MIN.
Use an unsigned constant '1U' to generate the mask in shift_and_mask().
--- kernel/workqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/workqueue.c +1 -1
@@ -896,7 +896,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work)static unsigned long shift_and_mask (unsigned long v,u32 shift,u32 bits) { -return (v >> shift) & ((1 << bits) -1 ); +return (v >> shift) & ((1U << bits) -1 ); }static void work_offqd_unpack (struct work_offq_data *offqd,unsigned long data)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 201/273 workqueue: Fix spruious data race in __flush_work()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 8bc35475ef1a23b0e224f3242eb11c76cab0ea88 ]
When flushing a work item for cancellation, __flush_work() knows that it exclusively owns the work item through its PENDING bit. 134874e2eee9 ("workqueue: Allow cancel_work_sync() and disable_work() from atomic contexts on BH work items") added a read of @work->data to determine whether to use busy wait for BH work items that are being canceled. While the read is safe when @from_cancel, @work->data was read before testing @from_cancel to simplify code structure:
data = *work_data_bits(work);
if (from_cancel &&
!WARN_ON_ONCE(data & WORK_STRUCT_PWQ) && (data & WORK_OFFQ_BH)) {While the read data was never used if !@from_cancel, this could trigger KCSAN data race detection spuriously:
==================================================================
BUG: KCSAN: data-race in __flush_work / __flush_work
write to 0xffff8881223aa3e8 of 8 bytes by task 3998 on cpu 0:
instrument_write include/linux/instrumented.h:41 [inline] ___set_bit include/asm-generic/bitops/instrumented-non-atomic.h:28 [inline] insert_wq_barrier kernel/workqueue.c:3790 [inline] start_flush_work kernel/workqueue.c:4142 [inline] __flush_work+0x30b/0x570 kernel/workqueue.c:4178 flush_work kernel/workqueue.c:4229 [inline] ...
read to 0xffff8881223aa3e8 of 8 bytes by task 50 on cpu 1:
__flush_work+0x42a/0x570 kernel/workqueue.c:4188 flush_work kernel/workqueue.c:4229 [inline] flush_delayed_work+0x66/0x70 kernel/workqueue.c:4251 ...
value changed: 0x0000000000400000 -> 0xffff88810006c00d
Reorganize the code so that @from_cancel is tested before @work->data is accessed. The only problem is triggering KCSAN detection spuriously. This shouldn't need READ_ONCE() or other access qualifiers.
No functional changes.
--- kernel/workqueue.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)
kernel/workqueue.c +25 -20
@@ -4190,7 +4190,6 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,static bool __flush_work (struct work_struct *work,bool from_cancel) {struct wq_barrier barr; -unsigned long data;if (WARN_ON (!wq_online))return false;
@@ -4208,29 +4207,35 @@ static bool __flush_work(struct work_struct *work, bool from_cancel)* was queued on a BH workqueue, we also know that it was running in the * BH context and thus can be busy-waited. */ - data = *work_data_bits (work); -if (from_cancel && - !WARN_ON_ONCE (data &WORK_STRUCT_PWQ ) && (data &WORK_OFFQ_BH )) { -/* -* On RT, prevent a live lock when %current preempted soft -* interrupt processing or prevents ksoftirqd from running by -* keeping flipping BH. If the BH work item runs on a different -* CPU then this has no effect other than doing the BH -* disable/enable dance for nothing. This is copied from -* kernel/softirq.c::tasklet_unlock_spin_wait(). -*/ -while (!try_wait_for_completion (&barr.done)) { -if (IS_ENABLED (CONFIG_PREEMPT_RT )) { -local_bh_disable (); -local_bh_enable (); - }else { -cpu_relax (); +if (from_cancel) { +unsigned long data = *work_data_bits (work); + +if (!WARN_ON_ONCE (data &WORK_STRUCT_PWQ ) && + (data &WORK_OFFQ_BH )) { +/* +* On RT, prevent a live lock when %current preempted +* soft interrupt processing or prevents ksoftirqd from +* running by keeping flipping BH. If the BH work item +* runs on a different CPU then this has no effect other +* than doing the BH disable/enable dance for nothing. +* This is copied from +* kernel/softirq.c::tasklet_unlock_spin_wait(). +*/ +while (!try_wait_for_completion (&barr.done)) { +if (IS_ENABLED (CONFIG_PREEMPT_RT )) { +local_bh_disable (); +local_bh_enable (); + }else { +cpu_relax (); + } } + goto out_destroy; } - }else { -wait_for_completion (&barr.done); } +wait_for_completion (&barr.done); + +out_destroy:destroy_work_on_stack (&barr.work);return true; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 202/273 drm/msm: fix the highest_bank_bit for sc7180
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhinav Kumar <[email protected]>
[ Upstream commit 3e30296b374af33cb4c12ff93df0b1e5b2d0f80b ]
sc7180 programs the ubwc settings as 0x1e as that would mean a highest bank bit of 14 which matches what the GPU sets as well.
However, the highest_bank_bit field of the msm_mdss_data which is being used to program the SSPP's fetch configuration is programmed to a highest bank bit of 16 as 0x3 translates to 16 and not 14.
Fix the highest bank bit field used for the SSPP to match the mdss and gpu settings.
Patchwork: https://patchwork.freedesktop.org/patch/607625/
--- drivers/gpu/drm/msm/msm_mdss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_mdss.c +1 -1
@@ -577,7 +577,7 @@ static const struct msm_mdss_data sc7180_data = { .ubwc_enc_version = UBWC_2_0, .ubwc_dec_version = UBWC_2_0, .ubwc_static = 0x1e, - .highest_bank_bit = 0x3, + .highest_bank_bit = 0x1, .reg_bus_bw = 76800, };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 203/273 spi: spi-cadence-quadspi: Fix OSPI NOR failures during system resume
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vignesh Raghavendra <[email protected]>
[ Upstream commit 57d5af2660e9443b081eeaf1c373b3ce48477828 ]
Its necessary to call pm_runtime_force_*() hooks as part of system suspend/resume calls so that the runtime_pm hooks get called. This ensures latest state of the IP is cached and restored during system sleep. This is especially true if runtime autosuspend is enabled as runtime suspend hooks may not be called at all before system sleeps.
Without this patch, OSPI NOR enumeration (READ_ID) fails during resume as context saved during suspend path is inconsistent.
--- drivers/spi/spi-cadence-quadspi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/spi/spi-cadence-quadspi.c +13 -1
@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev)static int cqspi_suspend (struct device *dev) {struct cqspi_st *cqspi =dev_get_drvdata (dev); +int ret; -return spi_controller_suspend (cqspi->host); + ret =spi_controller_suspend (cqspi->host); +if (ret) +return ret; + +return pm_runtime_force_suspend (dev); }static int cqspi_resume (struct device *dev) {struct cqspi_st *cqspi =dev_get_drvdata (dev); +int ret; + + ret =pm_runtime_force_resume (dev); +if (ret) { +dev_err (dev,"pm_runtime_force_resume failed on resume\n" ); +return ret; + }return spi_controller_resume (cqspi->host); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 204/273 drm/i915/hdcp: Use correct cp_irq_count
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suraj Kandpal <[email protected]>
[ Upstream commit 5d41eeb6725e3e24853629e5d7635e4bc45d736e ]
We are checking cp_irq_count from the wrong hdcp structure which ends up giving timed out errors. We only increment the cp_irq_count of the primary connector's hdcp structure but here in case of multidisplay setup we end up checking the secondary connector's hdcp structure, which will not have its cp_irq_count incremented. This leads to a timed out at CP_IRQ error even though a CP_IRQ was raised. Extract it from the correct intel_hdcp structure.
--v2
-Explain why it was the wrong hdcp structure [Jani]
--- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/display/intel_dp_hdcp.c +3 -1
@@ -39,7 +39,9 @@ static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)static void intel_dp_hdcp_wait_for_cp_irq (struct intel_connector *connector,int timeout) { -struct intel_hdcp *hdcp = &connector->hdcp; +struct intel_digital_port *dig_port =intel_attached_dig_port (connector); +struct intel_dp *dp = &dig_port->dp; +struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;long ret;#define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 205/273 drm/xe/display: stop calling domains_driver_remove twice
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
[ Upstream commit 48d74a0a45201de4efa016fb2f556889db37ed28 ]
Unclear why we call this twice.
Stable-dep-of: f4b2a0ae1a31 ("drm/xe: Fix opregion leak")
--- drivers/gpu/drm/xe/display/xe_display.c | 1 - 1 file changed, 1 deletion(-)
drivers/gpu/drm/xe/display/xe_display.c +0 -1
@@ -134,7 +134,6 @@ static void xe_display_fini_noirq(struct drm_device *dev, void *dummy)return ;intel_display_driver_remove_noirq (xe); -intel_power_domains_driver_remove (xe); }int xe_display_init_noirq (struct xe_device *xe)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 206/273 drm/xe: Fix opregion leak
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
[ Upstream commit f4b2a0ae1a31fd3d1b5ca18ee08319b479cf9b5f ]
Being part o the display, ideally the setup and cleanup would be done by display itself. However this is a bigger refactor that needs to be done on both i915 and xe. For now, just fix the leak:
unreferenced object 0xffff8881a0300008 (size 192):
comm "modprobe", pid 4354, jiffies 4295647021 hex dump (first 32 bytes):
00 00 87 27 81 88 ff ff 18 80 9b 00 00 c9 ff ff ...'............
18 81 9b 00 00 c9 ff ff 00 00 00 00 00 00 00 00 ................
backtrace (crc 99260e31):
[<ffffffff823ce65b>] kmemleak_alloc+0x4b/0x80
[<ffffffff81493be2>] kmalloc_trace_noprof+0x312/0x3d0
[<ffffffffa1345679>] intel_opregion_setup+0x89/0x700 [xe]
[<ffffffffa125bfaf>] xe_display_init_noirq+0x2f/0x90 [xe]
[<ffffffffa1199ec3>] xe_device_probe+0x7a3/0xbf0 [xe]
[<ffffffffa11f3713>] xe_pci_probe+0x333/0x5b0 [xe]
[<ffffffff81af6be8>] local_pci_probe+0x48/0xb0
[<ffffffff81af8778>] pci_device_probe+0xc8/0x280
[<ffffffff81d09048>] really_probe+0xf8/0x390
[<ffffffff81d0937a>] __driver_probe_device+0x8a/0x170
[<ffffffff81d09503>] driver_probe_device+0x23/0xb0
[<ffffffff81d097b7>] __driver_attach+0xc7/0x190
[<ffffffff81d0628d>] bus_for_each_dev+0x7d/0xd0
[<ffffffff81d0851e>] driver_attach+0x1e/0x30
[<ffffffff81d07ac7>] bus_add_driver+0x117/0x250--- drivers/gpu/drm/xe/display/xe_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/display/xe_display.c +4 -1
@@ -134,6 +134,7 @@ static void xe_display_fini_noirq(struct drm_device *dev, void *dummy)return ;intel_display_driver_remove_noirq (xe); +intel_opregion_cleanup (xe); }int xe_display_init_noirq (struct xe_device *xe)
@@ -159,8 +160,10 @@ int xe_display_init_noirq(struct xe_device *xe)intel_display_device_info_runtime_init (xe); err =intel_display_driver_probe_noirq (xe); -if (err) +if (err) { +intel_opregion_cleanup (xe);return err; + }return drmm_add_action_or_reset (&xe->drm, xe_display_fini_noirq,NULL ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 207/273 drm/xe/mmio: move mmio_fini over to devm
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
[ Upstream commit a0b834c8957a7d2848face008a12382a0ad11ffc ]
Not valid to touch mmio once the device is removed, so make sure we unmap on removal and not just when driver instance goes away. Also set the mmio pointers to NULL to hopefully catch such issues more easily.
Stable-dep-of: 15939ca77d44 ("drm/xe: Fix tile fini sequence")
--- drivers/gpu/drm/xe/xe_mmio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_mmio.c +5 -2
@@ -386,13 +386,16 @@ void xe_mmio_probe_tiles(struct xe_device *xe) } } -static void mmio_fini (struct drm_device *drm,void *arg) +static void mmio_fini (void *arg) {struct xe_device *xe = arg;pci_iounmap (to_pci_dev (xe->drm.dev), xe->mmio.regs);if (xe->mem.vram.mapping)iounmap (xe->mem.vram.mapping); + + xe->mem.vram.mapping =NULL ; + xe->mmio.regs =NULL ; }int xe_mmio_init (struct xe_device *xe)
@@ -417,7 +420,7 @@ int xe_mmio_init(struct xe_device *xe) root_tile->mmio.size =SZ_16M ; root_tile->mmio.regs = xe->mmio.regs; -return drmm_add_action_or_reset (&xe->drm, mmio_fini, xe); +return devm_add_action_or_reset (xe->drm.dev, mmio_fini, xe); }u8 xe_mmio_read8 (struct xe_gt *gt,struct xe_reg reg)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 208/273 drm/xe: reset mmio mappings with devm
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
[ Upstream commit c7117419784f612d59ee565145f722e8b5541fe6 ]
Set our various mmio mappings to NULL. This should make it easier to catch something rogue trying to mess with mmio after device removal. For example, we might unmap everything and then start hitting some mmio address which has already been unmamped by us and then remapped by something else, causing all kinds of carnage.
Stable-dep-of: 15939ca77d44 ("drm/xe: Fix tile fini sequence")
--- drivers/gpu/drm/xe/xe_device.c | 4 +++- drivers/gpu/drm/xe/xe_mmio.c | 35 ++++++++++++++++++++++++++++------ drivers/gpu/drm/xe/xe_mmio.h | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-)
drivers/gpu/drm/xe/xe_device.c +3 -1
@@ -551,7 +551,9 @@ int xe_device_probe(struct xe_device *xe)if (err)return err; -xe_mmio_probe_tiles (xe); + err =xe_mmio_probe_tiles (xe); +if (err) +return err;xe_ttm_sys_mgr_init (xe);
drivers/gpu/drm/xe/xe_mmio.c +29 -6
@@ -254,6 +254,21 @@ static int xe_mmio_tile_vram_size(struct xe_tile *tile, u64 *vram_size,return xe_force_wake_put (gt_to_fw (gt),XE_FW_GT ); } +static void vram_fini (void *arg) +{ +struct xe_device *xe = arg; +struct xe_tile *tile; +int id; + +if (xe->mem.vram.mapping) +iounmap (xe->mem.vram.mapping); + + xe->mem.vram.mapping =NULL ; + +for_each_tile (tile, xe, id) + tile->mem.vram.mapping =NULL ; +} +int xe_mmio_probe_vram (struct xe_device *xe) {struct xe_tile *tile;
@@ -330,10 +345,20 @@ int xe_mmio_probe_vram(struct xe_device *xe)drm_info (&xe->drm,"Available VRAM: %pa, %pa\n" , &xe->mem.vram.io_start, &available_size); -return 0 ; +return devm_add_action_or_reset (xe->drm.dev, vram_fini, xe); } -void xe_mmio_probe_tiles (struct xe_device *xe) +static void tiles_fini (void *arg) +{ +struct xe_device *xe = arg; +struct xe_tile *tile; +int id; + +for_each_tile (tile, xe, id) + tile->mmio.regs =NULL ; +} + +int xe_mmio_probe_tiles (struct xe_device *xe) {size_t tile_mmio_size =SZ_16M , tile_mmio_ext_size = xe->info.tile_mmio_ext_size;u8 id, tile_count = xe->info.tile_count;
@@ -384,6 +409,8 @@ void xe_mmio_probe_tiles(struct xe_device *xe) regs += tile_mmio_ext_size; } } + +return devm_add_action_or_reset (xe->drm.dev, tiles_fini, xe); }static void mmio_fini (void *arg)
@@ -391,10 +418,6 @@ static void mmio_fini(void *arg)struct xe_device *xe = arg;pci_iounmap (to_pci_dev (xe->drm.dev), xe->mmio.regs); -if (xe->mem.vram.mapping) -iounmap (xe->mem.vram.mapping); - - xe->mem.vram.mapping =NULL ; xe->mmio.regs =NULL ; }
drivers/gpu/drm/xe/xe_mmio.h +1 -1
@@ -21,7 +21,7 @@ struct xe_device;#define LMEM_BAR 2int xe_mmio_init (struct xe_device *xe); -void xe_mmio_probe_tiles (struct xe_device *xe); +int xe_mmio_probe_tiles (struct xe_device *xe);u8 xe_mmio_read8 (struct xe_gt *gt,struct xe_reg reg);u16 xe_mmio_read16 (struct xe_gt *gt,struct xe_reg reg);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 209/273 drm/xe: Fix tile fini sequence
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <[email protected]>
[ Upstream commit 15939ca77d4424f736e1e4953b4da2351cc9689d ]
Only set tile->mmio.regs to NULL if not the root tile in tile_fini. The root tile mmio regs is setup ealier in MMIO init thus it should be set to NULL in mmio_fini.
--- drivers/gpu/drm/xe/xe_mmio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_mmio.c +4 -1
@@ -355,7 +355,8 @@ static void tiles_fini(void *arg)int id;for_each_tile (tile, xe, id) - tile->mmio.regs =NULL ; +if (tile !=xe_device_get_root_tile (xe)) + tile->mmio.regs =NULL ; }int xe_mmio_probe_tiles (struct xe_device *xe)
@@ -416,9 +417,11 @@ int xe_mmio_probe_tiles(struct xe_device *xe)static void mmio_fini (void *arg) {struct xe_device *xe = arg; +struct xe_tile *root_tile =xe_device_get_root_tile (xe);pci_iounmap (to_pci_dev (xe->drm.dev), xe->mmio.regs); xe->mmio.regs =NULL ; + root_tile->mmio.regs =NULL ; }int xe_mmio_init (struct xe_device *xe)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 210/273 mmc: mmc_test: Fix NULL dereference on allocation failure
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit a1e627af32ed60713941cbfc8075d44cad07f6dd ]
If the "test->highmem = alloc_pages()" allocation fails then calling __free_pages(test->highmem) will result in a NULL dereference. Also change the error code to -ENOMEM instead of returning success.
--- drivers/mmc/core/mmc_test.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/mmc/core/mmc_test.c +5 -4
@@ -3125,13 +3125,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, test->buffer =kzalloc (BUFFER_SIZE ,GFP_KERNEL );#ifdef CONFIG_HIGHMEM test->highmem =alloc_pages (GFP_KERNEL | __GFP_HIGHMEM,BUFFER_ORDER ); +if (!test->highmem) { + count = -ENOMEM ; + goto free_test_buffer; + }#endif -#ifdef CONFIG_HIGHMEM -if (test->buffer && test->highmem) { -#else if (test->buffer) { -#endif mutex_lock (&mmc_test_lock);mmc_test_run (test, testcase);mutex_unlock (&mmc_test_lock);
@@ -3139,6 +3139,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,#ifdef CONFIG_HIGHMEM __free_pages (test->highmem,BUFFER_ORDER ); +free_test_buffer:#endif kfree (test->buffer);kfree (test);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 211/273 io_uring/kbuf: sanitize peek buffer setup
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
[ Upstream commit e0ee967630c8ee67bb47a5b38d235cd5a8789c48 ]
Harden the buffer peeking a bit, by adding a sanity check for it having a valid size. Outside of that, arg->max_len is a size_t, though it's only ever set to a 32-bit value (as it's governed by MAX_RW_COUNT). Bump our needed check to a size_t so we know it fits. Finally, cap the calculated needed iov value to the PEEK_MAX_IMPORT, which is the maximum number of segments that should be peeked.
--- io_uring/kbuf.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
io_uring/kbuf.c +6 -3
@@ -218,10 +218,13 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, buf =io_ring_head_to_buf (br, head, bl->mask);if (arg->max_len) { -int needed; +u32 len =READ_ONCE (buf->len); +size_t needed; - needed = (arg->max_len + buf->len -1 ) / buf->len; - needed =min (needed,PEEK_MAX_IMPORT ); +if (unlikely (!len)) +return -ENOBUFS ; + needed = (arg->max_len + len -1 ) / len; + needed =min_not_zero (needed, (size_t )PEEK_MAX_IMPORT );if (nr_avail > needed) nr_avail = needed; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 212/273 drm/xe: Fix missing workqueue destroy in xe_gt_pagefault
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stuart Summers <[email protected]>
[ Upstream commit a6f78359ac75f24cac3c1bdd753c49c1877bcd82 ]
On driver reload we never free up the memory for the pagefault and access counter workqueues. Add those destroy calls here.
--- drivers/gpu/drm/xe/xe_gt_pagefault.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_gt_pagefault.c +16 -2
@@ -402,6 +402,18 @@ static void pf_queue_work_func(struct work_struct *w)static void acc_queue_work_func (struct work_struct *w); +static void pagefault_fini (void *arg) +{ +struct xe_gt *gt = arg; +struct xe_device *xe =gt_to_xe (gt); + +if (!xe->info.has_usm) +return ; + +destroy_workqueue (gt->usm.acc_wq); +destroy_workqueue (gt->usm.pf_wq); +} +int xe_gt_pagefault_init (struct xe_gt *gt) {struct xe_device *xe =gt_to_xe (gt);
@@ -429,10 +441,12 @@ int xe_gt_pagefault_init(struct xe_gt *gt) gt->usm.acc_wq =alloc_workqueue ("xe_gt_access_counter_work_queue" ,WQ_UNBOUND |WQ_HIGHPRI ,NUM_ACC_QUEUE ); -if (!gt->usm.acc_wq) +if (!gt->usm.acc_wq) { +destroy_workqueue (gt->usm.pf_wq);return -ENOMEM ; + } -return 0 ; +return devm_add_action_or_reset (xe->drm.dev, pagefault_fini, gt); }void xe_gt_pagefault_reset (struct xe_gt *gt)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 213/273 drm/xe: Relax runtime pm protection during execution
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rodrigo Vivi <[email protected]>
[ Upstream commit ad1e331fc451a2cffc72ae193b843682ce237e24 ]
Limit the protection only during moments of actual job execution, and introduce protection for guc submit fini, which is currently unprotected due to the absence of exec_queue life protection.
In the regular use case scenario, user space will create an exec queue, and keep it alive to reuse that until it is done with that kind of workload.
For the regular desktop cases, it means that the exec_queue is alive even on idle scenarios where display goes off. This is unacceptable since this would entirely block runtime PM indefinitely, blocking deeper Package-C state. This would be a waste drainage of power.
Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
--- drivers/gpu/drm/xe/xe_exec_queue.c | 14 -------------- drivers/gpu/drm/xe/xe_guc_submit.c | 3 +++ drivers/gpu/drm/xe/xe_sched_job.c | 10 +++------- 3 files changed, 6 insertions(+), 21 deletions(-)
drivers/gpu/drm/xe/xe_exec_queue.c +0 -14
@@ -106,7 +106,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,static int __xe_exec_queue_init (struct xe_exec_queue *q) { -struct xe_device *xe =gt_to_xe (q->gt);int i, err;for (i =0 ; i < q->width; ++i) {
@@ -119,17 +118,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)if (err) goto err_lrc; -/* -* Normally the user vm holds an rpm ref to keep the device -* awake, and the context holds a ref for the vm, however for -* some engines we use the kernels migrate vm underneath which offers no -* such rpm ref, or we lack a vm. Make sure we keep a ref here, so we -* can perform GuC CT actions when needed. Caller is expected to have -* already grabbed the rpm ref outside any sensitive locks. -*/ -if (!(q->flags &EXEC_QUEUE_FLAG_PERMANENT ) && (q->flags &EXEC_QUEUE_FLAG_VM || !q->vm)) -xe_pm_runtime_get_noresume (xe); -return 0 ; err_lrc:
@@ -216,8 +204,6 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)for (i =0 ; i < q->width; ++i)xe_lrc_finish (q->lrc + i); -if (!(q->flags &EXEC_QUEUE_FLAG_PERMANENT ) && (q->flags &EXEC_QUEUE_FLAG_VM || !q->vm)) -xe_pm_runtime_put (gt_to_xe (q->gt));__xe_exec_queue_free (q); }
drivers/gpu/drm/xe/xe_guc_submit.c +3 -0
@@ -35,6 +35,7 @@#include "xe_macros.h" #include "xe_map.h" #include "xe_mocs.h" +#include "xe_pm.h" #include "xe_ring_ops_types.h" #include "xe_sched_job.h" #include "xe_trace.h"
@@ -1011,6 +1012,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)struct xe_exec_queue *q = ge->q;struct xe_guc *guc =exec_queue_to_guc (q); +xe_pm_runtime_get (guc_to_xe (guc));trace_xe_exec_queue_destroy (q);if (xe_exec_queue_is_lr (q))
@@ -1021,6 +1023,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)kfree (ge);xe_exec_queue_fini (q); +xe_pm_runtime_put (guc_to_xe (guc)); }static void guc_exec_queue_fini_async (struct xe_exec_queue *q)
drivers/gpu/drm/xe/xe_sched_job.c +3 -7
@@ -158,11 +158,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,for (i =0 ; i < width; ++i) job->batch_addr[i] = batch_addr[i]; -/* All other jobs require a VM to be open which has a ref */ -if (unlikely (q->flags &EXEC_QUEUE_FLAG_KERNEL )) -xe_pm_runtime_get_noresume (job_to_xe (job)); -xe_device_assert_mem_access (job_to_xe (job)); - +xe_pm_runtime_get_noresume (job_to_xe (job));trace_xe_sched_job_create (job);return job;
@@ -191,13 +187,13 @@ void xe_sched_job_destroy(struct kref *ref) {struct xe_sched_job *job = container_of(ref, struct xe_sched_job, refcount); +struct xe_device *xe =job_to_xe (job); -if (unlikely (job->q->flags &EXEC_QUEUE_FLAG_KERNEL )) -xe_pm_runtime_put (job_to_xe (job));xe_exec_queue_put (job->q);dma_fence_put (job->fence);drm_sched_job_cleanup (&job->drm);job_free (job); +xe_pm_runtime_put (xe); }void xe_sched_job_set_error (struct xe_sched_job *job,int error)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 214/273 drm/xe: Decouple job seqno and lrc seqno
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <[email protected]>
[ Upstream commit 08f7200899ca72dec550af092ae424b7db099abd ]
Tightly coupling these seqno presents problems if alternative fences for jobs are used. Decouple these for correctness.
v2:
- Slightly reword commit message (Thomas)
- Make sure the lrc fence ops are used in comparison (Thomas)
- Assume seqno is unsigned rather than signed in format string (Thomas)
Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
--- drivers/gpu/drm/xe/xe_exec_queue.c | 2 +- drivers/gpu/drm/xe/xe_guc_submit.c | 5 +++-- drivers/gpu/drm/xe/xe_ring_ops.c | 12 ++++++------ drivers/gpu/drm/xe/xe_sched_job.c | 16 ++++++++-------- drivers/gpu/drm/xe/xe_sched_job.h | 5 +++++ drivers/gpu/drm/xe/xe_sched_job_types.h | 2 ++ drivers/gpu/drm/xe/xe_trace.h | 7 +++++-- 7 files changed, 30 insertions(+), 19 deletions(-)
drivers/gpu/drm/xe/xe_exec_queue.c +1 -1
@@ -98,7 +98,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,if (xe_exec_queue_is_parallel (q)) { q->parallel.composite_fence_ctx =dma_fence_context_alloc (1 ); - q->parallel.composite_fence_seqno =XE_FENCE_INITIAL_SEQNO ; + q->parallel.composite_fence_seqno =0 ; }return q;
drivers/gpu/drm/xe/xe_guc_submit.c +3 -2
@@ -917,8 +917,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)return DRM_GPU_SCHED_STAT_NOMINAL ; } -drm_notice (&xe->drm,"Timedout job: seqno=%u, guc_id=%d, flags=0x%lx" , -xe_sched_job_seqno (job), q->guc->id, q->flags); +drm_notice (&xe->drm,"Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx" , +xe_sched_job_seqno (job),xe_sched_job_lrc_seqno (job), + q->guc->id, q->flags);xe_gt_WARN (q->gt, q->flags &EXEC_QUEUE_FLAG_KERNEL ,"Kernel-submitted job timed out\n" ); xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
drivers/gpu/drm/xe/xe_ring_ops.c +6 -6
@@ -412,7 +412,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job)__emit_job_gen12_simple (job, job->q->lrc, job->batch_addr[0 ], -xe_sched_job_seqno (job)); +xe_sched_job_lrc_seqno (job)); }static void emit_job_gen12_copy (struct xe_sched_job *job)
@@ -421,14 +421,14 @@ static void emit_job_gen12_copy(struct xe_sched_job *job)if (xe_sched_job_is_migration (job->q)) {emit_migration_job_gen12 (job, job->q->lrc, -xe_sched_job_seqno (job)); +xe_sched_job_lrc_seqno (job));return ; }for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_simple (job, job->q->lrc + i, - job->batch_addr[i], -xe_sched_job_seqno (job)); + job->batch_addr[i], +xe_sched_job_lrc_seqno (job)); }static void emit_job_gen12_video (struct xe_sched_job *job)
@@ -439,7 +439,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job)for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_video (job, job->q->lrc + i, job->batch_addr[i], -xe_sched_job_seqno (job)); +xe_sched_job_lrc_seqno (job)); }static void emit_job_gen12_render_compute (struct xe_sched_job *job)
@@ -449,7 +449,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job)for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_render_compute (job, job->q->lrc + i, job->batch_addr[i], -xe_sched_job_seqno (job)); +xe_sched_job_lrc_seqno (job)); }static const struct xe_ring_ops ring_ops_gen12_gsc = {
drivers/gpu/drm/xe/xe_sched_job.c +8 -8
@@ -117,6 +117,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, err =PTR_ERR (job->fence); goto err_sched_job; } + job->lrc_seqno = job->fence->seqno; }else {struct dma_fence_array *cf;
@@ -132,6 +133,8 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, err =PTR_ERR (fences[j]); goto err_fences; } +if (!j) + job->lrc_seqno = fences[0 ]->seqno; } cf = dma_fence_array_create(q->width, fences,
@@ -144,10 +147,6 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, goto err_fences; } -/* Sanity check */ -for (j =0 ; j < q->width; ++j) -xe_assert (job_to_xe (job), cf->base.seqno == fences[j]->seqno); - job->fence = &cf->base; }
@@ -229,9 +228,9 @@ bool xe_sched_job_started(struct xe_sched_job *job) {struct xe_lrc *lrc = job->q->lrc; -return !__dma_fence_is_later (xe_sched_job_seqno (job), +return !__dma_fence_is_later (xe_sched_job_lrc_seqno (job),xe_lrc_start_seqno (lrc), - job->fence->ops); +dma_fence_array_first (job->fence)->ops); }bool xe_sched_job_completed (struct xe_sched_job *job)
@@ -243,8 +242,9 @@ bool xe_sched_job_completed(struct xe_sched_job *job)* parallel handshake is done. */ -return !__dma_fence_is_later (xe_sched_job_seqno (job),xe_lrc_seqno (lrc), - job->fence->ops); +return !__dma_fence_is_later (xe_sched_job_lrc_seqno (job), +xe_lrc_seqno (lrc), +dma_fence_array_first (job->fence)->ops); }void xe_sched_job_arm (struct xe_sched_job *job)
drivers/gpu/drm/xe/xe_sched_job.h +5 -0
@@ -73,6 +73,11 @@ static inline u32 xe_sched_job_seqno(struct xe_sched_job *job)return job->fence->seqno; } +static inline u32 xe_sched_job_lrc_seqno (struct xe_sched_job *job) +{ +return job->lrc_seqno; +} +static inline void xe_sched_job_add_migrate_flush (struct xe_sched_job *job,u32 flags) {
drivers/gpu/drm/xe/xe_sched_job_types.h +2 -0
@@ -37,6 +37,8 @@ struct xe_sched_job {/** @user_fence.value: write back value */ u64 value; } user_fence; +/** @lrc_seqno: LRC seqno */ +u32 lrc_seqno;/** @migrate_flush_flags: Additional flush flags for migration jobs */ u32 migrate_flush_flags;/** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */
drivers/gpu/drm/xe/xe_trace.h +5 -2
@@ -254,6 +254,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,TP_STRUCT__entry (__field (u32 ,seqno ) +__field (u32, lrc_seqno)__field (u16, guc_id)__field (u32, guc_state) __field(u32, flags)
@@ -264,6 +265,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,TP_fast_assign ( __entry->seqno = xe_sched_job_seqno(job); + __entry->lrc_seqno =xe_sched_job_lrc_seqno (job); __entry->guc_id = job->q->guc->id; __entry->guc_state =atomic_read (&job->q->guc->state);
@@ -273,8 +275,9 @@ DECLARE_EVENT_CLASS(xe_sched_job, __entry->batch_addr = (u64 )job->batch_addr[0 ]; ), -TP_printk ("fence=%p, seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d" , - __entry->fence, __entry->seqno, __entry->guc_id, +TP_printk ("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d" , + __entry->fence, __entry->seqno, + __entry->lrc_seqno, __entry->guc_id, __entry->batch_addr, __entry->guc_state, __entry->flags, __entry->error) );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 215/273 drm/xe: Split lrc seqno fence creation up
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellström <[email protected]>
[ Upstream commit e183910ae4015214475b3248ce0b4c70f104f254 ]
Since sometimes a lock is required to initialize a seqno fence, and it might be desirable not to hold that lock while performing memory allocations, split the lrc seqno fence creation up into an allocation phase and an initialization phase.
Since lrc seqno fences under the hood are hw_fences, do the same for these and remove the xe_hw_fence_create() function since it is not used anymore.
Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
--- drivers/gpu/drm/xe/xe_hw_fence.c | 59 +++++++++++++++++++++++++------- drivers/gpu/drm/xe/xe_hw_fence.h | 7 ++-- drivers/gpu/drm/xe/xe_lrc.c | 48 ++++++++++++++++++++++++-- drivers/gpu/drm/xe/xe_lrc.h | 3 ++ 4 files changed, 101 insertions(+), 16 deletions(-)
drivers/gpu/drm/xe/xe_hw_fence.c +47 -12
@@ -208,23 +208,58 @@ static struct xe_hw_fence *to_xe_hw_fence(struct dma_fence *fence) return container_of(fence, struct xe_hw_fence, dma); } -struct xe_hw_fence *xe_hw_fence_create (struct xe_hw_fence_ctx *ctx, -struct iosys_map seqno_map) +/** +* xe_hw_fence_alloc() - Allocate an hw fence. +* +* Allocate but don't initialize an hw fence. +* +* Return: Pointer to the allocated fence or +* negative error pointer on error. +*/ +struct dma_fence *xe_hw_fence_alloc (void ) { -struct xe_hw_fence *fence; +struct xe_hw_fence *hw_fence =fence_alloc (); - fence =fence_alloc (); -if (!fence) +if (!hw_fence)return ERR_PTR (-ENOMEM ); - fence->ctx = ctx; - fence->seqno_map = seqno_map; -INIT_LIST_HEAD (&fence->irq_link); +return &hw_fence->dma; +} -dma_fence_init (&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, - ctx->dma_fence_ctx, ctx->next_seqno++); +/** +* xe_hw_fence_free() - Free an hw fence. +* @fence: Pointer to the fence to free. +* +* Frees an hw fence that hasn't yet been +* initialized. +*/ +void xe_hw_fence_free (struct dma_fence *fence) +{ +fence_free (&fence->rcu); +} -trace_xe_hw_fence_create (fence); +/** +* xe_hw_fence_init() - Initialize an hw fence. +* @fence: Pointer to the fence to initialize. +* @ctx: Pointer to the struct xe_hw_fence_ctx fence context. +* @seqno_map: Pointer to the map into where the seqno is blitted. +* +* Initializes a pre-allocated hw fence. +* After initialization, the fence is subject to normal +* dma-fence refcounting. +*/ +void xe_hw_fence_init (struct dma_fence *fence,struct xe_hw_fence_ctx *ctx, +struct iosys_map seqno_map) +{ +struct xe_hw_fence *hw_fence = +container_of (fence,typeof (*hw_fence), dma); + + hw_fence->ctx = ctx; + hw_fence->seqno_map = seqno_map; +INIT_LIST_HEAD (&hw_fence->irq_link); + +dma_fence_init (fence, &xe_hw_fence_ops, &ctx->irq->lock, + ctx->dma_fence_ctx, ctx->next_seqno++); -return fence; +trace_xe_hw_fence_create (hw_fence); }
drivers/gpu/drm/xe/xe_hw_fence.h +5 -2
@@ -24,7 +24,10 @@ void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, struct xe_hw_fence_irq *irq, const char *name);void xe_hw_fence_ctx_finish (struct xe_hw_fence_ctx *ctx); -struct xe_hw_fence *xe_hw_fence_create (struct xe_hw_fence_ctx *ctx, -struct iosys_map seqno_map); +struct dma_fence *xe_hw_fence_alloc (void ); +void xe_hw_fence_free (struct dma_fence *fence); + +void xe_hw_fence_init (struct dma_fence *fence,struct xe_hw_fence_ctx *ctx, +struct iosys_map seqno_map);#endif
drivers/gpu/drm/xe/xe_lrc.c +46 -2
56 lines not on this page · raw message
drivers/gpu/drm/xe/xe_lrc.h +3 -0
@@ -38,6 +38,9 @@ void xe_lrc_write_ctx_reg(struct xe_lrc *lrc, int reg_nr, u32 val);u64 xe_lrc_descriptor (struct xe_lrc *lrc);u32 xe_lrc_seqno_ggtt_addr (struct xe_lrc *lrc); +struct dma_fence *xe_lrc_alloc_seqno_fence (void ); +void xe_lrc_free_seqno_fence (struct dma_fence *fence); +void xe_lrc_init_seqno_fence (struct xe_lrc *lrc,struct dma_fence *fence);struct dma_fence *xe_lrc_create_seqno_fence (struct xe_lrc *lrc);s32 xe_lrc_seqno (struct xe_lrc *lrc);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 216/273 drm/xe: Dont initialize fences at xe_sched_job_create()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Hellström <[email protected]>
[ Upstream commit 0ac7a2c745e8a42803378b944fa0f4455b7240f6 ]
Pre-allocate but don't initialize fences at xe_sched_job_create(), and initialize / arm them instead at xe_sched_job_arm(). This makes it possible to move xe_sched_job_create() with its memory allocation out of any lock that is required for fence initialization, and that may not allow memory allocation under it.
Replaces the struct dma_fence_array for parallell jobs with a struct dma_fence_chain, since the former doesn't allow a split-up between allocation and initialization.
v2:
- Rebase.
- Don't always use the first lrc when initializing parallel lrc fences.
- Use dma_fence_chain_contained() to access the lrc fences.
v4:
- Add an assert that job->lrc_seqno == fence->seqno. (Matthew Brost)
Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
--- drivers/gpu/drm/xe/xe_exec_queue.c | 5 - drivers/gpu/drm/xe/xe_exec_queue_types.h | 10 -- drivers/gpu/drm/xe/xe_ring_ops.c | 12 +- drivers/gpu/drm/xe/xe_sched_job.c | 161 +++++++++++++---------- drivers/gpu/drm/xe/xe_sched_job_types.h | 18 ++- drivers/gpu/drm/xe/xe_trace.h | 2 +- 6 files changed, 115 insertions(+), 93 deletions(-)
drivers/gpu/drm/xe/xe_exec_queue.c +0 -5
@@ -96,11 +96,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, } } -if (xe_exec_queue_is_parallel (q)) { - q->parallel.composite_fence_ctx =dma_fence_context_alloc (1 ); - q->parallel.composite_fence_seqno =0 ; - } -return q; }
drivers/gpu/drm/xe/xe_exec_queue_types.h +0 -10
@@ -103,16 +103,6 @@ struct xe_exec_queue {struct xe_guc_exec_queue *guc; }; -/** -* @parallel: parallel submission state -*/ -struct { -/** @parallel.composite_fence_ctx: context composite fence */ -u64 composite_fence_ctx; -/** @parallel.composite_fence_seqno: seqno for composite fence */ -u32 composite_fence_seqno; - } parallel; -/** @sched_props: scheduling properties */ struct {/** @sched_props.timeslice_us: timeslice period in micro-seconds */
drivers/gpu/drm/xe/xe_ring_ops.c +6 -6
@@ -380,7 +380,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, dw[i++] =MI_ARB_ON_OFF |MI_ARB_DISABLE ;/* Enabled again below */ - i =emit_bb_start (job->batch_addr[0 ],BIT (8 ), dw, i); + i =emit_bb_start (job->ptrs[0 ].batch_addr,BIT (8 ), dw, i);if (!IS_SRIOV_VF (gt_to_xe (job->q->gt))) {/* XXX: Do we need this? Leaving for now. */
@@ -389,7 +389,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, dw[i++] =preparser_disable (false); } - i =emit_bb_start (job->batch_addr[1 ],BIT (8 ), dw, i); + i =emit_bb_start (job->ptrs[1 ].batch_addr,BIT (8 ), dw, i); dw[i++] =MI_FLUSH_DW |MI_INVALIDATE_TLB | job->migrate_flush_flags |MI_FLUSH_DW_OP_STOREDW |MI_FLUSH_IMM_DW ;
@@ -411,7 +411,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job)xe_gt_assert (gt, job->q->width <=1 );/* no parallel submission for GSCCS */ __emit_job_gen12_simple (job, job->q->lrc, - job->batch_addr[0 ], + job->ptrs[0 ].batch_addr,xe_sched_job_lrc_seqno (job)); }
@@ -427,7 +427,7 @@ static void emit_job_gen12_copy(struct xe_sched_job *job)for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_simple (job, job->q->lrc + i, - job->batch_addr[i], + job->ptrs[i].batch_addr,xe_sched_job_lrc_seqno (job)); }
@@ -438,7 +438,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job)/* FIXME: Not doing parallel handshake for now */ for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_video (job, job->q->lrc + i, - job->batch_addr[i], + job->ptrs[i].batch_addr,xe_sched_job_lrc_seqno (job)); }
@@ -448,7 +448,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job)for (i =0 ; i < job->q->width; ++i)__emit_job_gen12_render_compute (job, job->q->lrc + i, - job->batch_addr[i], + job->ptrs[i].batch_addr,xe_sched_job_lrc_seqno (job)); }
drivers/gpu/drm/xe/xe_sched_job.c +92 -69
267 lines not on this page · raw message
drivers/gpu/drm/xe/xe_sched_job_types.h +16 -2
@@ -11,6 +11,20 @@#include <drm/gpu_scheduler.h> struct xe_exec_queue ; +struct dma_fence ; +struct dma_fence_chain ; + +/** +* struct xe_job_ptrs - Per hw engine instance data +*/ +struct xe_job_ptrs { +/** @lrc_fence: Pre-allocated uinitialized lrc fence.*/ +struct dma_fence *lrc_fence; +/** @chain_fence: Pre-allocated ninitialized fence chain node. */ +struct dma_fence_chain *chain_fence; +/** @batch_addr: Batch buffer address. */ +u64 batch_addr; +};/** * struct xe_sched_job - XE schedule job (batch buffer tracking)
@@ -43,8 +57,8 @@ struct xe_sched_job {u32 migrate_flush_flags;/** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */ bool ring_ops_flush_tlb; -/** @batch_addr: batch buffer address of job */ -u64 batch_addr[]; +/** @ptrs: per instance pointers. */ +struct xe_job_ptrs ptrs[]; };struct xe_sched_job_snapshot {
drivers/gpu/drm/xe/xe_trace.h +1 -1
@@ -272,7 +272,7 @@ DECLARE_EVENT_CLASS(xe_sched_job, __entry->flags = job->q->flags; __entry->error = job->fence->error; __entry->fence = job->fence; - __entry->batch_addr = (u64 )job->batch_addr[0 ]; + __entry->batch_addr = (u64 )job->ptrs[0 ].batch_addr; ), TP_printk("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 217/273 drm/xe: Free job before xe_exec_queue_put
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <[email protected]>
[ Upstream commit 9e7f30563677fbeff62d368d5d2a5ac7aaa9746a ]
Free job depends on job->vm being valid, the last xe_exec_queue_put can destroy the VM. Prevent UAF by freeing job before xe_exec_queue_put.
--- drivers/gpu/drm/xe/xe_sched_job.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_sched_job.c +2 -1
@@ -171,12 +171,13 @@ void xe_sched_job_destroy(struct kref *ref)struct xe_sched_job *job = container_of(ref, struct xe_sched_job, refcount);struct xe_device *xe =job_to_xe (job); +struct xe_exec_queue *q = job->q;xe_sched_job_free_fences (job); -xe_exec_queue_put (job->q);dma_fence_put (job->fence);drm_sched_job_cleanup (&job->drm);job_free (job); +xe_exec_queue_put (q);xe_pm_runtime_put (xe); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 218/273 thermal/debugfs: Fix the NULL vs IS_ERR() confusion in debugfs_create_dir()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Ruibin <[email protected]>
[ Upstream commit 57df60e1f981fa8c288a49012a4bbb02ae0ecdbc ]
The debugfs_create_dir() return value is never NULL, it is either a valid pointer or an error one.
Use IS_ERR() to check it.
--- drivers/thermal/thermal_debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/thermal/thermal_debugfs.c +3 -3
@@ -178,11 +178,11 @@ struct thermal_debugfs {void thermal_debug_init (void ) { d_root =debugfs_create_dir ("thermal" ,NULL ); -if (!d_root) +if (IS_ERR (d_root))return ; d_cdev =debugfs_create_dir ("cooling_devices" , d_root); -if (!d_cdev) +if (IS_ERR (d_cdev))return ; d_tz =debugfs_create_dir ("thermal_zones" , d_root);
@@ -202,7 +202,7 @@ static struct thermal_debugfs *thermal_debugfs_add_id(struct dentry *d, int id)snprintf (ids,IDSLENGTH ,"%d" , id); thermal_dbg->d_top =debugfs_create_dir (ids, d); -if (!thermal_dbg->d_top) { +if (IS_ERR (thermal_dbg->d_top)) {kfree (thermal_dbg);return NULL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 219/273 s390/boot: Avoid possible physmem_info segment corruption
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Gordeev <[email protected]>
[ Upstream commit d7fd2941ae9a67423d1c7bee985f240e4686634f ]
When physical memory for the kernel image is allocated it does not consider extra memory required for offsetting the image start to match it with the lower 20 bits of KASLR virtual base address. That might lead to kernel access beyond its memory range.
--- arch/s390/boot/startup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/boot/startup.c +2 -2
@@ -446,9 +446,9 @@ void startup_kernel(void)*/ kaslr_large_page_offset = __kaslr_offset & ~_SEGMENT_MASK;if (kaslr_enabled ()) { -unsigned long end = ident_map_size - kaslr_large_page_offset; +unsigned long size = kernel_size + kaslr_large_page_offset; - __kaslr_offset_phys =randomize_within_range (kernel_size, _SEGMENT_SIZE,0 , end); + __kaslr_offset_phys =randomize_within_range (size, _SEGMENT_SIZE,0 , ident_map_size); }if (!__kaslr_offset_phys) __kaslr_offset_phys = nokaslr_offset_phys;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 220/273 s390/boot: Fix KASLR base offset off by __START_KERNEL bytes
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Gordeev <[email protected]>
[ Upstream commit 1642285e511c2a40b14e87a41aa8feace6123036 ]
Symbol offsets to the KASLR base do not match symbol address in the vmlinux image. That is the result of setting the KASLR base to the beginning of .text section as result of an optimization.
Revert that optimization and allocate virtual memory for the whole kernel image including __START_KERNEL bytes as per the linker script. That allows keeping the semantics of the KASLR base offset in sync with other architectures.
Rename __START_KERNEL to TEXT_OFFSET, since it represents the offset of the .text section within the kernel image, rather than a virtual address.
Still skip mapping TEXT_OFFSET bytes to save memory on pgtables and provoke exceptions in case an attempt to access this area is made, as no kernel symbol may reside there.
In case CONFIG_KASAN is enabled the location counter might exceed the value of TEXT_OFFSET, while the decompressor linker script forcefully resets it to TEXT_OFFSET, which leads to a sections overlap link failure. Use MAX() expression to avoid that.
--- arch/s390/boot/startup.c | 55 ++++++++++++++++++---------------- arch/s390/boot/vmem.c | 14 +++++++-- arch/s390/boot/vmlinux.lds.S | 7 ++++- arch/s390/include/asm/page.h | 3 +- arch/s390/kernel/vmlinux.lds.S | 2 +- arch/s390/tools/relocs.c | 2 +- 6 files changed, 52 insertions(+), 31 deletions(-)
arch/s390/boot/startup.c +30 -25
@@ -161,7 +161,7 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr, loc = (long )*reloc + phys_offset;if (loc < min_addr || loc > max_addr)error ("64-bit relocation outside of kernel!\n" ); - *(u64 *)loc += offset - __START_KERNEL; + *(u64 *)loc += offset; } }
@@ -176,7 +176,7 @@ static void kaslr_adjust_got(unsigned long offset)*/ for (entry = (u64 *)vmlinux.got_start; entry < (u64 *)vmlinux.got_end; entry++) {if (*entry) - *entry += offset - __START_KERNEL; + *entry += offset; } }
@@ -251,7 +251,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size) vmemmap_size =SECTION_ALIGN_UP (pages) *sizeof (struct page );/* choose kernel address space layout: 4 or 3 levels. */ -BUILD_BUG_ON (!IS_ALIGNED (__START_KERNEL,THREAD_SIZE )); +BUILD_BUG_ON (!IS_ALIGNED (TEXT_OFFSET ,THREAD_SIZE ));BUILD_BUG_ON (!IS_ALIGNED (__NO_KASLR_START_KERNEL,THREAD_SIZE ));BUILD_BUG_ON (__NO_KASLR_END_KERNEL > _REGION1_SIZE); vsize =get_vmem_size (ident_map_size, vmemmap_size, vmalloc_size, _REGION3_SIZE);
@@ -378,31 +378,25 @@ static void kaslr_adjust_vmlinux_info(long offset)#endif } -static void fixup_vmlinux_info (void ) -{ - vmlinux.entry -= __START_KERNEL; -kaslr_adjust_vmlinux_info (-__START_KERNEL); -} -void startup_kernel (void ) { -unsigned long kernel_size = vmlinux.image_size + vmlinux.bss_size; -unsigned long nokaslr_offset_phys, kaslr_large_page_offset; -unsigned long amode31_lma =0 ; +unsigned long vmlinux_size = vmlinux.image_size + vmlinux.bss_size; +unsigned long nokaslr_text_lma, text_lma =0 , amode31_lma =0 ; +unsigned long kernel_size =TEXT_OFFSET + vmlinux_size; +unsigned long kaslr_large_page_offset;unsigned long max_physmem_end;unsigned long asce_limit;unsigned long safe_addr;psw_t psw; -fixup_vmlinux_info ();setup_lpp ();/* * Non-randomized kernel physical start address must be _SEGMENT_SIZE * aligned (see blow). */ - nokaslr_offset_phys =ALIGN (mem_safe_offset (), _SEGMENT_SIZE); - safe_addr =PAGE_ALIGN (nokaslr_offset_phys + kernel_size); + nokaslr_text_lma =ALIGN (mem_safe_offset (), _SEGMENT_SIZE); + safe_addr =PAGE_ALIGN (nokaslr_text_lma + vmlinux_size);/* * Reserve decompressor memory together with decompression heap,
@@ -446,16 +440,27 @@ void startup_kernel(void)*/ kaslr_large_page_offset = __kaslr_offset & ~_SEGMENT_MASK;if (kaslr_enabled ()) { -unsigned long size = kernel_size + kaslr_large_page_offset; +unsigned long size = vmlinux_size + kaslr_large_page_offset; - __kaslr_offset_phys =randomize_within_range (size, _SEGMENT_SIZE,0 , ident_map_size); + text_lma =randomize_within_range (size, _SEGMENT_SIZE,TEXT_OFFSET , ident_map_size); } -if (!__kaslr_offset_phys) - __kaslr_offset_phys = nokaslr_offset_phys; - __kaslr_offset_phys |= kaslr_large_page_offset; +if (!text_lma) + text_lma = nokaslr_text_lma; + text_lma |= kaslr_large_page_offset; + +/* +* [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region is +* never accessed via the kernel image mapping as per the linker script: +* +* . = TEXT_OFFSET; +* +* Therefore, this region could be used for something else and does +* not need to be reserved. See how it is skipped in setup_vmem(). +*/ + __kaslr_offset_phys = text_lma -TEXT_OFFSET ;kaslr_adjust_vmlinux_info (__kaslr_offset_phys); -physmem_reserve (RR_VMLINUX , __kaslr_offset_phys, kernel_size); -deploy_kernel ((void *)__kaslr_offset_phys); +physmem_reserve (RR_VMLINUX , text_lma, vmlinux_size); +deploy_kernel ((void *)text_lma);/* vmlinux decompression is done, shrink reserved low memory */ physmem_reserve (RR_DECOMPRESSOR ,0 , (unsigned long )_decompressor_end);
@@ -474,7 +479,7 @@ void startup_kernel(void)if (kaslr_enabled ()) amode31_lma =randomize_within_range (vmlinux.amode31_size,PAGE_SIZE ,0 ,SZ_2G );if (!amode31_lma) - amode31_lma = __kaslr_offset_phys - vmlinux.amode31_size; + amode31_lma = text_lma - vmlinux.amode31_size;physmem_reserve (RR_AMODE31 , amode31_lma, vmlinux.amode31_size);/*
@@ -490,8 +495,8 @@ void startup_kernel(void)* - copy_bootdata() must follow setup_vmem() to propagate changes * to bootdata made by setup_vmem() */ -clear_bss_section (__kaslr_offset_phys); -kaslr_adjust_relocs (__kaslr_offset_phys, __kaslr_offset_phys + vmlinux.image_size, +clear_bss_section (text_lma); +kaslr_adjust_relocs (text_lma, text_lma + vmlinux.image_size, __kaslr_offset, __kaslr_offset_phys);kaslr_adjust_got (__kaslr_offset);setup_vmem (__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
arch/s390/boot/vmem.c +12 -2
@@ -89,7 +89,7 @@ static void kasan_populate_shadow(unsigned long kernel_start, unsigned long kern } memgap_start = end; } -kasan_populate (kernel_start, kernel_end,POPULATE_KASAN_MAP_SHADOW ); +kasan_populate (kernel_start +TEXT_OFFSET , kernel_end,POPULATE_KASAN_MAP_SHADOW );kasan_populate (0 , (unsigned long )__identity_va (0 ),POPULATE_KASAN_ZERO_SHADOW );kasan_populate (AMODE31_START ,AMODE31_END ,POPULATE_KASAN_ZERO_SHADOW );if (IS_ENABLED (CONFIG_KASAN_VMALLOC )) {
@@ -466,7 +466,17 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l (unsigned long )__identity_va (end), POPULATE_IDENTITY); } -pgtable_populate (kernel_start, kernel_end,POPULATE_KERNEL ); + +/* +* [kernel_start..kernel_start + TEXT_OFFSET] region is never +* accessed as per the linker script: +* +* . = TEXT_OFFSET; +* +* Therefore, skip mapping TEXT_OFFSET bytes to prevent access to +* [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region. +*/ +pgtable_populate (kernel_start +TEXT_OFFSET , kernel_end,POPULATE_KERNEL );pgtable_populate (AMODE31_START ,AMODE31_END ,POPULATE_DIRECT );pgtable_populate (__abs_lowcore, __abs_lowcore +sizeof (struct lowcore ),POPULATE_ABS_LOWCORE );
arch/s390/boot/vmlinux.lds.S +6 -1
@@ -109,7 +109,12 @@ SECTIONS #ifdef CONFIG_KERNEL_UNCOMPRESSED . = ALIGN(PAGE_SIZE); . += AMODE31_SIZE; /* .amode31 section */ - . = ALIGN(1 << 20); /* _SEGMENT_SIZE */ + + /* + * Make sure the location counter is not less than TEXT_OFFSET. + * _SEGMENT_SIZE is not available, use ALIGN(1 << 20) instead. + */ + . = MAX(TEXT_OFFSET, ALIGN(1 << 20)); #else . = ALIGN(8); #endif
arch/s390/include/asm/page.h +2 -1
@@ -276,8 +276,9 @@ static inline unsigned long virt_to_pfn(const void *kaddr)#define AMODE31_SIZE (3 * PAGE_SIZE)#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) -#define __START_KERNEL 0x100000#define __NO_KASLR_START_KERNEL CONFIG_KERNEL_IMAGE_BASE#define __NO_KASLR_END_KERNEL (__NO_KASLR_START_KERNEL + KERNEL_IMAGE_SIZE) +#define TEXT_OFFSET 0x100000 +#endif /* _S390_PAGE_H */
arch/s390/kernel/vmlinux.lds.S +1 -1
@@ -39,7 +39,7 @@ PHDRS { SECTIONS { - . = __START_KERNEL; + . = TEXT_OFFSET; .text : { _stext = .; /* Start of text section */ _text = .; /* Text and read-only data */
arch/s390/tools/relocs.c +1 -1
@@ -280,7 +280,7 @@ static int do_reloc(struct section *sec, Elf_Rel *rel)case R_390_GOTOFF64 :break ;case R_390_64 : -add_reloc (&relocs64, offset - ehdr.e_entry); +add_reloc (&relocs64, offset);break ;default :die ("Unsupported relocation type: %d\n" , r_type);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 221/273 smb: client: ignore unhandled reparse tags
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
[ Upstream commit ec686804117a0421cf31d54427768aaf93aa0069 ]
Just ignore reparse points that the client can't parse rather than bailing out and not opening the file or directory.
--- fs/smb/client/reparse.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
fs/smb/client/reparse.c +7 -4
@@ -378,6 +378,8 @@ int parse_reparse_point(struct reparse_data_buffer *buf, u32 plen, struct cifs_sb_info *cifs_sb, bool unicode, struct cifs_open_info_data *data) { + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); + data->reparse.buf = buf;/* See MS-FSCC 2.1.2 */
@@ -394,12 +396,13 @@ int parse_reparse_point(struct reparse_data_buffer *buf,case IO_REPARSE_TAG_LX_FIFO :case IO_REPARSE_TAG_LX_CHR :case IO_REPARSE_TAG_LX_BLK : -return 0 ; +break ;default : -cifs_dbg (VFS ,"%s: unhandled reparse tag: 0x%08x\n" , - __func__,le32_to_cpu (buf->ReparseTag)); -return -EOPNOTSUPP ; +cifs_tcon_dbg (VFS |ONCE ,"unhandled reparse tag: 0x%08x\n" , +le32_to_cpu (buf->ReparseTag)); +break ; } +return 0 ; } int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 222/273 nvme: move stopping keep-alive into nvme_uninit_ctrl()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
[ Upstream commit a54a93d0e3599b05856971734e15418ac551a14c ]
Commit 4733b65d82bd ("nvme: start keep-alive after admin queue setup") moves starting keep-alive from nvme_start_ctrl() into nvme_init_ctrl_finish(), but don't move stopping keep-alive into nvme_uninit_ctrl(), so keep-alive work can be started and keep pending after failing to start controller, finally use-after-free is triggered if nvme host driver is unloaded.
This patch fixes kernel panic when running nvme/004 in case that connection failure is triggered, by moving stopping keep-alive into nvme_uninit_ctrl().
This way is reasonable because keep-alive is now started in nvme_init_ctrl_finish().
--- drivers/nvme/host/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/core.c +1 -1
@@ -4522,7 +4522,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl) {nvme_mpath_stop (ctrl);nvme_auth_stop (ctrl); -nvme_stop_keep_alive (ctrl);nvme_stop_failfast_work (ctrl);flush_work (&ctrl->async_event_work);cancel_work_sync (&ctrl->fw_act_work);
@@ -4558,6 +4557,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl);void nvme_uninit_ctrl (struct nvme_ctrl *ctrl) { +nvme_stop_keep_alive (ctrl);nvme_hwmon_exit (ctrl);nvme_fault_inject_fini (&ctrl->fault_inject);dev_pm_qos_hide_latency_tolerance (ctrl->device);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 223/273 Bluetooth: MGMT: Add error handling to pair_device()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit 538fd3921afac97158d4177139a0ad39f056dbb2 upstream.
hci_conn_params_add() never checks for a NULL value and could lead to a NULL pointer dereference causing a crash.
Fixed by adding error handling in the function.
--- net/bluetooth/mgmt.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/mgmt.c +4 -0
@@ -3457,6 +3457,10 @@ static int pair_device(struct sock *sk,* will be kept and this function does nothing. */ p =hci_conn_params_add (hdev, &cp->addr.bdaddr, addr_type); +if (!p) { + err = -EIO ; + goto unlock; + }if (p->auto_connect ==HCI_AUTO_CONN_EXPLICIT ) p->auto_connect =HCI_AUTO_CONN_DISABLED ;
Greg Kroah-Hartman
maintainerPATCH 224/273 scsi: core: Fix the return value of scsi_logical_block_count()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chaotian Jing <[email protected]>
commit f03e94f23b04c2b71c0044c1534921b3975ef10c upstream.
scsi_logical_block_count() should return the block count of a given SCSI command. The original implementation ended up shifting twice, leading to an incorrect count being returned. Fix the conversion between bytes and logical blocks.
--- include/scsi/scsi_cmnd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/scsi/scsi_cmnd.h +1 -1
@@ -234,7 +234,7 @@ static inline sector_t scsi_get_lba(strustatic inline unsigned int scsi_logical_block_count (struct scsi_cmnd *scmd) { -unsigned int shift =ilog2 (scmd->device->sector_size) -SECTOR_SHIFT ; +unsigned int shift =ilog2 (scmd->device->sector_size);return blk_rq_bytes (scsi_cmd_to_rq (scmd)) >> shift; }
Greg Kroah-Hartman
maintainerPATCH 225/273 ksmbd: the buffer of smb2 query dir response has at least 1 byte
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
commit ce61b605a00502c59311d0a4b1f58d62b48272d0 upstream.
When STATUS_NO_MORE_FILES status is set to smb2 query dir response, ->StructureSize is set to 9, which mean buffer has 1 byte. This issue occurs because ->Buffer[1] in smb2_query_directory_rsp to flex-array.
--- fs/smb/server/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/smb/server/smb2pdu.c +2 -1
@@ -4406,7 +4406,8 @@ int smb2_query_dir(struct ksmbd_work *wo rsp->OutputBufferLength =cpu_to_le32 (0 ); rsp->Buffer[0 ] =0 ; rc =ksmbd_iov_pin_rsp (work, (void *)rsp, -sizeof (struct smb2_query_directory_rsp )); + offsetof(struct smb2_query_directory_rsp , Buffer) + +1 );if (rc) goto err_out; }else {
Greg Kroah-Hartman
maintainerPATCH 226/273 drm/amdgpu: Validate TA binary size
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Candice Li <[email protected]>
commit c99769bceab4ecb6a067b9af11f9db281eea3e2a upstream.
Add TA binary size validation to avoid OOB write.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +3 -0
@@ -166,6 +166,9 @@ static ssize_t ta_if_load_debugfs_write(if (ret)return -EFAULT ; +if (ta_bin_len >PSP_1_MEG ) +return -EINVAL ; + copy_pos +=sizeof (uint32_t ); ta_bin =kzalloc (ta_bin_len,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 227/273 drm/amdgpu/sdma5.2: limit wptr workaround to sdma 5.2.1
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit e3e4bf58bad1576ac732a1429f53e3d4bfb82b4b upstream.
The workaround seems to cause stability issues on other SDMA 5.2.x IPs.
--- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +10 -8
@@ -176,14 +176,16 @@ static void sdma_v5_2_ring_set_wptr(struDRM_DEBUG ("calling WDOORBELL64(0x%08x, 0x%016llx)\n" , ring->doorbell_index, ring->wptr <<2 );WDOORBELL64 (ring->doorbell_index, ring->wptr <<2 ); -/* SDMA seems to miss doorbells sometimes when powergating kicks in. -* Updating the wptr directly will wake it. This is only safe because -* we disallow gfxoff in begin_use() and then allow it again in end_use(). -*/ -WREG32 (sdma_v5_2_get_reg_offset (adev, ring->me, mmSDMA0_GFX_RB_WPTR), -lower_32_bits (ring->wptr <<2 )); -WREG32 (sdma_v5_2_get_reg_offset (adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI), -upper_32_bits (ring->wptr <<2 )); +if (amdgpu_ip_version (adev,SDMA0_HWIP ,0 ) ==IP_VERSION (5 ,2 ,1 )) { +/* SDMA seems to miss doorbells sometimes when powergating kicks in. +* Updating the wptr directly will wake it. This is only safe because +* we disallow gfxoff in begin_use() and then allow it again in end_use(). +*/ +WREG32 (sdma_v5_2_get_reg_offset (adev, ring->me, mmSDMA0_GFX_RB_WPTR), +lower_32_bits (ring->wptr <<2 )); +WREG32 (sdma_v5_2_get_reg_offset (adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI), +upper_32_bits (ring->wptr <<2 )); + } }else {DRM_DEBUG ("Not using doorbell -- " "mmSDMA%i_GFX_RB_WPTR == 0x%08x "
Greg Kroah-Hartman
maintainerPATCH 228/273 ACPI: video: Add Dell UART backlight controller detection
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit cd8e468efb4fb2742e06328a75b282c35c1abf8d upstream.
Dell All In One (AIO) models released after 2017 use a backlight controller board connected to an UART.
In DSDT this uart port will be defined as:
Name (_HID, "DELL0501")
Name (_CID, EisaId ("PNP0501")
Commit 484bae9e4d6a ("platform/x86: Add new Dell UART backlight driver") has added support for this, but I neglected to tie this into acpi_video_get_backlight_type().
Now the first AIO has turned up which has not only the DSDT bits for this, but also an actual controller attached to the UART, yet it is not using this controller for backlight control.
Add support to acpi_video_get_backlight_type() for a new dell_uart backlight type. So that the existing infra to override the backlight control method on the commandline or with DMI quirks can be used.
--- drivers/acpi/video_detect.c | 7 +++++++ include/acpi/video.h | 1 + 2 files changed, 8 insertions(+)
drivers/acpi/video_detect.c +7 -0
@@ -54,6 +54,8 @@ static void acpi_video_parse_cmdline(voi acpi_backlight_cmdline = acpi_backlight_nvidia_wmi_ec;if (!strcmp ("apple_gmux" , acpi_video_backlight_string)) acpi_backlight_cmdline = acpi_backlight_apple_gmux; +if (!strcmp ("dell_uart" , acpi_video_backlight_string)) + acpi_backlight_cmdline = acpi_backlight_dell_uart;if (!strcmp ("none" , acpi_video_backlight_string)) acpi_backlight_cmdline = acpi_backlight_none; }
@@ -902,6 +904,7 @@ enum acpi_backlight_type __acpi_video_gestatic DEFINE_MUTEX (init_mutex);static bool nvidia_wmi_ec_present;static bool apple_gmux_present; +static bool dell_uart_present;static bool native_available;static bool init_done;static long video_caps;
@@ -916,6 +919,7 @@ enum acpi_backlight_type __acpi_video_ge &video_caps, NULL); nvidia_wmi_ec_present =nvidia_wmi_ec_supported (); apple_gmux_present =apple_gmux_detect (NULL ,NULL ); + dell_uart_present =acpi_dev_present ("DELL0501" ,NULL ,-1 ); init_done = true; }if (native)
@@ -946,6 +950,9 @@ enum acpi_backlight_type __acpi_video_geif (apple_gmux_present)return acpi_backlight_apple_gmux; +if (dell_uart_present) +return acpi_backlight_dell_uart; +/* Use ACPI video if available, except when native should be preferred. */ if ((video_caps &ACPI_VIDEO_BACKLIGHT ) && !(native_available &&prefer_native_over_acpi_video ()))
include/acpi/video.h +1 -0
@@ -50,6 +50,7 @@ enum acpi_backlight_type { acpi_backlight_native, acpi_backlight_nvidia_wmi_ec, acpi_backlight_apple_gmux, + acpi_backlight_dell_uart, };#if IS_ENABLED (CONFIG_ACPI_VIDEO )
Greg Kroah-Hartman
maintainerPATCH 229/273 ACPI: video: Add backlight=native quirk for Dell OptiPlex 7760 AIO
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit 5c7bb62cb8f53de71d8ab3d619be22740da0b837 upstream.
Dell All In One (AIO) models released after 2017 may use a backlight controller board connected to an UART.
In DSDT this uart port will be defined as:
Name (_HID, "DELL0501")
Name (_CID, EisaId ("PNP0501")
The Dell OptiPlex 7760 AIO has an ACPI device for one if its UARTs with the above _HID + _CID. Loading the dell-uart-backlight driver shows that there actually is a backlight controller board attached to the UART, which reports a firmware version of "G&MX01-V15".
But the backlight controller board does not actually control the backlight brightness and the GPU's native backlight control method does work.
Add a quirk to use the GPU's native backlight control method on this model.
--- drivers/acpi/video_detect.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/acpi/video_detect.c +15 -0
@@ -808,6 +808,21 @@ static const struct dmi_system_id video_ },/* +* Dell AIO (All in Ones) which advertise an UART attached backlight +* controller board in their ACPI tables (and may even have one), but +* which need native backlight control nevertheless. +*/ + { + /* https://bugzilla.redhat.com/show_bug.cgi?id=2303936 */ + .callback = video_detect_force_native, + /* Dell OptiPlex 7760 AIO */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 7760 AIO"), + }, + }, + + /* * Models which have nvidia-ec-wmi support, but should not use it. * Note this indicates a likely firmware bug on these models and should * be revisited if/when Linux gets support for dynamic mux mode.
Greg Kroah-Hartman
maintainerPATCH 230/273 platform/x86: dell-uart-backlight: Use acpi_video_get_backlight_type()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
commit b5f0943001339c4d324a1af10470ce0bdd79f966 upstream.
The dell-uart-backlight driver supports backlight control on Dell All In One (AIO) models using a backlight controller board connected to an UART.
In DSDT this uart port will be defined as:
Name (_HID, "DELL0501")
Name (_CID, EisaId ("PNP0501")
Now the first AIO has turned up which has not only the DSDT bits for this, but also an actual controller attached to the UART, yet it is not using this controller for backlight control.
Use the acpi_video_get_backlight_type() function from the ACPI video-detect code to check if the dell-uart-backlight driver should actually be used. This allows reusing the existing ACPI video-detect infra to override the backlight control method on the commandline or with DMI quirks.
--- drivers/platform/x86/dell/Kconfig | 1 + drivers/platform/x86/dell/dell-uart-backlight.c | 8 ++++++++ 2 files changed, 9 insertions(+)
drivers/platform/x86/dell/Kconfig +1 -0
@@ -148,6 +148,7 @@ config DELL_SMO8800 config DELL_UART_BACKLIGHT tristate "Dell AIO UART Backlight driver" depends on ACPI + depends on ACPI_VIDEO depends on BACKLIGHT_CLASS_DEVICE depends on SERIAL_DEV_BUS help
drivers/platform/x86/dell/dell-uart-backlight.c +8 -0
@@ -20,6 +20,7 @@#include <linux/string.h> #include <linux/types.h> #include <linux/wait.h> +#include <acpi/video.h> #include "../serdev_helpers.h" /* The backlight controller must respond within 1 second */
@@ -332,10 +333,17 @@ struct serdev_device_driver dell_uart_blstatic int dell_uart_bl_pdev_probe (struct platform_device *pdev) { +enum acpi_backlight_type bl_type;struct serdev_device *serdev;struct device *ctrl_dev;int ret; + bl_type =acpi_video_get_backlight_type (); +if (bl_type != acpi_backlight_dell_uart) { +dev_dbg (&pdev->dev,"Not loading (ACPI backlight type = %d)\n" , bl_type); +return -ENODEV ; + } + ctrl_dev =get_serdev_controller ("DELL0501" ,NULL ,0 ,"serial0" );if (IS_ERR (ctrl_dev))return PTR_ERR (ctrl_dev);
Greg Kroah-Hartman
maintainerPATCH 231/273 platform/x86: ISST: Fix return value on last invalid resource
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Pandruvada <[email protected]>
commit 46ee21e9f59205e54943dfe51b2dc8a9352ca37d upstream.
When only the last resource is invalid, tpmi_sst_dev_add() is returing error even if there are other valid resources before. This function should return error when there are no valid resources.
Here tpmi_sst_dev_add() is returning "ret" variable. But this "ret" variable contains the failure status of last call to sst_main(), which failed for the invalid resource. But there may be other valid resources before the last entry.
To address this, do not update "ret" variable for sst_main() return status.
If there are no valid resources, it is already checked for by !inst below the loop and -ENODEV is returned.
--- drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +1 -2
@@ -1549,8 +1549,7 @@ int tpmi_sst_dev_add(struct auxiliary_de goto unlock_free; } - ret =sst_main (auxdev, &pd_info[i]); -if (ret) { +if (sst_main (auxdev, &pd_info[i])) {/* * This entry is not valid, hardware can partially * populate dies. In this case MMIO will have 0xFFs.
Greg Kroah-Hartman
maintainerPATCH 232/273 s390/ap: Refine AP bus bindings complete processing
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harald Freudenberger <[email protected]>
commit b4f5bd60d558f6ba451d7e76aa05782c07a182a3 upstream.
With the rework of the AP bus scan and the introduction of a bindings complete completion also the timing until the userspace finally receives a AP bus binding complete uevent had increased. Unfortunately this event triggers some important jobs for preparation of KVM guests, for example the modification of card/queue masks to reassign AP resources to the alternate AP queue device driver (vfio_ap) which is the precondition for building mediated devices which may be a precondition for starting KVM guests using AP resources.
This small fix now triggers the check for binding complete each time an AP device driver has registered. With this patch the bindings complete may be posted up to 30s earlier as there is no need to wait for the next AP bus scan any more.
--- drivers/s390/crypto/ap_bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/s390/crypto/ap_bus.c +6 -1
@@ -971,11 +971,16 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, char *name) {struct device_driver *drv = &ap_drv->driver; +int rc; drv->bus = &ap_bus_type; drv->owner = owner; drv->name = name; -return driver_register (drv); + rc =driver_register (drv); + +ap_check_bindings_complete (); + +return rc; }EXPORT_SYMBOL (ap_driver_register);
Signature · 1 line
2.46.0
Greg Kroah-Hartman
maintainerPATCH 233/273 net: ngbe: Fix phy mode set to external phy
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mengyuan Lou <[email protected]>
commit f2916c83d746eb99f50f42c15cf4c47c2ea5f3b3 upstream.
The MAC only has add the TX delay and it can not be modified. MAC and PHY are both set the TX delay cause transmission problems. So just disable TX delay in PHY, when use rgmii to attach to external phy, set PHY_INTERFACE_MODE_RGMII_RXID to phy drivers. And it is does not matter to internal phy.
--- drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +6 -2
@@ -124,8 +124,12 @@ static int ngbe_phylink_init(struct wx *MAC_SYM_PAUSE |MAC_ASYM_PAUSE ; config->mac_managed_pm = true; - phy_mode =PHY_INTERFACE_MODE_RGMII_ID ; -__set_bit (PHY_INTERFACE_MODE_RGMII_ID , config->supported_interfaces); +/* The MAC only has add the Tx delay and it can not be modified. +* So just disable TX delay in PHY, and it is does not matter to +* internal phy. +*/ + phy_mode =PHY_INTERFACE_MODE_RGMII_RXID ; +__set_bit (PHY_INTERFACE_MODE_RGMII_RXID , config->supported_interfaces); phylink =phylink_create (config,NULL , phy_mode, &ngbe_mac_ops);if (IS_ERR (phylink))
Greg Kroah-Hartman
maintainerPATCH 234/273 net: dsa: microchip: fix PTP config failure when using multiple ports
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Whitaker <[email protected]>
commit 6efea5135417ae8194485d1d05ea79a21cf1a11c upstream.
When performing the port_hwtstamp_set operation, ptp_schedule_worker() will be called if hardware timestamoing is enabled on any of the ports. When using multiple ports for PTP, port_hwtstamp_set is executed for each port. When called for the first time ptp_schedule_worker() returns
0. On subsequent calls it returns 1, indicating the worker is already scheduled. Currently the ksz driver treats 1 as an error and fails to complete the port_hwtstamp_set operation, thus leaving the timestamping configuration for those ports unchanged.
This patch fixes this by ignoring the ptp_schedule_worker() return value.
--- drivers/net/dsa/microchip/ksz_ptp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/net/dsa/microchip/ksz_ptp.c +1 -4
@@ -266,7 +266,6 @@ static int ksz_ptp_enable_mode(struct ksstruct ksz_port *prt;struct dsa_port *dp;bool tag_en = false; -int ret;dsa_switch_for_each_user_port (dp, dev->ds) { prt = &dev->ports[dp->index];
@@ -277,9 +276,7 @@ static int ksz_ptp_enable_mode(struct ks }if (tag_en) { - ret =ptp_schedule_worker (ptp_data->clock,0 ); -if (ret) -return ret; +ptp_schedule_worker (ptp_data->clock,0 ); }else {ptp_cancel_worker_sync (ptp_data->clock); }
Greg Kroah-Hartman
maintainerPATCH 235/273 MIPS: Loongson64: Set timer mode in cpu-probe
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiaxun Yang <[email protected]>
commit 1cb6ab446424649f03c82334634360c2e3043684 upstream.
Loongson64 C and G processors have EXTIMER feature which is conflicting with CP0 counter.
Although the processor resets in EXTIMER disabled & INTIMER enabled mode, which is compatible with MIPS CP0 compare, firmware may attempt to enable EXTIMER and interfere CP0 compare.
Set timer mode back to MIPS compatible mode to fix booting on systems with such firmware before we have an actual driver for EXTIMER.
--- arch/mips/kernel/cpu-probe.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/mips/kernel/cpu-probe.c +4 -0
@@ -1724,12 +1724,16 @@ static inline void cpu_probe_loongson(st c->ases |= (MIPS_ASE_LOONGSON_MMI |MIPS_ASE_LOONGSON_CAM |MIPS_ASE_LOONGSON_EXT |MIPS_ASE_LOONGSON_EXT2 ); c->ases &= ~MIPS_ASE_VZ ;/* VZ of Loongson-3A2000/3000 is incomplete */ +change_c0_config6 (LOONGSON_CONF6_EXTIMER |LOONGSON_CONF6_INTIMER , +LOONGSON_CONF6_INTIMER );break ;case PRID_IMP_LOONGSON_64G : __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );decode_cpucfg (c); +change_c0_config6 (LOONGSON_CONF6_EXTIMER |LOONGSON_CONF6_INTIMER , +LOONGSON_CONF6_INTIMER );break ;default :panic ("Unknown Loongson Processor ID!" );
Greg Kroah-Hartman
maintainerPATCH 236/273 HID: wacom: Defer calculation of resolution until resolution_code is known
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gerecke <[email protected]>
commit 1b8f9c1fb464968a5b18d3acc1da8c00bad24fad upstream.
The Wacom driver maps the HID_DG_TWIST usage to ABS_Z (rather than ABS_RZ) for historic reasons. When the code to support twist was introduced in commit 50066a042da5 ("HID: wacom: generic: Add support for height, tilt, and twist usages"), we were careful to write it in such a way that it had HID calculate the resolution of the twist axis assuming ABS_RZ instead (so that we would get correct angular behavior). This was broken with the introduction of commit 08a46b4190d3 ("HID: wacom: Set a default resolution for older tablets"), which moved the resolution calculation to occur *before* the adjustment from ABS_Z to ABS_RZ occurred.
This commit moves the calculation of resolution after the point that we are finished setting things up for its proper use.
--- drivers/hid/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +3 -1
@@ -1924,12 +1924,14 @@ static void wacom_map_usage(struct inputint fmax = field->logical_maximum;unsigned int equivalent_usage =wacom_equivalent_usage (usage->hid);int resolution_code = code; -int resolution =hidinput_calc_abs_res (field, resolution_code); +int resolution;if (equivalent_usage ==HID_DG_TWIST ) { resolution_code =ABS_RZ ; } + resolution =hidinput_calc_abs_res (field, resolution_code); +if (equivalent_usage ==HID_GD_X ) { fmin += features->offset_left; fmax -= features->offset_right;
Greg Kroah-Hartman
maintainerPATCH 237/273 iommufd/device: Fix hwpt at err_unresv in iommufd_device_do_replace()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen <[email protected]>
commit 950aeefb34923fe3c28ade35fe05f24e2c5b1d55 upstream.
The rewind routine should remove the reserved iovas added to the new hwpt.
--- drivers/iommu/iommufd/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/iommufd/device.c +1 -1
@@ -525,7 +525,7 @@ iommufd_device_do_replace(struct iommufd err_unresv:if (hwpt_is_paging (hwpt))iommufd_group_remove_reserved_iova (igroup, -to_hwpt_paging (old_hwpt)); +to_hwpt_paging (hwpt)); err_unlock:mutex_unlock (&idev->igroup->lock);return ERR_PTR (rc);
Greg Kroah-Hartman
maintainerPATCH 238/273 Input: i8042 - add forcenorestore quirk to leave controller untouched even on s3
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Werner Sembach <[email protected]>
commit 3d765ae2daccc570b3f4fbcb57eb321b12cdded2 upstream.
On s3 resume the i8042 driver tries to restore the controller to a known state by reinitializing things, however this can confuse the controller with different effects. Mostly occasionally unresponsive keyboards after resume.
These issues do not rise on s0ix resume as here the controller is assumed to preserved its state from before suspend.
This patch adds a quirk for devices where the reinitialization on s3 resume is not needed and might be harmful as described above. It does this by using the s0ix resume code path at selected locations.
This new quirk goes beyond what the preexisting reset=never quirk does, which only skips some reinitialization steps.
--- drivers/input/serio/i8042-acpipnpio.h | 10 +++++++--- drivers/input/serio/i8042.c | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-)
drivers/input/serio/i8042-acpipnpio.h +7 -3
@@ -83,6 +83,7 @@ static inline void i8042_write_command(i#define SERIO_QUIRK_KBDRESET BIT(12)#define SERIO_QUIRK_DRITEK BIT(13)#define SERIO_QUIRK_NOPNP BIT(14) +#define SERIO_QUIRK_FORCENORESTORE BIT(15)/* Quirk table for different mainboards. Options similar or identical to i8042 * module parameters.
@@ -1685,6 +1686,8 @@ static void __init i8042_check_quirks(voif (quirks &SERIO_QUIRK_NOPNP ) i8042_nopnp = true;#endif +if (quirks &SERIO_QUIRK_FORCENORESTORE ) + i8042_forcenorestore = true; }#else static inline void i8042_check_quirks (void ) {}
@@ -1718,7 +1721,7 @@ static int __init i8042_platform_init(voi8042_check_quirks (); - pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", i8042_nokbd ? " nokbd" : "", i8042_noaux ? " noaux" : "", i8042_nomux ? " nomux" : "",
@@ -1738,10 +1741,11 @@ static int __init i8042_platform_init(vo "",#endif #ifdef CONFIG_PNP - i8042_nopnp ? " nopnp" : ""); + i8042_nopnp ?" nopnp" :"" , #else - ""); +"" , #endif + i8042_forcenorestore ? " forcenorestore" : ""); retval =i8042_pnp_init ();if (retval)
drivers/input/serio/i8042.c +7 -3
@@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bMODULE_PARM_DESC (nopnp,"Do not use PNP to detect controller settings" );#endif +static bool i8042_forcenorestore; +module_param_named (forcenorestore, i8042_forcenorestore, bool,0 ); +MODULE_PARM_DESC (forcenorestore,"Force no restore on s3 resume, copying s2idle behaviour" ); +#define DEBUG #ifdef DEBUG static bool i8042_debug;
@@ -1232,7 +1236,7 @@ static int i8042_pm_suspend(struct devic {int i; -if (pm_suspend_via_firmware ()) +if (!i8042_forcenorestore &&pm_suspend_via_firmware ())i8042_controller_reset (true);/* Set up serio interrupts for system wakeup. */
@@ -1248,7 +1252,7 @@ static int i8042_pm_suspend(struct devicstatic int i8042_pm_resume_noirq (struct device *dev) { -if (!pm_resume_via_firmware ()) +if (i8042_forcenorestore || !pm_resume_via_firmware ())i8042_interrupt (0 ,NULL );return 0 ;
@@ -1271,7 +1275,7 @@ static int i8042_pm_resume(struct device* not restore the controller state to whatever it had been at boot * time, so we do not need to do anything. */ -if (!pm_suspend_via_firmware ()) +if (i8042_forcenorestore || !pm_suspend_via_firmware ())return 0 ;/*
Greg Kroah-Hartman
maintainerPATCH 239/273 Input: i8042 - use new forcenorestore quirk to replace old buggy quirk combination
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Werner Sembach <[email protected]>
commit aaa4ca873d3da768896ffc909795359a01e853ef upstream.
The old quirk combination sometimes cause a laggy keyboard after boot. With the new quirk the initial issue of an unresponsive keyboard after s3 resume is also fixed, but it doesn't have the negative side effect of the sometimes laggy keyboard.
--- drivers/input/serio/i8042-acpipnpio.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
drivers/input/serio/i8042-acpipnpio.h +1 -9
@@ -1150,18 +1150,10 @@ static const struct dmi_system_id i8042_ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) }, { -/* -* Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes -* the keyboard very laggy for ~5 seconds after boot and -* sometimes also after resume. -* However both are required for the keyboard to not fail -* completely sometimes after boot or resume. -*/ .matches = { DMI_MATCH(DMI_BOARD_NAME, "N150CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX |SERIO_QUIRK_RESET_ALWAYS | -SERIO_QUIRK_NOLOOP |SERIO_QUIRK_NOPNP ) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE ) }, { .matches = {
Greg Kroah-Hartman
maintainerPATCH 240/273 ata: pata_macio: Fix DMA table overflow
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Ellerman <[email protected]>
commit 822c8020aebcf5804a143b891e34f29873fee5e2 upstream.
Kolbjørn and Jonáš reported that their 32-bit PowerMacs were crashing in pata-macio since commit 09fe2bfa6b83 ("ata: pata_macio: Fix max_segment_size with PAGE_SIZE == 64K").
For example:
kernel BUG at drivers/ata/pata_macio.c:544!
Oops: Exception in kernel mode, sig: 5 [#1]
BE PAGE_SIZE=4K MMU=Hash SMP NR_CPUS=2 DEBUG_PAGEALLOC PowerMac
...
NIP pata_macio_qc_prep+0xf4/0x190
LR pata_macio_qc_prep+0xfc/0x190
Call Trace:
0xc1421660 (unreliable)
ata_qc_issue+0x14c/0x2d4
__ata_scsi_queuecmd+0x200/0x53c
ata_scsi_queuecmd+0x50/0xe0
scsi_queue_rq+0x788/0xb1c
__blk_mq_issue_directly+0x58/0xf4
blk_mq_plug_issue_direct+0x8c/0x1b4
blk_mq_flush_plug_list.part.0+0x584/0x5e0
__blk_flush_plug+0xf8/0x194
__submit_bio+0x1b8/0x2e0
submit_bio_noacct_nocheck+0x230/0x304
btrfs_work_helper+0x200/0x338
process_one_work+0x1a8/0x338
worker_thread+0x364/0x4c0
kthread+0x100/0x104
start_kernel_thread+0x10/0x14That commit increased max_segment_size to 64KB, with the justification that the SCSI core was already using that size when PAGE_SIZE == 64KB, and that there was existing logic to split over-sized requests.
However with a sufficiently large request, the splitting logic causes each sg to be split into two commands in the DMA table, leading to overflow of the DMA table, triggering the BUG_ON().
With default settings the bug doesn't trigger, because the request size is limited by max_sectors_kb == 1280, however max_sectors_kb can be increased, and apparently some distros do that by default using udev rules.
Fix the bug for 4KB kernels by reverting to the old max_segment_size.
For 64KB kernels the sg_tablesize needs to be halved, to allow for the possibility that each sg will be split into two.
--- drivers/ata/pata_macio.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/ata/pata_macio.c +15 -8
@@ -208,6 +208,19 @@ static const char* macio_ata_names[] = {/* Don't let a DMA segment go all the way to 64K */ #define MAX_DBDMA_SEG 0xff00 +#ifdef CONFIG_PAGE_SIZE_64KB +/* +* The SCSI core requires the segment size to cover at least a page, so +* for 64K page size kernels it must be at least 64K. However the +* hardware can't handle 64K, so pata_macio_qc_prep() will split large +* requests. To handle the split requests the tablesize must be halved. +*/ +#define PATA_MACIO_MAX_SEGMENT_SIZE SZ_64K +#define PATA_MACIO_SG_TABLESIZE (MAX_DCMDS / 2) +#else +#define PATA_MACIO_MAX_SEGMENT_SIZE MAX_DBDMA_SEG +#define PATA_MACIO_SG_TABLESIZE MAX_DCMDS +#endif /* * Wait 1s for disk to answer on IDE bus after a hard reset
@@ -912,16 +925,10 @@ static int pata_macio_do_resume(struct pata_macio_priv *priv)static const struct scsi_host_template pata_macio_sht = {__ATA_BASE_SHT (DRV_NAME ), - .sg_tablesize =MAX_DCMDS , + .sg_tablesize =PATA_MACIO_SG_TABLESIZE ,/* We may not need that strict one */ .dma_boundary =ATA_DMA_BOUNDARY , -/* -* The SCSI core requires the segment size to cover at least a page, so -* for 64K page size kernels this must be at least 64K. However the -* hardware can't handle 64K, so pata_macio_qc_prep() will split large -* requests. -*/ - .max_segment_size =SZ_64K , + .max_segment_size =PATA_MACIO_MAX_SEGMENT_SIZE , .device_configure = pata_macio_device_configure, .sdev_groups = ata_common_sdev_groups, .can_queue =ATA_DEF_QUEUE ,
Signature · 1 line
2.46.0
Greg Kroah-Hartman
maintainerPATCH 241/273 cxgb4: add forgotten u64 ivlan cast before shift
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Kuratov <[email protected]>
commit 80a1e7b83bb1834b5568a3872e64c05795d88f31 upstream.
It is done everywhere in cxgb4 code, e.g. in is_filter_exact_match() There is no reason it should not be done here
Found by Linux Verification Center (linuxtesting.org) with SVACE
--- drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +2 -1
@@ -1244,7 +1244,8 @@ static u64 hash_filter_ntuple(struct ch_* in the Compressed Filter Tuple. */ if (tp->vlan_shift >=0 && fs->mask.ivlan) - ntuple |= (FT_VLAN_VLD_F | fs->val.ivlan) << tp->vlan_shift; + ntuple |= (u64)(FT_VLAN_VLD_F | + fs->val.ivlan) << tp->vlan_shift;if (tp->port_shift >=0 && fs->mask.iport) ntuple |= (u64 )fs->val.iport << tp->port_shift;
Greg Kroah-Hartman
maintainerPATCH 242/273 KVM: arm64: vgic-debug: Dont put unmarked LPIs
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zenghui Yu <[email protected]>
commit 2240a50e6294214de791729e9dcba6880fa7e44e upstream.
If there were LPIs being mapped behind our back (i.e., between .start() and .stop()), we would put them at iter_unmark_lpis() without checking if they were actually *marked*, which is obviously not good.
Switch to use the xa_for_each_marked() iterator to fix it.
--- arch/arm64/kvm/vgic/vgic-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/vgic/vgic-debug.c +1 -1
@@ -84,7 +84,7 @@ static void iter_unmark_lpis(struct kvmstruct vgic_irq *irq;unsigned long intid; -xa_for_each (&dist->lpi_xa, intid, irq) { +xa_for_each_marked (&dist->lpi_xa, intid, irq,LPI_XA_MARK_DEBUG_ITER ) {xa_clear_mark (&dist->lpi_xa, intid,LPI_XA_MARK_DEBUG_ITER );vgic_put_irq (kvm, irq); }
Greg Kroah-Hartman
maintainerPATCH 243/273 KVM: arm64: Make ICC_*SGI*_EL1 undef in the absence of a vGICv3
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Zyngier <[email protected]>
commit 3e6245ebe7ef341639e9a7e402b3ade8ad45a19f upstream.
On a system with a GICv3, if a guest hasn't been configured with GICv3 and that the host is not capable of GICv2 emulation, a write to any of the ICC_*SGI*_EL1 registers is trapped to EL2.
We therefore try to emulate the SGI access, only to hit a NULL pointer as no private interrupt is allocated (no GIC, remember?).
The obvious fix is to give the guest what it deserves, in the shape of a UNDEF exception.
--- arch/arm64/kvm/sys_regs.c | 6 ++++++ arch/arm64/kvm/vgic/vgic.h | 7 +++++++ 2 files changed, 13 insertions(+)
arch/arm64/kvm/sys_regs.c +6 -0
@@ -33,6 +33,7 @@#include <trace/events/kvm.h> #include "sys_regs.h" +#include "vgic/vgic.h" #include "trace.h"
@@ -428,6 +429,11 @@ static bool access_gic_sgi(struct kvm_vc {bool g1; +if (!kvm_has_gicv3 (vcpu->kvm)) { +kvm_inject_undefined (vcpu); +return false; + } +if (!p->is_write)return read_from_write_only (vcpu, p, r);
arch/arm64/kvm/vgic/vgic.h +7 -0
@@ -346,4 +346,11 @@ void vgic_v4_configure_vsgis(struct kvmvoid vgic_v4_get_vlpi_state (struct vgic_irq *irq,bool *val);int vgic_v4_request_vpe_irq (struct kvm_vcpu *vcpu,int irq); +static inline bool kvm_has_gicv3 (struct kvm *kvm) +{ +return (static_branch_unlikely (&kvm_vgic_global_state.gicv3_cpuif) && +irqchip_in_kernel (kvm) && + kvm->arch.vgic.vgic_model ==KVM_DEV_TYPE_ARM_VGIC_V3 ); +} +#endif
Greg Kroah-Hartman
maintainerPATCH 244/273 cgroup/cpuset: fix panic caused by partcmd_update
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ridong <[email protected]>
commit 959ab6350add903e352890af53e86663739fcb9a upstream.
We find a bug as below:
BUG: unable to handle page fault for address: 00000003 PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 3 PID: 358 Comm: bash Tainted: G W I 6.6.0-10893-g60d6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/4 RIP: 0010:partition_sched_domains_locked+0x483/0x600 Code: 01 48 85 d2 74 0d 48 83 05 29 3f f8 03 01 f3 48 0f bc c2 89 c0 48 9 RSP: 0018:ffffc90000fdbc58 EFLAGS: 00000202 RAX: 0000000100000003 RBX: ffff888100b3dfa0 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 000000000002fe80 RBP: ffff888100b3dfb0 R08: 0000000000000001 R09: 0000000000000000 R10: ffffc90000fdbcb0 R11: 0000000000000004 R12: 0000000000000002 R13: ffff888100a92b48 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f44a5425740(0000) GS:ffff888237d80000(0000) knlGS:0000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000100030973 CR3: 000000010722c000 CR4: 00000000000006e0 Call Trace: <TASK> ? show_regs+0x8c/0xa0 ? __die_body+0x23/0xa0 ? __die+0x3a/0x50 ? page_fault_oops+0x1d2/0x5c0 ? partition_sched_domains_locked+0x483/0x600 ? search_module_extables+0x2a/0xb0 ? search_exception_tables+0x67/0x90 ? kernelmode_fixup_or_oops+0x144/0x1b0 ? __bad_area_nosemaphore+0x211/0x360 ? up_read+0x3b/0x50 ? bad_area_nosemaphore+0x1a/0x30 ? exc_page_fault+0x890/0xd90 ? __lock_acquire.constprop.0+0x24f/0x8d0 ? __lock_acquire.constprop.0+0x24f/0x8d0 ? asm_exc_page_fault+0x26/0x30 ? partition_sched_domains_locked+0x483/0x600 ? partition_sched_domains_locked+0xf0/0x600 rebuild_sched_domains_locked+0x806/0xdc0 update_partition_sd_lb+0x118/0x130 cpuset_write_resmask+0xffc/0x1420 cgroup_file_write+0xb2/0x290 kernfs_fop_write_iter+0x194/0x290 new_sync_write+0xeb/0x160 vfs_write+0x16f/0x1d0 ksys_write+0x81/0x180 __x64_sys_write+0x21/0x30 x64_sys_call+0x2f25/0x4630 do_syscall_64+0x44/0xb0 entry_SYSCALL_64_after_hwframe+0x78/0xe2 RIP: 0033:0x7f44a553c887
It can be reproduced with cammands:
cd /sys/fs/cgroup/
mkdir test
cd test/
echo +cpuset > ../cgroup.subtree_control
echo root > cpuset.cpus.partition
cat /sys/fs/cgroup/cpuset.cpus.effective
0-3
echo 0-3 > cpuset.cpus // taking away all cpus from root
This issue is caused by the incorrect rebuilding of scheduling domains. In this scenario, test/cpuset.cpus.partition should be an invalid root and should not trigger the rebuilding of scheduling domains. When calling update_parent_effective_cpumask with partcmd_update, if newmask is not null, it should recheck newmask whether there are cpus is available for parect/cs that has tasks.
--- kernel/cgroup/cpuset.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/cgroup/cpuset.c +2 -0
@@ -1940,6 +1940,8 @@ static int update_parent_effective_cpuma part_error =PERR_CPUSEMPTY ; goto write_error; } +/* Check newmask again, whether cpus are available for parent/cs */ + nocpu |=tasks_nocpu_error (parent, cs, newmask);/* * partcmd_update with newmask:
Greg Kroah-Hartman
maintainerPATCH 245/273 cgroup/cpuset: Clear effective_xcpus on cpus_allowed clearing only if cpus.exclusive not set
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long <[email protected]>
commit 311a1bdc44a8e06024df4fd3392be0dfc8298655 upstream.
Commit e2ffe502ba45 ("cgroup/cpuset: Add cpuset.cpus.exclusive for v2") adds a user writable cpuset.cpus.exclusive file for setting exclusive CPUs to be used for the creation of partitions. Since then effective_xcpus depends on both the cpuset.cpus and cpuset.cpus.exclusive setting. If cpuset.cpus.exclusive is set, effective_xcpus will depend only on cpuset.cpus.exclusive. When it is not set, effective_xcpus will be set according to the cpuset.cpus value when the cpuset becomes a valid partition root.
When cpuset.cpus is being cleared by the user, effective_xcpus should only be cleared when cpuset.cpus.exclusive is not set. However, that is not currently the case.
# cd /sys/fs/cgroup/ # mkdir test # echo +cpuset > cgroup.subtree_control # cd test # echo 3 > cpuset.cpus.exclusive # cat cpuset.cpus.exclusive.effective 3 # echo > cpuset.cpus # cat cpuset.cpus.exclusive.effective // was cleared
Fix it by clearing effective_xcpus only if cpuset.cpus.exclusive is not set.
--- kernel/cgroup/cpuset.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/cgroup/cpuset.c +2 -1
@@ -2474,7 +2474,8 @@ static int update_cpumask(struct cpuset*/ if (!*buf) {cpumask_clear (trialcs->cpus_allowed); -cpumask_clear (trialcs->effective_xcpus); +if (cpumask_empty (trialcs->exclusive_cpus)) +cpumask_clear (trialcs->effective_xcpus); }else { retval =cpulist_parse (buf, trialcs->cpus_allowed);if (retval <0 )
Greg Kroah-Hartman
maintainerPATCH 246/273 mmc: mtk-sd: receive cmd8 data when hs400 tuning fail
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mengqi Zhang <[email protected]>
commit 9374ae912dbb1eed8139ed75fd2c0f1b30ca454d upstream.
When we use cmd8 as the tuning command in hs400 mode, the command response sent back by some eMMC devices cannot be correctly sampled by MTK eMMC controller at some weak sample timing. In this case, command timeout error may occur. So we must receive the following data to make sure the next cmd8 send correctly.
--- drivers/mmc/host/mtk-sd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/mmc/host/mtk-sd.c +4 -4
@@ -1230,7 +1230,7 @@ static bool msdc_cmd_done(struct msdc_ho }if (!sbc_error && !(events &MSDC_INT_CMDRDY )) { -if (events &MSDC_INT_CMDTMO || +if ((events &MSDC_INT_CMDTMO && !host->hs400_tuning) || (!mmc_op_tuning (cmd->opcode) && !host->hs400_tuning))/* * should not clear fifo/interrupt as the tune data
@@ -1323,9 +1323,9 @@ static void msdc_start_command(struct msstatic void msdc_cmd_next (struct msdc_host *host,struct mmc_request *mrq,struct mmc_command *cmd) { -if ((cmd->error && - !(cmd->error == -EILSEQ && - (mmc_op_tuning (cmd->opcode) || host->hs400_tuning))) || +if ((cmd->error && !host->hs400_tuning && + !(cmd->error == -EILSEQ && +mmc_op_tuning (cmd->opcode))) || (mrq->sbc && mrq->sbc->error))msdc_request_done (host, mrq);else if (cmd == mrq->sbc)
Greg Kroah-Hartman
maintainerPATCH 247/273 mmc: dw_mmc: allow biu and ciu clocks to defer
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Whitten <[email protected]>
commit 6275c7bc8dd07644ea8142a1773d826800f0f3f7 upstream.
Fix a race condition if the clock provider comes up after mmc is probed, this causes mmc to fail without retrying.
When given the DEFER error from the clk source, pass it on up the chain.
--- drivers/mmc/host/dw_mmc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/mmc/host/dw_mmc.c +8 -0
@@ -3293,6 +3293,10 @@ int dw_mci_probe(struct dw_mci *host) host->biu_clk =devm_clk_get (host->dev,"biu" );if (IS_ERR (host->biu_clk)) {dev_dbg (host->dev,"biu clock not available\n" ); + ret =PTR_ERR (host->biu_clk); +if (ret == -EPROBE_DEFER ) +return ret; + }else { ret =clk_prepare_enable (host->biu_clk);if (ret) {
@@ -3304,6 +3308,10 @@ int dw_mci_probe(struct dw_mci *host) host->ciu_clk =devm_clk_get (host->dev,"ciu" );if (IS_ERR (host->ciu_clk)) {dev_dbg (host->dev,"ciu clock not available\n" ); + ret =PTR_ERR (host->ciu_clk); +if (ret == -EPROBE_DEFER ) + goto err_clk_biu; + host->bus_hz = host->pdata->bus_hz; }else { ret =clk_prepare_enable (host->ciu_clk);
Greg Kroah-Hartman
maintainerPATCH 248/273 smb3: fix broken cached reads when posix locks
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve French <[email protected]>
commit e4be320eeca842a3d7648258ee3673f1755a5a59 upstream.
Mandatory locking is enforced for cached reads, which violates default posix semantics, and also it is enforced inconsistently. This affected recent versions of libreoffice, and can be demonstrated by opening a file twice from the same client, locking it from handle one and trying to read from it from handle two (which fails, returning EACCES).
There is already a mount option "forcemandatorylock" (which defaults to off), so with this change only when the user intentionally specifies "forcemandatorylock" on mount will we break posix semantics on read to a locked range (ie we will only fail in this case, if the user mounts with "forcemandatorylock").
An earlier patch fixed the write path.
--- fs/smb/client/file.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/smb/client/file.c +1 -3
@@ -2912,9 +2912,7 @@ cifs_strict_readv(struct kiocb *iocb, stif (!CIFS_CACHE_READ (cinode))return netfs_unbuffered_read_iter (iocb, to); -if (cap_unix (tcon->ses) && - (CIFS_UNIX_FCNTL_CAP &le64_to_cpu (tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags &CIFS_MOUNT_NOPOSIXBRL ) ==0 )) { +if ((cifs_sb->mnt_cifs_flags &CIFS_MOUNT_NOPOSIXBRL ) ==0 ) {if (iocb->ki_flags &IOCB_DIRECT )return netfs_unbuffered_read_iter (iocb, to);return netfs_buffered_read_iter (iocb, to);
Greg Kroah-Hartman
maintainerPATCH 249/273 pmdomain: imx: scu-pd: Remove duplicated clocks
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Stein <[email protected]>
commit 50359c9c3cb3e55e840e3485f5ee37da5b2b16b6 upstream.
These clocks are already added to the list. Remove the duplicates ones.
--- drivers/pmdomain/imx/scu-pd.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/pmdomain/imx/scu-pd.c +0 -5
@@ -223,11 +223,6 @@ static const struct imx_sc_pd_range imx8 { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 }, { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 }, - { "mipi1", IMX_SC_R_MIPI_1, 1, 0 }, - { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, 0 }, - { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, 1 }, - { "lvds1", IMX_SC_R_LVDS_1, 1, 0 }, -/* DC SS */ { "dc0", IMX_SC_R_DC_0, 1, false, 0 }, { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
Greg Kroah-Hartman
maintainerPATCH 250/273 pmdomain: imx: wait SSAR when i.MX93 power domain on
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Fan <[email protected]>
commit 52dd070c62e4ae2b5e7411b920e3f7a64235ecfb upstream.
With "quiet" set in bootargs, there is power domain failure:
"imx93_power_domain 44462400.power-domain: pd_off timeout: name:
44462400.power-domain, stat: 4"
The current power on opertation takes ISO state as power on finished flag, but it is wrong. Before powering on operation really finishes, powering off comes and powering off will never finish because the last powering on still not finishes, so the following powering off actually not trigger hardware state machine to run. SSAR is the last step when powering on a domain, so need to wait SSAR done when powering on.
Since EdgeLock Enclave(ELE) handshake is involved in the flow, enlarge the waiting time to 10ms for both on and off to avoid timeout.
--- drivers/pmdomain/imx/imx93-pd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pmdomain/imx/imx93-pd.c +3 -2
@@ -20,6 +20,7 @@#define FUNC_STAT_PSW_STAT_MASK BIT(0)#define FUNC_STAT_RST_STAT_MASK BIT(2)#define FUNC_STAT_ISO_STAT_MASK BIT(4) +#define FUNC_STAT_SSAR_STAT_MASK BIT(8)struct imx93_power_domain {struct generic_pm_domain genpd;
@@ -50,7 +51,7 @@ static int imx93_pd_on(struct generic_pmwritel (val, addr +MIX_SLICE_SW_CTRL_OFF ); ret =readl_poll_timeout (addr +MIX_FUNC_STAT_OFF , val, - !(val &FUNC_STAT_ISO_STAT_MASK ),1 ,10000 ); + !(val &FUNC_STAT_SSAR_STAT_MASK ),1 ,10000 );if (ret) {dev_err (domain->dev,"pd_on timeout: name: %s, stat: %x\n" , genpd->name, val);return ret;
@@ -72,7 +73,7 @@ static int imx93_pd_off(struct generic_pwritel (val, addr +MIX_SLICE_SW_CTRL_OFF ); ret =readl_poll_timeout (addr +MIX_FUNC_STAT_OFF , val, - val &FUNC_STAT_PSW_STAT_MASK ,1 ,1000 ); + val &FUNC_STAT_PSW_STAT_MASK ,1 ,10000 );if (ret) {dev_err (domain->dev,"pd_off timeout: name: %s, stat: %x\n" , genpd->name, val);return ret;
Greg Kroah-Hartman
maintainerPATCH 251/273 nouveau/firmware: use dma non-coherent allocator
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Airlie <[email protected]>
commit 9b340aeb26d50e9a9ec99599e2a39b035fac978e upstream.
Currently, enabling SG_DEBUG in the kernel will cause nouveau to hit a BUG() on startup, when the iommu is enabled:
kernel BUG at include/linux/scatterlist.h:187!
invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
CPU: 7 PID: 930 Comm: (udev-worker) Not tainted 6.9.0-rc3Lyude-Test+ #30 Hardware name: MSI MS-7A39/A320M GAMING PRO (MS-7A39), BIOS 1.I0 01/22/2019 RIP: 0010:sg_init_one+0x85/0xa0 Code: 69 88 32 01 83 e1 03 f6 c3 03 75 20 a8 01 75 1e 48 09 cb 41 89 54 24 08 49 89 1c 24 41 89 6c 24 0c 5b 5d 41 5c e9 7b b9 88 00 <0f> 0b 0f 0b 0f 0b 48 8b 05 5e 46 9a 01 eb b2 66 66 2e 0f 1f 84 00 RSP: 0018:ffffa776017bf6a0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffffa77600d87000 RCX: 000000000000002b RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffffa77680d87000 RBP: 000000000000e000 R08: 0000000000000000 R09: 0000000000000000 R10: ffff98f4c46aa508 R11: 0000000000000000 R12: ffff98f4c46aa508 R13: ffff98f4c46aa008 R14: ffffa77600d4a000 R15: ffffa77600d4a018 FS: 00007feeb5aae980(0000) GS:ffff98f5c4dc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f22cb9a4520 CR3: 00000001043ba000 CR4: 00000000003506f0 Call Trace: <TASK> ? die+0x36/0x90 ? do_trap+0xdd/0x100 ? sg_init_one+0x85/0xa0 ? do_error_trap+0x65/0x80 ? sg_init_one+0x85/0xa0 ? exc_invalid_op+0x50/0x70 ? sg_init_one+0x85/0xa0 ? asm_exc_invalid_op+0x1a/0x20 ? sg_init_one+0x85/0xa0 nvkm_firmware_ctor+0x14a/0x250 [nouveau] nvkm_falcon_fw_ctor+0x42/0x70 [nouveau] ga102_gsp_booter_ctor+0xb4/0x1a0 [nouveau] r535_gsp_oneinit+0xb3/0x15f0 [nouveau] ? srso_return_thunk+0x5/0x5f ? srso_return_thunk+0x5/0x5f ? nvkm_udevice_new+0x95/0x140 [nouveau] ? srso_return_thunk+0x5/0x5f ? srso_return_thunk+0x5/0x5f ? ktime_get+0x47/0xb0
Fix this by using the non-coherent allocator instead, I think there might be a better answer to this, but it involve ripping up some of APIs using sg lists.
--- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 9 ++++++--- drivers/gpu/drm/nouveau/nvkm/falcon/fw.c | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-)
drivers/gpu/drm/nouveau/nvkm/core/firmware.c +6 -3
@@ -205,7 +205,8 @@ nvkm_firmware_dtor(struct nvkm_firmwarebreak ;case NVKM_FIRMWARE_IMG_DMA :nvkm_memory_unref (&memory); -dma_free_coherent (fw->device->dev,sg_dma_len (&fw->mem.sgl), fw->img, fw->phys); +dma_free_noncoherent (fw->device->dev,sg_dma_len (&fw->mem.sgl), + fw->img, fw->phys,DMA_TO_DEVICE );break ;case NVKM_FIRMWARE_IMG_SGT :nvkm_memory_unref (&memory);
@@ -236,10 +237,12 @@ nvkm_firmware_ctor(const struct nvkm_firbreak ;case NVKM_FIRMWARE_IMG_DMA : {dma_addr_t addr; - len =ALIGN (fw->len,PAGE_SIZE ); - fw->img =dma_alloc_coherent (fw->device->dev, len, &addr,GFP_KERNEL ); + fw->img =dma_alloc_noncoherent (fw->device->dev, + len, &addr, +DMA_TO_DEVICE , +GFP_KERNEL );if (fw->img) {memcpy (fw->img, src, fw->len); fw->phys = addr;
drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +6 -0
@@ -89,6 +89,12 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fnvkm_falcon_fw_dtor_sigs (fw); } +/* after last write to the img, sync dma mappings */ +dma_sync_single_for_device (fw->fw.device->dev, + fw->fw.phys, +sg_dma_len (&fw->fw.mem.sgl), +DMA_TO_DEVICE ); +FLCNFW_DBG (fw,"resetting" ); fw->func->reset (fw);
Greg Kroah-Hartman
maintainerPATCH 252/273 thermal: of: Fix OF node leak in thermal_of_trips_init() error path
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
commit afc954fd223ded70b1fa000767e2531db55cce58 upstream.
Terminating for_each_child_of_node() loop requires dropping OF node reference, so bailing out after thermal_of_populate_trip() error misses this. Solve the OF node reference leak with scoped for_each_child_of_node_scoped().
--- drivers/thermal/thermal_of.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/thermal/thermal_of.c +2 -2
@@ -125,7 +125,7 @@ static int thermal_of_populate_trip(strustatic struct thermal_trip *thermal_of_trips_init (struct device_node *np,int *ntrips) {struct thermal_trip *tt; -struct device_node *trips, *trip; +struct device_node *trips;int ret, count; trips =of_get_child_by_name (np,"trips" );
@@ -150,7 +150,7 @@ static struct thermal_trip *thermal_of_t *ntrips = count; count =0 ; -for_each_child_of_node (trips, trip) { +for_each_child_of_node_scoped (trips, trip) { ret =thermal_of_populate_trip (trip, &tt[count++]);if (ret) goto out_kfree;
Greg Kroah-Hartman
maintainerPATCH 253/273 thermal: of: Fix OF node leak in thermal_of_zone_register()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
commit 662b52b761bfe0ba970e5823759798faf809b896 upstream.
thermal_of_zone_register() calls of_thermal_zone_find() which will iterate over OF nodes with for_each_available_child_of_node() to find matching thermal zone node. When it finds such, it exits the loop and returns the node. Prematurely ending for_each_available_child_of_node() loops requires dropping OF node reference, thus success of of_thermal_zone_find() means that caller must drop the reference.
--- drivers/thermal/thermal_of.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/thermal/thermal_of.c +5 -1
@@ -491,7 +491,8 @@ static struct thermal_zone_device *therm trips =thermal_of_trips_init (np, &ntrips);if (IS_ERR (trips)) {pr_err ("Failed to find trip points for %pOFn id=%d\n" , sensor, id); -return ERR_CAST (trips); + ret =PTR_ERR (trips); + goto out_of_node_put; } ret =thermal_of_monitor_init (np, &delay, &pdelay);
@@ -519,6 +520,7 @@ static struct thermal_zone_device *therm goto out_kfree_trips; } +of_node_put (np);kfree (trips); ret =thermal_zone_device_enable (tz);
@@ -533,6 +535,8 @@ static struct thermal_zone_device *therm out_kfree_trips:kfree (trips); +out_of_node_put: +of_node_put (np);return ERR_PTR (ret); }
Greg Kroah-Hartman
maintainerPATCH 254/273 thermal: of: Fix OF node leak in of_thermal_zone_find() error paths
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
commit c0a1ef9c5be72ff28a5413deb1b3e1a066593c13 upstream.
Terminating for_each_available_child_of_node() loop requires dropping OF node reference, so bailing out on errors misses this. Solve the OF node reference leak with scoped for_each_available_child_of_node_scoped().
--- drivers/thermal/thermal_of.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/thermal/thermal_of.c +7 -6
@@ -184,14 +184,14 @@ static struct device_node *of_thermal_zo* Search for each thermal zone, a defined sensor * corresponding to the one passed as parameter */ -for_each_available_child_of_node (np, tz) { +for_each_available_child_of_node_scoped (np, child) {int count, i; - count =of_count_phandle_with_args (tz,"thermal-sensors" , + count =of_count_phandle_with_args (child,"thermal-sensors" ,"#thermal-sensor-cells" );if (count <=0 ) { -pr_err ("%pOFn: missing thermal sensor\n" , tz); +pr_err ("%pOFn: missing thermal sensor\n" , child); tz =ERR_PTR (-EINVAL ); goto out; }
@@ -200,18 +200,19 @@ static struct device_node *of_thermal_zoint ret; - ret =of_parse_phandle_with_args (tz,"thermal-sensors" , + ret =of_parse_phandle_with_args (child,"thermal-sensors" ,"#thermal-sensor-cells" , i, &sensor_specs);if (ret <0 ) { -pr_err ("%pOFn: Failed to read thermal-sensors cells: %d\n" , tz, ret); +pr_err ("%pOFn: Failed to read thermal-sensors cells: %d\n" , child, ret); tz =ERR_PTR (ret); goto out; }if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ? sensor_specs.args[0 ] :0 )) { -pr_debug ("sensor %pOFn id=%d belongs to %pOFn\n" , sensor, id, tz); +pr_debug ("sensor %pOFn id=%d belongs to %pOFn\n" , sensor, id, child); + tz =no_free_ptr (child); goto out; } }
Greg Kroah-Hartman
maintainerPATCH 255/273 mptcp: pm: re-using ID of unused removed ADD_ADDR
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit e255683c06df572ead96db5efb5d21be30c0efaa upstream.
If no subflow is attached to the 'signal' endpoint that is being removed, the addr ID will not be marked as available again.
Mark the linked ID as available when removing the address entry from the list to cover this case.
--- net/mptcp/pm_netlink.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/mptcp/pm_netlink.c +4 -1
@@ -1431,7 +1431,10 @@ static bool mptcp_pm_remove_anno_addr(st ret =remove_anno_list_by_saddr (msk, addr);if (ret || force) {spin_lock_bh (&msk->pm.lock); - msk->pm.add_addr_signaled -= ret; +if (ret) { +__set_bit (addr->id, msk->pm.id_avail_bitmap); + msk->pm.add_addr_signaled--; + }mptcp_pm_remove_addr (msk, &list);spin_unlock_bh (&msk->pm.lock); }
Greg Kroah-Hartman
maintainerPATCH 256/273 mptcp: pm: re-using ID of unused removed subflows
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit edd8b5d868a4d459f3065493001e293901af758d upstream.
If no subflow is attached to the 'subflow' endpoint that is being removed, the addr ID will not be marked as available again.
Mark the linked ID as available when removing the 'subflow' endpoint if no subflow is attached to it.
While at it, the local_addr_used counter is decremented if the ID was marked as being used to reflect the reality, but also to allow adding new endpoints after that.
--- net/mptcp/pm_netlink.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
net/mptcp/pm_netlink.c +10 -1
@@ -1469,8 +1469,17 @@ static int mptcp_nl_remove_subflow_and_s remove_subflow =lookup_subflow_by_saddr (&msk->conn_list, addr);mptcp_pm_remove_anno_addr (msk, addr, remove_subflow && !(entry->flags &MPTCP_PM_ADDR_FLAG_IMPLICIT )); -if (remove_subflow) + +if (remove_subflow) {mptcp_pm_remove_subflow (msk, &list); + }else if (entry->flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) { +/* If the subflow has been used, but now closed */ +spin_lock_bh (&msk->pm.lock); +if (!__test_and_set_bit (entry->addr.id, msk->pm.id_avail_bitmap)) + msk->pm.local_addr_used--; +spin_unlock_bh (&msk->pm.lock); + } +release_sock (sk); next:
Greg Kroah-Hartman
maintainerPATCH 257/273 mptcp: pm: re-using ID of unused flushed subflows
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit ef34a6ea0cab1800f4b3c9c3c2cefd5091e03379 upstream.
If no subflows are attached to the 'subflow' endpoints that are being flushed, the corresponding addr IDs will not be marked as available again.
Mark all ID as being available when flushing all the 'subflow' endpoints, and reset local_addr_used counter to cover these cases.
Note that mptcp_pm_remove_addrs_and_subflows() helper is only called for flushing operations, not to remove a specific set of addresses and subflows.
--- net/mptcp/pm_netlink.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/mptcp/pm_netlink.c +7 -0
@@ -1623,8 +1623,15 @@ static void mptcp_pm_remove_addrs_and_sumptcp_pm_remove_addr (msk, &alist);spin_unlock_bh (&msk->pm.lock); } +if (slist.nr)mptcp_pm_remove_subflow (msk, &slist); + +/* Reset counters: maybe some subflows have been removed before */ +spin_lock_bh (&msk->pm.lock); +bitmap_fill (msk->pm.id_avail_bitmap,MPTCP_PM_MAX_ADDR_ID +1 ); + msk->pm.local_addr_used =0 ; +spin_unlock_bh (&msk->pm.lock); } static void mptcp_nl_remove_addrs_list(struct net *net,
Greg Kroah-Hartman
maintainerPATCH 258/273 mptcp: pm: remove mptcp_pm_remove_subflow()
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit f448451aa62d54be16acb0034223c17e0d12bc69 upstream.
This helper is confusing. It is in pm.c, but it is specific to the in-kernel PM and it cannot be used by the userspace one. Also, it simply calls one in-kernel specific function with the PM lock, while the similar mptcp_pm_remove_addr() helper requires the PM lock.
What's left is the pr_debug(), which is not that useful, because a similar one is present in the only function called by this helper:
mptcp_pm_nl_rm_subflow_received()
After these modifications, this helper can be marked as 'static', and the lock can be taken only once in mptcp_pm_flush_addrs_and_subflows().
Note that it is not a bug fix, but it will help backporting the following commits.
--- net/mptcp/pm.c | 10 ---------- net/mptcp/pm_netlink.c | 16 +++++++--------- net/mptcp/protocol.h | 3 --- 3 files changed, 7 insertions(+), 22 deletions(-)
net/mptcp/pm.c +0 -10
@@ -60,16 +60,6 @@ int mptcp_pm_remove_addr(struct mptcp_soreturn 0 ; } -int mptcp_pm_remove_subflow (struct mptcp_sock *msk,const struct mptcp_rm_list *rm_list) -{ -pr_debug ("msk=%p, rm_list_nr=%d" , msk, rm_list->nr); - -spin_lock_bh (&msk->pm.lock); -mptcp_pm_nl_rm_subflow_received (msk, rm_list); -spin_unlock_bh (&msk->pm.lock); -return 0 ; -} -/* path manager event handlers */ void mptcp_pm_new_connection (struct mptcp_sock *msk,const struct sock *ssk,int server_side)
net/mptcp/pm_netlink.c +7 -9
@@ -857,8 +857,8 @@ static void mptcp_pm_nl_rm_addr_receivedmptcp_pm_nl_rm_addr_or_subflow (msk, &msk->pm.rm_list_rx,MPTCP_MIB_RMADDR ); } -void mptcp_pm_nl_rm_subflow_received (struct mptcp_sock *msk, -const struct mptcp_rm_list *rm_list) +static void mptcp_pm_nl_rm_subflow_received (struct mptcp_sock *msk, +const struct mptcp_rm_list *rm_list) {mptcp_pm_nl_rm_addr_or_subflow (msk, rm_list,MPTCP_MIB_RMSUBFLOW ); }
@@ -1471,7 +1471,9 @@ static int mptcp_nl_remove_subflow_and_s !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));if (remove_subflow) { -mptcp_pm_remove_subflow (msk, &list); +spin_lock_bh (&msk->pm.lock); +mptcp_pm_nl_rm_subflow_received (msk, &list); +spin_unlock_bh (&msk->pm.lock); }else if (entry->flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) {/* If the subflow has been used, but now closed */ spin_lock_bh (&msk->pm.lock);
@@ -1617,18 +1619,14 @@ static void mptcp_pm_remove_addrs_and_su alist.ids[alist.nr++] = entry->addr.id; } +spin_lock_bh (&msk->pm.lock);if (alist.nr) { -spin_lock_bh (&msk->pm.lock); msk->pm.add_addr_signaled -= alist.nr;mptcp_pm_remove_addr (msk, &alist); -spin_unlock_bh (&msk->pm.lock); } -if (slist.nr) -mptcp_pm_remove_subflow (msk, &slist); - +mptcp_pm_nl_rm_subflow_received (msk, &slist);/* Reset counters: maybe some subflows have been removed before */ -spin_lock_bh (&msk->pm.lock);bitmap_fill (msk->pm.id_avail_bitmap,MPTCP_PM_MAX_ADDR_ID +1 ); msk->pm.local_addr_used =0 ;spin_unlock_bh (&msk->pm.lock);
net/mptcp/protocol.h +0 -3
@@ -1021,7 +1021,6 @@ int mptcp_pm_announce_addr(struct mptcp_const struct mptcp_addr_info *addr, bool echo);int mptcp_pm_remove_addr (struct mptcp_sock *msk,const struct mptcp_rm_list *rm_list); -int mptcp_pm_remove_subflow (struct mptcp_sock *msk,const struct mptcp_rm_list *rm_list);void mptcp_pm_remove_addrs (struct mptcp_sock *msk,struct list_head *rm_list);void mptcp_free_local_addr_list (struct mptcp_sock *msk);
@@ -1128,8 +1127,6 @@ static inline u8 subflow_get_local_id(covoid __init mptcp_pm_nl_init (void );void mptcp_pm_nl_work (struct mptcp_sock *msk); -void mptcp_pm_nl_rm_subflow_received (struct mptcp_sock *msk, -const struct mptcp_rm_list *rm_list);unsigned int mptcp_pm_get_add_addr_signal_max (const struct mptcp_sock *msk);unsigned int mptcp_pm_get_add_addr_accept_max (const struct mptcp_sock *msk);unsigned int mptcp_pm_get_subflows_max (const struct mptcp_sock *msk);
Greg Kroah-Hartman
maintainerPATCH 259/273 mptcp: pm: only mark subflow endp as available
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 322ea3778965da72862cca2a0c50253aacf65fe6 upstream.
Adding the following warning ...
WARN_ON_ONCE(msk->pm.local_addr_used == 0)
... before decrementing the local_addr_used counter helped to find a bug when running the "remove single address" subtest from the mptcp_join.sh selftests.
Removing a 'signal' endpoint will trigger the removal of all subflows linked to this endpoint via mptcp_pm_nl_rm_addr_or_subflow() with rm_type == MPTCP_MIB_RMSUBFLOW. This will decrement the local_addr_used counter, which is wrong in this case because this counter is linked to 'subflow' endpoints, and here it is a 'signal' endpoint that is being removed.
Now, the counter is decremented, only if the ID is being used outside of mptcp_pm_nl_rm_addr_or_subflow(), only for 'subflow' endpoints, and if the ID is not 0 -- local_addr_used is not taking into account these ones. This marking of the ID as being available, and the decrement is done no matter if a subflow using this ID is currently available, because the subflow could have been closed before.
--- net/mptcp/pm_netlink.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
net/mptcp/pm_netlink.c +17 -9
@@ -833,10 +833,10 @@ static void mptcp_pm_nl_rm_addr_or_subflif (rm_type ==MPTCP_MIB_RMSUBFLOW )__MPTCP_INC_STATS (sock_net (sk), rm_type); } -if (rm_type ==MPTCP_MIB_RMSUBFLOW ) -__set_bit (rm_id ? rm_id : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap); -else if (rm_type ==MPTCP_MIB_RMADDR ) + +if (rm_type ==MPTCP_MIB_RMADDR )__MPTCP_INC_STATS (sock_net (sk), rm_type); +if (!removed)continue ;
@@ -846,8 +846,6 @@ static void mptcp_pm_nl_rm_addr_or_subflif (rm_type ==MPTCP_MIB_RMADDR ) { msk->pm.add_addr_accepted--;WRITE_ONCE (msk->pm.accept_addr, true); - }else if (rm_type ==MPTCP_MIB_RMSUBFLOW ) { - msk->pm.local_addr_used--; } } }
@@ -1441,6 +1439,14 @@ static bool mptcp_pm_remove_anno_addr(streturn ret; } +static void __mark_subflow_endp_available (struct mptcp_sock *msk,u8 id) +{ +/* If it was marked as used, and not ID 0, decrement local_addr_used */ +if (!__test_and_set_bit (id ? : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap) && + id && !WARN_ON_ONCE (msk->pm.local_addr_used ==0 )) + msk->pm.local_addr_used--; +} +static int mptcp_nl_remove_subflow_and_signal_addr (struct net *net,const struct mptcp_pm_addr_entry *entry) {
@@ -1474,11 +1480,11 @@ static int mptcp_nl_remove_subflow_and_sspin_lock_bh (&msk->pm.lock);mptcp_pm_nl_rm_subflow_received (msk, &list);spin_unlock_bh (&msk->pm.lock); - }else if (entry->flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) { -/* If the subflow has been used, but now closed */ + } + +if (entry->flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) {spin_lock_bh (&msk->pm.lock); -if (!__test_and_set_bit (entry->addr.id, msk->pm.id_avail_bitmap)) - msk->pm.local_addr_used--; +__mark_subflow_endp_available (msk, list.ids[0 ]);spin_unlock_bh (&msk->pm.lock); }
@@ -1516,6 +1522,7 @@ static int mptcp_nl_remove_id_zero_addrespin_lock_bh (&msk->pm.lock);mptcp_pm_remove_addr (msk, &list);mptcp_pm_nl_rm_subflow_received (msk, &list); +__mark_subflow_endp_available (msk,0 );spin_unlock_bh (&msk->pm.lock);release_sock (sk);
@@ -1917,6 +1924,7 @@ static void mptcp_pm_nl_fullmesh(structspin_lock_bh (&msk->pm.lock);mptcp_pm_nl_rm_subflow_received (msk, &list); +__mark_subflow_endp_available (msk, list.ids[0 ]);mptcp_pm_create_subflow_or_signal_addr (msk);spin_unlock_bh (&msk->pm.lock); }
Greg Kroah-Hartman
maintainerPATCH 260/273 mptcp: pm: only decrement add_addr_accepted for MPJ req
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 1c1f721375989579e46741f59523e39ec9b2a9bd upstream.
Adding the following warning ...
WARN_ON_ONCE(msk->pm.add_addr_accepted == 0)
... before decrementing the add_addr_accepted counter helped to find a bug when running the "remove single subflow" subtest from the mptcp_join.sh selftest.
Removing a 'subflow' endpoint will first trigger a RM_ADDR, then the subflow closure. Before this patch, and upon the reception of the RM_ADDR, the other peer will then try to decrement this add_addr_accepted. That's not correct because the attached subflows have not been created upon the reception of an ADD_ADDR.
A way to solve that is to decrement the counter only if the attached subflow was an MP_JOIN to a remote id that was not 0, and initiated by the host receiving the RM_ADDR.
--- net/mptcp/pm_netlink.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/mptcp/pm_netlink.c +6 -2
@@ -829,7 +829,7 @@ static void mptcp_pm_nl_rm_addr_or_subflmptcp_close_ssk (sk, ssk, subflow);spin_lock_bh (&msk->pm.lock); - removed = true; + removed |= subflow->request_join;if (rm_type ==MPTCP_MIB_RMSUBFLOW )__MPTCP_INC_STATS (sock_net (sk), rm_type); }
@@ -843,7 +843,11 @@ static void mptcp_pm_nl_rm_addr_or_subflif (!mptcp_pm_is_kernel (msk))continue ; -if (rm_type ==MPTCP_MIB_RMADDR ) { +if (rm_type ==MPTCP_MIB_RMADDR && rm_id && + !WARN_ON_ONCE (msk->pm.add_addr_accepted ==0 )) { +/* Note: if the subflow has been closed before, this +* add_addr_accepted counter will not be decremented. +*/ msk->pm.add_addr_accepted--;WRITE_ONCE (msk->pm.accept_addr, true); }
Greg Kroah-Hartman
maintainerPATCH 261/273 mptcp: pm: check add_addr_accept_max before accepting new ADD_ADDR
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 0137a3c7c2ea3f9df8ebfc65d78b4ba712a187bb upstream.
The limits might have changed in between, it is best to check them before accepting new ADD_ADDR.
--- net/mptcp/pm_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/mptcp/pm_netlink.c +2 -2
@@ -848,8 +848,8 @@ static void mptcp_pm_nl_rm_addr_or_subfl/* Note: if the subflow has been closed before, this * add_addr_accepted counter will not be decremented. */ - msk->pm.add_addr_accepted--; -WRITE_ONCE (msk->pm.accept_addr, true); +if (--msk->pm.add_addr_accepted <mptcp_pm_get_add_addr_accept_max (msk)) +WRITE_ONCE (msk->pm.accept_addr, true); } } }
Greg Kroah-Hartman
maintainerPATCH 262/273 mptcp: pm: only in-kernel cannot have entries with ID 0
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit ca6e55a703ca2894611bb5c5bca8bfd2290fd91e upstream.
The ID 0 is specific per MPTCP connections. The per netns entries cannot have this special ID 0 then.
But that's different for the userspace PM where the entries are per connection, they can then use this special ID 0.
--- net/mptcp/pm.c | 3 --- net/mptcp/pm_netlink.c | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-)
net/mptcp/pm.c +0 -3
@@ -434,9 +434,6 @@ int mptcp_pm_get_flags_and_ifindex_by_id *flags =0 ; *ifindex =0 ; -if (!id) -return 0 ; -if (mptcp_pm_is_userspace (msk))return mptcp_userspace_pm_get_flags_and_ifindex_by_id (msk, id, flags, ifindex);return mptcp_pm_nl_get_flags_and_ifindex_by_id (msk, id, flags, ifindex);
net/mptcp/pm_netlink.c +4 -0
@@ -1395,6 +1395,10 @@ int mptcp_pm_nl_get_flags_and_ifindex_bystruct sock *sk = (struct sock *)msk;struct net *net =sock_net (sk); +/* No entries with ID 0 */ +if (id ==0 ) +return 0 ; +rcu_read_lock (); entry =__lookup_addr_by_id (pm_nl_get_pernet (net), id);if (entry) {
Greg Kroah-Hartman
maintainerPATCH 263/273 mptcp: pm: fullmesh: select the right ID later
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 09355f7abb9fbfc1a240be029837921ea417bf4f upstream.
When reacting upon the reception of an ADD_ADDR, the in-kernel PM first looks for fullmesh endpoints. If there are some, it will pick them, using their entry ID.
It should set the ID 0 when using the endpoint corresponding to the initial subflow, it is a special case imposed by the MPTCP specs.
Note that msk->mpc_endpoint_id might not be set when receiving the first ADD_ADDR from the server. So better to compare the addresses.
--- net/mptcp/pm_netlink.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
net/mptcp/pm_netlink.c +10 -1
@@ -636,6 +636,7 @@ static unsigned int fill_local_addresses {struct sock *sk = (struct sock *)msk;struct mptcp_pm_addr_entry *entry; +struct mptcp_addr_info mpc_addr;struct pm_nl_pernet *pernet;unsigned int subflows_max;int i =0 ;
@@ -643,6 +644,8 @@ static unsigned int fill_local_addresses pernet =pm_nl_get_pernet_from_msk (msk); subflows_max =mptcp_pm_get_subflows_max (msk); +mptcp_local_address ((struct sock_common *)msk, &mpc_addr); +rcu_read_lock ();list_for_each_entry_rcu (entry, &pernet->local_addr_list, list) {if (!(entry->flags &MPTCP_PM_ADDR_FLAG_FULLMESH ))
@@ -653,7 +656,13 @@ static unsigned int fill_local_addressesif (msk->pm.subflows < subflows_max) { msk->pm.subflows++; - addrs[i++] = entry->addr; + addrs[i] = entry->addr; + +/* Special case for ID0: set the correct ID */ +if (mptcp_addresses_equal (&entry->addr, &mpc_addr, entry->addr.port)) + addrs[i].id =0 ; + + i++; } }rcu_read_unlock ();
Greg Kroah-Hartman
maintainerPATCH 264/273 mptcp: pm: avoid possible UaF when selecting endp
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 48e50dcbcbaaf713d82bf2da5c16aeced94ad07d upstream.
select_local_address() and select_signal_address() both select an endpoint entry from the list inside an RCU protected section, but return a reference to it, to be read later on. If the entry is dereferenced after the RCU unlock, reading info could cause a Use-after-Free.
A simple solution is to copy the required info while inside the RCU protected section to avoid any risk of UaF later. The address ID might need to be modified later to handle the ID0 case later, so a copy seems OK to deal with.
--- net/mptcp/pm_netlink.c | 64 ++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 30 deletions(-)
net/mptcp/pm_netlink.c +34 -30
@@ -143,11 +143,13 @@ static bool lookup_subflow_by_daddr(consreturn false; } -static struct mptcp_pm_addr_entry * +static bool select_local_address (const struct pm_nl_pernet *pernet, -const struct mptcp_sock *msk) +const struct mptcp_sock *msk, +struct mptcp_pm_addr_entry *new_entry) { -struct mptcp_pm_addr_entry *entry, *ret =NULL ; +struct mptcp_pm_addr_entry *entry; +bool found = false;msk_owned_by_me (msk);
@@ -159,17 +161,21 @@ select_local_address(const struct pm_nl_if (!test_bit (entry->addr.id, msk->pm.id_avail_bitmap))continue ; - ret = entry; + *new_entry = *entry; + found = true;break ; }rcu_read_unlock (); -return ret; + +return found; } -static struct mptcp_pm_addr_entry * -select_signal_address (struct pm_nl_pernet *pernet,const struct mptcp_sock *msk) +static bool +select_signal_address (struct pm_nl_pernet *pernet,const struct mptcp_sock *msk, +struct mptcp_pm_addr_entry *new_entry) { -struct mptcp_pm_addr_entry *entry, *ret =NULL ; +struct mptcp_pm_addr_entry *entry; +bool found = false;rcu_read_lock ();/* do not keep any additional per socket state, just signal
@@ -184,11 +190,13 @@ select_signal_address(struct pm_nl_perneif (!(entry->flags &MPTCP_PM_ADDR_FLAG_SIGNAL ))continue ; - ret = entry; + *new_entry = *entry; + found = true;break ; }rcu_read_unlock (); -return ret; + +return found; }unsigned int mptcp_pm_get_add_addr_signal_max (const struct mptcp_sock *msk)
@@ -512,9 +520,10 @@ __lookup_addr(struct pm_nl_pernet *pernestatic void mptcp_pm_create_subflow_or_signal_addr (struct mptcp_sock *msk) { -struct mptcp_pm_addr_entry *local, *signal_and_subflow =NULL ;struct sock *sk = (struct sock *)msk; +struct mptcp_pm_addr_entry local;unsigned int add_addr_signal_max; +bool signal_and_subflow = false;unsigned int local_addr_max;struct pm_nl_pernet *pernet;unsigned int subflows_max;
@@ -565,23 +574,22 @@ static void mptcp_pm_create_subflow_or_sif (msk->pm.addr_signal &BIT (MPTCP_ADD_ADDR_SIGNAL ))return ; - local =select_signal_address (pernet, msk); -if (!local) +if (!select_signal_address (pernet, msk, &local)) goto subflow;/* If the alloc fails, we are on memory pressure, not worth * continuing, and trying to create subflows. */ -if (!mptcp_pm_alloc_anno_list (msk, &local->addr)) +if (!mptcp_pm_alloc_anno_list (msk, &local.addr))return ; -__clear_bit (local->addr.id, msk->pm.id_avail_bitmap); +__clear_bit (local.addr.id, msk->pm.id_avail_bitmap); msk->pm.add_addr_signaled++; -mptcp_pm_announce_addr (msk, &local->addr, false); +mptcp_pm_announce_addr (msk, &local.addr, false);mptcp_pm_nl_addr_send_ack (msk); -if (local->flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) - signal_and_subflow = local; +if (local.flags &MPTCP_PM_ADDR_FLAG_SUBFLOW ) + signal_and_subflow = true; } subflow:
@@ -592,26 +600,22 @@ subflow:bool fullmesh;int i, nr; -if (signal_and_subflow) { - local = signal_and_subflow; - signal_and_subflow =NULL ; - }else { - local =select_local_address (pernet, msk); -if (!local) -break ; - } +if (signal_and_subflow) + signal_and_subflow = false; +else if (!select_local_address (pernet, msk, &local)) +break ; - fullmesh = !!(local->flags &MPTCP_PM_ADDR_FLAG_FULLMESH ); + fullmesh = !!(local.flags &MPTCP_PM_ADDR_FLAG_FULLMESH ); msk->pm.local_addr_used++; -__clear_bit (local->addr.id, msk->pm.id_avail_bitmap); - nr =fill_remote_addresses_vec (msk, &local->addr, fullmesh, addrs); +__clear_bit (local.addr.id, msk->pm.id_avail_bitmap); + nr =fill_remote_addresses_vec (msk, &local.addr, fullmesh, addrs);if (nr ==0 )continue ;spin_unlock_bh (&msk->pm.lock);for (i =0 ; i < nr; i++) -__mptcp_subflow_connect (sk, &local->addr, &addrs[i]); +__mptcp_subflow_connect (sk, &local.addr, &addrs[i]);spin_lock_bh (&msk->pm.lock); }mptcp_pm_nl_check_work_pending (msk);
Greg Kroah-Hartman
maintainerPATCH 265/273 selftests: mptcp: join: validate fullmesh endp on 1st sf
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 4878f9f8421f4587bee7b232c1c8a9d3a7d4d782 upstream.
This case was not covered, and the wrong ID was set before the previous commit.
The rest is not modified, it is just that it will increase the code coverage.
The right address ID can be verified by looking at the packet traces. We could automate that using Netfilter with some cBPF code for example, but that's always a bit cryptic. Packetdrill seems better fitted for that.
--- tools/testing/selftests/net/mptcp/mptcp_join.sh | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/net/mptcp/mptcp_join.sh +1 -0
@@ -3058,6 +3058,7 @@ fullmesh_tests() pm_nl_set_limits $ns1 1 3 pm_nl_set_limits $ns2 1 3 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,fullmesh fullmesh=1 speed=slow \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 3 3 3
Greg Kroah-Hartman
maintainerPATCH 266/273 selftests: mptcp: join: check re-using ID of closed subflow
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 65fb58afa341ad68e71e5c4d816b407e6a683a66 upstream.
This test extends "delete and re-add" to validate the previous commit. A new 'subflow' endpoint is added, but the subflow request will be rejected. The result is that no subflow will be established from this address.
Later, the endpoint is removed and re-added after having cleared the firewall rule. Before the previous commit, the client would not have been able to create this new subflow.
While at it, extra checks have been added to validate the expected numbers of MPJ and RM_ADDR.
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.
--- tools/testing/selftests/net/mptcp/mptcp_join.sh | 27 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_join.sh +22 -5
@@ -436,9 +436,10 @@ reset_with_tcp_filter() local ns="${!1}" local src="${2}" local target="${3}" + local chain="${4:-INPUT}" if ! ip netns exec "${ns}" ${iptables} \ - -A INPUT \ + -A "${chain}" \ -s "${src}" \ -p tcp \ -j "${target}"; then
@@ -3572,10 +3573,10 @@ endpoint_tests() mptcp_lib_kill_wait $tests_pid fi - if reset "delete and re-add" && + if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT && mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then - pm_nl_set_limits $ns1 1 1 - pm_nl_set_limits $ns2 1 1 + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 0 2 pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow test_linkfail=4 speed=20 \ run_tests $ns1 $ns2 10.0.1.1 &
@@ -3592,11 +3593,27 @@ endpoint_tests() chk_subflow_nr "after delete" 1 chk_mptcp_info subflows 0 subflows 0 - pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow + pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow wait_mpj $ns2 chk_subflow_nr "after re-add" 2 chk_mptcp_info subflows 1 subflows 1 + + pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow + wait_attempt_fail $ns2 + chk_subflow_nr "after new reject" 2 + chk_mptcp_info subflows 1 subflows 1 + + ip netns exec "${ns2}" ${iptables} -D OUTPUT -s "10.0.3.2" -p tcp -j REJECT + pm_nl_del_endpoint $ns2 3 10.0.3.2 + pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow + wait_mpj $ns2 + chk_subflow_nr "after no reject" 3 + chk_mptcp_info subflows 2 subflows 2 + mptcp_lib_kill_wait $tests_pid + + chk_join_nr 3 3 3 + chk_rm_nr 1 1 fi }
Greg Kroah-Hartman
maintainerPATCH 267/273 drm/xe: Do not dereference NULL job->fence in trace points
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <[email protected]>
commit 5d30de4311d2d4165e78dc021c5cacb7496b3491 upstream.
job->fence is not assigned until xe_sched_job_arm(), check for job->fence in xe_sched_job_seqno() so any usage of this function (trace points) do not result in NULL ptr dereference. Also check job->fence before assigning error in job trace points.
--- drivers/gpu/drm/xe/xe_sched_job.h | 2 +- drivers/gpu/drm/xe/xe_trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_sched_job.h +1 -1
@@ -70,7 +70,7 @@ to_xe_sched_job(struct drm_sched_job *drstatic inline u32 xe_sched_job_seqno (struct xe_sched_job *job) { -return job->fence->seqno; +return job->fence ? job->fence->seqno :0 ; }static inline u32 xe_sched_job_lrc_seqno (struct xe_sched_job *job)
drivers/gpu/drm/xe/xe_trace.h +1 -1
@@ -270,7 +270,7 @@ DECLARE_EVENT_CLASS(xe_sched_job, __entry->guc_state =atomic_read (&job->q->guc->state); __entry->flags = job->q->flags; - __entry->error = job->fence->error; + __entry->error = job->fence ? job->fence->error :0 ; __entry->fence = job->fence; __entry->batch_addr = (u64 )job->ptrs[0 ].batch_addr; ),
Greg Kroah-Hartman
maintainerPATCH 268/273 Revert "pidfd: prevent creation of pidfds for kthreads"
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 232590ea7fc125986a526e03081b98e5783f70d2 upstream.
This reverts commit 3b5bbe798b2451820e74243b738268f51901e7d0.
Eric reported that systemd-shutdown gets broken by blocking the creating of pidfds for kthreads as older versions seems to rely on being able to create a pidfd for any process in /proc.
--- kernel/fork.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-)
kernel/fork.c +3 -22
@@ -2069,23 +2069,10 @@ static int __pidfd_prepare(struct pid *p*/ int pidfd_prepare (struct pid *pid,unsigned int flags,struct file **ret) { -if (!pid) -return -EINVAL ; - -scoped_guard (rcu) { -struct task_struct *tsk; +bool thread = flags &PIDFD_THREAD ; -if (flags &PIDFD_THREAD ) - tsk =pid_task (pid,PIDTYPE_PID ); -else - tsk =pid_task (pid,PIDTYPE_TGID ); -if (!tsk) -return -EINVAL ; - -/* Don't create pidfds for kernel threads for now. */ -if (tsk->flags &PF_KTHREAD ) -return -EINVAL ; - } +if (!pid || !pid_has_task (pid, thread ?PIDTYPE_PID :PIDTYPE_TGID )) +return -EINVAL ;return __pidfd_prepare (pid, flags, ret); }
@@ -2432,12 +2419,6 @@ __latent_entropy struct task_struct *copif (clone_flags &CLONE_PIDFD ) {int flags = (clone_flags &CLONE_THREAD ) ?PIDFD_THREAD :0 ; -/* Don't create pidfds for kernel threads for now. */ -if (args->kthread) { - retval = -EINVAL ; - goto bad_fork_free_pid; - } -/* Note that no task has been attached to @pid yet. */ retval =__pidfd_prepare (pid, flags, &pidfile);if (retval <0 )
Greg Kroah-Hartman
maintainerPATCH 269/273 drm/amdgpu/vcn: identify unified queue in sw init
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boyuan Zhang <[email protected]>
commit ecfa23c8df7ef3ea2a429dfe039341bf792e95b4 upstream.
Determine whether VCN using unified queue in sw_init, instead of calling functions later on.
v2: fix coding style
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 39 ++++++++++++-------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 2 files changed, 16 insertions(+), 24 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +15 -24
@@ -151,6 +151,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_dev } } +/* from vcn4 and above, only unified queue is used */ + adev->vcn.using_unified_queue = +amdgpu_ip_version (adev,UVD_HWIP ,0 ) >=IP_VERSION (4 ,0 ,0 ); + hdr = (const struct common_firmware_header *)adev->vcn.fw[0 ]->data; adev->vcn.fw_version =le32_to_cpu (hdr->ucode_version);
@@ -279,18 +283,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_devreturn 0 ; } -/* from vcn4 and above, only unified queue is used */ -static bool amdgpu_vcn_using_unified_queue (struct amdgpu_ring *ring) -{ -struct amdgpu_device *adev = ring->adev; -bool ret = false; - -if (amdgpu_ip_version (adev,UVD_HWIP ,0 ) >=IP_VERSION (4 ,0 ,0 )) - ret = true; - -return ret; -} -bool amdgpu_vcn_is_disabled_vcn (struct amdgpu_device *adev,enum vcn_ring_type type,uint32_t vcn_instance) {bool ret = false;
@@ -728,12 +720,11 @@ static int amdgpu_vcn_dec_sw_send_msg(ststruct amdgpu_job *job;struct amdgpu_ib *ib;uint64_t addr =AMDGPU_GPU_PAGE_ALIGN (ib_msg->gpu_addr); -bool sq =amdgpu_vcn_using_unified_queue (ring);uint32_t *ib_checksum;uint32_t ib_pack_in_dw;int i, r; -if (sq) +if (adev->vcn.using_unified_queue) ib_size_dw +=8 ; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -746,7 +737,7 @@ static int amdgpu_vcn_dec_sw_send_msg(st ib->length_dw =0 ;/* single queue headers */ -if (sq) { +if (adev->vcn.using_unified_queue) { ib_pack_in_dw =sizeof (struct amdgpu_vcn_decode_buffer ) /sizeof (uint32_t ) +4 +2 ;/* engine info + decoding ib in dw */ ib_checksum =amdgpu_vcn_unified_ring_ib_header (ib, ib_pack_in_dw, false);
@@ -765,7 +756,7 @@ static int amdgpu_vcn_dec_sw_send_msg(stfor (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] =0x0 ; -if (sq) +if (adev->vcn.using_unified_queue)amdgpu_vcn_unified_ring_ib_checksum (&ib_checksum, ib_pack_in_dw); r =amdgpu_job_submit_direct (job, ring, &f);
@@ -855,15 +846,15 @@ static int amdgpu_vcn_enc_get_create_msg struct dma_fence **fence) {unsigned int ib_size_dw =16 ; +struct amdgpu_device *adev = ring->adev;struct amdgpu_job *job;struct amdgpu_ib *ib;struct dma_fence *f =NULL ;uint32_t *ib_checksum =NULL ;uint64_t addr; -bool sq =amdgpu_vcn_using_unified_queue (ring);int i, r; -if (sq) +if (adev->vcn.using_unified_queue) ib_size_dw +=8 ; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -877,7 +868,7 @@ static int amdgpu_vcn_enc_get_create_msg ib->length_dw =0 ; -if (sq) +if (adev->vcn.using_unified_queue) ib_checksum =amdgpu_vcn_unified_ring_ib_header (ib,0x11 , true); ib->ptr[ib->length_dw++] =0x00000018 ;
@@ -899,7 +890,7 @@ static int amdgpu_vcn_enc_get_create_msgfor (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] =0x0 ; -if (sq) +if (adev->vcn.using_unified_queue)amdgpu_vcn_unified_ring_ib_checksum (&ib_checksum,0x11 ); r =amdgpu_job_submit_direct (job, ring, &f);
@@ -922,15 +913,15 @@ static int amdgpu_vcn_enc_get_destroy_ms struct dma_fence **fence) {unsigned int ib_size_dw =16 ; +struct amdgpu_device *adev = ring->adev;struct amdgpu_job *job;struct amdgpu_ib *ib;struct dma_fence *f =NULL ;uint32_t *ib_checksum =NULL ;uint64_t addr; -bool sq =amdgpu_vcn_using_unified_queue (ring);int i, r; -if (sq) +if (adev->vcn.using_unified_queue) ib_size_dw +=8 ; r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
@@ -944,7 +935,7 @@ static int amdgpu_vcn_enc_get_destroy_ms ib->length_dw =0 ; -if (sq) +if (adev->vcn.using_unified_queue) ib_checksum =amdgpu_vcn_unified_ring_ib_header (ib,0x11 , true); ib->ptr[ib->length_dw++] =0x00000018 ;
@@ -966,7 +957,7 @@ static int amdgpu_vcn_enc_get_destroy_msfor (i = ib->length_dw; i < ib_size_dw; ++i) ib->ptr[i] =0x0 ; -if (sq) +if (adev->vcn.using_unified_queue)amdgpu_vcn_unified_ring_ib_checksum (&ib_checksum,0x11 ); r =amdgpu_job_submit_direct (job, ring, &f);
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +1 -0
@@ -329,6 +329,7 @@ struct amdgpu_vcn {uint16_t inst_mask;uint8_t num_inst_per_aid; +bool using_unified_queue; };struct amdgpu_fw_shared_rb_ptrs_struct {
Greg Kroah-Hartman
maintainerPATCH 270/273 drm/amdgpu/vcn: not pause dpg for unified queue
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boyuan Zhang <[email protected]>
commit 7d75ef3736a025db441be652c8cc8e84044a215f upstream.
For unified queue, DPG pause for encoding is done inside VCN firmware, so there is no need to pause dpg based on ring type in kernel.
For VCN3 and below, pausing DPG for encoding in kernel is still needed.
v2: add more comments
v3: update commit message
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +11 -3
@@ -393,7 +393,9 @@ static void amdgpu_vcn_idle_work_handlerfor (i =0 ; i < adev->vcn.num_enc_rings; ++i) fence[j] +=amdgpu_fence_count_emitted (&adev->vcn.inst[j].ring_enc[i]); -if (adev->pg_flags &AMD_PG_SUPPORT_VCN_DPG ) { +/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ +if (adev->pg_flags &AMD_PG_SUPPORT_VCN_DPG && + !adev->vcn.using_unified_queue) {struct dpg_pause_state new_state; if (fence[j] ||
@@ -439,7 +441,9 @@ void amdgpu_vcn_ring_begin_use(struct amamdgpu_device_ip_set_powergating_state (adev,AMD_IP_BLOCK_TYPE_VCN ,AMD_PG_STATE_UNGATE ); -if (adev->pg_flags &AMD_PG_SUPPORT_VCN_DPG ) { +/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ +if (adev->pg_flags &AMD_PG_SUPPORT_VCN_DPG && + !adev->vcn.using_unified_queue) {struct dpg_pause_state new_state;if (ring->funcs->type ==AMDGPU_RING_TYPE_VCN_ENC ) {
@@ -465,8 +469,12 @@ void amdgpu_vcn_ring_begin_use(struct amvoid amdgpu_vcn_ring_end_use (struct amdgpu_ring *ring) { +struct amdgpu_device *adev = ring->adev; + +/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ if (ring->adev->pg_flags &AMD_PG_SUPPORT_VCN_DPG && - ring->funcs->type ==AMDGPU_RING_TYPE_VCN_ENC ) + ring->funcs->type ==AMDGPU_RING_TYPE_VCN_ENC && + !adev->vcn.using_unified_queue)atomic_dec (&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);atomic_dec (&ring->adev->vcn.total_submission_cnt);
Greg Kroah-Hartman
maintainerPATCH 271/273 selftests/bpf: Add a test to verify previous stacksafe() fix
In reply to Greg Kroah-Hartman6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
commit 662c3e2db00f92e50c26e9dc4fe47c52223d9982 upstream.
A selftest is added such that without the previous patch, a crash can happen. With the previous patch, the test can run successfully. The new test is written in a way which mimics original crash case:
main_prog
static_prog_1
static_prog_2
where static_prog_1 has different paths to static_prog_2 and some path has stack allocated and some other path does not. A stacksafe() checking in static_prog_2() triggered the crash.
--- tools/testing/selftests/bpf/progs/iters.c | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
tools/testing/selftests/bpf/progs/iters.c +54 -0
@@ -1434,4 +1434,58 @@ int iter_arr_with_actual_elem_count(consreturn sum; } +__u32 upper, select_n, result; +__u64 global; + +static __noinline bool nest_2(char *str) +{ +/* some insns (including branch insns) to ensure stacksafe() is triggered +* in nest_2(). This way, stacksafe() can compare frame associated with nest_1(). +*/ +if (str[0 ] =='t' ) +return true; +if (str[1 ] =='e' ) +return true; +if (str[2 ] =='s' ) +return true; +if (str[3 ] =='t' ) +return true; +return false; +} + +static __noinline bool nest_1(int n) +{ +/* case 0: allocate stack, case 1: no allocate stack */ +switch (n) { +case 0 : { +char comm[16 ]; + +if (bpf_get_current_comm (comm,16 )) +return false; +return nest_2 (comm); + } +case 1 : +return nest_2 ((char *)&global); +default : +return false; + } +} + +SEC("raw_tp") +__success +int iter_subprog_check_stacksafe (const void *ctx) +{ +long i; + + bpf_for(i, 0, upper) { +if (!nest_1 (select_n)) { + result =1 ; +return 0 ; + } + } + + result =2 ; +return 0 ; +} + char _license[] SEC("license") = "GPL";