6.15.5-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainerPATCH 151/263 bnxt: properly flush XDP redirect lists
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yan Zhai <[email protected]>
[ Upstream commit 9caca6ac0e26cd20efd490d8b3b2ffb1c7c00f6f ]
We encountered following crash when testing a XDP_REDIRECT feature in production:
[56251.579676] list_add corruption. next->prev should be prev (ffff93120dd40f30), but was ffffb301ef3a6740. (next=ffff93120dd 40f30). [56251.601413] ------------[ cut here ]------------ [56251.611357] kernel BUG at lib/list_debug.c:29! [56251.621082] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI [56251.632073] CPU: 111 UID: 0 PID: 0 Comm: swapper/111 Kdump: loaded Tainted: P O 6.12.33-cloudflare-2025.6. 3 #1 [56251.653155] Tainted: [P]=PROPRIETARY_MODULE, [O]=OOT_MODULE [56251.663877] Hardware name: MiTAC GC68B-B8032-G11P6-GPU/S8032GM-HE-CFR, BIOS V7.020.B10-sig 01/22/2025 [56251.682626] RIP: 0010:__list_add_valid_or_report+0x4b/0xa0 [56251.693203] Code: 0e 48 c7 c7 68 e7 d9 97 e8 42 16 fe ff 0f 0b 48 8b 52 08 48 39 c2 74 14 48 89 f1 48 c7 c7 90 e7 d9 97 48 89 c6 e8 25 16 fe ff <0f> 0b 4c 8b 02 49 39 f0 74 14 48 89 d1 48 c7 c7 e8 e7 d9 97 4c 89 [56251.725811] RSP: 0018:ffff93120dd40b80 EFLAGS: 00010246 [56251.736094] RAX: 0000000000000075 RBX: ffffb301e6bba9d8 RCX: 0000000000000000 [56251.748260] RDX: 0000000000000000 RSI: ffff9149afda0b80 RDI: ffff9149afda0b80 [56251.760349] RBP: ffff9131e49c8000 R08: 0000000000000000 R09: ffff93120dd40a18 [56251.772382] R10: ffff9159cf2ce1a8 R11: 0000000000000003 R12: ffff911a80850000 [56251.784364] R13: ffff93120fbc7000 R14: 0000000000000010 R15: ffff9139e7510e40 [56251.796278] FS: 0000000000000000(0000) GS:ffff9149afd80000(0000) knlGS:0000000000000000 [56251.809133] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [56251.819561] CR2: 00007f5e85e6f300 CR3: 00000038b85e2006 CR4: 0000000000770ef0 [56251.831365] PKRU: 55555554 [56251.838653] Call Trace: [56251.845560] <IRQ> [56251.851943] cpu_map_enqueue.cold+0x5/0xa [56251.860243] xdp_do_redirect+0x2d9/0x480 [56251.868388] bnxt_rx_xdp+0x1d8/0x4c0 [bnxt_en] [56251.877028] bnxt_rx_pkt+0x5f7/0x19b0 [bnxt_en] [56251.885665] ? cpu_max_write+0x1e/0x100 [56251.893510] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.902276] __bnxt_poll_work+0x190/0x340 [bnxt_en] [56251.911058] bnxt_poll+0xab/0x1b0 [bnxt_en] [56251.919041] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.927568] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.935958] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.944250] __napi_poll+0x2b/0x160 [56251.951155] bpf_trampoline_6442548651+0x79/0x123 [56251.959262] __napi_poll+0x5/0x160 [56251.966037] net_rx_action+0x3d2/0x880 [56251.973133] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.981265] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.989262] ? __hrtimer_run_queues+0x162/0x2a0 [56251.996967] ? srso_alias_return_thunk+0x5/0xfbef5 [56252.004875] ? srso_alias_return_thunk+0x5/0xfbef5 [56252.012673] ? bnxt_msix+0x62/0x70 [bnxt_en] [56252.019903] handle_softirqs+0xcf/0x270 [56252.026650] irq_exit_rcu+0x67/0x90 [56252.032933] common_interrupt+0x85/0xa0 [56252.039498] </IRQ> [56252.044246] <TASK> [56252.048935] asm_common_interrupt+0x26/0x40 [56252.055727] RIP: 0010:cpuidle_enter_state+0xb8/0x420 [56252.063305] Code: dc 01 00 00 e8 f9 79 3b ff e8 64 f7 ff ff 49 89 c5 0f 1f 44 00 00 31 ff e8 a5 32 3a ff 45 84 ff 0f 85 ae 01 00 00 fb 45 85 f6 <0f> 88 88 01 00 00 48 8b 04 24 49 63 ce 4c 89 ea 48 6b f1 68 48 29 [56252.088911] RSP: 0018:ffff93120c97fe98 EFLAGS: 00000202 [56252.096912] RAX: ffff9149afd80000 RBX: ffff9141d3a72800 RCX: 0000000000000000 [56252.106844] RDX: 00003329176c6b98 RSI: ffffffe36db3fdc7 RDI: 0000000000000000 [56252.116733] RBP: 0000000000000002 R08: 0000000000000002 R09: 000000000000004e [56252.126652] R10: ffff9149afdb30c4 R11: 071c71c71c71c71c R12: ffffffff985ff860 [56252.136637] R13: 00003329176c6b98 R14: 0000000000000002 R15: 0000000000000000 [56252.146667] ? cpuidle_enter_state+0xab/0x420 [56252.153909] cpuidle_enter+0x2d/0x40 [56252.160360] do_idle+0x176/0x1c0 [56252.166456] cpu_startup_entry+0x29/0x30 [56252.173248] start_secondary+0xf7/0x100 [56252.179941] common_startup_64+0x13e/0x141 [56252.186886] </TASK>
Quoted 1 line
From the crash dump, we found that the
cpu_map_flush_listinside
redirect info is partially corrupted: its list_head->next points to itself, but list_head->prev points to a valid list of unflushed bq entries.
This turned out to be a result of missed XDP flush on redirect lists. By digging in the actual source code, we found that
commit 7f0a168b0441 ("bnxt_en: Add completion ring pointer in TX and RX ring structures") incorrectly overwrites the event mask for XDP_REDIRECT in bnxt_rx_xdp. We can stably reproduce this crash by returning XDP_TX and XDP_REDIRECT randomly for incoming packets in a naive XDP program. Properly propagate the XDP_REDIRECT events back fixes the crash.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +4 -1
@@ -2958,6 +2958,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, {struct bnxt_napi *bnapi = cpr->bnapi;u32 raw_cons = cpr->cp_raw_cons; +bool flush_xdp = false;u32 cons;int rx_pkts =0 ;u8 event =0 ;
@@ -3011,6 +3012,8 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,else rc =bnxt_force_rx_discard (bp, cpr, &raw_cons, &event); +if (event &BNXT_REDIRECT_EVENT ) + flush_xdp = true;if (likely (rc >=0 )) rx_pkts += rc;/* Increment rx_pkts when rc is -ENOMEM to count towards
@@ -3035,7 +3038,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } } -if (event &BNXT_REDIRECT_EVENT ) { +if (flush_xdp) {xdp_do_flush (); event &= ~BNXT_REDIRECT_EVENT ; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 152/263 um: ubd: Add missing error check in start_io_thread()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
[ Upstream commit c55c7a85e02a7bfee20a3ffebdff7cbeb41613ef ]
The subsequent call to os_set_fd_block() overwrites the previous return value. OR the two return values together to fix it.
--- arch/um/drivers/ubd_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/um/drivers/ubd_user.c +1 -1
@@ -41,7 +41,7 @@ int start_io_thread(struct os_helper_thread **td_out, int *fd_out) *fd_out = fds[1 ]; err =os_set_fd_block (*fd_out,0 ); - err =os_set_fd_block (kernel_fd,0 ); + err |=os_set_fd_block (kernel_fd,0 );if (err) {printk ("start_io_thread - failed to set nonblocking I/O.\n" ); goto out_close;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 153/263 io_uring/net: mark iov as dynamically allocated even for single segments
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
[ Upstream commit 9a709b7e98e6fa51600b5f2d24c5068efa6d39de ]
A bigger array of vecs could've been allocated, but io_ring_buffers_peek() still decided to cap the mapped range depending on how much data was available. Hence don't rely on the segment count to know if the request should be marked as needing cleanup, always check upfront if the iov array is different than the fast_iov array.
--- io_uring/net.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
io_uring/net.c +6 -5
@@ -1084,6 +1084,12 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsgif (unlikely (ret <0 ))return ret; +if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->vec.iovec) { + kmsg->vec.nr = ret; + kmsg->vec.iovec = arg.iovs; + req->flags |=REQ_F_NEED_CLEANUP ; + } +/* special case 1 vec, can be a fast path */ if (ret ==1 ) { sr->buf = arg.iovs[0 ].iov_base;
@@ -1092,11 +1098,6 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg }iov_iter_init (&kmsg->msg.msg_iter,ITER_DEST , arg.iovs, ret, arg.out_len); -if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->vec.iovec) { - kmsg->vec.nr = ret; - kmsg->vec.iovec = arg.iovs; - req->flags |=REQ_F_NEED_CLEANUP ; - } }else {void __user *buf;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 154/263 libbpf: Fix possible use-after-free for externs
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adin Scannell <[email protected]>
[ Upstream commit fa6f092cc0a02d0fcee37e9e8172eda372a03d33 ]
The name field in obj->externs points into the BTF data at initial open time. However, some functions may invalidate this after opening and before loading (e.g. bpf_map__set_value_size), which results in pointers into freed memory and undefined behavior.
The simplest solution is to simply strdup these strings, similar to the essent_name, and free them at the same time.
In order to test this path, the global_map_resize BPF selftest is modified slightly to ensure the presence of an extern, which causes this test to fail prior to the fix. Given there isn't an obvious API or error to test against, I opted to add this to the existing test as an aspect of the resizing feature rather than duplicate the test.
--- tools/lib/bpf/libbpf.c | 10 +++++++--- .../selftests/bpf/progs/test_global_map_resize.c | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-)
tools/lib/bpf/libbpf.c +7 -3
@@ -597,7 +597,7 @@ struct extern_desc {int sym_idx;int btf_id;int sec_btf_id; -const char *name; +char *name;char *essent_name;bool is_set;bool is_weak;
@@ -4259,7 +4259,9 @@ static int bpf_object__collect_externs(struct bpf_object *obj)return ext->btf_id; } t =btf__type_by_id (obj->btf, ext->btf_id); - ext->name =btf__name_by_offset (obj->btf, t->name_off); + ext->name =strdup (btf__name_by_offset (obj->btf, t->name_off)); +if (!ext->name) +return -ENOMEM ; ext->sym_idx = i; ext->is_weak =ELF64_ST_BIND (sym->st_info) ==STB_WEAK ;
@@ -9138,8 +9140,10 @@ void bpf_object__close(struct bpf_object *obj)zfree (&obj->btf_custom_path);zfree (&obj->kconfig); -for (i =0 ; i < obj->nr_extern; i++) +for (i =0 ; i < obj->nr_extern; i++) { +zfree (&obj->externs[i].name);zfree (&obj->externs[i].essent_name); + }zfree (&obj->externs); obj->nr_extern =0 ;
tools/testing/selftests/bpf/progs/test_global_map_resize.c +16 -0
@@ -32,6 +32,16 @@ int my_int_last SEC(".data.array_not_last"); int percpu_arr[1] SEC(".data.percpu_arr"); +/* at least one extern is included, to ensure that a specific +* regression is tested whereby resizing resulted in a free-after-use +* bug after type information is invalidated by the resize operation. +* +* There isn't a particularly good API to test for this specific condition, +* but by having externs for the resizing tests it will cover this path. +*/ +extern int LINUX_KERNEL_VERSION __kconfig; +long version_sink; + SEC("tp/syscalls/sys_enter_getpid")int bss_array_sum (void *ctx) {
@@ -44,6 +54,9 @@ int bss_array_sum(void *ctx)for (size_t i =0 ; i < bss_array_len; ++i) sum += array[i]; +/* see above; ensure this is not optimized out */ + version_sink =LINUX_KERNEL_VERSION ; +return 0 ; }
@@ -59,6 +72,9 @@ int data_array_sum(void *ctx)for (size_t i =0 ; i < data_array_len; ++i) sum += my_array[i]; +/* see above; ensure this is not optimized out */ + version_sink =LINUX_KERNEL_VERSION ; +return 0 ; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 155/263 net: enetc: Correct endianness handling in _enetc_rd_reg64
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Horman <[email protected]>
[ Upstream commit 7b515f35a911fdc31fbde6531828dcd6ae9803d3 ]
enetc_hw.h provides two versions of _enetc_rd_reg64. One which simply calls ioread64() when available.
And another that composes the 64-bit result from ioread32() calls.
In the second case the code appears to assume that each ioread32() call returns a little-endian value. However both the shift and logical or used to compose the return value would not work correctly on big endian systems if this were the case. Moreover, this is inconsistent with the first case where the return value of ioread64() is assumed to be in host byte order.
It appears that the correct approach is for both versions to treat the return value of ioread*() functions as being in host byte order. And this patch corrects the ioread32()-based version to do so.
This is a bug but would only manifest on big endian systems that make use of the ioread32-based implementation of _enetc_rd_reg64. While all in-tree users of this driver are little endian and make use of the ioread64-based implementation of _enetc_rd_reg64. Thus, no in-tree user of this driver is affected by this bug.
Flagged by Sparse.
Compile tested only.
--- drivers/net/ethernet/freescale/enetc/enetc_hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/enetc/enetc_hw.h +1 -1
@@ -507,7 +507,7 @@ static inline u64 _enetc_rd_reg64(void __iomem *reg) tmp = ioread32(reg + 4); }while (high != tmp); -return le64_to_cpu ((__le64 )high <<32 | low); +return (u64 )high <<32 | low; }#endif
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 156/263 netlink: specs: tc: replace underscores with dashes in names
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit eef0eaeca7fa8e358a31e89802f564451b797718 ]
We're trying to add a strict regexp for the name format in the spec. Underscores will not be allowed, dashes should be used instead. This makes no difference to C (codegen, if used, replaces special chars in names) but it gives more uniform naming in Python.
--- Documentation/netlink/specs/tc.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/netlink/specs/tc.yaml +2 -2
@@ -227,7 +227,7 @@ definitions: type: u8 doc: log(P_max / (qth-max - qth-min)) - - name: Scell_log + name: Scell-log type: u8 doc: cell size for idle damping -
@@ -248,7 +248,7 @@ definitions: name: DPs type: u32 - - name: def_DP + name: def-DP type: u32 - name: grio
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 157/263 atm: Release atm_dev_mutex after removing procfs in atm_dev_deregister().
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit a433791aeaea6e84df709e0b9584b9bbe040cd1c ]
syzbot reported a warning below during atm_dev_register(). [0]
Before creating a new device and procfs/sysfs for it, atm_dev_register() looks up a duplicated device by __atm_dev_lookup(). These operations are done under atm_dev_mutex.
However, when removing a device in atm_dev_deregister(), it releases the mutex just after removing the device from the list that __atm_dev_lookup() iterates over.
So, there will be a small race window where the device does not exist on the device list but procfs/sysfs are still not removed, triggering the splat.
Let's hold the mutex until procfs/sysfs are removed in atm_dev_deregister().
[0]:proc_dir_entry 'atm/atmtcp:0' already registered
WARNING: CPU: 0 PID: 5919 at fs/proc/generic.c:377 proc_register+0x455/0x5f0 fs/proc/generic.c:377 Modules linked in: CPU: 0 UID: 0 PID: 5919 Comm: syz-executor284 Not tainted 6.16.0-rc2-syzkaller-00047-g52da431bf03b #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 RIP: 0010:proc_register+0x455/0x5f0 fs/proc/generic.c:377 Code: 48 89 f9 48 c1 e9 03 80 3c 01 00 0f 85 a2 01 00 00 48 8b 44 24 10 48 c7 c7 20 c0 c2 8b 48 8b b0 d8 00 00 00 e8 0c 02 1c ff 90 <0f> 0b 90 90 48 c7 c7 80 f2 82 8e e8 0b de 23 09 48 8b 4c 24 28 48 RSP: 0018:ffffc9000466fa30 EFLAGS: 00010282 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff817ae248 RDX: ffff888026280000 RSI: ffffffff817ae255 RDI: 0000000000000001 RBP: ffff8880232bed48 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000001 R12: ffff888076ed2140 R13: dffffc0000000000 R14: ffff888078a61340 R15: ffffed100edda444 FS: 00007f38b3b0c6c0(0000) GS:ffff888124753000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f38b3bdf953 CR3: 0000000076d58000 CR4: 00000000003526f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> proc_create_data+0xbe/0x110 fs/proc/generic.c:585 atm_proc_dev_register+0x112/0x1e0 net/atm/proc.c:361 atm_dev_register+0x46d/0x890 net/atm/resources.c:113 atmtcp_create+0x77/0x210 drivers/atm/atmtcp.c:369 atmtcp_attach drivers/atm/atmtcp.c:403 [inline] atmtcp_ioctl+0x2f9/0xd60 drivers/atm/atmtcp.c:464 do_vcc_ioctl+0x12c/0x930 net/atm/ioctl.c:159 sock_do_ioctl+0x115/0x280 net/socket.c:1190 sock_ioctl+0x227/0x6b0 net/socket.c:1311 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl fs/ioctl.c:893 [inline] __x64_sys_ioctl+0x18b/0x210 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f38b3b74459 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 51 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f38b3b0c198 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007f38b3bfe318 RCX: 00007f38b3b74459 RDX: 0000000000000000 RSI: 0000000000006180 RDI: 0000000000000005 RBP: 00007f38b3bfe310 R08: 65732f636f72702f R09: 65732f636f72702f R10: 65732f636f72702f R11: 0000000000000246 R12: 00007f38b3bcb0ac R13: 00007f38b3b0c1a0 R14: 0000200000000200 R15: 00007f38b3bcb03b </TASK>
--- net/atm/resources.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/atm/resources.c +1 -2
@@ -146,11 +146,10 @@ void atm_dev_deregister(struct atm_dev *dev)*/ mutex_lock (&atm_dev_mutex);list_del (&dev->dev_list); -mutex_unlock (&atm_dev_mutex); -atm_dev_release_vccs (dev);atm_unregister_sysfs (dev);atm_proc_dev_deregister (dev); +mutex_unlock (&atm_dev_mutex);atm_dev_put (dev); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 158/263 ALSA: hda/realtek: Fix built-in mic on ASUS VivoBook X507UAR
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Salvatore Bonaccorso <[email protected]>
[ Upstream commit 7ab6847a03229e73bb7c58ca397630f699e79b53 ]
The built-in mic of ASUS VivoBook X507UAR is broken recently by the fix of the pin sort. The fixup ALC256_FIXUP_ASUS_MIC_NO_PRESENCE is working for addressing the regression, too.
--- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -11002,6 +11002,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x1043 ,0x1df3 ,"ASUS UM5606WA" ,ALC294_FIXUP_BASS_SPEAKER_15 ),SND_PCI_QUIRK (0x1043 ,0x1264 ,"ASUS UM5606KA" ,ALC294_FIXUP_BASS_SPEAKER_15 ),SND_PCI_QUIRK (0x1043 ,0x1e02 ,"ASUS UX3402ZA" ,ALC245_FIXUP_CS35L41_SPI_2 ), +SND_PCI_QUIRK (0x1043 ,0x1e10 ,"ASUS VivoBook X507UAR" ,ALC256_FIXUP_ASUS_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x1043 ,0x1e11 ,"ASUS Zephyrus G15" ,ALC289_FIXUP_ASUS_GA502 ),SND_PCI_QUIRK (0x1043 ,0x1e12 ,"ASUS UM3402" ,ALC287_FIXUP_CS35L41_I2C_2 ), SND_PCI_QUIRK(0x1043, 0x1e1f, "ASUS Vivobook 15 X1504VAP", ALC2XX_FIXUP_HEADSET_MIC),
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 159/263 net: selftests: fix TCP packet checksum
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 8d89661a36dd3bb8c9902cff36dc0c144dce3faf ]
The length in the pseudo header should be the length of the L3 payload AKA the L4 header+payload. The selftest code builds the packet from the lower layers up, so all the headers are pushed already when it constructs L4. We need to subtract the lower layer headers from skb->len.
--- net/core/selftests.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
net/core/selftests.c +3 -2
@@ -160,8 +160,9 @@ static struct sk_buff *net_test_get_skb(struct net_device *ndev, skb->csum =0 ; skb->ip_summed =CHECKSUM_PARTIAL ;if (attr->tcp) { - thdr->check = ~tcp_v4_check (skb->len, ihdr->saddr, - ihdr->daddr,0 ); +int l4len = skb->len -skb_transport_offset (skb); + + thdr->check = ~tcp_v4_check (l4len, ihdr->saddr, ihdr->daddr,0 ); skb->csum_start =skb_transport_header (skb) - skb->head; skb->csum_offset = offsetof(struct tcphdr , check); }else {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 160/263 nvme: refactor the atomic write unit detection
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit b2e607fecac15e07f50269c080e2e71b5049dfa2 ]
Move all the code out of nvme_update_disk_info into the helper, and rename the helper to have a somewhat less clumsy name.
Stable-dep-of: f46d273449ba ("nvme: fix atomic write size validation")
--- drivers/nvme/host/core.c | 72 +++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 34 deletions(-)
drivers/nvme/host/core.c +38 -34
@@ -1996,21 +1996,51 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl, } -static void nvme_update_atomic_write_disk_info (struct nvme_ns *ns, -struct nvme_id_ns *id,struct queue_limits *lim, -u32 bs,u32 atomic_bs) +static u32 nvme_configure_atomic_write (struct nvme_ns *ns, +struct nvme_id_ns *id,struct queue_limits *lim,u32 bs) { -unsigned int boundary =0 ; +u32 atomic_bs, boundary =0 ; -if (id->nsfeat &NVME_NS_FEAT_ATOMICS && id->nawupf) { -if (le16_to_cpu (id->nabspf)) +/* +* We do not support an offset for the atomic boundaries. +*/ +if (id->nabo) +return bs; + +if ((id->nsfeat &NVME_NS_FEAT_ATOMICS ) && id->nawupf) { +/* +* Use the per-namespace atomic write unit when available. +*/ + atomic_bs = (1 +le16_to_cpu (id->nawupf)) * bs; +if (id->nabspf) boundary = (le16_to_cpu (id->nabspf) +1 ) * bs; + }else { +/* +* Use the controller wide atomic write unit. This sucks +* because the limit is defined in terms of logical blocks while +* namespaces can have different formats, and because there is +* no clear language in the specification prohibiting different +* values for different controllers in the subsystem. +*/ + atomic_bs = (1 + ns->ctrl->awupf) * bs; + } + +if (!ns->ctrl->subsys->atomic_bs) { + ns->ctrl->subsys->atomic_bs = atomic_bs; + }else if (ns->ctrl->subsys->atomic_bs != atomic_bs) { +dev_err_ratelimited (ns->ctrl->device, +"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n" , + ns->disk ? ns->disk->disk_name :"?" , + ns->ctrl->subsys->atomic_bs, + atomic_bs); } + lim->atomic_write_hw_max = atomic_bs; lim->atomic_write_hw_boundary = boundary; lim->atomic_write_hw_unit_min = bs; lim->atomic_write_hw_unit_max =rounddown_pow_of_two (atomic_bs); lim->features |=BLK_FEAT_ATOMIC_WRITES ; +return atomic_bs; }static u32 nvme_max_drv_segments (struct nvme_ctrl *ctrl)
@@ -2048,34 +2078,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id, valid = false; } - atomic_bs = phys_bs = bs; -if (id->nabo ==0 ) { -/* -* Bit 1 indicates whether NAWUPF is defined for this namespace -* and whether it should be used instead of AWUPF. If NAWUPF == -* 0 then AWUPF must be used instead. -*/ -if (id->nsfeat &NVME_NS_FEAT_ATOMICS && id->nawupf) - atomic_bs = (1 +le16_to_cpu (id->nawupf)) * bs; -else - atomic_bs = (1 + ns->ctrl->awupf) * bs; - -/* -* Set subsystem atomic bs. -*/ -if (ns->ctrl->subsys->atomic_bs) { -if (atomic_bs != ns->ctrl->subsys->atomic_bs) { -dev_err_ratelimited (ns->ctrl->device, -"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n" , - ns->disk ? ns->disk->disk_name :"?" , - ns->ctrl->subsys->atomic_bs, - atomic_bs); - } - }else - ns->ctrl->subsys->atomic_bs = atomic_bs; - -nvme_update_atomic_write_disk_info (ns, id, lim, bs, atomic_bs); - } + phys_bs = bs; + atomic_bs =nvme_configure_atomic_write (ns, id, lim, bs);if (id->nsfeat &NVME_NS_FEAT_IO_OPT ) {/* NPWG = Namespace Preferred Write Granularity */
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 161/263 nvme: fix atomic write size validation
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit f46d273449ba65afd53f3dd8fe0182c9df877e08 ]
Don't mix the namespace and controller values, and validate the per-controller limit when probing the controller. This avoid spurious failures for controllers with namespaces that have different namespaces with different logical block sizes, or report the per-namespace values only for some namespaces.
It also fixes a missing queue_limits_cancel_update in an error path by removing that error path.
--- drivers/nvme/host/core.c | 33 +++++++++++---------------------- drivers/nvme/host/nvme.h | 3 +-- 2 files changed, 12 insertions(+), 24 deletions(-)
drivers/nvme/host/core.c +11 -22
@@ -2022,17 +2022,7 @@ static u32 nvme_configure_atomic_write(struct nvme_ns *ns,* no clear language in the specification prohibiting different * values for different controllers in the subsystem. */ - atomic_bs = (1 + ns->ctrl->awupf) * bs; - } - -if (!ns->ctrl->subsys->atomic_bs) { - ns->ctrl->subsys->atomic_bs = atomic_bs; - }else if (ns->ctrl->subsys->atomic_bs != atomic_bs) { -dev_err_ratelimited (ns->ctrl->device, -"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n" , - ns->disk ? ns->disk->disk_name :"?" , - ns->ctrl->subsys->atomic_bs, - atomic_bs); + atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs; } lim->atomic_write_hw_max = atomic_bs;
@@ -2219,16 +2209,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,if (!nvme_update_disk_info (ns, id, &lim)) capacity =0 ; -/* -* Validate the max atomic write size fits within the subsystem's -* atomic write capabilities. -*/ -if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) { -blk_mq_unfreeze_queue (ns->disk->queue, memflags); - ret = -ENXIO ; - goto out; - } -nvme_config_discard (ns, &lim);if (IS_ENABLED (CONFIG_BLK_DEV_ZONED ) && ns->head->ids.csi ==NVME_CSI_ZNS )
@@ -3044,6 +3024,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)memcpy (subsys->model, id->mn,sizeof (subsys->model)); subsys->vendor_id =le16_to_cpu (id->vid); subsys->cmic = id->cmic; + subsys->awupf =le16_to_cpu (id->awupf);/* Versions prior to 1.4 don't necessarily report a valid type */ if (id->cntrltype == NVME_CTRL_DISC ||
@@ -3373,6 +3354,15 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)if (ret) goto out_free; } + +if (le16_to_cpu (id->awupf) != ctrl->subsys->awupf) { +dev_err_ratelimited (ctrl->device, +"inconsistent AWUPF, controller not added (%u/%u).\n" , +le16_to_cpu (id->awupf), ctrl->subsys->awupf); + ret = -EINVAL ; + goto out_free; + } +memcpy (ctrl->subsys->firmware_rev, id->fr,sizeof (ctrl->subsys->firmware_rev));
@@ -3468,7 +3458,6 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)dev_pm_qos_expose_latency_tolerance (ctrl->device); else if (!ctrl->apst_enabled && prev_apst_enabled)dev_pm_qos_hide_latency_tolerance (ctrl->device); - ctrl->awupf =le16_to_cpu (id->awupf); out_free:kfree (id);return ret;
drivers/nvme/host/nvme.h +1 -2
@@ -410,7 +410,6 @@ struct nvme_ctrl {enum nvme_ctrl_type cntrltype;enum nvme_dctype dctype; -u16 awupf;/* 0's based value. */ };static inline enum nvme_ctrl_state nvme_ctrl_state (struct nvme_ctrl *ctrl)
@@ -443,11 +442,11 @@ struct nvme_subsystem {u8 cmic;enum nvme_subsys_type subtype;u16 vendor_id; +u16 awupf;/* 0's based value. */ struct ida ns_ida;#ifdef CONFIG_NVME_MULTIPATH enum nvme_iopolicy iopolicy;#endif -u32 atomic_bs; };/*
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 162/263 riscv: fix runtime constant support for nommu kernels
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Mirabile <[email protected]>
[ Upstream commit 8d90d9872edae7e78c3a12b98e239bfaa66f3639 ]
the __runtime_fixup_32 function does not handle the case where val is zero correctly (as might occur when patching a nommu kernel and referring to a physical address below the 4GiB boundary whose upper 32 bits are all zero) because nothing in the existing logic prevents the code from taking the else branch of both nop-checks and emitting two nop instructions.
This leaves random garbage in the register that is supposed to receive the upper 32 bits of the pointer instead of zero that when combined with the value for the lower 32 bits yields an invalid pointer and causes a kernel panic when that pointer is eventually accessed.
The author clearly considered the fact that if the lui is converted into a nop that the second instruction needs to be adjusted to become an li instead of an addi, hence introducing the addi_insn_mask variable, but didn't follow that logic through fully to the case where the else branch executes. To fix it just adjust the logic to ensure that the second else branch is not taken if the first instruction will be patched to a nop.
--- arch/riscv/include/asm/runtime-const.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/include/asm/runtime-const.h +1 -1
@@ -206,7 +206,7 @@ static inline void __runtime_fixup_32(__le16 *lui_parcel, __le16 *addi_parcel, u addi_insn_mask &=0x07fff ; } -if (lower_immediate &0x00000fff ) { +if (lower_immediate &0x00000fff || lui_insn ==RISCV_INSN_NOP4 ) {/* replace upper 12 bits of addi with lower 12 bits of val */ addi_insn &= addi_insn_mask; addi_insn |= (lower_immediate &0x00000fff ) <<20 ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 163/263 drm: writeback: Fix drm_writeback_connector_cleanup signature
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis Chauvet <[email protected]>
[ Upstream commit fb721b2c35b1829b8ecf62e3adb41cf30260316a ]
The drm_writeback_connector_cleanup have the signature:
static void drm_writeback_connector_cleanup(
struct drm_device *dev,
struct drm_writeback_connector *wb_connector)
But it is stored and used as a drmres_release_t
typedef void (*drmres_release_t)(struct drm_device *dev, void *res);
While the current code is valid and does not produce any warning, the CFI runtime check (CONFIG_CFI_CLANG) can fail because the function signature is not the same as drmres_release_t.
In order to fix this, change the function signature to match what is expected by drmres_release_t.
--- drivers/gpu/drm/drm_writeback.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_writeback.c +4 -3
@@ -343,17 +343,18 @@ EXPORT_SYMBOL(drm_writeback_connector_init_with_encoder);/** * drm_writeback_connector_cleanup - Cleanup the writeback connector * @dev: DRM device -* @wb_connector: Pointer to the writeback connector to clean up +* @data: Pointer to the writeback connector to clean up * * This will decrement the reference counter of blobs and destroy properties. It * will also clean the remaining jobs in this writeback connector. Caution: This helper will not * clean up the attached encoder and the drm_connector. */ static void drm_writeback_connector_cleanup (struct drm_device *dev, -struct drm_writeback_connector *wb_connector) +void *data) {unsigned long flags;struct drm_writeback_job *pos, *n; +struct drm_writeback_connector *wb_connector = data;delete_writeback_properties (dev);drm_property_blob_put (wb_connector->pixel_formats_blob_ptr);
@@ -405,7 +406,7 @@ int drmm_writeback_connector_init(struct drm_device *dev,if (ret)return ret; - ret =drmm_add_action_or_reset (dev, (void *)drm_writeback_connector_cleanup, + ret =drmm_add_action_or_reset (dev, drm_writeback_connector_cleanup, wb_connector);if (ret)return ret;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 164/263 drm/amd: Adjust output for discovery error handling
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit 73eab78721f7b85216f1ca8c7b732f13213b5b32 ]
commit 017fbb6690c2 ("drm/amdgpu/discovery: check ip_discovery fw file available") added support for reading an amdgpu IP discovery bin file for some specific products. If it's not found then it will fallback to hardcoded values. However if it's not found there is also a lot of noise about missing files and errors.
Adjust the error handling to decrease most messages to DEBUG and to show users less about missing files.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +13 -15
@@ -311,10 +311,12 @@ static int amdgpu_discovery_read_binary_from_file(struct amdgpu_device *adev,const struct firmware *fw;int r; - r =request_firmware (&fw, fw_name, adev->dev); + r =firmware_request_nowarn (&fw, fw_name, adev->dev);if (r) { -dev_err (adev->dev,"can't load firmware \"%s\"\n" , - fw_name); +if (amdgpu_discovery ==2 ) +dev_err (adev->dev,"can't load firmware \"%s\"\n" , fw_name); +else +drm_info (&adev->ddev,"Optional firmware \"%s\" was not found\n" , fw_name);return r; }
@@ -449,16 +451,12 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)/* Read from file if it is the preferred option */ fw_name =amdgpu_discovery_get_fw_name (adev);if (fw_name !=NULL ) { -dev_info (adev->dev,"use ip discovery information from file" ); +drm_dbg (&adev->ddev,"use ip discovery information from file" ); r =amdgpu_discovery_read_binary_from_file (adev, adev->mman.discovery_bin, fw_name); - -if (r) { -dev_err (adev->dev,"failed to read ip discovery binary from file\n" ); - r = -EINVAL ; +if (r) goto out; - } - }else { +drm_dbg (&adev->ddev,"use ip discovery information from memory" ); r =amdgpu_discovery_read_binary_from_mem ( adev, adev->mman.discovery_bin);if (r)
@@ -1328,10 +1326,8 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)int r; r =amdgpu_discovery_init (adev); -if (r) { -DRM_ERROR ("amdgpu_discovery_init failed\n" ); +if (r)return r; - } wafl_ver =0 ; adev->gfx.xcc_mask =0 ;
@@ -2569,8 +2565,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)break ;default : r =amdgpu_discovery_reg_base_init (adev); -if (r) -return -EINVAL ; +if (r) { +drm_err (&adev->ddev,"discovery failed: %d\n" , r); +return r; + }amdgpu_discovery_harvest_ip (adev);amdgpu_discovery_get_gfx_info (adev);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 165/263 drm/i915: fix build error some more
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit d02b2103a08b6d6908f1d3d8e8783d3f342555ac ]
An earlier patch fixed a build failure with clang, but I still see the same problem with some configurations using gcc:
drivers/gpu/drm/i915/i915_pmu.c: In function 'config_mask':include/linux/compiler_types.h:568:38: error: call to '__compiletime_assert_462' declared with attribute error: BUILD_BUG_ON failed: bit > BITS_PER_TYPE(typeof_member(struct i915_pmu, enable)) - 1 drivers/gpu/drm/i915/i915_pmu.c:116:3: note: in expansion of macro 'BUILD_BUG_ON'
116 | BUILD_BUG_ON(bit >
As I understand it, the problem is that the function is not always fully inlined, but the __builtin_constant_p() can still evaluate the argument as being constant.
Marking it as __always_inline so far works for me in all configurations.
--- drivers/gpu/drm/i915/i915_pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_pmu.c +1 -1
@@ -108,7 +108,7 @@ static unsigned int config_bit(const u64 config)return other_bit (config); } -static u32 config_mask (const u64 config) +static __always_inline u32 config_mask(const u64 config) {unsigned int bit =config_bit (config);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 166/263 drm/bridge: ti-sn65dsi86: make use of debugfs_init callback
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 1d1f7b15cb9c11974cebfd39da51dc69b8cb31ff ]
Do not create a custom directory in debugfs-root, but use the debugfs_init callback to create a custom directory at the given place for the bridge. The new directory layout looks like this on a Renesas GrayHawk-Single with a R-Car V4M SoC:
/sys/kernel/debug/dri/feb00000.display/DP-1/1-002c
Stable-dep-of: 55e8ff842051 ("drm/bridge: ti-sn65dsi86: Add HPD for DisplayPort connector type")
--- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 40 +++++++-------------------- 1 file changed, 10 insertions(+), 30 deletions(-)
drivers/gpu/drm/bridge/ti-sn65dsi86.c +10 -30
@@ -423,36 +423,8 @@ static int status_show(struct seq_file *s, void *data)return 0 ; } -DEFINE_SHOW_ATTRIBUTE (status); -static void ti_sn65dsi86_debugfs_remove (void *data) -{ -debugfs_remove_recursive (data); -} - -static void ti_sn65dsi86_debugfs_init (struct ti_sn65dsi86 *pdata) -{ -struct device *dev = pdata->dev; -struct dentry *debugfs; -int ret; - - debugfs =debugfs_create_dir (dev_name (dev),NULL ); - -/* -* We might get an error back if debugfs wasn't enabled in the kernel -* so let's just silently return upon failure. -*/ -if (IS_ERR_OR_NULL (debugfs)) -return ; - - ret =devm_add_action_or_reset (dev, ti_sn65dsi86_debugfs_remove, debugfs); -if (ret) -return ; - -debugfs_create_file ("status" ,0600 , debugfs, pdata, &status_fops); -} -/* ----------------------------------------------------------------------------- * Auxiliary Devices (*not* AUX) */
@@ -1216,6 +1188,15 @@ static const struct drm_edid *ti_sn_bridge_edid_read(struct drm_bridge *bridge,return drm_edid_read_ddc (connector, &pdata->aux.ddc); } +static void ti_sn65dsi86_debugfs_init (struct drm_bridge *bridge,struct dentry *root) +{ +struct ti_sn65dsi86 *pdata =bridge_to_ti_sn65dsi86 (bridge); +struct dentry *debugfs; + + debugfs =debugfs_create_dir (dev_name (pdata->dev), root); +debugfs_create_file ("status" ,0600 , debugfs, pdata, &status_fops); +} +static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach,
@@ -1229,6 +1210,7 @@ static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .atomic_reset = drm_atomic_helper_bridge_reset, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .debugfs_init = ti_sn65dsi86_debugfs_init, }; static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata,
@@ -1937,8 +1919,6 @@ static int ti_sn65dsi86_probe(struct i2c_client *client)if (ret)return ret; -ti_sn65dsi86_debugfs_init (pdata); -/* * Break ourselves up into a collection of aux devices. The only real * motiviation here is to solve the chicken-and-egg problem of probe
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 167/263 drm/bridge: ti-sn65dsi86: Add HPD for DisplayPort connector type
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jayesh Choudhary <[email protected]>
[ Upstream commit 55e8ff842051b1150461d7595d8f1d033c69d66b ]
By default, HPD was disabled on SN65DSI86 bridge. When the driver was added (commit "a095f15c00e27"), the HPD_DISABLE bit was set in pre-enable call which was moved to other function calls subsequently. Later on, commit "c312b0df3b13" added detect utility for DP mode. But with HPD_DISABLE bit set, all the HPD events are disabled[0] and the debounced state always return 1 (always connected state).
Set HPD_DISABLE bit conditionally based on display sink's connector type. Since the HPD_STATE is reflected correctly only after waiting for debounce time (~100-400ms) and adding this delay in detect() is not feasible owing to the performace impact (glitches and frame drop), remove runtime calls in detect() and add hpd_enable()/disable() bridge hooks with runtime calls, to detect hpd properly without any delay.
[0]: <https://www.ti.com/lit/gpn/SN65DSI86> (Pg. 32)
--- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 69 +++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 9 deletions(-)
drivers/gpu/drm/bridge/ti-sn65dsi86.c +60 -9
@@ -330,12 +330,18 @@ static void ti_sn65dsi86_enable_comms(struct ti_sn65dsi86 *pdata)* 200 ms. We'll assume that the panel driver will have the hardcoded * delay in its prepare and always disable HPD. * -* If HPD somehow makes sense on some future panel we'll have to -* change this to be conditional on someone specifying that HPD should -* be used. +* For DisplayPort bridge type, we need HPD. So we use the bridge type +* to conditionally disable HPD. +* NOTE: The bridge type is set in ti_sn_bridge_probe() but enable_comms() +* can be called before. So for DisplayPort, HPD will be enabled once +* bridge type is set. We are using bridge type instead of "no-hpd" +* property because it is not used properly in devicetree description +* and hence is unreliable. */ -regmap_update_bits (pdata->regmap,SN_HPD_DISABLE_REG ,HPD_DISABLE , -HPD_DISABLE ); + +if (pdata->bridge.type != DRM_MODE_CONNECTOR_DisplayPort) +regmap_update_bits (pdata->regmap,SN_HPD_DISABLE_REG ,HPD_DISABLE , +HPD_DISABLE ); pdata->comms_enabled = true;
@@ -1172,9 +1178,14 @@ static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge)struct ti_sn65dsi86 *pdata =bridge_to_ti_sn65dsi86 (bridge);int val =0 ; -pm_runtime_get_sync (pdata->dev); +/* +* Runtime reference is grabbed in ti_sn_bridge_hpd_enable() +* as the chip won't report HPD just after being powered on. +* HPD_DEBOUNCED_STATE reflects correct state only after the +* debounce time (~100-400 ms). +*/ +regmap_read (pdata->regmap,SN_HPD_DISABLE_REG , &val); -pm_runtime_put_autosuspend (pdata->dev);return val &HPD_DEBOUNCED_STATE ? connector_status_connected : connector_status_disconnected;
@@ -1197,6 +1208,26 @@ static void ti_sn65dsi86_debugfs_init(struct drm_bridge *bridge, struct dentry *debugfs_create_file ("status" ,0600 , debugfs, pdata, &status_fops); } +static void ti_sn_bridge_hpd_enable (struct drm_bridge *bridge) +{ +struct ti_sn65dsi86 *pdata =bridge_to_ti_sn65dsi86 (bridge); + +/* +* Device needs to be powered on before reading the HPD state +* for reliable hpd detection in ti_sn_bridge_detect() due to +* the high debounce time. +*/ + +pm_runtime_get_sync (pdata->dev); +} + +static void ti_sn_bridge_hpd_disable (struct drm_bridge *bridge) +{ +struct ti_sn65dsi86 *pdata =bridge_to_ti_sn65dsi86 (bridge); + +pm_runtime_put_autosuspend (pdata->dev); +} +static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .attach = ti_sn_bridge_attach, .detach = ti_sn_bridge_detach,
@@ -1211,6 +1242,8 @@ static const struct drm_bridge_funcs ti_sn_bridge_funcs = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .debugfs_init = ti_sn65dsi86_debugfs_init, + .hpd_enable = ti_sn_bridge_hpd_enable, + .hpd_disable = ti_sn_bridge_hpd_disable, }; static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata,
@@ -1299,8 +1332,26 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; -if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) - pdata->bridge.ops =DRM_BRIDGE_OP_EDID |DRM_BRIDGE_OP_DETECT ; +if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) { + pdata->bridge.ops =DRM_BRIDGE_OP_EDID |DRM_BRIDGE_OP_DETECT | +DRM_BRIDGE_OP_HPD ; +/* +* If comms were already enabled they would have been enabled +* with the wrong value of HPD_DISABLE. Update it now. Comms +* could be enabled if anyone is holding a pm_runtime reference +* (like if a GPIO is in use). Note that in most cases nobody +* is doing AUX channel xfers before the bridge is added so +* HPD doesn't _really_ matter then. The only exception is in +* the eDP case where the panel wants to read the EDID before +* the bridge is added. We always consistently have HPD disabled +* for eDP. +*/ +mutex_lock (&pdata->comms_mutex); +if (pdata->comms_enabled) +regmap_update_bits (pdata->regmap,SN_HPD_DISABLE_REG , +HPD_DISABLE ,0 ); +mutex_unlock (&pdata->comms_mutex); + };drm_bridge_add (&pdata->bridge);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 168/263 drm/xe/guc: Explicitly exit CT safe mode on unwind
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit ad40098da5c3b43114d860a5b5740e7204158534 ]
During driver probe we might be briefly using CT safe mode, which is based on a delayed work, but usually we are able to stop this once we have IRQ fully operational. However, if we abort the probe quite early then during unwind we might try to destroy the workqueue while there is still a pending delayed work that attempts to restart itself which triggers a WARN.
This was recently observed during unsuccessful VF initialization:
[ ] xe 0000:00:02.1: probe with driver xe failed with error -62
[ ] ------------[ cut here ]------------
[ ] workqueue: cannot queue safe_mode_worker_func [xe] on wq xe-g2h-wq [ ] WARNING: CPU: 9 PID: 0 at kernel/workqueue.c:2257 __queue_work+0x287/0x710 [ ] RIP: 0010:__queue_work+0x287/0x710
[ ] Call Trace:
[ ] delayed_work_timer_fn+0x19/0x30
[ ] call_timer_fn+0xa1/0x2a0
Exit the CT safe mode on unwind to avoid that warning.
--- drivers/gpu/drm/xe/xe_guc_ct.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_guc_ct.c +6 -4
@@ -34,6 +34,11 @@#include "xe_pm.h" #include "xe_trace_guc.h" +static void receive_g2h (struct xe_guc_ct *ct); +static void g2h_worker_func (struct work_struct *w); +static void safe_mode_worker_func (struct work_struct *w); +static void ct_exit_safe_mode (struct xe_guc_ct *ct); +#if IS_ENABLED (CONFIG_DRM_XE_DEBUG )enum { /* Internal states, not error conditions */
@@ -186,14 +191,11 @@ static void guc_ct_fini(struct drm_device *drm, void *arg) {struct xe_guc_ct *ct = arg; +ct_exit_safe_mode (ct);destroy_workqueue (ct->g2h_wq);xa_destroy (&ct->fence_lookup); } -static void receive_g2h (struct xe_guc_ct *ct); -static void g2h_worker_func (struct work_struct *w); -static void safe_mode_worker_func (struct work_struct *w); -static void primelockdep (struct xe_guc_ct *ct) {if (!IS_ENABLED (CONFIG_LOCKDEP ))
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 169/263 drm/xe: Process deferred GGTT node removals on device unwind
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit af2b588abe006bd55ddd358c4c3b87523349c475 ]
While we are indirectly draining our dedicated workqueue ggtt->wq that we use to complete asynchronous removal of some GGTT nodes, this happends as part of the managed-drm unwinding (ggtt_fini_early), which could be later then manage-device unwinding, where we could already unmap our MMIO/GMS mapping (mmio_fini).
This was recently observed during unsuccessful VF initialization:
[ ] xe 0000:00:02.1: probe with driver xe failed with error -62
[ ] xe 0000:00:02.1: DEVRES REL ffff88811e747340 __xe_bo_unpin_map_no_vm (16 bytes) [ ] xe 0000:00:02.1: DEVRES REL ffff88811e747540 __xe_bo_unpin_map_no_vm (16 bytes) [ ] xe 0000:00:02.1: DEVRES REL ffff88811e747240 __xe_bo_unpin_map_no_vm (16 bytes) [ ] xe 0000:00:02.1: DEVRES REL ffff88811e747040 tiles_fini (16 bytes)
[ ] xe 0000:00:02.1: DEVRES REL ffff88811e746840 mmio_fini (16 bytes)
[ ] xe 0000:00:02.1: DEVRES REL ffff88811e747f40 xe_bo_pinned_fini (16 bytes)
[ ] xe 0000:00:02.1: DEVRES REL ffff88811e746b40 devm_drm_dev_init_release (16 bytes) [ ] xe 0000:00:02.1: [drm:drm_managed_release] drmres release begin
[ ] xe 0000:00:02.1: [drm:drm_managed_release] REL ffff88810ef81640 __fini_relay (8 bytes) [ ] xe 0000:00:02.1: [drm:drm_managed_release] REL ffff88810ef80d40 guc_ct_fini (8 bytes) [ ] xe 0000:00:02.1: [drm:drm_managed_release] REL ffff88810ef80040 __drmm_mutex_release (8 bytes) [ ] xe 0000:00:02.1: [drm:drm_managed_release] REL ffff88810ef80140 ggtt_fini_early (8 bytes)
and this was leading to:
[ ] BUG: unable to handle page fault for address: ffffc900058162a0 [ ] #PF: supervisor write access in kernel mode
[ ] #PF: error_code(0x0002) - not-present page
[ ] Oops: Oops: 0002 [#1] SMP NOPTI
[ ] Tainted: [W]=WARN
[ ] Workqueue: xe-ggtt-wq ggtt_node_remove_work_func [xe] [ ] RIP: 0010:xe_ggtt_set_pte+0x6d/0x350 [xe]
[ ] Call Trace:
[ ] <TASK> [ ] xe_ggtt_clear+0xb0/0x270 [xe] [ ] ggtt_node_remove+0xbb/0x120 [xe] [ ] ggtt_node_remove_work_func+0x30/0x50 [xe] [ ] process_one_work+0x22b/0x6f0 [ ] worker_thread+0x1e8/0x3d
Add managed-device action that will explicitly drain the workqueue with all pending node removals prior to releasing MMIO/GSM mapping.
--- drivers/gpu/drm/xe/xe_ggtt.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/gpu/drm/xe/xe_ggtt.c +11 -0
@@ -201,6 +201,13 @@ static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = { .ggtt_set_pte = xe_ggtt_set_pte_and_flush, }; +static void dev_fini_ggtt (void *arg) +{ +struct xe_ggtt *ggtt = arg; + +drain_workqueue (ggtt->wq); +} +/** * xe_ggtt_init_early - Early GGTT initialization * @ggtt: the &xe_ggtt to be initialized
@@ -257,6 +264,10 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)if (err)return err; + err =devm_add_action_or_reset (xe->drm.dev, dev_fini_ggtt, ggtt); +if (err) +return err; +if (IS_SRIOV_VF (xe)) { err =xe_gt_sriov_vf_prepare_ggtt (xe_tile_get_gt (ggtt->tile,0 ));if (err)
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 170/263 smb: client: fix potential deadlock when reconnecting channels
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
[ Upstream commit 711741f94ac3cf9f4e3aa73aa171e76d188c0819 ]
Fix cifs_signal_cifsd_for_reconnect() to take the correct lock order and prevent the following deadlock from happening
======================================================
WARNING: possible circular locking dependency detected
6.16.0-rc3-build2+ #1301 Tainted: G S W
------------------------------------------------------
cifsd/6055 is trying to acquire lock:ffff88810ad56038 (&tcp_ses->srv_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x134/0x200
but task is already holding lock:ffff888119c64330 (&ret_buf->chan_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0xcf/0x200
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&ret_buf->chan_lock){+.+.}-{3:3}:
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_setup_session+0x81/0x4b0
cifs_get_smb_ses+0x771/0x900
cifs_mount_get_session+0x7e/0x170
cifs_mount+0x92/0x2d0
cifs_smb3_do_mount+0x161/0x460
smb3_get_tree+0x55/0x90
vfs_get_tree+0x46/0x180
do_new_mount+0x1b0/0x2e0
path_mount+0x6ee/0x740
do_mount+0x98/0xe0
__do_sys_mount+0x148/0x180
do_syscall_64+0xa4/0x260
entry_SYSCALL_64_after_hwframe+0x76/0x7e-> #1 (&ret_buf->ses_lock){+.+.}-{3:3}:
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_match_super+0x101/0x320
sget+0xab/0x270
cifs_smb3_do_mount+0x1e0/0x460
smb3_get_tree+0x55/0x90
vfs_get_tree+0x46/0x180
do_new_mount+0x1b0/0x2e0
path_mount+0x6ee/0x740
do_mount+0x98/0xe0
__do_sys_mount+0x148/0x180
do_syscall_64+0xa4/0x260
entry_SYSCALL_64_after_hwframe+0x76/0x7e-> #0 (&tcp_ses->srv_lock){+.+.}-{3:3}:
check_noncircular+0x95/0xc0
check_prev_add+0x115/0x2f0
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_signal_cifsd_for_reconnect+0x134/0x200
__cifs_reconnect+0x8f/0x500
cifs_handle_standard+0x112/0x280
cifs_demultiplex_thread+0x64d/0xbc0
kthread+0x2f7/0x310
ret_from_fork+0x2a/0x230
ret_from_fork_asm+0x1a/0x30other info that might help us debug this:
Chain exists of: &tcp_ses->srv_lock --> &ret_buf->ses_lock --> &ret_buf->chan_lock Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&ret_buf->chan_lock);
lock(&ret_buf->ses_lock);
lock(&ret_buf->chan_lock); lock(&tcp_ses->srv_lock);
*** DEADLOCK ***
3 locks held by cifsd/6055:
#0: ffffffff857de398 (&cifs_tcp_ses_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x7b/0x200 #1: ffff888119c64060 (&ret_buf->ses_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x9c/0x200 #2: ffff888119c64330 (&ret_buf->chan_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0xcf/0x200
--- fs/smb/client/cifsglob.h | 1 + fs/smb/client/connect.c | 58 +++++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 22 deletions(-)
fs/smb/client/cifsglob.h +1 -0
@@ -709,6 +709,7 @@ inc_rfc1001_len(void *buf, int count)struct TCP_Server_Info {struct list_head tcp_ses_list;struct list_head smb_ses_list; +struct list_head rlist;/* reconnect list */ spinlock_t srv_lock;/* protect anything here that is not protected */ __u64 conn_id;/* connection identifier (useful for debugging) */ int srv_count;/* reference counter */
fs/smb/client/connect.c +36 -22
81 lines not on this page · raw message
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 171/263 EDAC/amd64: Fix size calculation for Non-Power-of-Two DIMMs
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Avadhut Naik <[email protected]>
commit a3f3040657417aeadb9622c629d4a0c2693a0f93 upstream.
Each Chip-Select (CS) of a Unified Memory Controller (UMC) on AMD Zen-based SOCs has an Address Mask and a Secondary Address Mask register associated with it. The amd64_edac module logs DIMM sizes on a per-UMC per-CS granularity during init using these two registers.
Currently, the module primarily considers only the Address Mask register for computing DIMM sizes. The Secondary Address Mask register is only considered for odd CS. Additionally, if it has been considered, the Address Mask register is ignored altogether for that CS. For power-of-two DIMMs i.e. DIMMs whose total capacity is a power of two (32GB, 64GB, etc), this is not an issue since only the Address Mask register is used.
For non-power-of-two DIMMs i.e., DIMMs whose total capacity is not a power of two (48GB, 96GB, etc), however, the Secondary Address Mask register is used in conjunction with the Address Mask register. However, since the module only considers either of the two registers for a CS, the size computed by the module is incorrect. The Secondary Address Mask register is not considered for even CS, and the Address Mask register is not considered for odd CS.
Introduce a new helper function so that both Address Mask and Secondary Address Mask registers are considered, when valid, for computing DIMM sizes. Furthermore, also rename some variables for greater clarity.
--- drivers/edac/amd64_edac.c | 57 +++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 21 deletions(-)
drivers/edac/amd64_edac.c +36 -21
@@ -1209,7 +1209,9 @@ static int umc_get_cs_mode(int dimm, u8if (csrow_enabled (2 * dimm +1 , ctrl, pvt)) cs_mode |=CS_ODD_PRIMARY ; -/* Asymmetric dual-rank DIMM support. */ +if (csrow_sec_enabled (2 * dimm, ctrl, pvt)) + cs_mode |=CS_EVEN_SECONDARY ; +if (csrow_sec_enabled (2 * dimm +1 , ctrl, pvt)) cs_mode |=CS_ODD_SECONDARY ;
@@ -1230,12 +1232,13 @@ static int umc_get_cs_mode(int dimm, u8return cs_mode; } -static int __addr_mask_to_cs_size (u32 addr_mask_orig,unsigned int cs_mode, -int csrow_nr,int dimm) +static int calculate_cs_size (u32 mask,unsigned int cs_mode) { -u32 msb, weight, num_zero_bits; -u32 addr_mask_deinterleaved; -int size =0 ; +int msb, weight, num_zero_bits; +u32 deinterleaved_mask; + +if (!mask) +return 0 ;/* * The number of zero bits in the mask is equal to the number of bits
@@ -1248,19 +1251,30 @@ static int __addr_mask_to_cs_size(u32 ad* without swapping with the most significant bit. This can be handled * by keeping the MSB where it is and ignoring the single zero bit. */ - msb =fls (addr_mask_orig) -1 ; - weight =hweight_long (addr_mask_orig); + msb =fls (mask) -1 ; + weight =hweight_long (mask); num_zero_bits = msb - weight - !!(cs_mode &CS_3R_INTERLEAVE );/* Take the number of zero bits off from the top of the mask. */ - addr_mask_deinterleaved =GENMASK_ULL (msb - num_zero_bits,1 ); + deinterleaved_mask =GENMASK (msb - num_zero_bits,1 ); +edac_dbg (1 ," Deinterleaved AddrMask: 0x%x\n" , deinterleaved_mask); + +return (deinterleaved_mask >>2 ) +1 ; +} + +static int __addr_mask_to_cs_size (u32 addr_mask,u32 addr_mask_sec, +unsigned int cs_mode,int csrow_nr,int dimm) +{ +int size;edac_dbg (1 ,"CS%d DIMM%d AddrMasks:\n" , csrow_nr, dimm); -edac_dbg (1 ," Original AddrMask: 0x%x\n" , addr_mask_orig); -edac_dbg (1 ," Deinterleaved AddrMask: 0x%x\n" , addr_mask_deinterleaved); +edac_dbg (1 ," Primary AddrMask: 0x%x\n" , addr_mask);/* Register [31:1] = Address [39:9]. Size is in kBs here. */ - size = (addr_mask_deinterleaved >>2 ) +1 ; + size =calculate_cs_size (addr_mask, cs_mode); + +edac_dbg (1 ," Secondary AddrMask: 0x%x\n" , addr_mask_sec); + size +=calculate_cs_size (addr_mask_sec, cs_mode);/* Return size in MBs. */ return size >>10 ;
@@ -1269,8 +1283,8 @@ static int __addr_mask_to_cs_size(u32 adstatic int umc_addr_mask_to_cs_size (struct amd64_pvt *pvt,u8 umc,unsigned int cs_mode,int csrow_nr) { +u32 addr_mask =0 , addr_mask_sec =0 ;int cs_mask_nr = csrow_nr; -u32 addr_mask_orig;int dimm, size =0 ;/* No Chip Selects are enabled. */
@@ -1308,13 +1322,13 @@ static int umc_addr_mask_to_cs_size(struif (!pvt->flags.zn_regs_v2) cs_mask_nr >>=1 ; -/* Asymmetric dual-rank DIMM support. */ -if ((csrow_nr &1 ) && (cs_mode &CS_ODD_SECONDARY )) - addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr]; -else - addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr]; +if (cs_mode & (CS_EVEN_PRIMARY |CS_ODD_PRIMARY )) + addr_mask = pvt->csels[umc].csmasks[cs_mask_nr]; + +if (cs_mode & (CS_EVEN_SECONDARY |CS_ODD_SECONDARY )) + addr_mask_sec = pvt->csels[umc].csmasks_sec[cs_mask_nr]; -return __addr_mask_to_cs_size (addr_mask_orig, cs_mode, csrow_nr, dimm); +return __addr_mask_to_cs_size (addr_mask, addr_mask_sec, cs_mode, csrow_nr, dimm); }static void umc_debug_display_dimm_sizes (struct amd64_pvt *pvt,u8 ctrl)
@@ -3512,9 +3526,10 @@ static void gpu_get_err_info(struct mcestatic int gpu_addr_mask_to_cs_size (struct amd64_pvt *pvt,u8 umc,unsigned int cs_mode,int csrow_nr) { -u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr]; +u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr]; +u32 addr_mask_sec = pvt->csels[umc].csmasks_sec[csrow_nr]; -return __addr_mask_to_cs_size (addr_mask_orig, cs_mode, csrow_nr, csrow_nr >>1 ); +return __addr_mask_to_cs_size (addr_mask, addr_mask_sec, cs_mode, csrow_nr, csrow_nr >>1 ); }static void gpu_debug_display_dimm_sizes (struct amd64_pvt *pvt,u8 ctrl)
Greg Kroah-Hartman
maintainerPATCH 172/263 x86/traps: Initialize DR6 by writing its architectural reset value
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Li (Intel) <[email protected]>
commit 5f465c148c61e876b6d6eacd8e8e365f2d47758f upstream.
Initialize DR6 by writing its architectural reset value to avoid incorrectly zeroing DR6 to clear DR6.BLD at boot time, which leads to a false bus lock detected warning.
The Intel SDM says:
1) Certain debug exceptions may clear bits 0-3 of DR6.
2) BLD induced #DB clears DR6.BLD and any other debug exception doesn't modify DR6.BLD.
3) RTM induced #DB clears DR6.RTM and any other debug exception sets DR6.RTM.
To avoid confusion in identifying debug exceptions, debug handlers should set DR6.BLD and DR6.RTM, and clear other DR6 bits before returning.
The DR6 architectural reset value 0xFFFF0FF0, already defined as macro DR6_RESERVED, satisfies these requirements, so just use it to reinitialize DR6 whenever needed.
Since clear_all_debug_regs() no longer zeros all debug registers, rename it to initialize_debug_regs() to better reflect its current behavior.
Since debug_read_clear_dr6() no longer clears DR6, rename it to debug_read_reset_dr6() to better reflect its current behavior.
--- arch/x86/include/uapi/asm/debugreg.h | 21 ++++++++++++++++++++- arch/x86/kernel/cpu/common.c | 24 ++++++++++-------------- arch/x86/kernel/traps.c | 34 +++++++++++++++++++++------------- 3 files changed, 51 insertions(+), 28 deletions(-)
arch/x86/include/uapi/asm/debugreg.h +20 -1
@@ -15,7 +15,26 @@which debugging register was responsible for the trap. The other bits are either reserved or not of interest to us. */ -/* Define reserved bits in DR6 which are always set to 1 */ +/* +* Define bits in DR6 which are set to 1 by default. +* +* This is also the DR6 architectural value following Power-up, Reset or INIT. +* +* Note, with the introduction of Bus Lock Detection (BLD) and Restricted +* Transactional Memory (RTM), the DR6 register has been modified: +* +* 1) BLD flag (bit 11) is no longer reserved to 1 if the CPU supports +* Bus Lock Detection. The assertion of a bus lock could clear it. +* +* 2) RTM flag (bit 16) is no longer reserved to 1 if the CPU supports +* restricted transactional memory. #DB occurred inside an RTM region +* could clear it. +* +* Apparently, DR6.BLD and DR6.RTM are active low bits. +* +* As a result, DR6_RESERVED is an incorrect name now, but it is kept for +* compatibility. +*/ #define DR6_RESERVED (0xFFFF0FF0)#define DR_TRAP0 (0x1)/* db0 */
arch/x86/kernel/cpu/common.c +10 -14
@@ -2205,20 +2205,16 @@ EXPORT_PER_CPU_SYMBOL(__stack_chk_guard)#endif #endif -/* -* Clear all 6 debug registers: -*/ -static void clear_all_debug_regs (void ) +static void initialize_debug_regs (void ) { -int i; - -for (i =0 ; i <8 ; i++) { -/* Ignore db4, db5 */ -if ((i ==4 ) || (i ==5 )) -continue ; - -set_debugreg (0 , i); - } +/* Control register first -- to make sure everything is disabled. */ +set_debugreg (0 ,7 ); +set_debugreg (DR6_RESERVED ,6 ); +/* dr5 and dr4 don't exist */ +set_debugreg (0 ,3 ); +set_debugreg (0 ,2 ); +set_debugreg (0 ,1 ); +set_debugreg (0 ,0 ); }#ifdef CONFIG_KGDB
@@ -2379,7 +2375,7 @@ void cpu_init(void)load_mm_ldt (&init_mm); -clear_all_debug_regs (); +initialize_debug_regs ();dbg_restore_debug_regs ();doublefault_init_cpu_tss ();
arch/x86/kernel/traps.c +21 -13
@@ -1021,24 +1021,32 @@ static bool is_sysenter_singlestep(struc#endif } -static __always_inline unsigned long debug_read_clear_dr6 (void ) +static __always_inline unsigned long debug_read_reset_dr6 (void ) {unsigned long dr6; +get_debugreg (dr6,6 ); + dr6 ^=DR6_RESERVED ;/* Flip to positive polarity */ +/* * The Intel SDM says: * -* Certain debug exceptions may clear bits 0-3. The remaining -* contents of the DR6 register are never cleared by the -* processor. To avoid confusion in identifying debug -* exceptions, debug handlers should clear the register before -* returning to the interrupted task. +* Certain debug exceptions may clear bits 0-3 of DR6. +* +* BLD induced #DB clears DR6.BLD and any other debug +* exception doesn't modify DR6.BLD. * -* Keep it simple: clear DR6 immediately. +* RTM induced #DB clears DR6.RTM and any other debug +* exception sets DR6.RTM. +* +* To avoid confusion in identifying debug exceptions, +* debug handlers should set DR6.BLD and DR6.RTM, and +* clear other DR6 bits before returning. +* +* Keep it simple: write DR6 with its architectural reset +* value 0xFFFF0FF0, defined as DR6_RESERVED, immediately. */ -get_debugreg (dr6,6 );set_debugreg (DR6_RESERVED ,6 ); - dr6 ^=DR6_RESERVED ;/* Flip to positive polarity */ return dr6; }
@@ -1238,13 +1246,13 @@ out:/* IST stack entry */ DEFINE_IDTENTRY_DEBUG (exc_debug) { -exc_debug_kernel (regs,debug_read_clear_dr6 ()); +exc_debug_kernel (regs,debug_read_reset_dr6 ()); }/* User entry, runs on regular task stack */ DEFINE_IDTENTRY_DEBUG_USER (exc_debug) { -exc_debug_user (regs,debug_read_clear_dr6 ()); +exc_debug_user (regs,debug_read_reset_dr6 ()); }#ifdef CONFIG_X86_FRED
@@ -1263,7 +1271,7 @@ DEFINE_FREDENTRY_DEBUG(exc_debug) {/* * FRED #DB stores DR6 on the stack in the format which -* debug_read_clear_dr6() returns for the IDT entry points. +* debug_read_reset_dr6() returns for the IDT entry points. */ unsigned long dr6 =fred_event_data (regs);
@@ -1278,7 +1286,7 @@ DEFINE_FREDENTRY_DEBUG(exc_debug)/* 32 bit does not have separate entry points. */ DEFINE_IDTENTRY_RAW (exc_debug) { -unsigned long dr6 =debug_read_clear_dr6 (); +unsigned long dr6 =debug_read_reset_dr6 ();if (user_mode (regs))exc_debug_user (regs, dr6);
Greg Kroah-Hartman
maintainerPATCH 173/263 staging: rtl8723bs: Avoid memset() in aes_cipher() and aes_decipher()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit a55bc4ffc06d8c965a7d6f0a01ed0ed41380df28 upstream.
After commit 6f110a5e4f99 ("Disable SLUB_TINY for build testing"), which causes CONFIG_KASAN to be enabled in allmodconfig again, arm64 allmodconfig builds with older versions of clang (15 through 17) show an instance of -Wframe-larger-than (which breaks the build with CONFIG_WERROR=y):
drivers/staging/rtl8723bs/core/rtw_security.c:1287:5: error: stack frame size (2208) exceeds limit (2048) in 'rtw_aes_decrypt' [-Werror,-Wframe-larger-than]
1287 | u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
| ^
This comes from aes_decipher() being inlined in rtw_aes_decrypt(). Running the same build with CONFIG_FRAME_WARN=128 shows aes_cipher() also uses a decent amount of stack, just under the limit of 2048:
drivers/staging/rtl8723bs/core/rtw_security.c:864:19: warning: stack frame size (1952) exceeds limit (128) in 'aes_cipher' [-Wframe-larger-than]
864 | static signed int aes_cipher(u8 *key, uint hdrlen,
| ^
-Rpass-analysis=stack-frame-layout only shows one large structure on the stack, which is the ctx variable inlined from aes128k128d(). A good number of the other variables come from the additional checks of fortified string routines, which are present in memset(), which both aes_cipher() and aes_decipher() use to initialize some temporary buffers. In this case, since the size is known at compile time, these additional checks should not result in any code generation changes but allmodconfig has several sanitizers enabled, which may make it harder for the compiler to eliminate the compile time checks and the variables that come about from them.
The memset() calls are just initializing these buffers to zero, so use '= {}' instead, which is used all over the kernel and does the exact same thing as memset() without the fortify checks, which drops the stack usage of these functions by a few hundred kilobytes.
drivers/staging/rtl8723bs/core/rtw_security.c:864:19: warning: stack frame size (1584) exceeds limit (128) in 'aes_cipher' [-Wframe-larger-than]
864 | static signed int aes_cipher(u8 *key, uint hdrlen,
| ^
drivers/staging/rtl8723bs/core/rtw_security.c:1271:5: warning: stack frame size (1456) exceeds limit (128) in 'rtw_aes_decrypt' [-Wframe-larger-than]
1271 | u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
| ^
--- drivers/staging/rtl8723bs/core/rtw_security.c | 44 ++++++++------------------ 1 file changed, 14 insertions(+), 30 deletions(-)
drivers/staging/rtl8723bs/core/rtw_security.c +14 -30
@@ -868,29 +868,21 @@ static signed int aes_cipher(u8 *key, ui num_blocks, payload_index;u8 pn_vector[6 ]; -u8 mic_iv[16 ]; -u8 mic_header1[16 ]; -u8 mic_header2[16 ]; -u8 ctr_preload[16 ]; +u8 mic_iv[16 ] = {}; +u8 mic_header1[16 ] = {}; +u8 mic_header2[16 ] = {}; +u8 ctr_preload[16 ] = {};/* Intermediate Buffers */ -u8 chain_buffer[16 ]; -u8 aes_out[16 ]; -u8 padded_buffer[16 ]; +u8 chain_buffer[16 ] = {}; +u8 aes_out[16 ] = {}; +u8 padded_buffer[16 ] = {};u8 mic[8 ];uint frtype =GetFrameType (pframe);uint frsubtype =GetFrameSubType (pframe); frsubtype = frsubtype>>4 ; -memset ((void *)mic_iv,0 ,16 ); -memset ((void *)mic_header1,0 ,16 ); -memset ((void *)mic_header2,0 ,16 ); -memset ((void *)ctr_preload,0 ,16 ); -memset ((void *)chain_buffer,0 ,16 ); -memset ((void *)aes_out,0 ,16 ); -memset ((void *)padded_buffer,0 ,16 ); -if ((hdrlen ==WLAN_HDR_A3_LEN ) || (hdrlen ==WLAN_HDR_A3_QOS_LEN )) a4_exists =0 ;else
@@ -1080,15 +1072,15 @@ static signed int aes_decipher(u8 *key, num_blocks, payload_index;signed int res = _SUCCESS;u8 pn_vector[6 ]; -u8 mic_iv[16 ]; -u8 mic_header1[16 ]; -u8 mic_header2[16 ]; -u8 ctr_preload[16 ]; +u8 mic_iv[16 ] = {}; +u8 mic_header1[16 ] = {}; +u8 mic_header2[16 ] = {}; +u8 ctr_preload[16 ] = {};/* Intermediate Buffers */ -u8 chain_buffer[16 ]; -u8 aes_out[16 ]; -u8 padded_buffer[16 ]; +u8 chain_buffer[16 ] = {}; +u8 aes_out[16 ] = {}; +u8 padded_buffer[16 ] = {};u8 mic[8 ];uint frtype =GetFrameType (pframe);
@@ -1096,14 +1088,6 @@ static signed int aes_decipher(u8 *key, frsubtype = frsubtype>>4 ; -memset ((void *)mic_iv,0 ,16 ); -memset ((void *)mic_header1,0 ,16 ); -memset ((void *)mic_header2,0 ,16 ); -memset ((void *)ctr_preload,0 ,16 ); -memset ((void *)chain_buffer,0 ,16 ); -memset ((void *)aes_out,0 ,16 ); -memset ((void *)padded_buffer,0 ,16 ); -/* start to decrypt the payload */ num_blocks = (plen-8 ) /16 ;/* plen including LLC, payload_length and mic) */
Greg Kroah-Hartman
maintainerPATCH 174/263 dt-bindings: serial: 8250: Make clocks and clock-frequency exclusive
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yao Zi <[email protected]>
commit 09812134071b3941fb81def30b61ed36d3a5dfb5 upstream.
The 8250 binding before converting to json-schema states,
- clock-frequency : the input clock frequency for the UART
or
- clocks phandle to refer to the clk used as per Documentation/devicetree
for clock-related properties, where "or" indicates these properties shouldn't exist at the same time.
Additionally, the behavior of Linux's driver is strange when both clocks and clock-frequency are specified: it ignores clocks and obtains the frequency from clock-frequency, left the specified clocks unclaimed. It may even be disabled, which is undesired most of the time.
But "anyOf" doesn't prevent these two properties from coexisting, as it considers the object valid as long as there's at LEAST one match.
Let's switch to "oneOf" and disallows the other property if one exists, precisely matching the original binding and avoiding future confusion on the driver's behavior.
--- Documentation/devicetree/bindings/serial/8250.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/devicetree/bindings/serial/8250.yaml +1 -1
@@ -45,7 +45,7 @@ allOf: - ns16550 - ns16550a then: - anyOf: + oneOf: - required: [ clock-frequency ] - required: [ clocks ]
Greg Kroah-Hartman
maintainerPATCH 175/263 serial: core: restore of_node information in sysfs
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aidan Stewart <[email protected]>
commit d36f0e9a0002f04f4d6dd9be908d58fe5bd3a279 upstream.
Since in v6.8-rc1, the of_node symlink under tty devices is missing. This breaks any udev rules relying on this information.
Link the of_node information in the serial controller device with the parent defined in the device tree. This will also apply to the serial device which takes the serial controller as a parent device.
--- drivers/tty/serial/serial_base_bus.c | 1 + 1 file changed, 1 insertion(+)
drivers/tty/serial/serial_base_bus.c +1 -0
@@ -72,6 +72,7 @@ static int serial_base_device_init(struc dev->parent = parent_dev; dev->bus = &serial_base_bus_type; dev->release = release; +device_set_of_node_from_dev (dev, parent_dev);if (!serial_base_initialized) {dev_dbg (port->dev,"uart_add_one_port() called before arch_initcall()?\n" );
Greg Kroah-Hartman
maintainerPATCH 176/263 serial: imx: Restore original RXTL for console to fix data loss
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Estevam <[email protected]>
commit f23c52aafb1675ab1d1f46914556d8e29cbbf7b3 upstream.
Commit 7a637784d517 ("serial: imx: reduce RX interrupt frequency") introduced a regression on the i.MX6UL EVK board. The issue can be reproduced with the following steps:
- Open vi on the board.
- Paste a text file (~150 characters).
- Save the file, then repeat the process.
- Compare the sha256sum of the saved files.
The checksums do not match due to missing characters or entire lines.
Fix this by restoring the RXTL value to 1 when the UART is used as a console.
This ensures timely RX interrupts and reliable data reception in console mode.
With this change, pasted content is saved correctly, and checksums are always consistent.
--- drivers/tty/serial/imx.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/tty/serial/imx.c +12 -5
@@ -235,6 +235,7 @@ struct imx_port {enum imx_tx_state tx_state;struct hrtimer trigger_start_tx;struct hrtimer trigger_stop_tx; +unsigned int rxtl; };struct imx_port_ucrs {
@@ -1339,6 +1340,7 @@ static void imx_uart_clear_rx_errors(str#define TXTL_DEFAULT 8#define RXTL_DEFAULT 8/* 8 characters or aging timer */ +#define RXTL_CONSOLE_DEFAULT 1#define TXTL_DMA 8/* DMA burst setting */ #define RXTL_DMA 9/* DMA burst setting */
@@ -1457,7 +1459,7 @@ static void imx_uart_disable_dma(struct ucr1 &= ~(UCR1_RXDMAEN |UCR1_TXDMAEN |UCR1_ATDMAEN );imx_uart_writel (sport, ucr1,UCR1 ); -imx_uart_setup_ufcr (sport,TXTL_DEFAULT ,RXTL_DEFAULT ); +imx_uart_setup_ufcr (sport,TXTL_DEFAULT , sport->rxtl); sport->dma_is_enabled =0 ; }
@@ -1482,7 +1484,12 @@ static int imx_uart_startup(struct uart_return retval; } -imx_uart_setup_ufcr (sport,TXTL_DEFAULT ,RXTL_DEFAULT ); +if (uart_console (&sport->port)) + sport->rxtl =RXTL_CONSOLE_DEFAULT ; +else + sport->rxtl =RXTL_DEFAULT ; + +imx_uart_setup_ufcr (sport,TXTL_DEFAULT , sport->rxtl);/* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs
@@ -1948,7 +1955,7 @@ static int imx_uart_poll_init(struct uarif (retval)clk_disable_unprepare (sport->clk_ipg); -imx_uart_setup_ufcr (sport,TXTL_DEFAULT ,RXTL_DEFAULT ); +imx_uart_setup_ufcr (sport,TXTL_DEFAULT , sport->rxtl);uart_port_lock_irqsave (&sport->port, &flags);
@@ -2040,7 +2047,7 @@ static int imx_uart_rs485_config(struct/* If the receiver trigger is 0, set it to a default value */ ufcr =imx_uart_readl (sport,UFCR );if ((ufcr &UFCR_RXTL_MASK ) ==0 ) -imx_uart_setup_ufcr (sport,TXTL_DEFAULT ,RXTL_DEFAULT ); +imx_uart_setup_ufcr (sport,TXTL_DEFAULT , sport->rxtl);imx_uart_start_rx (port); }
@@ -2302,7 +2309,7 @@ imx_uart_console_setup(struct console *celse imx_uart_console_get_options (sport, &baud, &parity, &bits); -imx_uart_setup_ufcr (sport,TXTL_DEFAULT ,RXTL_DEFAULT ); +imx_uart_setup_ufcr (sport,TXTL_DEFAULT , sport->rxtl); retval =uart_set_options (&sport->port, co, baud, parity, bits, flow);
Greg Kroah-Hartman
maintainerPATCH 177/263 Bluetooth: L2CAP: Fix L2CAP MTU negotiation
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frédéric Danis <[email protected]>
commit 042bb9603c44620dce98717a2d23235ca57a00d7 upstream.
OBEX download from iPhone is currently slow due to small packet size used to transfer data which doesn't follow the MTU negotiated during L2CAP connection, i.e. 672 bytes instead of 32767:
< ACL Data TX: Handle 11 flags 0x00 dlen 12
L2CAP: Connection Request (0x02) ident 18 len 4
PSM: 4103 (0x1007)
Source CID: 72Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 16
L2CAP: Connection Response (0x03) ident 18 len 8
Destination CID: 14608
Source CID: 72
Result: Connection successful (0x0000)
Status: No further information available (0x0000)
< ACL Data TX: Handle 11 flags 0x00 dlen 27
L2CAP: Configure Request (0x04) ident 20 len 19
Destination CID: 14608
Flags: 0x0000
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 32767
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 63
Max transmit: 3
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 26
L2CAP: Configure Request (0x04) ident 72 len 18
Destination CID: 72
Flags: 0x0000
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 32
Max transmit: 255
Retransmission timeout: 0
Monitor timeout: 0
Maximum PDU size: 65527
Option: Frame Check Sequence (0x05) [mandatory]
FCS: 16-bit FCS (0x01)
< ACL Data TX: Handle 11 flags 0x00 dlen 29
L2CAP: Configure Response (0x05) ident 72 len 21
Source CID: 14608
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 672
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 32
Max transmit: 255
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 32
L2CAP: Configure Response (0x05) ident 20 len 24
Source CID: 72
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 32767
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 63
Max transmit: 3
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009
Option: Frame Check Sequence (0x05) [mandatory]
FCS: 16-bit FCS (0x01)...
Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 680
Channel: 72 len 676 ctrl 0x0202 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
I-frame: Unsegmented TxSeq 1 ReqSeq 2
< ACL Data TX: Handle 11 flags 0x00 dlen 13
Channel: 14608 len 9 ctrl 0x0204 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
I-frame: Unsegmented TxSeq 2 ReqSeq 2
Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 680
Channel: 72 len 676 ctrl 0x0304 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
I-frame: Unsegmented TxSeq 2 ReqSeq 3
The MTUs are negotiated for each direction. In this traces 32767 for iPhone->localhost and no MTU for localhost->iPhone, which based on '4.4 L2CAP_CONFIGURATION_REQ' (Core specification v5.4, Vol. 3, Part A):
The only parameters that should be included in the L2CAP_CONFIGURATION_REQ packet are those that require different values than the default or previously agreed values.
...
Any missing configuration parameters are assumed to have their most recently explicitly or implicitly accepted values.
and '5.1 Maximum transmission unit (MTU)':
If the remote device sends a positive L2CAP_CONFIGURATION_RSP packet it should include the actual MTU to be used on this channel for traffic flowing into the local device.
...
The default value is 672 octets.
is set by BlueZ to 672 bytes.
It seems that the iPhone used the lowest negotiated value to transfer data to the localhost instead of the negotiated one for the incoming direction.
This could be fixed by using the MTU negotiated for the other direction, if exists, in the L2CAP_CONFIGURATION_RSP. This allows to use segmented packets as in the following traces:
< ACL Data TX: Handle 11 flags 0x00 dlen 12
L2CAP: Connection Request (0x02) ident 22 len 4
PSM: 4103 (0x1007)
Source CID: 72
< ACL Data TX: Handle 11 flags 0x00 dlen 27
L2CAP: Configure Request (0x04) ident 24 len 19
Destination CID: 2832
Flags: 0x0000
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 32767
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 63
Max transmit: 3
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 26
L2CAP: Configure Request (0x04) ident 15 len 18
Destination CID: 72
Flags: 0x0000
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 32
Max transmit: 255
Retransmission timeout: 0
Monitor timeout: 0
Maximum PDU size: 65527
Option: Frame Check Sequence (0x05) [mandatory]
FCS: 16-bit FCS (0x01)
< ACL Data TX: Handle 11 flags 0x00 dlen 29
L2CAP: Configure Response (0x05) ident 15 len 21
Source CID: 2832
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 32767
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 32
Max transmit: 255
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 32
L2CAP: Configure Response (0x05) ident 24 len 24
Source CID: 72
Flags: 0x0000
Result: Success (0x0000)
Option: Maximum Transmission Unit (0x01) [mandatory]
MTU: 32767
Option: Retransmission and Flow Control (0x04) [mandatory]
Mode: Enhanced Retransmission (0x03)
TX window size: 63
Max transmit: 3
Retransmission timeout: 2000
Monitor timeout: 12000
Maximum PDU size: 1009
Option: Frame Check Sequence (0x05) [mandatory]
FCS: 16-bit FCS (0x01)...
Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 1009
Channel: 72 len 1005 ctrl 0x4202 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
I-frame: Start (len 21884) TxSeq 1 ReqSeq 2Quoted 1 line
ACL Data RX: Handle 11 flags
0x02dlen 1009
Channel: 72 len 1005 ctrl 0xc204 [PSM 4103 mode Enhanced Retransmission (0x03)] {chan 8}
I-frame: Continuation TxSeq 2 ReqSeq 2
This has been tested with kernel 5.4 and BlueZ 5.77.
--- net/bluetooth/l2cap_core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +8 -1
@@ -3415,7 +3415,7 @@ static int l2cap_parse_conf_req(struct lstruct l2cap_conf_rfc rfc = { .mode =L2CAP_MODE_BASIC };struct l2cap_conf_efs efs;u8 remote_efs =0 ; -u16 mtu =L2CAP_DEFAULT_MTU ; +u16 mtu =0 ;u16 result =L2CAP_CONF_SUCCESS ;u16 size;
@@ -3520,6 +3520,13 @@ done:/* Configure output options and let the other side know * which ones we don't like. */ +/* If MTU is not provided in configure request, use the most recently +* explicitly or implicitly accepted value for the other direction, +* or the default value. +*/ +if (mtu ==0 ) + mtu = chan->imtu ? chan->imtu :L2CAP_DEFAULT_MTU ; +if (mtu <L2CAP_DEFAULT_MIN_MTU ) result =L2CAP_CONF_UNACCEPT ;else {
Greg Kroah-Hartman
maintainerPATCH 178/263 dm-raid: fix variable in journal device check
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heinz Mauelshagen <[email protected]>
commit db53805156f1e0aa6d059c0d3f9ac660d4ef3eb4 upstream.
Replace "rdev" with correct loop variable name "r".
--- drivers/md/dm-raid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-raid.c +1 -1
@@ -2410,7 +2410,7 @@ static int super_init_validation(struct*/ sb_retrieve_failed_devices (sb, failed_devices);rdev_for_each (r, mddev) { -if (test_bit (Journal, &rdev->flags) || +if (test_bit (Journal, &r->flags) || !r->sb_page)continue ; sb2 =page_address (r->sb_page);
Greg Kroah-Hartman
maintainerPATCH 179/263 bcache: remove unnecessary select MIN_HEAP
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuan-Wei Chiu <[email protected]>
commit 95b2e31e1752494d477c5da89d6789f769b0d67b upstream.
After reverting the transition to the generic min heap library, bcache no longer depends on MIN_HEAP. The select entry can be removed to reduce code size and shrink the kernel's attack surface.
This change effectively reverts the bcache-related part of commit 92a8b224b833 ("lib/min_heap: introduce non-inline versions of min heap API functions").
This is part of a series of changes to address a performance regression caused by the use of the generic min_heap implementation.
As reported by Robert, bcache now suffers from latency spikes, with P100 (max) latency increasing from 600 ms to 2.4 seconds every 5 minutes. These regressions degrade bcache's effectiveness as a low-latency cache layer and lead to frequent timeouts and application stalls in production environments.
--- drivers/md/bcache/Kconfig | 1 - 1 file changed, 1 deletion(-)
drivers/md/bcache/Kconfig +0 -1
@@ -5,7 +5,6 @@ config BCACHE select BLOCK_HOLDER_DEPRECATED if SYSFS select CRC64 select CLOSURES - select MIN_HEAP help Allows a block device to be used as cache for other devices; uses a btree for indexing and the layout is optimized for SSDs.
Greg Kroah-Hartman
maintainerPATCH 180/263 btrfs: fix a race between renames and directory logging
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit 3ca864de852bc91007b32d2a0d48993724f4abad upstream.
We have a race between a rename and directory inode logging that if it happens and we crash/power fail before the rename completes, the next time the filesystem is mounted, the log replay code will end up deleting the file that was being renamed.
This is best explained following a step by step analysis of an interleaving of steps that lead into this situation.
Consider the initial conditions:
1) We are at transaction N;
2) We have directories A and B created in a past transaction (< N);
3) We have inode X corresponding to a file that has 2 hardlinks, one in directory A and the other in directory B, so we'll name them as "A/foo_link1" and "B/foo_link2". Both hard links were persisted in a past transaction (< N);
4) We have inode Y corresponding to a file that as a single hard link and is located in directory A, we'll name it as "A/bar". This file was also persisted in a past transaction (< N).
The steps leading to a file loss are the following and for all of them we are under transaction N:
1) Link "A/foo_link1" is removed, so inode's X last_unlink_trans field
is updated to N, through btrfs_unlink() -> btrfs_record_unlink_dir();
2) Task A starts a rename for inode Y, with the goal of renaming from
"A/bar" to "A/baz", so we enter btrfs_rename();
3) Task A inserts the new BTRFS_INODE_REF_KEY for inode Y by calling
btrfs_insert_inode_ref();
4) Because the rename happens in the same directory, we don't set the last_unlink_trans field of directoty A's inode to the current transaction id, that is, we don't cal btrfs_record_unlink_dir();
5) Task A then removes the entries from directory A (BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items) when calling __btrfs_unlink_inode() (actually the dir index item is added as a delayed item, but the effect is the same);
6) Now before task A adds the new entry "A/baz" to directory A by
calling btrfs_add_link(), another task, task B is logging inode X;
7) Task B starts a fsync of inode X and after logging inode X, at btrfs_log_inode_parent() it calls btrfs_log_all_parents(), since inode X has a last_unlink_trans value of N, set at in step 1;
8) At btrfs_log_all_parents() we search for all parent directories of inode X using the commit root, so we find directories A and B and log them. Bu when logging direct A, we don't have a dir index item for inode Y anymore, neither the old name "A/bar" nor for the new name "A/baz" since the rename has deleted the old name but has not yet inserted the new name - task A hasn't called yet btrfs_add_link() to do that.
Note that logging directory A doesn't fallback to a transaction commit because its last_unlink_trans has a lower value than the current transaction's id (see step 4);
9) Task B finishes logging directories A and B and gets back to btrfs_sync_file() where it calls btrfs_sync_log() to persist the log tree;
10) Task B successfully persisted the log tree, btrfs_sync_log() completed with success, and a power failure happened.
We have a log tree without any directory entry for inode Y, so the log replay code deletes the entry for inode Y, name "A/bar", from the subvolume tree since it doesn't exist in the log tree and the log tree is authorative for its index (we logged a BTRFS_DIR_LOG_INDEX_KEY item that covers the index range for the dentry that corresponds to "A/bar").
Since there's no other hard link for inode Y and the log replay code deletes the name "A/bar", the file is lost.
The issue wouldn't happen if task B synced the log only after task A called btrfs_log_new_name(), which would update the log with the new name for inode Y ("A/bar").
Fix this by pinning the log root during renames before removing the old directory entry, and unpinning after btrfs_log_new_name() is called.
--- fs/btrfs/inode.c | 81 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 17 deletions(-)
fs/btrfs/inode.c +64 -17
@@ -7979,6 +7979,7 @@ static int btrfs_rename_exchange(structint ret;int ret2;bool need_abort = false; +bool logs_pinned = false;struct fscrypt_name old_fname, new_fname;struct fscrypt_str *old_name, *new_name;
@@ -8102,6 +8103,31 @@ static int btrfs_rename_exchange(structinode_inc_iversion (new_inode);simple_rename_timestamp (old_dir, old_dentry, new_dir, new_dentry); +if (old_ino !=BTRFS_FIRST_FREE_OBJECTID && + new_ino !=BTRFS_FIRST_FREE_OBJECTID ) { +/* +* If we are renaming in the same directory (and it's not for +* root entries) pin the log early to prevent any concurrent +* task from logging the directory after we removed the old +* entries and before we add the new entries, otherwise that +* task can sync a log without any entry for the inodes we are +* renaming and therefore replaying that log, if a power failure +* happens after syncing the log, would result in deleting the +* inodes. +* +* If the rename affects two different directories, we want to +* make sure the that there's no log commit that contains +* updates for only one of the directories but not for the +* other. +* +* If we are renaming an entry for a root, we don't care about +* log updates since we called btrfs_set_log_full_commit(). +*/ +btrfs_pin_log_trans (root); +btrfs_pin_log_trans (dest); + logs_pinned = true; + } +if (old_dentry->d_parent != new_dentry->d_parent) {btrfs_record_unlink_dir (trans,BTRFS_I (old_dir),BTRFS_I (old_inode), true);
@@ -8173,30 +8199,23 @@ static int btrfs_rename_exchange(structBTRFS_I (new_inode)->dir_index = new_idx;/* -* Now pin the logs of the roots. We do it to ensure that no other task -* can sync the logs while we are in progress with the rename, because -* that could result in an inconsistency in case any of the inodes that -* are part of this rename operation were logged before. +* Do the log updates for all inodes. +* +* If either entry is for a root we don't need to update the logs since +* we've called btrfs_set_log_full_commit() before. */ -if (old_ino !=BTRFS_FIRST_FREE_OBJECTID ) -btrfs_pin_log_trans (root); -if (new_ino !=BTRFS_FIRST_FREE_OBJECTID ) -btrfs_pin_log_trans (dest); - -/* Do the log updates for all inodes. */ -if (old_ino !=BTRFS_FIRST_FREE_OBJECTID ) +if (logs_pinned) {btrfs_log_new_name (trans, old_dentry,BTRFS_I (old_dir), old_rename_ctx.index, new_dentry->d_parent); -if (new_ino !=BTRFS_FIRST_FREE_OBJECTID )btrfs_log_new_name (trans, new_dentry,BTRFS_I (new_dir), new_rename_ctx.index, old_dentry->d_parent); + } -/* Now unpin the logs. */ -if (old_ino !=BTRFS_FIRST_FREE_OBJECTID ) +out_fail: +if (logs_pinned) {btrfs_end_log_trans (root); -if (new_ino !=BTRFS_FIRST_FREE_OBJECTID )btrfs_end_log_trans (dest); -out_fail: + } ret2 =btrfs_end_transaction (trans); ret = ret ? ret : ret2; out_notrans:
@@ -8246,6 +8265,7 @@ static int btrfs_rename(struct mnt_idmapint ret2;u64 old_ino =btrfs_ino (BTRFS_I (old_inode));struct fscrypt_name old_fname, new_fname; +bool logs_pinned = false;if (btrfs_ino (BTRFS_I (new_dir)) ==BTRFS_EMPTY_SUBVOL_DIR_OBJECTID )return -EPERM ;
@@ -8380,6 +8400,29 @@ static int btrfs_rename(struct mnt_idmapinode_inc_iversion (old_inode);simple_rename_timestamp (old_dir, old_dentry, new_dir, new_dentry); +if (old_ino !=BTRFS_FIRST_FREE_OBJECTID ) { +/* +* If we are renaming in the same directory (and it's not a +* root entry) pin the log to prevent any concurrent task from +* logging the directory after we removed the old entry and +* before we add the new entry, otherwise that task can sync +* a log without any entry for the inode we are renaming and +* therefore replaying that log, if a power failure happens +* after syncing the log, would result in deleting the inode. +* +* If the rename affects two different directories, we want to +* make sure the that there's no log commit that contains +* updates for only one of the directories but not for the +* other. +* +* If we are renaming an entry for a root, we don't care about +* log updates since we called btrfs_set_log_full_commit(). +*/ +btrfs_pin_log_trans (root); +btrfs_pin_log_trans (dest); + logs_pinned = true; + } +if (old_dentry->d_parent != new_dentry->d_parent)btrfs_record_unlink_dir (trans,BTRFS_I (old_dir),BTRFS_I (old_inode), true);
@@ -8444,7 +8487,7 @@ static int btrfs_rename(struct mnt_idmapif (old_inode->i_nlink ==1 )BTRFS_I (old_inode)->dir_index = index; -if (old_ino !=BTRFS_FIRST_FREE_OBJECTID ) +if (logs_pinned)btrfs_log_new_name (trans, old_dentry,BTRFS_I (old_dir), rename_ctx.index, new_dentry->d_parent);
@@ -8460,6 +8503,10 @@ static int btrfs_rename(struct mnt_idmap } } out_fail: +if (logs_pinned) { +btrfs_end_log_trans (root); +btrfs_end_log_trans (dest); + } ret2 =btrfs_end_transaction (trans); ret = ret ? ret : ret2; out_notrans:
Greg Kroah-Hartman
maintainerPATCH 181/263 btrfs: update superblocks device bytes_used when dropping chunk
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Harmstone <[email protected]>
commit ae4477f937569d097ca5dbce92a89ba384b49bc6 upstream.
Each superblock contains a copy of the device item for that device. In a transaction which drops a chunk but doesn't create any new ones, we were correctly updating the device item in the chunk tree but not copying over the new bytes_used value to the superblock.
This can be seen by doing the following:
# dd if=/dev/zero of=test bs=4096 count=2621440 # mkfs.btrfs test # mount test /root/temp
# cd /root/temp
# for i in {00..10}; do dd if=/dev/zero of=$i bs=4096 count=32768; done
# sync
# rm *
# sync
# btrfs balance start -dusage=0 .
# sync# cd # umount /root/temp # btrfs check test
For btrfs-check to detect this, you will also need my patch at
https://github.com/kdave/btrfs-progs/pull/991.
Change btrfs_remove_dev_extents() so that it adds the devices to the fs_info->post_commit_list if they're not there already. This causes btrfs_commit_device_sizes() to be called, which updates the bytes_used value in the superblock.
--- fs/btrfs/volumes.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/btrfs/volumes.c +6 -0
@@ -3281,6 +3281,12 @@ int btrfs_remove_chunk(struct btrfs_tran device->bytes_used - dev_extent_len);atomic64_add (dev_extent_len, &fs_info->free_chunk_space);btrfs_clear_space_info_full (fs_info); + +if (list_empty (&device->post_commit_list)) { +list_add_tail (&device->post_commit_list, + &trans->transaction->dev_update_list); + } +mutex_unlock (&fs_info->chunk_mutex); } }
Greg Kroah-Hartman
maintainerPATCH 182/263 btrfs: fix invalid inode pointer dereferences during log replay
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit 2dcf838cf5c2f0f4501edaa1680fcad03618d760 upstream.
In a few places where we call read_one_inode(), if we get a NULL pointer we end up jumping into an error path, or fallthrough in case of __add_inode_ref(), where we then do something like this:
iput(&inode->vfs_inode);
which results in an invalid inode pointer that triggers an invalid memory access, resulting in a crash.
Fix this by making sure we don't do such dereferences.
--- fs/btrfs/tree-log.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
fs/btrfs/tree-log.c +6 -8
@@ -668,15 +668,12 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, extent_end =ALIGN (start + size, fs_info->sectorsize); }else { - ret =0 ; - goto out; +return 0 ; } inode =read_one_inode (root, key->objectid); -if (!inode) { - ret = -EIO ; - goto out; - } +if (!inode) +return -EIO ;/* * first check to see if we already have this extent in the
@@ -961,7 +958,8 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, ret =unlink_inode_for_log_replay (trans, dir, inode, &name); out:kfree (name.name); -iput (&inode->vfs_inode); +if (inode) +iput (&inode->vfs_inode);return ret; }
@@ -1176,8 +1174,8 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans, ret =unlink_inode_for_log_replay (trans, victim_parent, inode, &victim_name); +iput (&victim_parent->vfs_inode); } -iput (&victim_parent->vfs_inode);kfree (victim_name.name);if (ret)return ret;
Signature · 1 line
2.50.0
Greg Kroah-Hartman
maintainerPATCH 183/263 Revert "bcache: update min_heap_callbacks to use default builtin swap"
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuan-Wei Chiu <[email protected]>
commit 845f1f2d69f3f49b3d8c142265952c8257e3368c upstream.
Patch series "bcache: Revert min_heap migration due to performance regression".
This patch series reverts the migration of bcache from its original heap implementation to the generic min_heap library. While the original change aimed to simplify the code and improve maintainability, it introduced a severe performance regression in real-world scenarios.
As reported by Robert, systems using bcache now suffer from periodic latency spikes, with P100 (max) latency increasing from 600 ms to 2.4 seconds every 5 minutes. This degrades bcache's value as a low-latency caching layer, and leads to frequent timeouts and application stalls in production environments.
The primary cause of this regression is the behavior of the generic min_heap implementation's bottom-up sift_down, which performs up to 2 * log2(n) comparisons when many elements are equal. The original top-down variant used by bcache only required O(1) comparisons in such cases. The issue was further exacerbated by commit 92a8b224b833 ("lib/min_heap:
introduce non-inline versions of min heap API functions"), which introduced non-inlined versions of the min_heap API, adding function call overhead to a performance-critical hot path.
This patch (of 3):
This reverts commit 3d8a9a1c35227c3f1b0bd132c9f0a80dbda07b65.
Although removing the custom swap function simplified the code, this change is part of a broader migration to the generic min_heap API that introduced significant performance regressions in bcache.
As reported by Robert, bcache now suffers from latency spikes, with P100 (max) latency increasing from 600 ms to 2.4 seconds every 5 minutes. These regressions degrade bcache's effectiveness as a low-latency cache layer and lead to frequent timeouts and application stalls in production environments.
This revert is part of a series of changes to restore previous performance by undoing the min_heap transition.
--- drivers/md/bcache/alloc.c | 11 +++++++++-- drivers/md/bcache/bset.c | 14 +++++++++++--- drivers/md/bcache/extents.c | 10 +++++++++- drivers/md/bcache/movinggc.c | 10 +++++++++- 4 files changed, 38 insertions(+), 7 deletions(-)
drivers/md/bcache/alloc.c +9 -2
@@ -189,16 +189,23 @@ static inline bool new_bucket_min_cmp(const void *l, const void *r, void *args)return new_bucket_prio (ca, *lhs) <new_bucket_prio (ca, *rhs); } +static inline void new_bucket_swap (void *l,void *r,void __always_unused *args) +{ +struct bucket **lhs = l, **rhs = r; + +swap (*lhs, *rhs); +} +static void invalidate_buckets_lru (struct cache *ca) {struct bucket *b;const struct min_heap_callbacks bucket_max_cmp_callback = { .less = new_bucket_max_cmp, - .swp =NULL , + .swp = new_bucket_swap, };const struct min_heap_callbacks bucket_min_cmp_callback = { .less = new_bucket_min_cmp, - .swp =NULL , + .swp = new_bucket_swap, }; ca->heap.nr =0 ;
drivers/md/bcache/bset.c +11 -3
@@ -1093,6 +1093,14 @@ static inline bool new_btree_iter_cmp(const void *l, const void *r, void __alwayreturn bkey_cmp (_l->k, _r->k) <=0 ; } +static inline void new_btree_iter_swap (void *iter1,void *iter2,void __always_unused *args) +{ +struct btree_iter_set *_iter1 = iter1; +struct btree_iter_set *_iter2 = iter2; + +swap (*_iter1, *_iter2); +} +static inline bool btree_iter_end (struct btree_iter *iter) {return !iter->heap.nr;
@@ -1103,7 +1111,7 @@ void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k, {const struct min_heap_callbacks callbacks = { .less = new_btree_iter_cmp, - .swp =NULL , + .swp = new_btree_iter_swap, };if (k != end)
@@ -1149,7 +1157,7 @@ static inline struct bkey *__bch_btree_iter_next(struct btree_iter *iter,struct bkey *ret =NULL ;const struct min_heap_callbacks callbacks = { .less = cmp, - .swp =NULL , + .swp = new_btree_iter_swap, };if (!btree_iter_end (iter)) {
@@ -1223,7 +1231,7 @@ static void btree_mergesort(struct btree_keys *b, struct bset *out, : bch_ptr_invalid;const struct min_heap_callbacks callbacks = { .less = b->ops->sort_cmp, - .swp =NULL , + .swp = new_btree_iter_swap, };/* Heapify the iterator, using our comparison function */
drivers/md/bcache/extents.c +9 -1
@@ -266,12 +266,20 @@ static bool new_bch_extent_sort_cmp(const void *l, const void *r, void __always_return !(c ? c >0 : _l->k < _r->k); } +static inline void new_btree_iter_swap (void *iter1,void *iter2,void __always_unused *args) +{ +struct btree_iter_set *_iter1 = iter1; +struct btree_iter_set *_iter2 = iter2; + +swap (*_iter1, *_iter2); +} +static struct bkey *bch_extent_sort_fixup (struct btree_iter *iter,struct bkey *tmp) {const struct min_heap_callbacks callbacks = { .less = new_bch_extent_sort_cmp, - .swp =NULL , + .swp = new_btree_iter_swap, };while (iter->heap.nr >1 ) {struct btree_iter_set *top = iter->heap.data, *i = top +1 ;
drivers/md/bcache/movinggc.c +9 -1
@@ -190,6 +190,14 @@ static bool new_bucket_cmp(const void *l, const void *r, void __always_unused *areturn GC_SECTORS_USED (*_l) >=GC_SECTORS_USED (*_r); } +static void new_bucket_swap (void *l,void *r,void __always_unused *args) +{ +struct bucket **_l = l; +struct bucket **_r = r; + +swap (*_l, *_r); +} +static unsigned int bucket_heap_top (struct cache *ca) {struct bucket *b;
@@ -204,7 +212,7 @@ void bch_moving_gc(struct cache_set *c)unsigned long sectors_to_move, reserve_sectors;const struct min_heap_callbacks callbacks = { .less = new_bucket_cmp, - .swp =NULL , + .swp = new_bucket_swap, };if (!c->copy_gc_enabled)
Signature · 1 line
2.50.0
Greg Kroah-Hartman
maintainerPATCH 184/263 Revert "bcache: remove heap-related macros and switch to generic min_heap"
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuan-Wei Chiu <[email protected]>
commit 48fd7ebe00c1cdc782b42576548b25185902f64c upstream.
This reverts commit 866898efbb25bb44fd42848318e46db9e785973a.
The generic bottom-up min_heap implementation causes performance regression in invalidate_buckets_lru(), a hot path in bcache. Before the cache is fully populated, new_bucket_prio() often returns zero, leading to many equal comparisons. In such cases, bottom-up sift_down performs up to 2 * log2(n) comparisons, while the original top-down approach completes with just O() comparisons, resulting in a measurable performance gap.
The performance degradation is further worsened by the non-inlined min_heap API functions introduced in commit 92a8b224b833 ("lib/min_heap:
introduce non-inline versions of min heap API functions"), adding function call overhead to this critical path.
As reported by Robert, bcache now suffers from latency spikes, with P100 (max) latency increasing from 600 ms to 2.4 seconds every 5 minutes. These regressions degrade bcache's effectiveness as a low-latency cache layer and lead to frequent timeouts and application stalls in production environments.
This revert aims to restore bcache's original low-latency behavior.
--- drivers/md/bcache/alloc.c | 64 +++++---------------- drivers/md/bcache/bcache.h | 2 drivers/md/bcache/bset.c | 124 +++++++++++++++--------------------------- drivers/md/bcache/bset.h | 42 ++++++++------ drivers/md/bcache/btree.c | 69 +++++++++-------------- drivers/md/bcache/extents.c | 51 ++++++----------- drivers/md/bcache/movinggc.c | 41 +++---------- drivers/md/bcache/super.c | 3 - drivers/md/bcache/sysfs.c | 4 - drivers/md/bcache/util.h | 67 ++++++++++++++++++++++ drivers/md/bcache/writeback.c | 13 +--- 11 files changed, 217 insertions(+), 263 deletions(-)
drivers/md/bcache/alloc.c +17 -47
@@ -164,68 +164,40 @@ static void bch_invalidate_one_bucket(st* prio is worth 1/8th of what INITIAL_PRIO is worth. */ -static inline unsigned int new_bucket_prio (struct cache *ca,struct bucket *b) -{ -unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) /8 ; - -return (b->prio - ca->set->min_prio + min_prio) *GC_SECTORS_USED (b); -} - -static inline bool new_bucket_max_cmp (const void *l,const void *r,void *args) -{ -struct bucket **lhs = (struct bucket **)l; -struct bucket **rhs = (struct bucket **)r; -struct cache *ca = args; - -return new_bucket_prio (ca, *lhs) >new_bucket_prio (ca, *rhs); -} - -static inline bool new_bucket_min_cmp (const void *l,const void *r,void *args) -{ -struct bucket **lhs = (struct bucket **)l; -struct bucket **rhs = (struct bucket **)r; -struct cache *ca = args; - -return new_bucket_prio (ca, *lhs) <new_bucket_prio (ca, *rhs); -} - -static inline void new_bucket_swap (void *l,void *r,void __always_unused *args) -{ -struct bucket **lhs = l, **rhs = r; +#define bucket_prio (b) \ +({ \ + unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; \ + \ + (b->prio - ca->set->min_prio + min_prio) * GC_SECTORS_USED(b); \ +}) -swap (*lhs, *rhs); -} +#define bucket_max_cmp (l, r) (bucket_prio(l) < bucket_prio(r)) +#define bucket_min_cmp (l, r) (bucket_prio(l) > bucket_prio(r))static void invalidate_buckets_lru (struct cache *ca) {struct bucket *b; -const struct min_heap_callbacks bucket_max_cmp_callback = { - .less = new_bucket_max_cmp, - .swp = new_bucket_swap, - }; -const struct min_heap_callbacks bucket_min_cmp_callback = { - .less = new_bucket_min_cmp, - .swp = new_bucket_swap, - }; +ssize_t i; - ca->heap.nr =0 ; + ca->heap.used =0 ;for_each_bucket (b, ca) {if (!bch_can_invalidate_bucket (ca, b))continue ; -if (!min_heap_full (&ca->heap)) -min_heap_push (&ca->heap, &b, &bucket_max_cmp_callback, ca); -else if (!new_bucket_max_cmp (&b,min_heap_peek (&ca->heap), ca)) { +if (!heap_full (&ca->heap)) +heap_add (&ca->heap, b, bucket_max_cmp); +else if (bucket_max_cmp (b,heap_peek (&ca->heap))) { ca->heap.data[0 ] = b; -min_heap_sift_down (&ca->heap,0 , &bucket_max_cmp_callback, ca); +heap_sift (&ca->heap,0 , bucket_max_cmp); } } -min_heapify_all (&ca->heap, &bucket_min_cmp_callback, ca); +for (i = ca->heap.used /2 -1 ; i >=0 ; --i) +heap_sift (&ca->heap, i, bucket_min_cmp);while (!fifo_full (&ca->free_inc)) { -if (!ca->heap.nr) { +if (!heap_pop (&ca->heap, b, bucket_min_cmp)) {/* * We don't want to be calling invalidate_buckets() * multiple times when it can't do anything
@@ -234,8 +206,6 @@ static void invalidate_buckets_lru(strucwake_up_gc (ca->set);return ; } - b =min_heap_peek (&ca->heap)[0 ]; -min_heap_pop (&ca->heap, &bucket_min_cmp_callback, ca);bch_invalidate_one_bucket (ca, b); }
drivers/md/bcache/bcache.h +1 -1
@@ -458,7 +458,7 @@ struct cache {/* Allocation stuff: */ struct bucket *buckets; - DEFINE_MIN_HEAP(struct bucket *, cache_heap) heap; + DECLARE_HEAP(struct bucket *, heap);/* * If nonzero, we know we aren't going to find any buckets to invalidate
drivers/md/bcache/bset.c +45 -79
257 lines not on this page · raw message
drivers/md/bcache/bset.h +24 -18
72 lines not on this page · raw message
drivers/md/bcache/btree.c +29 -40
188 lines not on this page · raw message
drivers/md/bcache/extents.c +18 -33
105 lines not on this page · raw message
drivers/md/bcache/movinggc.c +10 -31
85 lines not on this page · raw message
drivers/md/bcache/super.c +2 -1
@@ -1912,7 +1912,8 @@ struct cache_set *bch_cache_set_alloc(stINIT_LIST_HEAD (&c->btree_cache_freed);INIT_LIST_HEAD (&c->data_buckets); - iter_size = ((meta_bucket_pages (sb) *PAGE_SECTORS ) / sb->block_size) * + iter_size =sizeof (struct btree_iter ) + + ((meta_bucket_pages (sb) *PAGE_SECTORS ) / sb->block_size) *sizeof (struct btree_iter_set ); c->devices =kcalloc (c->nr_uuids,sizeof (void *),GFP_KERNEL );
drivers/md/bcache/sysfs.c +1 -3
@@ -660,9 +660,7 @@ static unsigned int bch_root_usage(strucunsigned int bytes =0 ;struct bkey *k;struct btree *b; -struct btree_iter iter; - -min_heap_init (&iter.heap,NULL ,MAX_BSETS ); +struct btree_iter_stack iter; goto lock_root;
drivers/md/bcache/util.h +65 -2
88 lines not on this page · raw message
drivers/md/bcache/writeback.c +5 -8
@@ -908,16 +908,15 @@ static int bch_dirty_init_thread(void *astruct dirty_init_thrd_info *info = arg;struct bch_dirty_init_state *state = info->state;struct cache_set *c = state->c; -struct btree_iter iter; +struct btree_iter_stack iter;struct bkey *k, *p;int cur_idx, prev_idx, skip_nr; k = p =NULL ; prev_idx =0 ; -min_heap_init (&iter.heap,NULL ,MAX_BSETS ); -bch_btree_iter_init (&c->root->keys, &iter,NULL ); - k =bch_btree_iter_next_filter (&iter, &c->root->keys, bch_ptr_bad); +bch_btree_iter_stack_init (&c->root->keys, &iter,NULL ); + k =bch_btree_iter_next_filter (&iter.iter, &c->root->keys, bch_ptr_bad);BUG_ON (!k); p = k;
@@ -931,7 +930,7 @@ static int bch_dirty_init_thread(void *a skip_nr = cur_idx - prev_idx;while (skip_nr) { - k =bch_btree_iter_next_filter (&iter, + k =bch_btree_iter_next_filter (&iter.iter, &c->root->keys, bch_ptr_bad);if (k)
@@ -980,13 +979,11 @@ void bch_sectors_dirty_init(struct bcachint i;struct btree *b =NULL ;struct bkey *k =NULL ; -struct btree_iter iter; +struct btree_iter_stack iter;struct sectors_dirty_init op;struct cache_set *c = d->c;struct bch_dirty_init_state state; -min_heap_init (&iter.heap,NULL ,MAX_BSETS ); - retry_lock: b = c->root;rw_lock (0 , b, b->level);
Greg Kroah-Hartman
maintainerPATCH 185/263 selinux: change security_compute_sid to return the ssid or tsid on match
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Smalley <[email protected]>
commit fde46f60f6c5138ee422087addbc5bf5b4968bf1 upstream.
If the end result of a security_compute_sid() computation matches the ssid or tsid, return that SID rather than looking it up again. This avoids the problem of multiple initial SIDs that map to the same context.
--- security/selinux/ss/services.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
security/selinux/ss/services.c +11 -5
@@ -1909,11 +1909,17 @@ retry: goto out_unlock; }/* Obtain the sid for the context. */ - rc =sidtab_context_to_sid (sidtab, &newcontext, out_sid); -if (rc == -ESTALE ) { -rcu_read_unlock (); -context_destroy (&newcontext); - goto retry; +if (context_equal (scontext, &newcontext)) + *out_sid = ssid; +else if (context_equal (tcontext, &newcontext)) + *out_sid = tsid; +else { + rc =sidtab_context_to_sid (sidtab, &newcontext, out_sid); +if (rc == -ESTALE ) { +rcu_read_unlock (); +context_destroy (&newcontext); + goto retry; + } } out_unlock:rcu_read_unlock ();
Greg Kroah-Hartman
maintainerPATCH 186/263 spi: spi-cadence-quadspi: Fix pm runtime unbalance
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Khairul Anuar Romli <[email protected]>
commit b07f349d1864abe29436f45e3047da2bdd476462 upstream.
Having PM put sync in remove function is causing PM underflow during remove operation. This is caused by the function, runtime_pm_get_sync, not being called anywhere during the op. Ensure that calls to pm_runtime_enable()/pm_runtime_disable() and pm_runtime_get_sync()/pm_runtime_put_sync() match.
echo 108d2000.spi > /sys/bus/platform/drivers/cadence-qspi/unbind
[ 49.644256] Deleting MTD partitions on "108d2000.spi.0": [ 49.649575] Deleting u-boot MTD partition [ 49.684087] Deleting root MTD partition [ 49.724188] cadence-qspi 108d2000.spi: Runtime PM usage count underflow!
Continuous bind/unbind will result in an "Unbalanced pm_runtime_enable" error. Subsequent unbind attempts will return a "No such device" error, while bind attempts will return a "Resource temporarily unavailable" error.
[ 47.592434] cadence-qspi 108d2000.spi: Runtime PM usage count underflow! [ 49.592233] cadence-qspi 108d2000.spi: detected FIFO depth (1024) different from config (128) [ 53.232309] cadence-qspi 108d2000.spi: Runtime PM usage count underflow! [ 55.828550] cadence-qspi 108d2000.spi: detected FIFO depth (1024) different from config (128) [ 57.940627] cadence-qspi 108d2000.spi: Runtime PM usage count underflow! [ 59.912490] cadence-qspi 108d2000.spi: detected FIFO depth (1024) different from config (128) [ 61.876243] cadence-qspi 108d2000.spi: Runtime PM usage count underflow! [ 61.883000] platform 108d2000.spi: Unbalanced pm_runtime_enable! [ 532.012270] cadence-qspi 108d2000.spi: probe with driver cadence-qspi failed1
Also, change clk_disable_unprepare() to clk_disable() since continuous bind and unbind operations will trigger a warning indicating that the clock is already unprepared.
--- drivers/spi/spi-cadence-quadspi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/spi/spi-cadence-quadspi.c +7 -5
@@ -1958,10 +1958,10 @@ static int cqspi_probe(struct platform_d goto probe_setup_failed; } - ret =devm_pm_runtime_enable (dev); -if (ret) { -if (cqspi->rx_chan) -dma_release_channel (cqspi->rx_chan); +pm_runtime_enable (dev); + +if (cqspi->rx_chan) { +dma_release_channel (cqspi->rx_chan); goto probe_setup_failed; }
@@ -1981,6 +1981,7 @@ static int cqspi_probe(struct platform_dreturn 0 ; probe_setup_failed:cqspi_controller_enable (cqspi,0 ); +pm_runtime_disable (dev); probe_reset_failed:if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi);
@@ -1999,7 +2000,8 @@ static void cqspi_remove(struct platformif (cqspi->rx_chan)dma_release_channel (cqspi->rx_chan); -clk_disable_unprepare (cqspi->clk); +if (pm_runtime_get_sync (&pdev->dev) >=0 ) +clk_disable (cqspi->clk);if (cqspi->is_jh7110)cqspi_jh7110_disable_clk (pdev, cqspi);
Greg Kroah-Hartman
maintainerPATCH 187/263 net: libwx: fix the creation of page_pool
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiawen Wu <[email protected]>
commit 85720e04d9af0b77f8092b12a06661a8d459d4a0 upstream.
'rx_ring->size' means the count of ring descriptors multiplied by the size of one descriptor. When increasing the count of ring descriptors, it may exceed the limit of pool size.
[ 864.209610] page_pool_create_percpu() gave up with errno -7 [ 864.209613] txgbe 0000:11:00.0: Page pool creation failed: -7
Fix to set the pool_size to the count of ring descriptors.
--- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/wangxun/libwx/wx_lib.c +1 -1
@@ -2496,7 +2496,7 @@ static int wx_alloc_page_pool(struct wx_struct page_pool_params pp_params = { .flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV , .order =0 , - .pool_size = rx_ring->size, + .pool_size = rx_ring->count, .nid =dev_to_node (rx_ring->dev), .dev = rx_ring->dev, .dma_dir =DMA_FROM_DEVICE ,
Greg Kroah-Hartman
maintainerPATCH 188/263 maple_tree: fix MA_STATE_PREALLOC flag in mas_preallocate()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liam R. Howlett <[email protected]>
commit fba46a5d83ca8decb338722fb4899026d8d9ead2 upstream.
Temporarily clear the preallocation flag when explicitly requesting allocations. Pre-existing allocations are already counted against the request through mas_node_count_gfp(), but the allocations will not happen if the MA_STATE_PREALLOC flag is set. This flag is meant to avoid re-allocating in bulk allocation mode, and to detect issues with preallocation calculations.
The MA_STATE_PREALLOC flag should also always be set on zero allocations so that detection of underflow allocations will print a WARN_ON() during consumption.
User visible effect of this flaw is a WARN_ON() followed by a null pointer dereference when subsequent requests for larger number of nodes is ignored, such as the vma merge retry in mmap_region() caused by drivers altering the vma flags (which happens in v6.6, at least)
--- lib/maple_tree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
lib/maple_tree.c +3 -1
@@ -5496,8 +5496,9 @@ int mas_preallocate(struct ma_state *mas mas->store_type =mas_wr_store_type (&wr_mas); request =mas_prealloc_calc (mas, entry);if (!request) -return ret; + goto set_flag; + mas->mas_flags &= ~MA_STATE_PREALLOC ;mas_node_count_gfp (mas, request, gfp);if (mas_is_err (mas)) {mas_set_alloc_req (mas,0 );
@@ -5507,6 +5508,7 @@ int mas_preallocate(struct ma_state *masreturn ret; } +set_flag: mas->mas_flags |=MA_STATE_PREALLOC ;return ret; }
Greg Kroah-Hartman
maintainerPATCH 189/263 mm: userfaultfd: fix race of userfaultfd_move and swap cache
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kairui Song <[email protected]>
commit 0ea148a799198518d8ebab63ddd0bb6114a103bc upstream.
This commit fixes two kinds of races, they may have different results:
Barry reported a BUG_ON in commit c50f8e6053b0, we may see the same BUG_ON if the filemap lookup returned NULL and folio is added to swap cache after that.
If another kind of race is triggered (folio changed after lookup) we may see RSS counter is corrupted:
[ 406.893936] BUG: Bad rss-counter state mm:ffff0000c5a9ddc0 type:MM_ANONPAGES val:-1 [ 406.894071] BUG: Bad rss-counter state mm:ffff0000c5a9ddc0
type:MM_SHMEMPAGES val:1
Because the folio is being accounted to the wrong VMA.
I'm not sure if there will be any data corruption though, seems no. The issues above are critical already.
On seeing a swap entry PTE, userfaultfd_move does a lockless swap cache lookup, and tries to move the found folio to the faulting vma. Currently, it relies on checking the PTE value to ensure that the moved folio still belongs to the src swap entry and that no new folio has been added to the swap cache, which turns out to be unreliable.
While working and reviewing the swap table series with Barry, following existing races are observed and reproduced [1]:
In the example below, move_pages_pte is moving src_pte to dst_pte, where src_pte is a swap entry PTE holding swap entry S1, and S1 is not in the swap cache:
CPU1 CPU2userfaultfd_move
move_pages_pte()
entry = pte_to_swp_entry(orig_src_pte);
// Here it got entry = S1
... < interrupted> ...
<swapin src_pte, alloc and use folio A>
// folio A is a new allocated folio
// and get installed into src_pte
<frees swap entry S1>
// src_pte now points to folio A, S1
// has swap count == 0, it can be freed
// by folio_swap_swap or swap
// allocator's reclaim.
<try to swap out another folio B>
// folio B is a folio in another VMA.
<put folio B to swap cache using S1 >
// S1 is freed, folio B can use it
// for swap out with no problem.
...
folio = filemap_get_folio(S1)
// Got folio B here !!!
... < interrupted again> ...
<swapin folio B and free S1>
// Now S1 is free to be used again.
<swapout src_pte & folio A using S1>
// Now src_pte is a swap entry PTE
// holding S1 again.
folio_trylock(folio)
move_swap_pte
double_pt_lock
is_pte_pages_stable
// Check passed because src_pte == S1
folio_move_anon_rmap(...)
// Moved invalid folio B here !!!The race window is very short and requires multiple collisions of multiple rare events, so it's very unlikely to happen, but with a deliberately constructed reproducer and increased time window, it can be reproduced easily.
This can be fixed by checking if the folio returned by filemap is the valid swap cache folio after acquiring the folio lock.
Another similar race is possible: filemap_get_folio may return NULL, but folio (A) could be swapped in and then swapped out again using the same swap entry after the lookup. In such a case, folio (A) may remain in the swap cache, so it must be moved too:
CPU1 CPU2userfaultfd_move
move_pages_pte()
entry = pte_to_swp_entry(orig_src_pte);
// Here it got entry = S1, and S1 is not in swap cache
folio = filemap_get_folio(S1)
// Got NULL
... < interrupted again> ...
<swapin folio A and free S1>
<swapout folio A re-using S1>
move_swap_pte
double_pt_lock
is_pte_pages_stable
// Check passed because src_pte == S1
folio_move_anon_rmap(...)
// folio A is ignored !!!Fix this by checking the swap cache again after acquiring the src_pte lock. And to avoid the filemap overhead, we check swap_map directly [2].
The SWP_SYNCHRONOUS_IO path does make the problem more complex, but so far we don't need to worry about that, since folios can only be exposed to the swap cache in the swap out path, and this is covered in this patch by checking the swap cache again after acquiring the src_pte lock.
Testing with a simple C program that allocates and moves several GB of memory did not show any observable performance change.
--- mm/userfaultfd.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
mm/userfaultfd.c +31 -2
@@ -1084,8 +1084,18 @@ static int move_swap_pte(struct mm_struc pte_t orig_dst_pte, pte_t orig_src_pte, pmd_t *dst_pmd, pmd_t dst_pmdval, spinlock_t *dst_ptl, spinlock_t *src_ptl, - struct folio *src_folio) + struct folio *src_folio, + struct swap_info_struct *si, swp_entry_t entry) { + /* + * Check if the folio still belongs to the target swap entry after + * acquiring the lock. Folio can be freed in the swap cache while + * not locked. + */ + if (src_folio && unlikely(!folio_test_swapcache(src_folio) || + entry.val != src_folio->swap.val)) + return -EAGAIN; +double_pt_lock (dst_ptl ,src_ptl ); if (!is_pte_pages_stable(dst_pte, src_pte, orig_dst_pte, orig_src_pte,
@@ -1102,6 +1112,25 @@ static int move_swap_pte(struct mm_strucif (src_folio) {folio_move_anon_rmap (src_folio, dst_vma); src_folio->index =linear_page_index (dst_vma, dst_addr); + }else { +/* +* Check if the swap entry is cached after acquiring the src_pte +* lock. Otherwise, we might miss a newly loaded swap cache folio. +* +* Check swap_map directly to minimize overhead, READ_ONCE is sufficient. +* We are trying to catch newly added swap cache, the only possible case is +* when a folio is swapped in and out again staying in swap cache, using the +* same entry before the PTE check above. The PTL is acquired and released +* twice, each time after updating the swap_map's flag. So holding +* the PTL here ensures we see the updated value. False positive is possible, +* e.g. SWP_SYNCHRONOUS_IO swapin may set the flag without touching the +* cache, or during the tiny synchronization window between swap cache and +* swap_map, but it will be gone very quickly, worst result is retry jitters. +*/ +if (READ_ONCE (si->swap_map[swp_offset (entry)]) &SWAP_HAS_CACHE ) { +double_pt_unlock (dst_ptl, src_ptl); +return -EAGAIN ; + } } orig_src_pte =ptep_get_and_clear (mm, src_addr, src_pte);
@@ -1412,7 +1441,7 @@ retry: } err =move_swap_pte (mm, dst_vma, dst_addr, src_addr, dst_pte, src_pte, orig_dst_pte, orig_src_pte, dst_pmd, dst_pmdval, - dst_ptl, src_ptl, src_folio); + dst_ptl, src_ptl, src_folio, si, entry); } out:
Greg Kroah-Hartman
maintainerPATCH 190/263 mm/shmem, swap: fix softlockup with mTHP swapin
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kairui Song <[email protected]>
commit a05dd8ae5cbb1cb45f349922cfea4f548a5e5d6f upstream.
Following softlockup can be easily reproduced on my test machine with:
echo always > /sys/kernel/mm/transparent_hugepage/hugepages-64kB/enabled swapon /dev/zram0 # zram0 is a 48G swap device
mkdir -p /sys/fs/cgroup/memory/test
echo 1G > /sys/fs/cgroup/test/memory.max
echo $BASHPID > /sys/fs/cgroup/test/cgroup.procs
while true; do
dd if=/dev/zero of=/tmp/test.img bs=1M count=5120
cat /tmp/test.img > /dev/null
rm /tmp/test.img
done
Then after a while:
watchdog: BUG: soft lockup - CPU#0 stuck for 763s! [cat:5787] Modules linked in: zram virtiofs CPU: 0 UID: 0 PID: 5787 Comm: cat Kdump: loaded Tainted: G L 6.15.0.orig-gf3021d9246bc-dirty #118 PREEMPT(voluntary)· Tainted: [L]=SOFTLOCKUP Hardware name: Red Hat KVM/RHEL-AV, BIOS 0.0.0 02/06/2015 RIP: 0010:mpol_shared_policy_lookup+0xd/0x70 Code: e9 b8 b4 ff ff 31 c0 c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 66 0f 1f 00 0f 1f 44 00 00 41 54 55 53 <48> 8b 1f 48 85 db 74 41 4c 8d 67 08 48 89 fb 48 89 f5 4c 89 e7 e8 RSP: 0018:ffffc90002b1fc28 EFLAGS: 00000202 RAX: 00000000001c20ca RBX: 0000000000724e1e RCX: 0000000000000001 RDX: ffff888118e214c8 RSI: 0000000000057d42 RDI: ffff888118e21518 RBP: 000000000002bec8 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000bf4 R11: 0000000000000000 R12: 0000000000000001 R13: 00000000001c20ca R14: 00000000001c20ca R15: 0000000000000000 FS: 00007f03f995c740(0000) GS:ffff88a07ad9a000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f03f98f1000 CR3: 0000000144626004 CR4: 0000000000770eb0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> shmem_alloc_folio+0x31/0xc0 shmem_swapin_folio+0x309/0xcf0 ? filemap_get_entry+0x117/0x1e0 ? xas_load+0xd/0xb0 ? filemap_get_entry+0x101/0x1e0 shmem_get_folio_gfp+0x2ed/0x5b0 shmem_file_read_iter+0x7f/0x2e0 vfs_read+0x252/0x330 ksys_read+0x68/0xf0 do_syscall_64+0x4c/0x1c0 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f03f9a46991 Code: 00 48 8b 15 81 14 10 00 f7 d8 64 89 02 b8 ff ff ff ff eb bd e8 20 ad 01 00 f3 0f 1e fa 80 3d 35 97 10 00 00 74 13 31 c0 0f 05 <48> 3d 00 f0 ff ff 77 4f c3 66 0f 1f 44 00 00 55 48 89 e5 48 83 ec RSP: 002b:00007fff3c52bd28 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 RAX: ffffffffffffffda RBX: 0000000000040000 RCX: 00007f03f9a46991 RDX: 0000000000040000 RSI: 00007f03f98ba000 RDI: 0000000000000003 RBP: 00007fff3c52bd50 R08: 0000000000000000 R09: 00007f03f9b9a380 R10: 0000000000000022 R11: 0000000000000246 R12: 0000000000040000 R13: 00007f03f98ba000 R14: 0000000000000003 R15: 0000000000000000 </TASK>
The reason is simple, readahead brought some order 0 folio in swap cache, and the swapin mTHP folio being allocated is in conflict with it, so swapcache_prepare fails and causes shmem_swap_alloc_folio to return -EEXIST, and shmem simply retries again and again causing this loop.
Fix it by applying a similar fix for anon mTHP swapin.
The performance change is very slight, time of swapin 10g zero folios with shmem (test for 12 times):
Before: 2.47s After: 2.48s
--- mm/memory.c | 20 -------------------- mm/shmem.c | 6 +++++- mm/swap.h | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 21 deletions(-)
mm/memory.c +0 -20
@@ -4224,26 +4224,6 @@ static struct folio *__alloc_swap_folio( }#ifdef CONFIG_TRANSPARENT_HUGEPAGE -static inline int non_swapcache_batch (swp_entry_t entry,int max_nr) -{ -struct swap_info_struct *si =swp_swap_info (entry); -pgoff_t offset =swp_offset (entry); -int i; - -/* -* While allocating a large folio and doing swap_read_folio, which is -* the case the being faulted pte doesn't have swapcache. We need to -* ensure all PTEs have no cache as well, otherwise, we might go to -* swap devices while the content is in swapcache. -*/ -for (i =0 ; i < max_nr; i++) { -if ((si->swap_map[offset + i] &SWAP_HAS_CACHE )) -return i; - } - -return i; -} -/* * Check if the PTEs within a range are contiguous swap entries * and have consistent swapcache, zeromap.
mm/shmem.c +5 -1
@@ -2262,6 +2262,7 @@ static int shmem_swapin_folio(struct ino folio =swap_cache_get_folio (swap,NULL ,0 ); order =xa_get_order (&mapping->i_pages, index);if (!folio) { +int nr_pages =1 << order;bool fallback_order0 = false;/* Or update major stats only when swapin succeeds?? */
@@ -2275,9 +2276,12 @@ static int shmem_swapin_folio(struct ino* If uffd is active for the vma, we need per-page fault * fidelity to maintain the uffd semantics, then fallback * to swapin order-0 folio, as well as for zswap case. +* Any existing sub folio in the swap cache also blocks +* mTHP swapin. */ if (order >0 && ((vma &&unlikely (userfaultfd_armed (vma))) || - !zswap_never_enabled ())) + !zswap_never_enabled () || +non_swapcache_batch (swap, nr_pages) != nr_pages)) fallback_order0 = true;/* Skip swapcache for synchronous device. */
mm/swap.h +23 -0
@@ -106,6 +106,25 @@ static inline int swap_zeromap_batch(swp return find_next_bit(sis->zeromap, end, start) - start; } +static inline int non_swapcache_batch (swp_entry_t entry,int max_nr) +{ +struct swap_info_struct *si =swp_swap_info (entry); +pgoff_t offset =swp_offset (entry); +int i; + +/* +* While allocating a large folio and doing mTHP swapin, we need to +* ensure all entries are not cached, otherwise, the mTHP folio will +* be in conflict with the folio in swap cache. +*/ +for (i =0 ; i < max_nr; i++) { +if ((si->swap_map[offset + i] &SWAP_HAS_CACHE )) +return i; + } + +return i; +} +#else /* CONFIG_SWAP */ struct swap_iocb ;static inline void swap_read_folio (struct folio *folio,struct swap_iocb **plug)
@@ -199,6 +218,10 @@ static inline int swap_zeromap_batch(swpreturn 0 ; } +static inline int non_swapcache_batch (swp_entry_t entry,int max_nr) +{ +return 0 ; +}#endif /* CONFIG_SWAP */ #endif /* _MM_SWAP_H */
Greg Kroah-Hartman
maintainerPATCH 191/263 mm/gup: revert "mm: gup: fix infinite loop within __get_longterm_locked"
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit 517f496e1e61bd169d585dab4dd77e7147506322 upstream.
After commit 1aaf8c122918 ("mm: gup: fix infinite loop within __get_longterm_locked") we are able to longterm pin folios that are not supposed to get longterm pinned, simply because they temporarily have the LRU flag cleared (esp. temporarily isolated).
For example, two __get_longterm_locked() callers can race, or __get_longterm_locked() can race with anything else that temporarily isolates folios.
The introducing commit mentions the use case of a driver that uses vm_ops->fault to insert pages allocated through cma_alloc() into the page tables, assuming they can later get longterm pinned. These pages/ folios would never have the LRU flag set and consequently cannot get isolated. There is no known in-tree user making use of that so far, fortunately.
To handle that in the future -- and avoid retrying forever to isolate/migrate them -- we will need a different mechanism for the CMA area *owner* to indicate that it actually already allocated the page and is fine with longterm pinning it. The LRU flag is not suitable for that.
Probably we can lookup the relevant CMA area and query the bitmap; we only have have to care about some races, probably. If already allocated, we could just allow longterm pinning)
Anyhow, let's fix the "must not be longterm pinned" problem first by reverting the original commit.
--- mm/gup.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
mm/gup.c +10 -4
@@ -2320,13 +2320,13 @@ static void pofs_unpin(struct pages_or_f/* * Returns the number of collected folios. Return value is always >= 0. */ -static void collect_longterm_unpinnable_folios ( +static unsigned long collect_longterm_unpinnable_folios (struct list_head *movable_folio_list,struct pages_or_folios *pofs) { +unsigned long i, collected =0 ;struct folio *prev_folio =NULL ;bool drain_allow = true; -unsigned long i;for (i =0 ; i < pofs->nr_entries; i++) {struct folio *folio =pofs_get_folio (pofs, i);
@@ -2338,6 +2338,8 @@ static void collect_longterm_unpinnable_if (folio_is_longterm_pinnable (folio))continue ; + collected++; +if (folio_is_device_coherent (folio))continue ;
@@ -2359,6 +2361,8 @@ static void collect_longterm_unpinnable_NR_ISOLATED_ANON +folio_is_file_lru (folio), folio_nr_pages(folio)); } + +return collected; }/*
@@ -2435,9 +2439,11 @@ static long check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs) {LIST_HEAD (movable_folio_list); +unsigned long collected; -collect_longterm_unpinnable_folios (&movable_folio_list, pofs); -if (list_empty (&movable_folio_list)) + collected =collect_longterm_unpinnable_folios (&movable_folio_list, + pofs); +if (!collected)return 0 ;return migrate_longterm_unpinnable_folios (&movable_folio_list, pofs);
Greg Kroah-Hartman
maintainerPATCH 192/263 f2fs: fix to zero post-eof page
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
commit ba8dac350faf16afc129ce6303ca4feaf083ccb1 upstream.
fstest reports a f2fs bug:
#generic/363 42s ... [failed, exit status 1]- output mismatch (see /share/git/fstests/results//generic/363.out.bad)
# --- tests/generic/363.out 2025-01-12 21:57:40.271440542 +0800 # +++ /share/git/fstests/results//generic/363.out.bad 2025-05-19 19:55:58.000000000 +0800 # @@ -1,2 +1,78 @@ # QA output created by 363 # fsx -q -S 0 -e 1 -N 100000 # +READ BAD DATA: offset = 0xd6fb, size = 0xf044, fname = /mnt/f2fs/junk # +OFFSET GOOD BAD RANGE # +0x1540d 0x0000 0x2a25 0x0 # +operation# (mod 256) for the bad data may be 37 # +0x1540e 0x0000 0x2527 0x1 # ... # (Run 'diff -u /share/git/fstests/tests/generic/363.out /share/git/fstests/results//generic/363.out.bad' to see the entire diff)
Ran: generic/363
Failures: generic/363
Failed 1 of 1 tests
The root cause is user can update post-eof page via mmap [1], however, f2fs missed to zero post-eof page in below operations, so, once it expands i_size, then it will include dummy data locates previous post-eof page, so during below operations, we need to zero post-eof page.
Operations which can include dummy data after previous i_size after expanding i_size:
- write
- mapwrite [1]
- truncate
- fallocate
* preallocate
* zero_range
* insert_range
* collapse_range
- clone_range (doesn’t support in f2fs)
- copy_range (doesn’t support in f2fs)
[1] https://man7.org/linux/man-pages/man2/mmap.2.html 'BUG section'
--- fs/f2fs/file.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
fs/f2fs/file.c +38 -0
@@ -35,6 +35,17 @@#include <trace/events/f2fs.h> #include <uapi/linux/f2fs.h> +static void f2fs_zero_post_eof_page (struct inode *inode,loff_t new_size) +{ +loff_t old_size =i_size_read (inode); + +if (old_size >= new_size) +return ; + +/* zero or drop pages only in range of [old_size, new_size] */ +truncate_pagecache (inode, old_size); +} +static vm_fault_t f2fs_filemap_fault (struct vm_fault *vmf) {struct inode *inode =file_inode (vmf->vma->vm_file);
@@ -103,8 +114,13 @@ static vm_fault_t f2fs_vm_page_mkwrite(sf2fs_bug_on (sbi,f2fs_has_inline_data (inode)); +filemap_invalidate_lock (inode->i_mapping); +f2fs_zero_post_eof_page (inode, (folio->index +1 ) <<PAGE_SHIFT ); +filemap_invalidate_unlock (inode->i_mapping); +file_update_time (vmf->vma->vm_file);filemap_invalidate_lock_shared (inode->i_mapping); +folio_lock (folio); if (unlikely(folio->mapping != inode->i_mapping || folio_pos(folio) > i_size_read(inode) ||
@@ -1106,6 +1122,8 @@ int f2fs_setattr(struct mnt_idmap *idmapf2fs_down_write (&fi->i_gc_rwsem[WRITE ]);filemap_invalidate_lock (inode->i_mapping); +if (attr->ia_size > old_size) +f2fs_zero_post_eof_page (inode, attr->ia_size);truncate_setsize (inode, attr->ia_size);if (attr->ia_size <= old_size)
@@ -1224,6 +1242,10 @@ static int f2fs_punch_hole(struct inodeif (ret)return ret; +filemap_invalidate_lock (inode->i_mapping); +f2fs_zero_post_eof_page (inode, offset + len); +filemap_invalidate_unlock (inode->i_mapping); + pg_start = ((unsigned long long ) offset) >>PAGE_SHIFT ; pg_end = ((unsigned long long ) offset + len) >>PAGE_SHIFT ;
@@ -1507,6 +1529,8 @@ static int f2fs_do_collapse(struct inodef2fs_down_write (&F2FS_I (inode)->i_gc_rwsem[WRITE ]);filemap_invalidate_lock (inode->i_mapping); +f2fs_zero_post_eof_page (inode, offset + len); +f2fs_lock_op (sbi);f2fs_drop_extent_tree (inode);truncate_pagecache (inode, offset);
@@ -1628,6 +1652,10 @@ static int f2fs_zero_range(struct inodeif (ret)return ret; +filemap_invalidate_lock (mapping); +f2fs_zero_post_eof_page (inode, offset + len); +filemap_invalidate_unlock (mapping); + pg_start = ((unsigned long long ) offset) >>PAGE_SHIFT ; pg_end = ((unsigned long long ) offset + len) >>PAGE_SHIFT ;
@@ -1759,6 +1787,8 @@ static int f2fs_insert_range(struct inod/* avoid gc operation during block exchange */ f2fs_down_write (&F2FS_I (inode)->i_gc_rwsem[WRITE ]);filemap_invalidate_lock (mapping); + +f2fs_zero_post_eof_page (inode, offset + len);truncate_pagecache (inode, offset);while (!ret && idx > pg_start) {
@@ -1816,6 +1846,10 @@ static int f2fs_expand_inode_data(structif (err)return err; +filemap_invalidate_lock (inode->i_mapping); +f2fs_zero_post_eof_page (inode, offset + len); +filemap_invalidate_unlock (inode->i_mapping); +f2fs_balance_fs (sbi, true); pg_start = ((unsigned long long )offset) >>PAGE_SHIFT ;
@@ -4846,6 +4880,10 @@ static ssize_t f2fs_write_checks(struct err =file_modified (file);if (err)return err; + +filemap_invalidate_lock (inode->i_mapping); +f2fs_zero_post_eof_page (inode, iocb->ki_pos +iov_iter_count (from)); +filemap_invalidate_unlock (inode->i_mapping);return count; }
Greg Kroah-Hartman
maintainerPATCH 193/263 HID: appletb-kbd: fix "appletb_backlight" backlight device reference counting
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qasim Ijaz <[email protected]>
commit 4540e41e753a7d69ecd3f5bad51fe620205c3a18 upstream.
During appletb_kbd_probe, probe attempts to get the backlight device by name. When this happens backlight_device_get_by_name looks for a device in the backlight class which has name "appletb_backlight" and upon finding a match it increments the reference count for the device and returns it to the caller. However this reference is never released leading to a reference leak.
Fix this by decrementing the backlight device reference count on removal via put_device and on probe failure.
--- drivers/hid/hid-appletb-kbd.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hid/hid-appletb-kbd.c +5 -0
@@ -435,6 +435,8 @@ static int appletb_kbd_probe(struct hid_return 0 ; close_hw: +if (kbd->backlight_dev) +put_device (&kbd->backlight_dev->dev);hid_hw_close (hdev); stop_hw:hid_hw_stop (hdev);
@@ -450,6 +452,9 @@ static void appletb_kbd_remove(struct hiinput_unregister_handler (&kbd->inp_handler);timer_delete_sync (&kbd->inactivity_timer); +if (kbd->backlight_dev) +put_device (&kbd->backlight_dev->dev); +hid_hw_close (hdev);hid_hw_stop (hdev); }
Greg Kroah-Hartman
maintainerPATCH 194/263 HID: lenovo: Restrict F7/9/11 mode to compact keyboards only
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Iusico Maxim <[email protected]>
commit 9327e3ee5b077c4ab4495a09b67624f670ed88b6 upstream.
Commit 2f2bd7cbd1d1 ("hid: lenovo: Resend all settings on reset_resume for compact keyboards") introduced a regression for ThinkPad TrackPoint Keyboard II by removing the conditional check for enabling F7/9/11 mode needed for compact keyboards only. As a result, the non-compact keyboards can no longer toggle Fn-lock via Fn+Esc, although it can be controlled via sysfs knob that directly sends raw commands.
This patch restores the previous conditional check without any additions.
--- drivers/hid/hid-lenovo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/hid/hid-lenovo.c +7 -4
@@ -548,11 +548,14 @@ static void lenovo_features_set_cptkbd(s/* * Tell the keyboard a driver understands it, and turn F7, F9, F11 into -* regular keys +* regular keys (Compact only) */ - ret =lenovo_send_cmd_cptkbd (hdev,0x01 ,0x03 ); -if (ret) -hid_warn (hdev,"Failed to switch F7/9/11 mode: %d\n" , ret); +if (hdev->product ==USB_DEVICE_ID_LENOVO_CUSBKBD || + hdev->product ==USB_DEVICE_ID_LENOVO_CBTKBD ) { + ret =lenovo_send_cmd_cptkbd (hdev,0x01 ,0x03 ); +if (ret) +hid_warn (hdev,"Failed to switch F7/9/11 mode: %d\n" , ret); + }/* Switch middle button to native mode */ ret =lenovo_send_cmd_cptkbd (hdev,0x09 ,0x01 );
Greg Kroah-Hartman
maintainerPATCH 195/263 HID: wacom: fix memory leak on kobject creation failure
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qasim Ijaz <[email protected]>
commit 5ae416c5b1e2e816aee7b3fc8347adf70afabb4c upstream.
During wacom_initialize_remotes() a fifo buffer is allocated with kfifo_alloc() and later a cleanup action is registered during devm_add_action_or_reset() to clean it up.
However if the code fails to create a kobject and register it with sysfs the code simply returns -ENOMEM before the cleanup action is registered leading to a memory leak.
Fix this by ensuring the fifo is freed when the kobject creation and registration process fails.
--- drivers/hid/wacom_sys.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/wacom_sys.c +3 -1
@@ -2048,8 +2048,10 @@ static int wacom_initialize_remotes(stru remote->remote_dir =kobject_create_and_add ("wacom_remote" , &wacom->hdev->dev.kobj); -if (!remote->remote_dir) +if (!remote->remote_dir) { +kfifo_free (&remote->remote_fifo);return -ENOMEM ; + } error =sysfs_create_files (remote->remote_dir, remote_unpair_attrs);
Greg Kroah-Hartman
maintainerPATCH 196/263 HID: wacom: fix memory leak on sysfs attribute creation failure
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qasim Ijaz <[email protected]>
commit 1a19ae437ca5d5c7d9ec2678946fb339b1c706bf upstream.
When sysfs_create_files() fails during wacom_initialize_remotes() the fifo buffer is not freed leading to a memory leak.
Fix this by calling kfifo_free() before returning.
--- drivers/hid/wacom_sys.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/wacom_sys.c +1 -0
@@ -2058,6 +2058,7 @@ static int wacom_initialize_remotes(struif (error) {hid_err (wacom->hdev,"cannot create sysfs group err: %d\n" , error); +kfifo_free (&remote->remote_fifo);return error; }
Greg Kroah-Hartman
maintainerPATCH 197/263 HID: wacom: fix kobject reference count leak
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qasim Ijaz <[email protected]>
commit 85a720f4337f0ddf1603c8b75a8f1ffbbe022ef9 upstream.
When sysfs_create_files() fails in wacom_initialize_remotes() the error is returned and the cleanup action will not have been registered yet.
As a result the kobject???s refcount is never dropped, so the kobject can never be freed leading to a reference leak.
Fix this by calling kobject_put() before returning.
--- drivers/hid/wacom_sys.c | 1 + 1 file changed, 1 insertion(+)
drivers/hid/wacom_sys.c +1 -0
@@ -2059,6 +2059,7 @@ static int wacom_initialize_remotes(struhid_err (wacom->hdev,"cannot create sysfs group err: %d\n" , error);kfifo_free (&remote->remote_fifo); +kobject_put (remote->remote_dir);return error; }
Greg Kroah-Hartman
maintainerPATCH 198/263 scsi: megaraid_sas: Fix invalid node index
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Yu <[email protected]>
commit 752eb816b55adb0673727ba0ed96609a17895654 upstream.
On a system with DRAM interleave enabled, out-of-bound access is detected:
megaraid_sas 0000:3f:00.0: requested/available msix 128/128 poll_queue 0
------------[ cut here ]------------ UBSAN: array-index-out-of-bounds in ./arch/x86/include/asm/topology.h:72:28 index -1 is out of range for type 'cpumask *[1024]' dump_stack_lvl+0x5d/0x80 ubsan_epilogue+0x5/0x2b __ubsan_handle_out_of_bounds.cold+0x46/0x4b megasas_alloc_irq_vectors+0x149/0x190 [megaraid_sas] megasas_probe_one.cold+0xa4d/0x189c [megaraid_sas] local_pci_probe+0x42/0x90 pci_device_probe+0xdc/0x290 really_probe+0xdb/0x340 __driver_probe_device+0x78/0x110 driver_probe_device+0x1f/0xa0 __driver_attach+0xba/0x1c0 bus_for_each_dev+0x8b/0xe0 bus_add_driver+0x142/0x220 driver_register+0x72/0xd0 megasas_init+0xdf/0xff0 [megaraid_sas] do_one_initcall+0x57/0x310 do_init_module+0x90/0x250 init_module_from_file+0x85/0xc0 idempotent_init_module+0x114/0x310 __x64_sys_finit_module+0x65/0xc0 do_syscall_64+0x82/0x170 entry_SYSCALL_64_after_hwframe+0x76/0x7e
Fix it accordingly.
--- drivers/scsi/megaraid/megaraid_sas_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/scsi/megaraid/megaraid_sas_base.c +5 -1
@@ -5910,7 +5910,11 @@ megasas_set_high_iops_queue_affinity_andconst struct cpumask *mask;if (instance->perf_mode ==MR_BALANCED_PERF_MODE ) { - mask =cpumask_of_node (dev_to_node (&instance->pdev->dev)); +int nid =dev_to_node (&instance->pdev->dev); + +if (nid ==NUMA_NO_NODE ) + nid =0 ; + mask =cpumask_of_node (nid);for (i =0 ; i < instance->low_latency_index_start; i++) { irq =pci_irq_vector (instance->pdev, i);
Greg Kroah-Hartman
maintainerPATCH 199/263 scsi: ufs: core: Fix clk scaling to be conditional in reset and restore
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: anvithdosapati <[email protected]>
commit 2e083cd802294693a5414e4557a183dd7e442e71 upstream.
In ufshcd_host_reset_and_restore(), scale up clocks only when clock scaling is supported. Without this change CPU latency is voted for 0 (ufshcd_pm_qos_update) during resume unconditionally.
--- drivers/ufs/core/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/ufs/core/ufshcd.c +2 -1
@@ -7753,7 +7753,8 @@ static int ufshcd_host_reset_and_restore hba->silence_err_logs = false;/* scale up clocks to max frequency before full reinitialization */ -ufshcd_scale_clks (hba,ULONG_MAX , true); +if (ufshcd_is_clkscaling_supported (hba)) +ufshcd_scale_clks (hba,ULONG_MAX , true); err =ufshcd_hba_enable (hba);
Greg Kroah-Hartman
maintainerPATCH 200/263 scsi: fnic: Fix crash in fnic_wq_cmpl_handler when FDMI times out
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karan Tilak Kumar <[email protected]>
commit a35b29bdedb4d2ae3160d4d6684a6f1ecd9ca7c2 upstream.
When both the RHBA and RPA FDMI requests time out, fnic reuses a frame to send ABTS for each of them. On send completion, this causes an attempt to free the same frame twice that leads to a crash.
Fix crash by allocating separate frames for RHBA and RPA, and modify ABTS logic accordingly.
Tested by checking MDS for FDMI information.
Tested by using instrumented driver to:
- Drop PLOGI response
- Drop RHBA response
- Drop RPA response
- Drop RHBA and RPA response
- Drop PLOGI response + ABTS response
- Drop RHBA response + ABTS response
- Drop RPA response + ABTS response
- Drop RHBA and RPA response + ABTS response for both of them
--- drivers/scsi/fnic/fdls_disc.c | 113 +++++++++++++++++++++++++++++++----------- drivers/scsi/fnic/fnic.h | 2 drivers/scsi/fnic/fnic_fdls.h | 1 3 files changed, 87 insertions(+), 29 deletions(-)
drivers/scsi/fnic/fdls_disc.c +85 -28
@@ -763,47 +763,69 @@ static void fdls_send_fabric_abts(struct iport->fabric.timer_pending =1 ; } -static void fdls_send_fdmi_abts (struct fnic_iport_s *iport) +static uint8_t *fdls_alloc_init_fdmi_abts_frame (struct fnic_iport_s *iport, +uint16_t oxid) { -uint8_t *frame; +struct fc_frame_header *pfdmi_abts;uint8_t d_id[3 ]; +uint8_t *frame;struct fnic *fnic = iport->fnic; -struct fc_frame_header *pfabric_abts; -unsigned long fdmi_tov; -uint16_t oxid; -uint16_t frame_size =FNIC_ETH_FCOE_HDRS_OFFSET + -sizeof (struct fc_frame_header ); frame =fdls_alloc_frame (iport);if (frame ==NULL ) {FNIC_FCS_DBG (KERN_ERR , fnic->host, fnic->fnic_num,"Failed to allocate frame to send FDMI ABTS" ); -return ; +return NULL ; } - pfabric_abts = (struct fc_frame_header *) (frame +FNIC_ETH_FCOE_HDRS_OFFSET ); + pfdmi_abts = (struct fc_frame_header *) (frame +FNIC_ETH_FCOE_HDRS_OFFSET );fdls_init_fabric_abts_frame (frame, iport);hton24 (d_id,FC_FID_MGMT_SERV ); -FNIC_STD_SET_D_ID (*pfabric_abts, d_id); +FNIC_STD_SET_D_ID (*pfdmi_abts, d_id); +FNIC_STD_SET_OX_ID (*pfdmi_abts, oxid); + +return frame; +} + +static void fdls_send_fdmi_abts (struct fnic_iport_s *iport) +{ +uint8_t *frame; +unsigned long fdmi_tov; +uint16_t frame_size =FNIC_ETH_FCOE_HDRS_OFFSET + +sizeof (struct fc_frame_header );if (iport->fabric.fdmi_pending &FDLS_FDMI_PLOGI_PENDING ) { - oxid = iport->active_oxid_fdmi_plogi; -FNIC_STD_SET_OX_ID (*pfabric_abts, oxid); + frame =fdls_alloc_init_fdmi_abts_frame (iport, + iport->active_oxid_fdmi_plogi); +if (frame ==NULL ) +return ; +fnic_send_fcoe_frame (iport, frame, frame_size); }else {if (iport->fabric.fdmi_pending &FDLS_FDMI_REG_HBA_PENDING ) { - oxid = iport->active_oxid_fdmi_rhba; -FNIC_STD_SET_OX_ID (*pfabric_abts, oxid); + frame =fdls_alloc_init_fdmi_abts_frame (iport, + iport->active_oxid_fdmi_rhba); +if (frame ==NULL ) +return ; +fnic_send_fcoe_frame (iport, frame, frame_size); }if (iport->fabric.fdmi_pending &FDLS_FDMI_RPA_PENDING ) { - oxid = iport->active_oxid_fdmi_rpa; -FNIC_STD_SET_OX_ID (*pfabric_abts, oxid); + frame =fdls_alloc_init_fdmi_abts_frame (iport, + iport->active_oxid_fdmi_rpa); +if (frame ==NULL ) { +if (iport->fabric.fdmi_pending &FDLS_FDMI_REG_HBA_PENDING ) + goto arm_timer; +else +return ; + } +fnic_send_fcoe_frame (iport, frame, frame_size); } } +arm_timer: fdmi_tov = jiffies +msecs_to_jiffies (2 * iport->e_d_tov);mod_timer (&iport->fabric.fdmi_timer,round_jiffies (fdmi_tov)); iport->fabric.fdmi_pending |=FDLS_FDMI_ABORT_PENDING ;
@@ -2244,6 +2266,21 @@ void fdls_fabric_timer_callback(struct tspin_unlock_irqrestore (&fnic->fnic_lock, flags); } +void fdls_fdmi_retry_plogi (struct fnic_iport_s *iport) +{ +struct fnic *fnic = iport->fnic; + + iport->fabric.fdmi_pending =0 ; +/* If max retries not exhausted, start over from fdmi plogi */ +if (iport->fabric.fdmi_retry <FDLS_FDMI_MAX_RETRY ) { + iport->fabric.fdmi_retry++; +FNIC_FCS_DBG (KERN_INFO , fnic->host, fnic->fnic_num, +"Retry FDMI PLOGI. FDMI retry: %d" , + iport->fabric.fdmi_retry); +fdls_send_fdmi_plogi (iport); + } +} +void fdls_fdmi_timer_callback (struct timer_list *t) {struct fnic_fdls_fabric_s *fabric =from_timer (fabric, t, fdmi_timer);
@@ -2289,14 +2326,7 @@ void fdls_fdmi_timer_callback(struct timFNIC_FCS_DBG (KERN_INFO , fnic->host, fnic->fnic_num,"fdmi timer callback : 0x%x\n" , iport->fabric.fdmi_pending); - iport->fabric.fdmi_pending =0 ; -/* If max retries not exhaused, start over from fdmi plogi */ -if (iport->fabric.fdmi_retry <FDLS_FDMI_MAX_RETRY ) { - iport->fabric.fdmi_retry++; -FNIC_FCS_DBG (KERN_INFO , fnic->host, fnic->fnic_num, -"retry fdmi timer %d" , iport->fabric.fdmi_retry); -fdls_send_fdmi_plogi (iport); - } +fdls_fdmi_retry_plogi (iport);FNIC_FCS_DBG (KERN_INFO , fnic->host, fnic->fnic_num,"fdmi timer callback : 0x%x\n" , iport->fabric.fdmi_pending);spin_unlock_irqrestore (&fnic->fnic_lock, flags);
@@ -3714,11 +3744,32 @@ static void fdls_process_fdmi_abts_rsp(sswitch (FNIC_FRAME_TYPE (oxid)) {case FNIC_FRAME_TYPE_FDMI_PLOGI :fdls_free_oxid (iport, oxid, &iport->active_oxid_fdmi_plogi); + + iport->fabric.fdmi_pending &= ~FDLS_FDMI_PLOGI_PENDING ; + iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING ;break ;case FNIC_FRAME_TYPE_FDMI_RHBA : + iport->fabric.fdmi_pending &= ~FDLS_FDMI_REG_HBA_PENDING ; + +/* If RPA is still pending, don't turn off ABORT PENDING. +* We count on the timer to detect the ABTS timeout and take +* corrective action. +*/ +if (!(iport->fabric.fdmi_pending &FDLS_FDMI_RPA_PENDING )) + iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING ; +fdls_free_oxid (iport, oxid, &iport->active_oxid_fdmi_rhba);break ;case FNIC_FRAME_TYPE_FDMI_RPA : + iport->fabric.fdmi_pending &= ~FDLS_FDMI_RPA_PENDING ; + +/* If RHBA is still pending, don't turn off ABORT PENDING. +* We count on the timer to detect the ABTS timeout and take +* corrective action. +*/ +if (!(iport->fabric.fdmi_pending &FDLS_FDMI_REG_HBA_PENDING )) + iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING ; +fdls_free_oxid (iport, oxid, &iport->active_oxid_fdmi_rpa);break ;default :
@@ -3728,10 +3779,16 @@ static void fdls_process_fdmi_abts_rsp(sbreak ; } -timer_delete_sync (&iport->fabric.fdmi_timer); - iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING ; - -fdls_send_fdmi_plogi (iport); +/* +* Only if ABORT PENDING is off, delete the timer, and if no other +* operations are pending, retry FDMI. +* Otherwise, let the timer pop and take the appropriate action. +*/ +if (!(iport->fabric.fdmi_pending &FDLS_FDMI_ABORT_PENDING )) { +timer_delete_sync (&iport->fabric.fdmi_timer); +if (!iport->fabric.fdmi_pending) +fdls_fdmi_retry_plogi (iport); + } } static void
drivers/scsi/fnic/fnic.h +1 -1
@@ -30,7 +30,7 @@#define DRV_NAME "fnic"#define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.8.0.0" +#define DRV_VERSION "1.8.0.1"#define PFX DRV_NAME ": "#define DFX DRV_NAME "%d: "
drivers/scsi/fnic/fnic_fdls.h +1 -0
@@ -394,6 +394,7 @@ void fdls_send_tport_abts(struct fnic_ipbool fdls_delete_tport (struct fnic_iport_s *iport,struct fnic_tport_s *tport);void fdls_fdmi_timer_callback (struct timer_list *t); +void fdls_fdmi_retry_plogi (struct fnic_iport_s *iport);/* fnic_fcs.c */ void fnic_fdls_init (struct fnic *fnic,int usefip);
Greg Kroah-Hartman
maintainerPATCH 201/263 scsi: fnic: Turn off FDMI ACTIVE flags on link down
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karan Tilak Kumar <[email protected]>
commit 74f46a0524f8d2f01dc7ca95bb5fc463a8603e72 upstream.
When the link goes down and comes up, FDMI requests are not sent out anymore.
Fix bug by turning off FNIC_FDMI_ACTIVE when the link goes down.
--- drivers/scsi/fnic/fdls_disc.c | 9 ++++++--- drivers/scsi/fnic/fnic.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
drivers/scsi/fnic/fdls_disc.c +6 -3
@@ -5027,9 +5027,12 @@ void fnic_fdls_link_down(struct fnic_ipofdls_delete_tport (iport, tport); } -if ((fnic_fdmi_support ==1 ) && (iport->fabric.fdmi_pending >0 )) { -timer_delete_sync (&iport->fabric.fdmi_timer); - iport->fabric.fdmi_pending =0 ; +if (fnic_fdmi_support ==1 ) { +if (iport->fabric.fdmi_pending >0 ) { +timer_delete_sync (&iport->fabric.fdmi_timer); + iport->fabric.fdmi_pending =0 ; + } + iport->flags &= ~FNIC_FDMI_ACTIVE ; } FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
drivers/scsi/fnic/fnic.h +1 -1
@@ -30,7 +30,7 @@#define DRV_NAME "fnic"#define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.8.0.1" +#define DRV_VERSION "1.8.0.2"#define PFX DRV_NAME ": "#define DFX DRV_NAME "%d: "
Greg Kroah-Hartman
maintainerPATCH 202/263 drm/ast: Fix comment on modeset lock
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit 7cce65f3789e04c0f7668a66563e680d81d54493 upstream.
The ast driver protects the commit tail against concurrent reads of the display modes by acquiring a lock. The comment is misleading as the lock is not released in atomic_flush, but at the end of the commit-tail helper. Rewrite the comment.
--- drivers/gpu/drm/ast/ast_mode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/ast/ast_mode.c +3 -3
@@ -922,9 +922,9 @@ static void ast_mode_config_helper_atomi/* * Concurrent operations could possibly trigger a call to -* drm_connector_helper_funcs.get_modes by trying to read the -* display modes. Protect access to I/O registers by acquiring -* the I/O-register lock. Released in atomic_flush(). +* drm_connector_helper_funcs.get_modes by reading the display +* modes. Protect access to registers by acquiring the modeset +* lock. */ mutex_lock (&ast->modeset_lock);drm_atomic_helper_commit_tail (state);
Greg Kroah-Hartman
maintainerPATCH 203/263 drm/cirrus-qemu: Fix pitch programming
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit 4bfb389a0136a13f0802eeb5e97a0e76d88f77ae upstream.
Do not set CR1B[6] when programming the pitch. The bit effects VGA text mode and is not interpreted by qemu. [1] It has no affect on the scanline pitch.
The scanline bit that is set into CR1B[6] belongs into CR13[7], which the driver sets up correctly.
This bug goes back to the driver's initial commit.
--- drivers/gpu/drm/tiny/cirrus-qemu.c | 1 - 1 file changed, 1 deletion(-)
drivers/gpu/drm/tiny/cirrus-qemu.c +0 -1
@@ -318,7 +318,6 @@ static void cirrus_pitch_set(struct cirr/* Enable extended blanking and pitch bits, and enable full memory */ cr1b =0x22 ; cr1b |= (pitch >>7 ) &0x10 ; - cr1b |= (pitch >>6 ) &0x40 ;wreg_crt (cirrus,0x1b , cr1b);cirrus_set_start_address (cirrus,0 );
Greg Kroah-Hartman
maintainerPATCH 204/263 drm/etnaviv: Protect the schedulers pending list with its lock
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maíra Canal <[email protected]>
commit 61ee19dedb8d753249e20308782bf4e9e2fb7344 upstream.
Commit 704d3d60fec4 ("drm/etnaviv: don't block scheduler when GPU is still active") ensured that active jobs are returned to the pending list when extending the timeout. However, it didn't use the pending list's lock to manipulate the list, which causes a race condition as the scheduler's workqueues are running.
Hold the lock while manipulating the scheduler's pending list to prevent a race.
--- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/etnaviv/etnaviv_sched.c +4 -1
@@ -35,6 +35,7 @@ static enum drm_gpu_sched_stat etnaviv_s *sched_job) {struct etnaviv_gem_submit *submit =to_etnaviv_submit (sched_job); +struct drm_gpu_scheduler *sched = sched_job->sched;struct etnaviv_gpu *gpu = submit->gpu;u32 dma_addr, primid =0 ;int change;
@@ -89,7 +90,9 @@ static enum drm_gpu_sched_stat etnaviv_sreturn DRM_GPU_SCHED_STAT_NOMINAL ; out_no_timeout: -list_add (&sched_job->list, &sched_job->sched->pending_list); +spin_lock (&sched->job_list_lock); +list_add (&sched_job->list, &sched->pending_list); +spin_unlock (&sched->job_list_lock);return DRM_GPU_SCHED_STAT_NOMINAL ; }
Greg Kroah-Hartman
maintainerPATCH 205/263 drm/panel: simple: Tianma TM070JDHG34-00: add delays
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Ceresoli <[email protected]>
commit 716c75afd83c837f14042309126e838de040658b upstream.
Add power on/off delays for the Tianma TM070JDHG34-00.
--- drivers/gpu/drm/panel/panel-simple.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/panel/panel-simple.c +6 -0
@@ -4455,6 +4455,12 @@ static const struct panel_desc tianma_tm .width = 150, /* 149.76 */ .height = 94, /* 93.60 */ }, + .delay = { + .prepare = 15, /* Tp1 */ + .enable = 150, /* Tp2 */ + .disable = 150, /* Tp4 */ + .unprepare = 120, /* Tp3 */ + }, .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, .connector_type = DRM_MODE_CONNECTOR_LVDS, };
Greg Kroah-Hartman
maintainerPATCH 206/263 drm/simpledrm: Do not upcast in release helpers
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit d231cde7c84359fb18fb268cf6cff03b5bce48ff upstream.
The res pointer passed to simpledrm_device_release_clocks() and simpledrm_device_release_regulators() points to an instance of struct simpledrm_device. No need to upcast from struct drm_device. The upcast is harmless, as DRM device is the first field in struct simpledrm_device.
--- drivers/gpu/drm/tiny/simpledrm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/tiny/simpledrm.c +2 -2
@@ -284,7 +284,7 @@ static struct simpledrm_device *simpledrstatic void simpledrm_device_release_clocks (void *res) { -struct simpledrm_device *sdev =simpledrm_device_of_dev (res); +struct simpledrm_device *sdev = res;unsigned int i;for (i =0 ; i < sdev->clk_count; ++i) {
@@ -382,7 +382,7 @@ static int simpledrm_device_init_clocks(static void simpledrm_device_release_regulators (void *res) { -struct simpledrm_device *sdev =simpledrm_device_of_dev (res); +struct simpledrm_device *sdev = res;unsigned int i;for (i =0 ; i < sdev->regulator_count; ++i) {
Greg Kroah-Hartman
maintainerPATCH 207/263 drm/tegra: Assign plane type before registration
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thierry Reding <[email protected]>
commit 9ff4fdf4f44b69237c0afc1d3a8dac916ce66f3e upstream.
Changes to a plane's type after it has been registered aren't propagated to userspace automatically. This could possibly be achieved by updating the property, but since we can already determine which type this should be before the registration, passing in the right type from the start is a much better solution.
--- drivers/gpu/drm/tegra/dc.c | 12 ++++++++---- drivers/gpu/drm/tegra/hub.c | 4 ++-- drivers/gpu/drm/tegra/hub.h | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-)
drivers/gpu/drm/tegra/dc.c +8 -4
@@ -1321,10 +1321,16 @@ static struct drm_plane *tegra_dc_add_shif (wgrp->dc == dc->pipe) {for (j =0 ; j < wgrp->num_windows; j++) {unsigned int index = wgrp->windows[j]; +enum drm_plane_type type; + +if (primary) + type =DRM_PLANE_TYPE_OVERLAY ; +else + type =DRM_PLANE_TYPE_PRIMARY ; plane =tegra_shared_plane_create (drm, dc, wgrp->index, - index); + index, type);if (IS_ERR (plane))return plane;
@@ -1332,10 +1338,8 @@ static struct drm_plane *tegra_dc_add_sh* Choose the first shared plane owned by this * head as the primary plane. */ -if (!primary) { - plane->type =DRM_PLANE_TYPE_PRIMARY ; +if (!primary) primary = plane; - } } } }
drivers/gpu/drm/tegra/hub.c +2 -2
@@ -755,9 +755,9 @@ static const struct drm_plane_helper_funstruct drm_plane *tegra_shared_plane_create (struct drm_device *drm,struct tegra_dc *dc,unsigned int wgrp, -unsigned int index) +unsigned int index, +enum drm_plane_type type) { -enum drm_plane_type type =DRM_PLANE_TYPE_OVERLAY ;struct tegra_drm *tegra = drm->dev_private;struct tegra_display_hub *hub = tegra->hub;struct tegra_shared_plane *plane;
drivers/gpu/drm/tegra/hub.h +2 -1
@@ -80,7 +80,8 @@ void tegra_display_hub_cleanup(struct testruct drm_plane *tegra_shared_plane_create (struct drm_device *drm,struct tegra_dc *dc,unsigned int wgrp, -unsigned int index); +unsigned int index, +enum drm_plane_type type);int tegra_display_hub_atomic_check (struct drm_device *drm,struct drm_atomic_state *state);
Greg Kroah-Hartman
maintainerPATCH 208/263 drm/tegra: Fix a possible null pointer dereference
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qiu-ji Chen <[email protected]>
commit 780351a5f61416ed2ba1199cc57e4a076fca644d upstream.
In tegra_crtc_reset(), new memory is allocated with kzalloc(), but no check is performed. Before calling __drm_atomic_helper_crtc_reset, state should be checked to prevent possible null pointer dereference.
--- drivers/gpu/drm/tegra/dc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/tegra/dc.c +4 -1
@@ -1393,7 +1393,10 @@ static void tegra_crtc_reset(struct drm_if (crtc->state)tegra_crtc_atomic_destroy_state (crtc, crtc->state); -__drm_atomic_helper_crtc_reset (crtc, &state->base); +if (state) +__drm_atomic_helper_crtc_reset (crtc, &state->base); +else +__drm_atomic_helper_crtc_reset (crtc,NULL ); } static struct drm_crtc_state *
Greg Kroah-Hartman
maintainerPATCH 209/263 drm/udl: Unregister device before cleaning up on disconnect
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
commit ff9cb6d2035c586ea7c8f1754d4409eec7a2d26d upstream.
Disconnecting a DisplayLink device results in the following kernel error messages
[ 93.041748] [drm:udl_urb_completion [udl]] *ERROR* udl_urb_completion - nonzero write bulk status received: -115 [ 93.055299] [drm:udl_submit_urb [udl]] *ERROR* usb_submit_urb error fffffffe [ 93.065363] [drm:udl_urb_completion [udl]] *ERROR* udl_urb_completion - nonzero write bulk status received: -115 [ 93.078207] [drm:udl_submit_urb [udl]] *ERROR* usb_submit_urb error fffffffe
coming from KMS poll helpers. Shutting down poll helpers runs them one final time when the USB device is already gone.
Run drm_dev_unplug() first in udl's USB disconnect handler. Udl's polling code already handles disconnects gracefully if the device has been marked as unplugged.
--- drivers/gpu/drm/udl/udl_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/udl/udl_drv.c +1 -1
@@ -127,9 +127,9 @@ static void udl_usb_disconnect(struct us {struct drm_device *dev =usb_get_intfdata (interface); +drm_dev_unplug (dev);drm_kms_helper_poll_fini (dev);udl_drop_usb (dev); -drm_dev_unplug (dev); }/*
Greg Kroah-Hartman
maintainerPATCH 210/263 drm/msm/gpu: Fix crash when throttling GPU immediately during boot
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
commit b71717735be48d7743a34897e9e44a0b53e30c0e upstream.
There is a small chance that the GPU is already hot during boot. In that case, the call to of_devfreq_cooling_register() will immediately try to apply devfreq cooling, as seen in the following crash:
Unable to handle kernel paging request at virtual address 0000000000014110 pc : a6xx_gpu_busy+0x1c/0x58 [msm] lr : msm_devfreq_get_dev_status+0xbc/0x140 [msm] Call trace: a6xx_gpu_busy+0x1c/0x58 [msm] (P) devfreq_simple_ondemand_func+0x3c/0x150 devfreq_update_target+0x44/0xd8 qos_max_notifier_call+0x30/0x84 blocking_notifier_call_chain+0x6c/0xa0 pm_qos_update_target+0xd0/0x110 freq_qos_apply+0x3c/0x74 apply_constraint+0x88/0x148 __dev_pm_qos_update_request+0x7c/0xcc dev_pm_qos_update_request+0x38/0x5c devfreq_cooling_set_cur_state+0x98/0xf0 __thermal_cdev_update+0x64/0xb4 thermal_cdev_update+0x4c/0x58 step_wise_manage+0x1f0/0x318 __thermal_zone_device_update+0x278/0x424 __thermal_cooling_device_register+0x2bc/0x308 thermal_of_cooling_device_register+0x10/0x1c of_devfreq_cooling_register_power+0x240/0x2bc of_devfreq_cooling_register+0x14/0x20 msm_devfreq_init+0xc4/0x1a0 [msm] msm_gpu_init+0x304/0x574 [msm] adreno_gpu_init+0x1c4/0x2e0 [msm] a6xx_gpu_init+0x5c8/0x9c8 [msm] adreno_bind+0x2a8/0x33c [msm] ...
At this point we haven't initialized the GMU at all yet, so we cannot read the GMU registers inside a6xx_gpu_busy(). A similar issue was fixed before in commit 6694482a70e9 ("drm/msm: Avoid unclocked GMU register access in 6xx gpu_busy"): msm_devfreq_init() does call devfreq_suspend_device(), but unlike msm_devfreq_suspend(), it doesn't set the df->suspended flag accordingly. This means the df->suspended flag does not match the actual devfreq state after initialization and msm_devfreq_get_dev_status() will end up accessing GMU registers, causing the crash.
Fix this by setting df->suspended correctly during initialization.
Patchwork: https://patchwork.freedesktop.org/patch/650772/
--- drivers/gpu/drm/msm/msm_gpu_devfreq.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/msm_gpu_devfreq.c +1 -0
@@ -156,6 +156,7 @@ void msm_devfreq_init(struct msm_gpu *gp priv->gpu_devfreq_config.downdifferential =10 ;mutex_init (&df->lock); + df->suspended = true; ret =dev_pm_qos_add_request (&gpu->pdev->dev, &df->boost_freq,DEV_PM_QOS_MIN_FREQUENCY ,0 );
Greg Kroah-Hartman
maintainerPATCH 211/263 drm/amdkfd: Fix race in GWS queue scheduling
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jay Cornwall <[email protected]>
commit cfb05257ae168a0496c7637e1d9e3ab8a25cbffe upstream.
q->gws is not updated atomically with qpd->mapped_gws_queue. If a runlist is created between pqm_set_gws and update_queue it will contain a queue which uses GWS in a process with no GWS allocated. This will result in a scheduler hang.
Use q->properties.is_gws which is changed while holding the DQM lock.
--- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c +1 -1
@@ -237,7 +237,7 @@ static int pm_map_queues_v9(struct packe packet->bitfields2.engine_sel = engine_sel__mes_map_queues__compute_vi; - packet->bitfields2.gws_control_queue = q->gws ?1 :0 ; + packet->bitfields2.gws_control_queue = q->properties.is_gws ?1 :0 ; packet->bitfields2.extended_engine_sel = extended_engine_sel__mes_map_queues__legacy_engine_sel; packet->bitfields2.queue_type =
Greg Kroah-Hartman
maintainerPATCH 212/263 drm/i915/ptl: Use everywhere the correct DDI port clock select mask
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak <[email protected]>
commit a38b3232d618653155032a51208e974511c151e4 upstream.
The PTL XELPDP_PORT_CLOCK_CTL register XELPDP_DDI_CLOCK_SELECT field's size is 5 bits vs. the earlier platforms where its size is 4 bits. Make sure the field is read-out/programmed everywhere correctly, according to the above.
--- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 ++++++++-------------- drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h | 15 ++++++++---- 2 files changed, 21 insertions(+), 21 deletions(-)
drivers/gpu/drm/i915/display/intel_cx0_phy.c +10 -17
@@ -2761,9 +2761,9 @@ static void intel_program_port_clock_ctl val |=XELPDP_FORWARD_CLOCK_UNGATE ;if (!is_dp &&is_hdmi_frl (port_clock)) - val |=XELPDP_DDI_CLOCK_SELECT (XELPDP_DDI_CLOCK_SELECT_DIV18CLK ); + val |=XELPDP_DDI_CLOCK_SELECT_PREP (display,XELPDP_DDI_CLOCK_SELECT_DIV18CLK );else - val |=XELPDP_DDI_CLOCK_SELECT (XELPDP_DDI_CLOCK_SELECT_MAXPCLK ); + val |=XELPDP_DDI_CLOCK_SELECT_PREP (display,XELPDP_DDI_CLOCK_SELECT_MAXPCLK );/* TODO: HDMI FRL */ /* DP2.0 10G and 20G rates enable MPLLA*/
@@ -2774,7 +2774,7 @@ static void intel_program_port_clock_ctlintel_de_rmw (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port),XELPDP_LANE1_PHY_CLOCK_SELECT |XELPDP_FORWARD_CLOCK_UNGATE | -XELPDP_DDI_CLOCK_SELECT_MASK |XELPDP_SSC_ENABLE_PLLA | +XELPDP_DDI_CLOCK_SELECT_MASK (display) |XELPDP_SSC_ENABLE_PLLA |XELPDP_SSC_ENABLE_PLLB , val); }
@@ -3097,10 +3097,7 @@ int intel_mtl_tbt_calc_port_clock(struct val =intel_de_read (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port)); -if (DISPLAY_VER (display) >=30 ) - clock =REG_FIELD_GET (XE3_DDI_CLOCK_SELECT_MASK , val); -else - clock =REG_FIELD_GET (XELPDP_DDI_CLOCK_SELECT_MASK , val); + clock =XELPDP_DDI_CLOCK_SELECT_GET (display, val);drm_WARN_ON (display->drm, !(val &XELPDP_FORWARD_CLOCK_UNGATE ));drm_WARN_ON (display->drm, !(val &XELPDP_TBT_CLOCK_REQUEST ));
@@ -3168,13 +3165,9 @@ static void intel_mtl_tbt_pll_enable(str* clock muxes, gating and SSC */ -if (DISPLAY_VER (display) >=30 ) { - mask =XE3_DDI_CLOCK_SELECT_MASK ; - val |=XE3_DDI_CLOCK_SELECT (intel_mtl_tbt_clock_select (display, crtc_state->port_clock)); - }else { - mask =XELPDP_DDI_CLOCK_SELECT_MASK ; - val |=XELPDP_DDI_CLOCK_SELECT (intel_mtl_tbt_clock_select (display, crtc_state->port_clock)); - } + mask =XELPDP_DDI_CLOCK_SELECT_MASK (display); + val |=XELPDP_DDI_CLOCK_SELECT_PREP (display, +intel_mtl_tbt_clock_select (display, crtc_state->port_clock)); mask |=XELPDP_FORWARD_CLOCK_UNGATE ; val |=XELPDP_FORWARD_CLOCK_UNGATE ;
@@ -3287,7 +3280,7 @@ static void intel_cx0pll_disable(struct/* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */ intel_de_rmw (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port), -XELPDP_DDI_CLOCK_SELECT_MASK ,0 ); +XELPDP_DDI_CLOCK_SELECT_MASK (display),0 );intel_de_rmw (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port),XELPDP_FORWARD_CLOCK_UNGATE ,0 );
@@ -3336,7 +3329,7 @@ static void intel_mtl_tbt_pll_disable(st* 5. Program PORT CLOCK CTRL register to disable and gate clocks */ intel_de_rmw (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port), -XELPDP_DDI_CLOCK_SELECT_MASK | +XELPDP_DDI_CLOCK_SELECT_MASK (display) |XELPDP_FORWARD_CLOCK_UNGATE ,0 );/* 6. Program DDI_CLK_VALFREQ to 0. */
@@ -3365,7 +3358,7 @@ intel_mtl_port_pll_type(struct intel_enc* handling is done via the standard shared DPLL framework. */ val =intel_de_read (display,XELPDP_PORT_CLOCK_CTL (display, encoder->port)); - clock =REG_FIELD_GET (XELPDP_DDI_CLOCK_SELECT_MASK , val); + clock =XELPDP_DDI_CLOCK_SELECT_GET (display, val);if (clock ==XELPDP_DDI_CLOCK_SELECT_MAXPCLK || clock ==XELPDP_DDI_CLOCK_SELECT_DIV18CLK )
drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h +11 -4
@@ -192,10 +192,17 @@#define XELPDP_TBT_CLOCK_REQUEST REG_BIT(19)#define XELPDP_TBT_CLOCK_ACK REG_BIT(18) -#define XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) -#define XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) -#define XELPDP_DDI_CLOCK_SELECT (val) REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val) -#define XE3_DDI_CLOCK_SELECT (val) REG_FIELD_PREP(XE3_DDI_CLOCK_SELECT_MASK, val) +#define _XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12) +#define _XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12) +#define XELPDP_DDI_CLOCK_SELECT_MASK (display) (DISPLAY_VER(display) >= 30 ? \ + _XE3_DDI_CLOCK_SELECT_MASK : _XELPDP_DDI_CLOCK_SELECT_MASK) +#define XELPDP_DDI_CLOCK_SELECT_PREP (display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_PREP(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_PREP(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) +#define XELPDP_DDI_CLOCK_SELECT_GET (display, val) (DISPLAY_VER(display) >= 30 ? \ + REG_FIELD_GET(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \ + REG_FIELD_GET(_XELPDP_DDI_CLOCK_SELECT_MASK, (val))) +#define XELPDP_DDI_CLOCK_SELECT_NONE 0x0#define XELPDP_DDI_CLOCK_SELECT_MAXPCLK 0x8#define XELPDP_DDI_CLOCK_SELECT_DIV18CLK 0x9
Greg Kroah-Hartman
maintainerPATCH 213/263 drm/i915/dp_mst: Work around Thunderbolt sink disconnect after SINK_COUNT_ESI read
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak <[email protected]>
commit 9cb15478916e849d62a6ec44b10c593b9663328c upstream.
Due to a problem in the iTBT DP-in adapter's firmware the sink on a TBT link may get disconnected inadvertently if the SINK_COUNT_ESI and the DP_LINK_SERVICE_IRQ_VECTOR_ESI0 registers are read in a single AUX transaction. Work around the issue by reading these registers in separate transactions.
The issue affects MTL+ platforms and will be fixed in the DP-in adapter firmware, however releasing that firmware fix may take some time and is not guaranteed to be available for all systems. Based on this apply the workaround on affected platforms.
See HSD #13013007775.
v2: Cc'ing Mika Westerberg.
--- drivers/gpu/drm/i915/display/intel_dp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
drivers/gpu/drm/i915/display/intel_dp.c +17 -0
@@ -4457,6 +4457,23 @@ intel_dp_mst_disconnect(struct intel_dpstatic bool intel_dp_get_sink_irq_esi (struct intel_dp *intel_dp,u8 *esi) { +struct intel_display *display =to_intel_display (intel_dp); + +/* +* Display WA for HSD #13013007775: mtl/arl/lnl +* Read the sink count and link service IRQ registers in separate +* transactions to prevent disconnecting the sink on a TBT link +* inadvertently. +*/ +if (IS_DISPLAY_VER (display,14 ,20 ) && !display->platform.battlemage) { +if (drm_dp_dpcd_read (&intel_dp->aux,DP_SINK_COUNT_ESI , esi,3 ) !=3 ) +return false; + +/* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */ +return drm_dp_dpcd_readb (&intel_dp->aux,DP_LINK_SERVICE_IRQ_VECTOR_ESI0 , + &esi[3 ]) ==1 ; + } +return drm_dp_dpcd_read (&intel_dp->aux,DP_SINK_COUNT_ESI , esi,4 ) ==4 ; }
Greg Kroah-Hartman
maintainerPATCH 214/263 drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aradhya Bhatia <[email protected]>
commit 132bdcec399be6ae947582249a134b38cf56731c upstream.
The crtc_* mode parameters do not get generated (duplicated in this case) from the regular parameters before the mode validation phase begins.
The rest of the code conditionally uses the crtc_* parameters only during the bridge enable phase, but sticks to the regular parameters for mode validation. In this singular instance, however, the driver tries to use the crtc_clock parameter even during the mode validation, causing the validation to fail.
Allow the D-Phy config checks to use mode->clock instead of mode->crtc_clock during mode_valid checks, like everywhere else in the driver.
--- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +2 -1
@@ -568,13 +568,14 @@ static int cdns_dsi_check_conf(struct cdstruct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;unsigned long dsi_hss_hsa_hse_hbp;unsigned int nlanes = output->dev->lanes; +int mode_clock = (mode_valid_check ? mode->clock : mode->crtc_clock);int ret; ret =cdns_dsi_mode2cfg (dsi, mode, dsi_cfg, mode_valid_check);if (ret)return ret; -phy_mipi_dphy_get_default_config (mode->crtc_clock *1000 , +phy_mipi_dphy_get_default_config (mode_clock *1000 ,mipi_dsi_pixel_format_to_bpp (output->dev->format), nlanes, phy_cfg);
Greg Kroah-Hartman
maintainerPATCH 215/263 drm/bridge: cdns-dsi: Fix phy de-init and flag it so
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aradhya Bhatia <[email protected]>
commit fd2611c13f69cbbc6b81d9fc7502abf4f7031d21 upstream.
The driver code doesn't have a Phy de-initialization path as yet, and so it does not clear the phy_initialized flag while suspending. This is a problem because after resume the driver looks at this flag to determine if a Phy re-initialization is required or not. It is in fact required because the hardware is resuming from a suspend, but the driver does not carry out any re-initialization causing the D-Phy to not work at all.
Call the counterparts of phy_init() and phy_power_on(), that are phy_exit() and phy_power_off(), from _bridge_post_disable(), and clear the flags so that the Phy can be initialized again when required.
--- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +5 -1
@@ -681,6 +681,11 @@ static void cdns_dsi_bridge_post_disablestruct cdns_dsi_input *input =bridge_to_cdns_dsi_input (bridge);struct cdns_dsi *dsi =input_to_dsi (input); + dsi->phy_initialized = false; + dsi->link_initialized = false; +phy_power_off (dsi->dphy); +phy_exit (dsi->dphy); +pm_runtime_put (dsi->base.dev); }
@@ -1153,7 +1158,6 @@ static int __maybe_unused cdns_dsi_suspeclk_disable_unprepare (dsi->dsi_sys_clk);clk_disable_unprepare (dsi->dsi_p_clk);reset_control_assert (dsi->dsi_p_rst); - dsi->link_initialized = false;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 216/263 drm/bridge: cdns-dsi: Fix connecting to next bridge
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aradhya Bhatia <[email protected]>
commit 688eb4d465484bc2a3471a6a6f06f833b58c7867 upstream.
Fix the OF node pointer passed to the of_drm_find_bridge() call to find the next bridge in the display chain.
The code to find the next panel (and create its panel-bridge) works fine, but to find the next (non-panel) bridge does not.
To find the next bridge in the pipeline, we need to pass "np" - the OF node pointer of the next entity in the devicetree chain. Passing "of_node" to of_drm_find_bridge (which is what the code does currently) will fetch the bridge for the cdns-dsi which is not what's required.
Fix that.
--- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +1 -1
@@ -958,7 +958,7 @@ static int cdns_dsi_attach(struct mipi_d bridge =drm_panel_bridge_add_typed (panel,DRM_MODE_CONNECTOR_DSI ); }else { - bridge =of_drm_find_bridge (dev->dev.of_node); + bridge =of_drm_find_bridge (np);if (!bridge) bridge =ERR_PTR (-EINVAL ); }
Greg Kroah-Hartman
maintainerPATCH 217/263 drm/bridge: cdns-dsi: Check return value when getting default PHY config
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aradhya Bhatia <[email protected]>
commit c6a7ef0d4856b9629df390e9935d7fd67fe39f81 upstream.
Check for the return value of the phy_mipi_dphy_get_default_config() call, and in case of an error, return back the same.
--- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +5 -3
@@ -575,9 +575,11 @@ static int cdns_dsi_check_conf(struct cdif (ret)return ret; -phy_mipi_dphy_get_default_config (mode_clock *1000 , -mipi_dsi_pixel_format_to_bpp (output->dev->format), - nlanes, phy_cfg); + ret =phy_mipi_dphy_get_default_config (mode_clock *1000 , +mipi_dsi_pixel_format_to_bpp (output->dev->format), + nlanes, phy_cfg); +if (ret) +return ret; ret =cdns_dsi_adjust_phy_config (dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);if (ret)
Greg Kroah-Hartman
maintainerPATCH 218/263 drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aradhya Bhatia <[email protected]>
commit 47c03e6660e96cbba0239125b1d4a9db3c724b1d upstream.
Once the DSI Link and DSI Phy are initialized, the code needs to wait for Clk and Data Lanes to be ready, before continuing configuration. This is in accordance with the DSI Start-up procedure, found in the Technical Reference Manual of Texas Instrument's J721E SoC[0] which houses this DSI TX controller.
If the previous bridge (or crtc/encoder) are configured pre-maturely, the input signal FIFO gets corrupt. This introduces a color-shift on the display.
Allow the driver to wait for the clk and data lanes to get ready during DSI enable.
[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
TRM Link: http://www.ti.com/lit/pdf/spruil1
--- drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c +14 -1
@@ -769,7 +769,7 @@ static void cdns_dsi_bridge_enable(strucstruct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;unsigned long tx_byte_period;struct cdns_dsi_cfg dsi_cfg; -u32 tmp, reg_wakeup, div; +u32 tmp, reg_wakeup, div, status;int nlanes;if (WARN_ON (pm_runtime_get_sync (dsi->base.dev) <0 ))
@@ -786,6 +786,19 @@ static void cdns_dsi_bridge_enable(struccdns_dsi_hs_init (dsi);cdns_dsi_init_link (dsi); +/* +* Now that the DSI Link and DSI Phy are initialized, +* wait for the CLK and Data Lanes to be ready. +*/ + tmp =CLK_LANE_RDY ; +for (int i =0 ; i < nlanes; i++) + tmp |=DATA_LANE_RDY (i); + +if (readl_poll_timeout (dsi->regs +MCTL_MAIN_STS , status, + (tmp == (status & tmp)),100 ,500000 )) +dev_err (dsi->base.dev, +"Timed Out: DSI-DPhy Clock and Data Lanes not ready.\n" ); +writel (HBP_LEN (dsi_cfg.hbp) |HSA_LEN (dsi_cfg.hsa), dsi->regs +VID_HSIZE1 ); writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
Greg Kroah-Hartman
maintainerPATCH 219/263 drm/amd/display: Add null pointer check for get_first_active_display()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit c3e9826a22027a21d998d3e64882fa377b613006 upstream.
The function mod_hdcp_hdcp1_enable_encryption() calls the function get_first_active_display(), but does not check its return value. The return value is a null pointer if the display list is empty. This will lead to a null pointer dereference in mod_hdcp_hdcp2_enable_encryption().
Add a null pointer check for get_first_active_display() and return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND if the function return null.
--- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +3 -0
@@ -368,6 +368,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enabstruct mod_hdcp_display *display =get_first_active_display (hdcp);enum mod_hdcp_status status =MOD_HDCP_STATUS_SUCCESS ; +if (!display) +return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND ; +mutex_lock (&psp->hdcp_context.mutex); hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;memset (hdcp_cmd,0 ,sizeof (struct ta_hdcp_shared_memory ));
Greg Kroah-Hartman
maintainerPATCH 220/263 drm/amdgpu: amdgpu_vram_mgr_new(): Clamp lpfn to total vram
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Olender <[email protected]>
commit 4d2f6b4e4c7ed32e7fa39fcea37344a9eab99094 upstream.
The drm_mm allocator tolerated being passed end > mm->size, but the drm_buddy allocator does not.
Restore the pre-buddy-allocator behavior of allowing such placements.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +1 -1
@@ -463,7 +463,7 @@ static int amdgpu_vram_mgr_new(struct ttint r; lpfn = (u64 )place->lpfn <<PAGE_SHIFT ; -if (!lpfn) +if (!lpfn || lpfn > man->size) lpfn = man->size; fpfn = (u64 )place->fpfn <<PAGE_SHIFT ;
Greg Kroah-Hartman
maintainerPATCH 221/263 drm/amdgpu: disable workload profile switching when OD is enabled
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit 5cccf10f652122a17b40df9d672ccf2ed69cd82f upstream.
Users have reported that they have to reduce the level of undervolting to acheive stability when dynamic workload profiles are enabled on GC 10.3.x. Disable dynamic workload profiles if the user has enabled OD.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 8 ++++++++ drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 + 3 files changed, 31 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +8 -0
@@ -2192,6 +2192,9 @@ void amdgpu_gfx_profile_ring_begin_use(senum PP_SMC_POWER_PROFILE profile;int r; +if (amdgpu_dpm_is_overdrive_enabled (adev)) +return ; +if (adev->gfx.num_gfx_rings) profile =PP_SMC_POWER_PROFILE_FULLSCREEN3D ;else
@@ -2222,6 +2225,11 @@ void amdgpu_gfx_profile_ring_begin_use(svoid amdgpu_gfx_profile_ring_end_use (struct amdgpu_ring *ring) { +struct amdgpu_device *adev = ring->adev; + +if (amdgpu_dpm_is_overdrive_enabled (adev)) +return ; +atomic_dec (&ring->adev->gfx.total_submission_cnt);schedule_delayed_work (&ring->adev->gfx.idle_work,GFX_PROFILE_IDLE_TIMEOUT );
drivers/gpu/drm/amd/pm/amdgpu_dpm.c +22 -0
@@ -1654,6 +1654,28 @@ int amdgpu_dpm_is_overdrive_supported(st } } +int amdgpu_dpm_is_overdrive_enabled (struct amdgpu_device *adev) +{ +if (is_support_sw_smu (adev)) { +struct smu_context *smu = adev->powerplay.pp_handle; + +return smu->od_enabled; + }else { +struct pp_hwmgr *hwmgr; + +/* +* dpm on some legacy asics don't carry od_enabled member +* as its pp_handle is casted directly from adev. +*/ +if (amdgpu_dpm_is_legacy_dpm (adev)) +return false; + + hwmgr = (struct pp_hwmgr *)adev->powerplay.pp_handle; + +return hwmgr->od_enabled; + } +} +int amdgpu_dpm_set_pp_table (struct amdgpu_device *adev,const char *buf,size_t size)
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +1 -0
@@ -559,6 +559,7 @@ int amdgpu_dpm_get_smu_prv_buf_details(svoid **addr, size_t *size);int amdgpu_dpm_is_overdrive_supported (struct amdgpu_device *adev); +int amdgpu_dpm_is_overdrive_enabled (struct amdgpu_device *adev);int amdgpu_dpm_set_pp_table (struct amdgpu_device *adev,const char *buf,size_t size);
Greg Kroah-Hartman
maintainerPATCH 222/263 drm/amd/display: Correct non-OLED pre_T11_delay.
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhongwei Zhang <[email protected]>
commit 893f07452bca56ff146a6be02b3294a9ea23d18a upstream.
[Why]
Only OLED panels require non-zero pre_T11_delay defaultly. Others should be controlled by power sequence.
[How]
For non OLED, pre_T11_delay delay in code should be zero. Also post_T7_delay.
--- drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +4 -3
@@ -952,8 +952,8 @@ void dce110_edp_backlight_control(struct dc_context *ctx = link->ctx;struct bp_transmitter_control cntl = {0 };uint8_t pwrseq_instance =0 ; -unsigned int pre_T11_delay =OLED_PRE_T11_DELAY ; -unsigned int post_T7_delay =OLED_POST_T7_DELAY ; +unsigned int pre_T11_delay = (link->dpcd_sink_ext_caps.bits.oled ?OLED_PRE_T11_DELAY :0 ); +unsigned int post_T7_delay = (link->dpcd_sink_ext_caps.bits.oled ?OLED_POST_T7_DELAY :0 );if (dal_graphics_object_id_get_connector_id (link->link_enc->connector) !=CONNECTOR_ID_EDP ) {
@@ -1069,7 +1069,8 @@ void dce110_edp_backlight_control(if (!enable) {/*follow oem panel config's requirement*/ pre_T11_delay += link->panel_config.pps.extra_pre_t11_ms; -msleep (pre_T11_delay); +if (pre_T11_delay) +msleep (pre_T11_delay); } }
Greg Kroah-Hartman
maintainerPATCH 223/263 drm/xe/vm: move rebind_work init earlier
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
commit a63e99b4d6d3a0353ef47146dd5bd562f08e1786 upstream.
In xe_vm_close_and_put() we need to be able to call flush_work(rebind_work), however during vm creation we can call this on the error path, before having actually set up the worker, leading to a splat from flush_work().
It looks like we can simply move the worker init step earlier to fix this.
--- drivers/gpu/drm/xe/xe_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_vm.c +4 -4
@@ -1678,8 +1678,10 @@ struct xe_vm *xe_vm_create(struct xe_dev* scheduler drops all the references of it, hence protecting the VM * for this case is necessary. */ -if (flags &XE_VM_FLAG_LR_MODE ) +if (flags &XE_VM_FLAG_LR_MODE ) { +INIT_WORK (&vm->preempt.rebind_work, preempt_rebind_work_func);xe_pm_runtime_get_noresume (xe); + }if (flags &XE_VM_FLAG_FAULT_MODE ) { err =xe_svm_init (vm);
@@ -1730,10 +1732,8 @@ struct xe_vm *xe_vm_create(struct xe_dev vm->batch_invalidate_tlb = true; } -if (vm->flags &XE_VM_FLAG_LR_MODE ) { -INIT_WORK (&vm->preempt.rebind_work, preempt_rebind_work_func); +if (vm->flags &XE_VM_FLAG_LR_MODE ) vm->batch_invalidate_tlb = false; - }/* Fill pt_root after allocating scratch tables */ for_each_tile (tile, xe, id) {
Greg Kroah-Hartman
maintainerPATCH 224/263 drm/xe/sched: stop re-submitting signalled jobs
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
commit 0ee54d5cacc0276ec631ac149825a24b59c51c38 upstream.
Customer is reporting a really subtle issue where we get random DMAR faults, hangs and other nasties for kernel migration jobs when stressing stuff like s2idle/s3/s4. The explosions seems to happen somewhere after resuming the system with splats looking something like:
PM: suspend exit
rfkill: input handler disabled
xe 0000:00:02.0: [drm] GT0: Engine reset: engine_class=bcs, logical_mask: 0x2, guc_id=0
xe 0000:00:02.0: [drm] GT0: Timedout job: seqno=24496, lrc_seqno=24496, guc_id=0, flags=0x13 in no process [-1] xe 0000:00:02.0: [drm] GT0: Kernel-submitted job timed out
The likely cause appears to be a race between suspend cancelling the worker that processes the free_job()'s, such that we still have pending jobs to be freed after the cancel. Following from this, on resume the pending_list will now contain at least one already complete job, but it looks like we call drm_sched_resubmit_jobs(), which will then call run_job() on everything still on the pending_list. But if the job was already complete, then all the resources tied to the job, like the bb itself, any memory that is being accessed, the iommu mappings etc. might be long gone since those are usually tied to the fence signalling.
This scenario can be seen in ftrace when running a slightly modified xe_pm IGT (kernel was only modified to inject artificial latency into free_job to make the race easier to hit):
xe_sched_job_run: dev=0000:00:02.0, fence=0xffff888276cc8540, seqno=0, lrc_seqno=0, gt=0, guc_id=0, batch_addr=0x000000146910 ... xe_exec_queue_stop: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x0, flags=0x13 xe_exec_queue_stop: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=1, guc_state=0x0, flags=0x4 xe_exec_queue_stop: dev=0000:00:02.0, 4:0x1, gt=1, width=1, guc_id=0, guc_state=0x0, flags=0x3 xe_exec_queue_stop: dev=0000:00:02.0, 1:0x1, gt=1, width=1, guc_id=1, guc_state=0x0, flags=0x3 xe_exec_queue_stop: dev=0000:00:02.0, 4:0x1, gt=1, width=1, guc_id=2, guc_state=0x0, flags=0x3 xe_exec_queue_resubmit: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x0, flags=0x13 xe_sched_job_run: dev=0000:00:02.0, fence=0xffff888276cc8540, seqno=0, lrc_seqno=0, gt=0, guc_id=0, batch_addr=0x000000146910 ...
.....xe_exec_queue_memory_cat_error: dev=0000:00:02.0, 3:0x2, gt=0, width=1, guc_id=0, guc_state=0x3, flags=0x13
So the job_run() is clearly triggered twice for the same job, even though the first must have already signalled to completion during suspend. We can also see a CAT error after the re-submit.
To prevent this only resubmit jobs on the pending_list that have not yet signalled.
v2:
- Make sure to re-arm the fence callbacks with sched_start().
v3 (Matt B):
- Stop using drm_sched_resubmit_jobs(), which appears to be deprecated and just open-code a simple loop such that we skip calling run_job() on anything already signalled.
--- drivers/gpu/drm/xe/xe_gpu_scheduler.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_gpu_scheduler.h +9 -1
@@ -51,7 +51,15 @@ static inline void xe_sched_tdr_queue_imstatic inline void xe_sched_resubmit_jobs (struct xe_gpu_scheduler *sched) { -drm_sched_resubmit_jobs (&sched->base); +struct drm_sched_job *s_job; + +list_for_each_entry (s_job, &sched->base.pending_list, list) { +struct drm_sched_fence *s_fence = s_job->s_fence; +struct dma_fence *hw_fence = s_fence->parent; + +if (hw_fence && !dma_fence_is_signaled (hw_fence)) + sched->base.ops->run_job (s_job); + } } static inline bool
Greg Kroah-Hartman
maintainerPATCH 225/263 drm/xe/guc_submit: add back fix
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Auld <[email protected]>
commit 2e824747cfbdf1fba88df5e5800d284b2602ae8f upstream.
Daniele noticed that the fix in commit 2d2be279f1ca ("drm/xe: fix UAF around queue destruction") looks to have been unintentionally removed as part of handling a conflict in some past merge commit. Add it back.
--- drivers/gpu/drm/xe/xe_guc_submit.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/gpu/drm/xe/xe_guc_submit.c +11 -0
@@ -229,6 +229,17 @@ static bool exec_queue_killed_or_banned_static void guc_submit_fini (struct drm_device *drm,void *arg) {struct xe_guc *guc = arg; +struct xe_device *xe =guc_to_xe (guc); +struct xe_gt *gt =guc_to_gt (guc); +int ret; + + ret =wait_event_timeout (guc->submission_state.fini_wq, +xa_empty (&guc->submission_state.exec_queue_lookup), +HZ *5 ); + +drain_workqueue (xe->destroy_wq); + +xe_gt_assert (gt, ret);xa_destroy (&guc->submission_state.exec_queue_lookup); }
Greg Kroah-Hartman
maintainerPATCH 226/263 drm/amd/display: Fix RMCM programming seq errors
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yihan Zhu <[email protected]>
commit 158f9944ac05dafd2d3a23d0688e6cf40ef68b90 upstream.
[WHY & HOW]
Fix RMCM programming sequence errors and mapping issues to pass the RMCM test.
--- drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c +4 -1
@@ -4750,7 +4750,10 @@ static void calculate_tdlut_setting(//the tdlut is fetched during the 2 row times of prefetch. if (p->setup_for_tdlut) { *p->tdlut_groups_per_2row_ub = (unsigned int )math_ceil2 ((double ) *p->tdlut_bytes_per_frame / *p->tdlut_bytes_per_group,1 ); - *p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size *1024 ) / tdlut_drain_rate; +if (*p->tdlut_bytes_per_frame > p->cursor_buffer_size *1024 ) + *p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size *1024 ) / tdlut_drain_rate; +else + *p->tdlut_opt_time =0 ; *p->tdlut_drain_time = p->cursor_buffer_size *1024 / tdlut_drain_rate; *p->tdlut_bytes_to_deliver = (unsigned int ) (p->cursor_buffer_size *1024.0 ); }
Greg Kroah-Hartman
maintainerPATCH 227/263 drm/amdgpu: VCN v5_0_1 to prevent FW checking RB during DPG pause
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonny Jiang <[email protected]>
commit 46e15197b513e60786a44107759d6ca293d6288c upstream.
Add a protection to ensure programming are all complete prior VCPU starting. This is a WA for an unintended VCPU running.
--- drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +5 -1
@@ -629,6 +629,9 @@ static int vcn_v5_0_1_start_dpg_mode(strif (indirect)amdgpu_vcn_psp_update_sram (adev, inst_idx,AMDGPU_UCODE_ID_VCN0_RAM ); +/* resetting ring, fw should not check RB ring */ + fw_shared->sq.queue_mode |=FW_QUEUE_RING_RESET ; +/* Pause dpg */ vcn_v5_0_1_pause_dpg_mode (vinst, &state);
@@ -641,7 +644,7 @@ static int vcn_v5_0_1_start_dpg_mode(str tmp =RREG32_SOC15 (VCN , vcn_inst, regVCN_RB_ENABLE); tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK );WREG32_SOC15 (VCN , vcn_inst, regVCN_RB_ENABLE, tmp); - fw_shared->sq.queue_mode |=FW_QUEUE_RING_RESET ; +WREG32_SOC15 (VCN , vcn_inst, regUVD_RB_RPTR,0 );WREG32_SOC15 (VCN , vcn_inst, regUVD_RB_WPTR,0 );
@@ -652,6 +655,7 @@ static int vcn_v5_0_1_start_dpg_mode(str tmp =RREG32_SOC15 (VCN , vcn_inst, regVCN_RB_ENABLE); tmp |=VCN_RB_ENABLE__RB1_EN_MASK ;WREG32_SOC15 (VCN , vcn_inst, regVCN_RB_ENABLE, tmp); +/* resetting done, fw can check RB ring */ fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET |FW_QUEUE_DPG_HOLD_OFF ); WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
Greg Kroah-Hartman
maintainerPATCH 228/263 drm/amdgpu: Add kicker device detection
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Min <[email protected]>
commit 0bbf5fd86c585d437b75003f11365b324360a5d6 upstream.
1. add kicker device list
2. add kicker device checking helper function
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 6 ++++++ 2 files changed, 23 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +17 -0
@@ -30,6 +30,10 @@#define AMDGPU_UCODE_NAME_MAX (128) +static const struct kicker_device kicker_device_list[] = { + {0x744B ,0x00 }, +}; +static void amdgpu_ucode_print_common_hdr (const struct common_firmware_header *hdr) {DRM_DEBUG ("size_bytes: %u\n" ,le32_to_cpu (hdr->size_bytes));
@@ -1384,6 +1388,19 @@ static const char *amdgpu_ucode_legacy_nreturn NULL ; } +bool amdgpu_is_kicker_fw (struct amdgpu_device *adev) +{ +int i; + +for (i =0 ; i <ARRAY_SIZE (kicker_device_list); i++) { +if (adev->pdev->device == kicker_device_list[i].device && + adev->pdev->revision == kicker_device_list[i].revision) +return true; + } + +return false; +} +void amdgpu_ucode_ip_version_decode (struct amdgpu_device *adev,int block_type,char *ucode_prefix,int len) {int maj, min, rev;
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +6 -0
@@ -602,6 +602,11 @@ struct amdgpu_firmware {uint64_t fw_buf_mc; }; +struct kicker_device { +unsigned short device; +u8 revision; +}; +void amdgpu_ucode_print_mc_hdr (const struct common_firmware_header *hdr);void amdgpu_ucode_print_smc_hdr (const struct common_firmware_header *hdr);void amdgpu_ucode_print_imu_hdr (const struct common_firmware_header *hdr);
@@ -629,5 +634,6 @@ amdgpu_ucode_get_load_type(struct amdgpuconst char *amdgpu_ucode_name (enum AMDGPU_UCODE_ID ucode_id);void amdgpu_ucode_ip_version_decode (struct amdgpu_device *adev,int block_type,char *ucode_prefix,int len); +bool amdgpu_is_kicker_fw (struct amdgpu_device *adev);#endif
Greg Kroah-Hartman
maintainerPATCH 229/263 drm/amd/display: Check dce_hwseq before dereferencing it
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
commit b669507b637eb6b1aaecf347f193efccc65d756e upstream.
[WHAT]
hws was checked for null earlier in dce110_blank_stream, indicating hws can be null, and should be checked whenever it is used.
--- drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +1 -1
@@ -1222,7 +1222,7 @@ void dce110_blank_stream(struct pipe_ctxstruct dce_hwseq *hws = link->dc->hwseq;if (link->local_sink && link->local_sink->sink_signal ==SIGNAL_TYPE_EDP ) { -if (!link->skip_implict_edp_power_control) +if (!link->skip_implict_edp_power_control && hws) hws->funcs.edp_backlight_control (link, false); link->dc->hwss.set_abm_immediate_disable (pipe_ctx); }
Greg Kroah-Hartman
maintainerPATCH 230/263 drm/xe: Fix memset on iomem
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
commit 87a15c89d8c7b00b0fc94e0d4f554f7ee2fe6961 upstream.
It should rather use xe_map_memset() as the BO is created with XE_BO_FLAG_VRAM_IF_DGFX in xe_guc_pc_init().
--- drivers/gpu/drm/xe/xe_guc_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_guc_pc.c +1 -1
@@ -1053,7 +1053,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc goto out; } -memset (pc->bo->vmap.vaddr,0 , size); +xe_map_memset (xe, &pc->bo->vmap,0 ,0 , size);slpc_shared_data_write (pc, header.size, size); earlier =ktime_get ();
Greg Kroah-Hartman
maintainerPATCH 231/263 drm/xe: Fix taking invalid lock on wedge
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
commit 1e1981b16bb1bbe2fafa57ed439b45cb5b34e32d upstream.
If device wedges on e.g. GuC upload, the submission is not yet enabled and the state is not even initialized. Protect the wedge call so it does nothing in this case. It fixes the following splat:
[] xe 0000:bf:00.0: [drm] device wedged, needs recovery [] ------------[ cut here ]------------ [] DEBUG_LOCKS_WARN_ON(lock->magic != lock) [] WARNING: CPU: 48 PID: 312 at kernel/locking/mutex.c:564 __mutex_lock+0x8a1/0xe60 ... [] RIP: 0010:__mutex_lock+0x8a1/0xe60 [] mutex_lock_nested+0x1b/0x30 [] xe_guc_submit_wedge+0x80/0x2b0 [xe]
--- drivers/gpu/drm/xe/xe_guc_submit.c | 9 +++++++++ drivers/gpu/drm/xe/xe_guc_types.h | 5 +++++ 2 files changed, 14 insertions(+)
drivers/gpu/drm/xe/xe_guc_submit.c +9 -0
@@ -311,6 +311,8 @@ int xe_guc_submit_init(struct xe_guc *guprimelockdep (guc); + guc->submission_state.initialized = true; +return drmm_add_action_or_reset (&xe->drm, guc_submit_fini, guc); }
@@ -845,6 +847,13 @@ void xe_guc_submit_wedge(struct xe_guc *xe_gt_assert (guc_to_gt (guc),guc_to_xe (guc)->wedged.mode); +/* +* If device is being wedged even before submission_state is +* initialized, there's nothing to do here. +*/ +if (!guc->submission_state.initialized) +return ; + err =devm_add_action_or_reset (guc_to_xe (guc)->drm.dev, guc_submit_wedged_fini, guc);if (err) {
drivers/gpu/drm/xe/xe_guc_types.h +5 -0
@@ -89,6 +89,11 @@ struct xe_guc {struct mutex lock;/** @submission_state.enabled: submission is enabled */ bool enabled; +/** +* @submission_state.initialized: mark when submission state is +* even initialized - before that not even the lock is valid +*/ +bool initialized;/** @submission_state.fini_wq: submit fini wait queue */ wait_queue_head_t fini_wq; } submission_state;
Greg Kroah-Hartman
maintainerPATCH 232/263 drm/xe: Fix early wedge on GuC load failure
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniele Ceraolo Spurio <[email protected]>
commit a39d082c3553d35b4fe5585e1e2fb221c130cae8 upstream.
When the GuC fails to load we declare the device wedged. However, the very first GuC load attempt on GT0 (from xe_gt_init_hwconfig) is done before the GT1 GuC objects are initialized, so things go bad when the wedge code attempts to cleanup GT1. To fix this, check the initialization status in the functions called during wedge.
--- drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 8 ++++++++ drivers/gpu/drm/xe/xe_guc_ct.c | 7 +++++-- drivers/gpu/drm/xe/xe_guc_ct.h | 5 +++++ drivers/gpu/drm/xe/xe_guc_submit.c | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +8 -0
@@ -138,6 +138,14 @@ void xe_gt_tlb_invalidation_reset(structint pending_seqno;/* +* we can get here before the CTs are even initialized if we're wedging +* very early, in which case there are not going to be any pending +* fences so we can bail immediately. +*/ +if (!xe_guc_ct_initialized (>->uc.guc.ct)) +return ; + +/* * CT channel is already disabled at this point. No new TLB requests can * appear. */
drivers/gpu/drm/xe/xe_guc_ct.c +5 -2
@@ -515,6 +515,9 @@ void xe_guc_ct_disable(struct xe_guc_ct*/ void xe_guc_ct_stop (struct xe_guc_ct *ct) { +if (!xe_guc_ct_initialized (ct)) +return ; +xe_guc_ct_set_state (ct,XE_GUC_CT_STATE_STOPPED );stop_g2h_handler (ct); }
@@ -761,7 +764,7 @@ static int __guc_ct_send_locked(struct xu16 seqno;int ret; -xe_gt_assert (gt, ct->state !=XE_GUC_CT_STATE_NOT_INITIALIZED ); +xe_gt_assert (gt,xe_guc_ct_initialized (ct));xe_gt_assert (gt, !g2h_len || !g2h_fence);xe_gt_assert (gt, !num_g2h || !g2h_fence);xe_gt_assert (gt, !g2h_len || num_g2h);
@@ -1344,7 +1347,7 @@ static int g2h_read(struct xe_guc_ct *ctu32 action;u32 *hxg; -xe_gt_assert (gt, ct->state !=XE_GUC_CT_STATE_NOT_INITIALIZED ); +xe_gt_assert (gt,xe_guc_ct_initialized (ct));lockdep_assert_held (&ct->fast_lock);if (ct->state ==XE_GUC_CT_STATE_DISABLED )
drivers/gpu/drm/xe/xe_guc_ct.h +5 -0
@@ -22,6 +22,11 @@ void xe_guc_ct_snapshot_print(struct xe_void xe_guc_ct_snapshot_free (struct xe_guc_ct_snapshot *snapshot);void xe_guc_ct_print (struct xe_guc_ct *ct,struct drm_printer *p,bool want_ctb); +static inline bool xe_guc_ct_initialized (struct xe_guc_ct *ct) +{ +return ct->state !=XE_GUC_CT_STATE_NOT_INITIALIZED ; +} +static inline bool xe_guc_ct_enabled (struct xe_guc_ct *ct) {return ct->state ==XE_GUC_CT_STATE_ENABLED ;
drivers/gpu/drm/xe/xe_guc_submit.c +3 -0
@@ -1759,6 +1759,9 @@ int xe_guc_submit_reset_prepare(struct x {int ret; +if (!guc->submission_state.initialized) +return 0 ; +/* * Using an atomic here rather than submission_state.lock as this * function can be called while holding the CT lock (engine reset
Greg Kroah-Hartman
maintainerPATCH 233/263 drm/i915/dsi: Fix off by one in BXT_MIPI_TRANS_VTOTAL
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ville Syrjälä <[email protected]>
commit c464ce6af332e7c802c36cd337cacf81db05400c upstream.
BXT_MIPI_TRANS_VTOTAL must be programmed with vtotal-1 instead of vtotal. Make it so.
--- drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/display/vlv_dsi.c +2 -2
@@ -1060,7 +1060,7 @@ static void bxt_dsi_get_pipe_config(stru BXT_MIPI_TRANS_VACTIVE(port)); adjusted_mode->crtc_vtotal =intel_de_read (display, -BXT_MIPI_TRANS_VTOTAL (port)); +BXT_MIPI_TRANS_VTOTAL (port)) +1 ; hactive = adjusted_mode->crtc_hdisplay; hfp =intel_de_read (display,MIPI_HFP_COUNT (display, port));
@@ -1265,7 +1265,7 @@ static void set_dsi_timings(struct intelintel_de_write (display,BXT_MIPI_TRANS_VACTIVE (port), adjusted_mode->crtc_vdisplay);intel_de_write (display,BXT_MIPI_TRANS_VTOTAL (port), - adjusted_mode->crtc_vtotal); + adjusted_mode->crtc_vtotal -1 ); } intel_de_write(display, MIPI_HACTIVE_AREA_COUNT(display, port),
Greg Kroah-Hartman
maintainerPATCH 234/263 drm/amdgpu: Fix SDMA UTC_L1 handling during start/stop sequences
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jesse Zhang <[email protected]>
commit 7f3b16f3f229e37cc3e02e9e4e7106c523b119e9 upstream.
This commit makes two key fixes to SDMA v4.4.2 handling:
1. disable UTC_L1 in sdma_cntl register when stopping SDMA engines by reading the current value before modifying UTC_L1_ENABLE bit.
2. Ensure UTC_L1_ENABLE is consistently managed by:
- Adding the missing register write when enabling UTC_L1 during start
- Keeping UTC_L1 enabled by default as per hardware requirements
v2: Correct SDMA_CNTL setting (Philip)
--- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +5 -1
@@ -489,7 +489,7 @@ static void sdma_v4_4_2_inst_gfx_stop(st {struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES ];u32 doorbell_offset, doorbell; -u32 rb_cntl, ib_cntl; +u32 rb_cntl, ib_cntl, sdma_cntl;int i;for_each_inst (i, inst_mask) {
@@ -501,6 +501,9 @@ static void sdma_v4_4_2_inst_gfx_stop(st ib_cntl =RREG32_SDMA (i, regSDMA_GFX_IB_CNTL); ib_cntl =REG_SET_FIELD (ib_cntl,SDMA_GFX_IB_CNTL ,IB_ENABLE ,0 );WREG32_SDMA (i, regSDMA_GFX_IB_CNTL, ib_cntl); + sdma_cntl =RREG32_SDMA (i, regSDMA_CNTL); + sdma_cntl =REG_SET_FIELD (sdma_cntl,SDMA_CNTL ,UTC_L1_ENABLE ,0 ); +WREG32_SDMA (i, regSDMA_CNTL, sdma_cntl);if (sdma[i]->use_doorbell) { doorbell =RREG32_SDMA (i, regSDMA_GFX_DOORBELL);
@@ -994,6 +997,7 @@ static int sdma_v4_4_2_inst_start(struct/* set utc l1 enable flag always to 1 */ temp =RREG32_SDMA (i, regSDMA_CNTL); temp =REG_SET_FIELD (temp,SDMA_CNTL ,UTC_L1_ENABLE ,1 ); +WREG32_SDMA (i, regSDMA_CNTL, temp);if (amdgpu_ip_version (adev,SDMA0_HWIP ,0 ) <IP_VERSION (4 ,4 ,5 )) {/* enable context empty interrupt during initialization */
Greg Kroah-Hartman
maintainerPATCH 235/263 drm/amdgpu: switch job hw_fence to amdgpu_fence
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit ebe43542702c3d15d1a1d95e8e13b1b54076f05a upstream.
Use the amdgpu fence container so we can store additional data in the fence. This also fixes the start_time handling for MCBP since we were casting the fence to an amdgpu_fence and it wasn't.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 30 ++++++---------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 12 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 16 ++++++++++++++ 6 files changed, 32 insertions(+), 32 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +1 -1
@@ -1902,7 +1902,7 @@ no_preempt:continue ; } job =to_amdgpu_job (s_job); -if (preempted && (&job->hw_fence) == fence) +if (preempted && (&job->hw_fence.base) == fence)/* mark the job as preempted */ job->preemption_status |=AMDGPU_IB_PREEMPTED ; }
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +1 -1
@@ -6083,7 +6083,7 @@ int amdgpu_device_gpu_recover(struct amd* * job->base holds a reference to parent fence */ -if (job &&dma_fence_is_signaled (&job->hw_fence)) { +if (job &&dma_fence_is_signaled (&job->hw_fence.base)) { job_signaled = true;dev_info (adev->dev,"Guilty job already signaled, skipping HW reset" ); goto skip_hw_reset;
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +7 -23
@@ -41,22 +41,6 @@#include "amdgpu_trace.h" #include "amdgpu_reset.h" -/* -* Fences mark an event in the GPUs pipeline and are used -* for GPU/CPU synchronization. When the fence is written, -* it is expected that all buffers associated with that fence -* are no longer in use by the associated ring on the GPU and -* that the relevant GPU caches have been flushed. -*/ - -struct amdgpu_fence { -struct dma_fence base; - -/* RB, DMA, etc. */ -struct amdgpu_ring *ring; -ktime_t start_timestamp; -}; -static struct kmem_cache *amdgpu_fence_slab;int amdgpu_fence_slab_init (void )
@@ -151,12 +135,12 @@ int amdgpu_fence_emit(struct amdgpu_ring am_fence =kmem_cache_alloc (amdgpu_fence_slab,GFP_ATOMIC );if (am_fence ==NULL )return -ENOMEM ; - fence = &am_fence->base; - am_fence->ring = ring; }else {/* take use of job-embedded fence */ - fence = &job->hw_fence; + am_fence = &job->hw_fence; } + fence = &am_fence->base; + am_fence->ring = ring; seq = ++ring->fence_drv.sync_seq;if (job && job->job_run_counter) {
@@ -718,7 +702,7 @@ void amdgpu_fence_driver_clear_job_fence* it right here or we won't be able to track them in fence_drv * and they will remain unsignaled during sa_bo free. */ - job = container_of(old, struct amdgpu_job, hw_fence); + job = container_of(old, struct amdgpu_job, hw_fence.base);if (!job->base.s_fence && !dma_fence_is_signaled (old))dma_fence_signal (old);RCU_INIT_POINTER (*ptr,NULL );
@@ -780,7 +764,7 @@ static const char *amdgpu_fence_get_timestatic const char *amdgpu_job_fence_get_timeline_name (struct dma_fence *f) { - struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); + struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base);return (const char *)to_amdgpu_ring (job->base.sched)->name; }
@@ -810,7 +794,7 @@ static bool amdgpu_fence_enable_signalin*/ static bool amdgpu_job_fence_enable_signaling (struct dma_fence *f) { - struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); + struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base);if (!timer_pending (&to_amdgpu_ring (job->base.sched)->fence_drv.fallback_timer))amdgpu_fence_schedule_fallback (to_amdgpu_ring (job->base.sched));
@@ -845,7 +829,7 @@ static void amdgpu_job_fence_free(struct struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);/* free job if fence has a parent job */ -kfree (container_of(f ,struct amdgpu_job ,hw_fence )); + kfree(container_of(f, struct amdgpu_job, hw_fence.base)); }/**
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +6 -6
@@ -272,8 +272,8 @@ void amdgpu_job_free_resources(struct am/* Check if any fences where initialized */ if (job->base.s_fence && job->base.s_fence->finished.ops) f = &job->base.s_fence->finished; -else if (job->hw_fence.ops) - f = &job->hw_fence; +else if (job->hw_fence.base.ops) + f = &job->hw_fence.base;else f =NULL ;
@@ -290,10 +290,10 @@ static void amdgpu_job_free_cb(struct dramdgpu_sync_free (&job->explicit_sync);/* only put the hw fence if has embedded fence */ -if (!job->hw_fence.ops) +if (!job->hw_fence.base.ops)kfree (job);else -dma_fence_put (&job->hw_fence); +dma_fence_put (&job->hw_fence.base); } void amdgpu_job_set_gang_leader(struct amdgpu_job *job,
@@ -322,10 +322,10 @@ void amdgpu_job_free(struct amdgpu_job *if (job->gang_submit != &job->base.s_fence->scheduled)dma_fence_put (job->gang_submit); -if (!job->hw_fence.ops) +if (!job->hw_fence.base.ops)kfree (job);else -dma_fence_put (&job->hw_fence); +dma_fence_put (&job->hw_fence.base); }struct dma_fence *amdgpu_job_submit (struct amdgpu_job *job)
drivers/gpu/drm/amd/amdgpu/amdgpu_job.h +1 -1
@@ -48,7 +48,7 @@ struct amdgpu_job {struct drm_sched_job base;struct amdgpu_vm *vm;struct amdgpu_sync explicit_sync; -struct dma_fence hw_fence; +struct amdgpu_fence hw_fence;struct dma_fence *gang_submit;uint32_t preamble_status;uint32_t preemption_status;
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +16 -0
@@ -127,6 +127,22 @@ struct amdgpu_fence_driver {struct dma_fence **fences; }; +/* +* Fences mark an event in the GPUs pipeline and are used +* for GPU/CPU synchronization. When the fence is written, +* it is expected that all buffers associated with that fence +* are no longer in use by the associated ring on the GPU and +* that the relevant GPU caches have been flushed. +*/ + +struct amdgpu_fence { +struct dma_fence base; + +/* RB, DMA, etc. */ +struct amdgpu_ring *ring; +ktime_t start_timestamp; +}; +extern const struct drm_sched_backend_ops amdgpu_sched_ops;void amdgpu_fence_driver_clear_job_fences (struct amdgpu_ring *ring);
Greg Kroah-Hartman
maintainerPATCH 236/263 drm/amdgpu: add kicker fws loading for gfx11/smu13/psp13
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Min <[email protected]>
commit 854171405e7f093532b33d8ed0875b9e34fc55b4 upstream.
1. Add kicker firmwares loading for gfx11/smu13/psp13
2. Register additional MODULE_FIRMWARE entries for kicker fws
- gc_11_0_0_rlc_kicker.bin
- gc_11_0_0_imu_kicker.bin
- psp_13_0_0_sos_kicker.bin
- psp_13_0_0_ta_kicker.bin
- smu_13_0_0_kicker.bin
--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 16 ++++++++++++---- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 5 +++++ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 9 +++++++-- drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 12 +++++++++--- 5 files changed, 35 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +12 -4
@@ -3521,8 +3521,12 @@ int psp_init_sos_microcode(struct psp_couint8_t *ucode_array_start_addr;int err =0 ; - err =amdgpu_ucode_request (adev, &adev->psp.sos_fw,AMDGPU_UCODE_REQUIRED , -"amdgpu/%s_sos.bin" , chip_name); +if (amdgpu_is_kicker_fw (adev)) + err =amdgpu_ucode_request (adev, &adev->psp.sos_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_sos_kicker.bin" , chip_name); +else + err =amdgpu_ucode_request (adev, &adev->psp.sos_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_sos.bin" , chip_name);if (err) goto out;
@@ -3798,8 +3802,12 @@ int psp_init_ta_microcode(struct psp_construct amdgpu_device *adev = psp->adev;int err; - err =amdgpu_ucode_request (adev, &adev->psp.ta_fw,AMDGPU_UCODE_REQUIRED , -"amdgpu/%s_ta.bin" , chip_name); +if (amdgpu_is_kicker_fw (adev)) + err =amdgpu_ucode_request (adev, &adev->psp.ta_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_ta_kicker.bin" , chip_name); +else + err =amdgpu_ucode_request (adev, &adev->psp.ta_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_ta.bin" , chip_name);if (err)return err;
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +5 -0
@@ -83,6 +83,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.biMODULE_FIRMWARE ("amdgpu/gc_11_0_0_me.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_0_mec.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_0_rlc.bin" ); +MODULE_FIRMWARE ("amdgpu/gc_11_0_0_rlc_kicker.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_0_rlc_1.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_0_toc.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_1_pfp.bin" );
@@ -744,6 +745,10 @@ static int gfx_v11_0_init_microcode(stru err =amdgpu_ucode_request (adev, &adev->gfx.rlc_fw,AMDGPU_UCODE_REQUIRED ,"amdgpu/gc_11_0_0_rlc_1.bin" ); + else if (amdgpu_is_kicker_fw(adev)) + err =amdgpu_ucode_request (adev, &adev->gfx.rlc_fw, +AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_rlc_kicker.bin" , ucode_prefix); else err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, AMDGPU_UCODE_REQUIRED,
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c +7 -2
@@ -32,6 +32,7 @@#include "gc/gc_11_0_0_sh_mask.h" MODULE_FIRMWARE ("amdgpu/gc_11_0_0_imu.bin" ); +MODULE_FIRMWARE ("amdgpu/gc_11_0_0_imu_kicker.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_1_imu.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_2_imu.bin" );MODULE_FIRMWARE ("amdgpu/gc_11_0_3_imu.bin" );
@@ -51,8 +52,12 @@ static int imu_v11_0_init_microcode(struDRM_DEBUG ("\n" );amdgpu_ucode_ip_version_decode (adev,GC_HWIP , ucode_prefix,sizeof (ucode_prefix)); - err =amdgpu_ucode_request (adev, &adev->gfx.imu_fw,AMDGPU_UCODE_REQUIRED , -"amdgpu/%s_imu.bin" , ucode_prefix); +if (amdgpu_is_kicker_fw (adev)) + err =amdgpu_ucode_request (adev, &adev->gfx.imu_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_imu_kicker.bin" , ucode_prefix); +else + err =amdgpu_ucode_request (adev, &adev->gfx.imu_fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_imu.bin" , ucode_prefix);if (err) goto out;
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c +2 -0
@@ -42,7 +42,9 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_5_ta.biMODULE_FIRMWARE ("amdgpu/psp_13_0_8_toc.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_8_ta.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_0_sos.bin" ); +MODULE_FIRMWARE ("amdgpu/psp_13_0_0_sos_kicker.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_0_ta.bin" ); +MODULE_FIRMWARE ("amdgpu/psp_13_0_0_ta_kicker.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_7_sos.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_7_ta.bin" );MODULE_FIRMWARE ("amdgpu/psp_13_0_10_sos.bin" );
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +9 -3
@@ -58,6 +58,7 @@MODULE_FIRMWARE ("amdgpu/aldebaran_smc.bin" );MODULE_FIRMWARE ("amdgpu/smu_13_0_0.bin" ); +MODULE_FIRMWARE ("amdgpu/smu_13_0_0_kicker.bin" );MODULE_FIRMWARE ("amdgpu/smu_13_0_7.bin" );MODULE_FIRMWARE ("amdgpu/smu_13_0_10.bin" );
@@ -92,7 +93,7 @@ const int pmfw_decoded_link_width[7] = {int smu_v13_0_init_microcode (struct smu_context *smu) {struct amdgpu_device *adev = smu->adev; -char ucode_prefix[15 ]; +char ucode_prefix[30 ];int err =0 ;const struct smc_firmware_header_v1_0 *hdr;const struct common_firmware_header *header;
@@ -103,8 +104,13 @@ int smu_v13_0_init_microcode(struct smu_return 0 ;amdgpu_ucode_ip_version_decode (adev,MP1_HWIP , ucode_prefix,sizeof (ucode_prefix)); - err =amdgpu_ucode_request (adev, &adev->pm.fw,AMDGPU_UCODE_REQUIRED , -"amdgpu/%s.bin" , ucode_prefix); + +if (amdgpu_is_kicker_fw (adev)) + err =amdgpu_ucode_request (adev, &adev->pm.fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s_kicker.bin" , ucode_prefix); +else + err =amdgpu_ucode_request (adev, &adev->pm.fw,AMDGPU_UCODE_REQUIRED , +"amdgpu/%s.bin" , ucode_prefix);if (err) goto out;
Greg Kroah-Hartman
maintainerPATCH 237/263 drm/amd/display: Add more checks for DSC / HUBP ONO guarantees
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Kazlauskas <[email protected]>
commit 0d57dd1765d311111d9885346108c4deeae1deb4 upstream.
[WHY]
For non-zero DSC instances it's possible that the HUBP domain required to drive it for sequential ONO ASICs isn't met, potentially causing the logic to the tile to enter an undefined state leading to a system hang.
[HOW]
Add more checks to ensure that the HUBP domain matching the DSC instance is appropriately powered.
--- drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 28 ++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +28 -0
@@ -1047,6 +1047,15 @@ void dcn35_calc_blocks_to_gate(struct dcif (dc->caps.sequential_ono) { update_state->pg_pipe_res_update[PG_HUBP ][pipe_ctx->stream_res.dsc->inst] = false; update_state->pg_pipe_res_update[PG_DPP ][pipe_ctx->stream_res.dsc->inst] = false; + +/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */ +if (!pipe_ctx->top_pipe && pipe_ctx->plane_res.hubp && + pipe_ctx->plane_res.hubp->inst != pipe_ctx->stream_res.dsc->inst) { +for (j =0 ; j < dc->res_pool->pipe_count; ++j) { + update_state->pg_pipe_res_update[PG_HUBP ][j] = false; + update_state->pg_pipe_res_update[PG_DPP ][j] = false; + } + } } }
@@ -1193,6 +1202,25 @@ void dcn35_calc_blocks_to_ungate(struct update_state->pg_pipe_res_update[PG_HDMISTREAM ][0 ] = true;if (dc->caps.sequential_ono) { +for (i =0 ; i < dc->res_pool->pipe_count; i++) { +struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; + +if (new_pipe->stream_res.dsc && !new_pipe->top_pipe && + update_state->pg_pipe_res_update[PG_DSC ][new_pipe->stream_res.dsc->inst]) { + update_state->pg_pipe_res_update[PG_HUBP ][new_pipe->stream_res.dsc->inst] = true; + update_state->pg_pipe_res_update[PG_DPP ][new_pipe->stream_res.dsc->inst] = true; + +/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */ +if (new_pipe->plane_res.hubp && + new_pipe->plane_res.hubp->inst != new_pipe->stream_res.dsc->inst) { +for (j =0 ; j < dc->res_pool->pipe_count; ++j) { + update_state->pg_pipe_res_update[PG_HUBP ][j] = true; + update_state->pg_pipe_res_update[PG_DPP ][j] = true; + } + } + } + } +for (i = dc->res_pool->pipe_count -1 ; i >=0 ; i--) {if (update_state->pg_pipe_res_update[PG_HUBP ][i] && update_state->pg_pipe_res_update[PG_DPP ][i]) {
Greg Kroah-Hartman
maintainerPATCH 238/263 drm/amd/display: Add dc cap for dp tunneling
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peichen Huang <[email protected]>
commit 3251b69b7efb82eba24c9e168a6142a3078de72f upstream.
[WHAT]
1. add dc cap for dp tunneling
2. add function to get index of host router
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 33 ++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 8 ++ drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c | 3 drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c | 3 drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 3 drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c | 3 drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c | 3 7 files changed, 55 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc.c +33 -0
@@ -239,6 +239,7 @@ static bool create_links(DC_LOG_DC ("BIOS object table - end" );/* Create a link for each usb4 dpia port */ + dc->lowest_dpia_link_index =MAX_LINKS ;for (i =0 ; i < dc->res_pool->usb4_dpia_count; i++) {struct link_init_data link_init_params = {0 };struct dc_link *link;
@@ -251,6 +252,9 @@ static bool create_links( link = dc->link_srv->create_link (&link_init_params);if (link) { +if (dc->lowest_dpia_link_index > dc->link_count) + dc->lowest_dpia_link_index = dc->link_count; + dc->links[dc->link_count] = link; link->dc = dc; ++dc->link_count;
@@ -6247,6 +6251,35 @@ struct dc_power_profile dc_get_power_pro profile.power_level = dc->res_pool->funcs->get_power_profile (context);return profile; } +/** +*********************************************************************************************** +* dc_get_host_router_index: Get index of host router from a dpia link +* +* This function return a host router index of the target link. If the target link is dpia link. +* +* @param [in] link: target link +* @param [out] host_router_index: host router index of the target link +* +* @return: true if the host router index is found and valid. +* +*********************************************************************************************** +*/ +bool dc_get_host_router_index (const struct dc_link *link,unsigned int *host_router_index) +{ +struct dc *dc = link->ctx->dc; + +if (link->ep_type !=DISPLAY_ENDPOINT_USB4_DPIA ) +return false; + +if (link->link_index < dc->lowest_dpia_link_index) +return false; + + *host_router_index = (link->link_index - dc->lowest_dpia_link_index) / dc->caps.num_of_dpias_per_host_router; +if (*host_router_index < dc->caps.num_of_host_routers) +return true; +else +return false; +}/* **********************************************************************************
drivers/gpu/drm/amd/display/dc/dc.h +7 -1
@@ -66,7 +66,8 @@ struct dmub_notification;#define MAX_STREAMS 6#define MIN_VIEWPORT_SIZE 12#define MAX_NUM_EDP 2 -#define MAX_HOST_ROUTERS_NUM 2 +#define MAX_HOST_ROUTERS_NUM 3 +#define MAX_DPIA_PER_HOST_ROUTER 2/* Display Core Interfaces */ struct dc_versions {
@@ -303,6 +304,8 @@ struct dc_caps {/* Conservative limit for DCC cases which require ODM4:1 to support*/ uint32_t dcc_plane_width_limit;struct dc_scl_caps scl_caps; +uint8_t num_of_host_routers; +uint8_t num_of_dpias_per_host_router; };struct dc_bug_wa {
@@ -1431,6 +1434,7 @@ struct dc {uint8_t link_count;struct dc_link *links[MAX_LINKS ]; +uint8_t lowest_dpia_link_index;struct link_service *link_srv;struct dc_state *current_state;
@@ -2586,6 +2590,8 @@ struct dc_power_profile dc_get_power_prounsigned int dc_get_det_buffer_size_from_state (const struct dc_state *context); +bool dc_get_host_router_index (const struct dc_link *link,unsigned int *host_router_index); +/* DSC Interfaces */ #include "dc_dsc.h"
drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +3 -0
@@ -1954,6 +1954,9 @@ static bool dcn31_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg =0 ; dc->caps.color.mpc.ocsc =1 ; + dc->caps.num_of_host_routers =2 ; + dc->caps.num_of_dpias_per_host_router =2 ; +/* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true; dc->config.disable_hbr_audio_dp2 = true;
drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +3 -0
@@ -1885,6 +1885,9 @@ static bool dcn314_resource_construct( dc->caps.max_disp_clock_khz_at_vmin =650000 ; + dc->caps.num_of_host_routers =2 ; + dc->caps.num_of_dpias_per_host_router =2 ; +/* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true;
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +3 -0
@@ -1894,6 +1894,9 @@ static bool dcn35_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg =0 ; dc->caps.color.mpc.ocsc =1 ; + dc->caps.num_of_host_routers =2 ; + dc->caps.num_of_dpias_per_host_router =2 ; +/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order * to provide some margin. * It's expected for furture ASIC to have equal or higher value, in order to
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +3 -0
@@ -1866,6 +1866,9 @@ static bool dcn351_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg =0 ; dc->caps.color.mpc.ocsc =1 ; + dc->caps.num_of_host_routers =2 ; + dc->caps.num_of_dpias_per_host_router =2 ; +/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order * to provide some margin. * It's expected for furture ASIC to have equal or higher value, in order to
drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c +3 -0
@@ -1867,6 +1867,9 @@ static bool dcn36_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg =0 ; dc->caps.color.mpc.ocsc =1 ; + dc->caps.num_of_host_routers =2 ; + dc->caps.num_of_dpias_per_host_router =2 ; +/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order * to provide some margin. * It's expected for furture ASIC to have equal or higher value, in order to
Greg Kroah-Hartman
maintainerPATCH 239/263 drm/amd/display: Fix mpv playback corruption on weston
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
commit 8724a5380c4390eed81e271d22f34ff06453ded9 upstream.
[WHAT]
Severe video playback corruption is observed in the following setup:
weston 14.0.90 (built from source) + mpv v0.40.0 with command:
mpv bbb_sunflower_1080p_60fps_normal.mp4 --vo=gpu
[HOW]
ABGR16161616 needs to be included in dml2/2.1 translation.
--- drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c | 1 + drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c | 1 + 2 files changed, 2 insertions(+)
drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +1 -0
@@ -785,6 +785,7 @@ static void populate_dml21_plane_config_ plane->pixel_format = dml2_420_10;break ;case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 : +case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 :case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F :case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F : plane->pixel_format = dml2_444_64;
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +1 -0
@@ -953,6 +953,7 @@ static void populate_dml_surface_cfg_fro out->SourcePixelFormat[location] = dml_420_10;break ;case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 : +case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 :case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F :case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F : out->SourcePixelFormat[location] = dml_444_64;
Greg Kroah-Hartman
maintainerPATCH 240/263 arm64: dts: qcom: Commonize X1 CRD DTSI
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit fbf5e007588f3f2bace84309b4a0d428ad619322 ]
Certain X1 SKUs vary very noticeably, but the CRDs based on them don't.
Commonize the existing X1E80100 DTSI to allow reuse.
--- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 1275 +++++++++++++++++++++ arch/arm64/boot/dts/qcom/x1e80100-crd.dts | 1270 +------------------- arch/arm64/boot/dts/qcom/x1e80100.dtsi | 2 +- 3 files changed, 1279 insertions(+), 1268 deletions(-) create mode 100644 arch/arm64/boot/dts/qcom/x1-crd.dtsi
arch/arm64/boot/dts/qcom/x1-crd.dtsi new file +1275 -0
@@ -0,0 +1,1275 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/gpio-keys.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pinctrl/qcom,pmic-gpio.h> +#include <dt-bindings/regulator/qcom,rpmh-regulator.h> + +#include "x1e80100-pmics.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. X1E80100 CRD"; + compatible = "qcom,x1e80100-crd", "qcom,x1e80100"; + + aliases { + serial0 = &uart21; + }; + + wcd938x: audio-codec { + compatible = "qcom,wcd9385-codec"; + + pinctrl-names = "default"; + pinctrl-0 = <&wcd_default>; + + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>; + qcom,mbhc-headset-vthreshold-microvolt = <1700000>; + qcom,mbhc-headphone-vthreshold-microvolt = <50000>; + qcom,rx-device = <&wcd_rx>; + qcom,tx-device = <&wcd_tx>; + + reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>; + + vdd-buck-supply = <&vreg_l15b_1p8>; + vdd-rxtx-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l15b_1p8>; + vdd-mic-bias-supply = <&vreg_bob1>; + + #sound-dai-cells = <1>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + pinctrl-0 = <&hall_int_n_default>; + pinctrl-names = "default"; + + switch-lid { + gpios = <&tlmm 92 GPIO_ACTIVE_LOW>; + linux,input-type = <EV_SW>; + linux,code = <SW_LID>; + wakeup-source; + wakeup-event-action = <EV_ACT_DEASSERTED>; + }; + }; + + pmic-glink { + compatible = "qcom,x1e80100-pmic-glink", + "qcom,sm8550-pmic-glink", + "qcom,pmic-glink"; + #address-cells = <1>; + #size-cells = <0>; + orientation-gpios = <&tlmm 121 GPIO_ACTIVE_HIGH>, + <&tlmm 123 GPIO_ACTIVE_HIGH>, + <&tlmm 125 GPIO_ACTIVE_HIGH>; + + /* Left-side rear port */ + connector@0 { + compatible = "usb-c-connector"; + reg = <0>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss0_hs_in: endpoint { + remote-endpoint = <&usb_1_ss0_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss0_ss_in: endpoint { + remote-endpoint = <&usb_1_ss0_qmpphy_out>; + }; + }; + }; + }; + + /* Left-side front port */ + connector@1 { + compatible = "usb-c-connector"; + reg = <1>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss1_hs_in: endpoint { + remote-endpoint = <&usb_1_ss1_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss1_ss_in: endpoint { + remote-endpoint = <&usb_1_ss1_qmpphy_out>; + }; + }; + }; + }; + + /* Right-side port */ + connector@2 { + compatible = "usb-c-connector"; + reg = <2>; + power-role = "dual"; + data-role = "dual"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + pmic_glink_ss2_hs_in: endpoint { + remote-endpoint = <&usb_1_ss2_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + pmic_glink_ss2_ss_in: endpoint { + remote-endpoint = <&usb_1_ss2_qmpphy_out>; + }; + }; + }; + }; + }; + + reserved-memory { + linux,cma { + compatible = "shared-dma-pool"; + size = <0x0 0x8000000>; + reusable; + linux,cma-default; + }; + }; + + sound { + compatible = "qcom,x1e80100-sndcard"; + model = "X1E80100-CRD"; + audio-routing = "WooferLeft IN", "WSA WSA_SPK1 OUT", + "TweeterLeft IN", "WSA WSA_SPK2 OUT", + "WooferRight IN", "WSA2 WSA_SPK2 OUT", + "TweeterRight IN", "WSA2 WSA_SPK2 OUT", + "IN1_HPHL", "HPHL_OUT", + "IN2_HPHR", "HPHR_OUT", + "AMIC2", "MIC BIAS2", + "VA DMIC0", "MIC BIAS3", + "VA DMIC1", "MIC BIAS3", + "VA DMIC2", "MIC BIAS1", + "VA DMIC3", "MIC BIAS1", + "VA DMIC0", "VA MIC BIAS3", + "VA DMIC1", "VA MIC BIAS3", + "VA DMIC2", "VA MIC BIAS1", + "VA DMIC3", "VA MIC BIAS1", + "TX SWR_INPUT1", "ADC2_OUTPUT"; + + wcd-playback-dai-link { + link-name = "WCD Playback"; + + cpu { + sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&wcd938x 0>, <&swr1 0>, <&lpass_rxmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wcd-capture-dai-link { + link-name = "WCD Capture"; + + cpu { + sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>; + }; + + codec { + sound-dai = <&wcd938x 1>, <&swr2 1>, <&lpass_txmacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + wsa-dai-link { + link-name = "WSA Playback"; + + cpu { + sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + }; + + codec { + sound-dai = <&left_woofer>, <&left_tweeter>, + <&swr0 0>, <&lpass_wsamacro 0>, + <&right_woofer>, <&right_tweeter>, + <&swr3 0>, <&lpass_wsa2macro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + + va-dai-link { + link-name = "VA Capture"; + + cpu { + sound-dai = <&q6apmbedai VA_CODEC_DMA_TX_0>; + }; + + codec { + sound-dai = <&lpass_vamacro 0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + + vreg_edp_3p3: regulator-edp-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_EDP_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 70 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&edp_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; + + vreg_misc_3p3: regulator-misc-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VREG_MISC_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pm8550ve_8_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-names = "default"; + pinctrl-0 = <&misc_3p3_reg_en>; + + regulator-boot-on; + regulator-always-on; + }; + + vreg_nvme: regulator-nvme { + compatible = "regulator-fixed"; + + regulator-name = "VREG_NVME_3P3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 18 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-names = "default"; + pinctrl-0 = <&nvme_reg_en>; + + regulator-boot-on; + }; + + vph_pwr: regulator-vph-pwr { + compatible = "regulator-fixed"; + + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + + regulator-always-on; + regulator-boot-on; + }; + + vreg_wwan: regulator-wwan { + compatible = "regulator-fixed"; + + regulator-name = "SDX_VPH_PWR"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&tlmm 221 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&wwan_sw_en>; + pinctrl-names = "default"; + + regulator-boot-on; + }; +}; + +&apps_rsc { + regulators-0 { + compatible = "qcom,pm8550-rpmh-regulators"; + qcom,pmic-id = "b"; + + vdd-bob1-supply = <&vph_pwr>; + vdd-bob2-supply = <&vph_pwr>; + vdd-l1-l4-l10-supply = <&vreg_s4c_1p8>; + vdd-l2-l13-l14-supply = <&vreg_bob1>; + vdd-l5-l16-supply = <&vreg_bob1>; + vdd-l6-l7-supply = <&vreg_bob2>; + vdd-l8-l9-supply = <&vreg_bob1>; + vdd-l12-supply = <&vreg_s5j_1p2>; + vdd-l15-supply = <&vreg_s4c_1p8>; + vdd-l17-supply = <&vreg_bob2>; + + vreg_bob1: bob1 { + regulator-name = "vreg_bob1"; + regulator-min-microvolt = <3008000>; + regulator-max-microvolt = <3960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_bob2: bob2 { + regulator-name = "vreg_bob2"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <3008000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1b_1p8: ldo1 { + regulator-name = "vreg_l1b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2b_3p0: ldo2 { + regulator-name = "vreg_l2b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l4b_1p8: ldo4 { + regulator-name = "vreg_l4b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l5b_3p0: ldo5 { + regulator-name = "vreg_l5b_3p0"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l6b_1p8: ldo6 { + regulator-name = "vreg_l6b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l8b_3p0: ldo8 { + regulator-name = "vreg_l8b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l9b_2p9: ldo9 { + regulator-name = "vreg_l9b_2p9"; + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <2960000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l10b_1p8: ldo10 { + regulator-name = "vreg_l10b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l12b_1p2: ldo12 { + regulator-name = "vreg_l12b_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l13b_3p0: ldo13 { + regulator-name = "vreg_l13b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l14b_3p0: ldo14 { + regulator-name = "vreg_l14b_3p0"; + regulator-min-microvolt = <3072000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l15b_1p8: ldo15 { + regulator-name = "vreg_l15b_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l16b_2p9: ldo16 { + regulator-name = "vreg_l16b_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l17b_2p5: ldo17 { + regulator-name = "vreg_l17b_2p5"; + regulator-min-microvolt = <2504000>; + regulator-max-microvolt = <2504000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-1 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "c"; + + vdd-l1-supply = <&vreg_s5j_1p2>; + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s4-supply = <&vph_pwr>; + + vreg_s4c_1p8: smps4 { + regulator-name = "vreg_s4c_1p8"; + regulator-min-microvolt = <1856000>; + regulator-max-microvolt = <2000000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1c_1p2: ldo1 { + regulator-name = "vreg_l1c_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2c_0p8: ldo2 { + regulator-name = "vreg_l2c_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3c_0p8: ldo3 { + regulator-name = "vreg_l3c_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-2 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "d"; + + vdd-l1-supply = <&vreg_s1f_0p7>; + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s4c_1p8>; + vdd-s1-supply = <&vph_pwr>; + + vreg_l1d_0p8: ldo1 { + regulator-name = "vreg_l1d_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2d_0p9: ldo2 { + regulator-name = "vreg_l2d_0p9"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3d_1p8: ldo3 { + regulator-name = "vreg_l3d_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-3 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "e"; + + vdd-l2-supply = <&vreg_s1f_0p7>; + vdd-l3-supply = <&vreg_s5j_1p2>; + + vreg_l2e_0p8: ldo2 { + regulator-name = "vreg_l2e_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3e_1p2: ldo3 { + regulator-name = "vreg_l3e_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-4 { + compatible = "qcom,pmc8380-rpmh-regulators"; + qcom,pmic-id = "f"; + + vdd-l1-supply = <&vreg_s5j_1p2>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s5j_1p2>; + vdd-s1-supply = <&vph_pwr>; + + vreg_s1f_0p7: smps1 { + regulator-name = "vreg_s1f_0p7"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1f_1p0: ldo1 { + regulator-name = "vreg_l1f_1p0"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2f_1p0: ldo2 { + regulator-name = "vreg_l2f_1p0"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3f_1p0: ldo3 { + regulator-name = "vreg_l3f_1p0"; + regulator-min-microvolt = <1024000>; + regulator-max-microvolt = <1024000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-6 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "i"; + + vdd-l1-supply = <&vreg_s4c_1p8>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s1-supply = <&vph_pwr>; + vdd-s2-supply = <&vph_pwr>; + + vreg_s1i_0p9: smps1 { + regulator-name = "vreg_s1i_0p9"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_s2i_1p0: smps2 { + regulator-name = "vreg_s2i_1p0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1100000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1i_1p8: ldo1 { + regulator-name = "vreg_l1i_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2i_1p2: ldo2 { + regulator-name = "vreg_l2i_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3i_0p8: ldo3 { + regulator-name = "vreg_l3i_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; + + regulators-7 { + compatible = "qcom,pm8550ve-rpmh-regulators"; + qcom,pmic-id = "j"; + + vdd-l1-supply = <&vreg_s1f_0p7>; + vdd-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-supply = <&vreg_s1f_0p7>; + vdd-s5-supply = <&vph_pwr>; + + vreg_s5j_1p2: smps5 { + regulator-name = "vreg_s5j_1p2"; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1304000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l1j_0p8: ldo1 { + regulator-name = "vreg_l1j_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l2j_1p2: ldo2 { + regulator-name = "vreg_l2j_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + + vreg_l3j_0p8: ldo3 { + regulator-name = "vreg_l3j_0p8"; + regulator-min-microvolt = <880000>; + regulator-max-microvolt = <920000>; + regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + }; + }; +}; + +&gpu { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + + status = "okay"; + + touchpad@15 { + compatible = "hid-over-i2c"; + reg = <0x15>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l12b_1p2>; + + pinctrl-0 = <&tpad_default>; + pinctrl-names = "default"; + + wakeup-source; + }; + + keyboard@3a { + compatible = "hid-over-i2c"; + reg = <0x3a>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>; + + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l12b_1p2>; + + pinctrl-0 = <&kybd_default>; + pinctrl-names = "default"; + + wakeup-source; + }; +}; + +&i2c8 { + clock-frequency = <400000>; + + status = "okay"; + + touchscreen@10 { + compatible = "hid-over-i2c"; + reg = <0x10>; + + hid-descr-addr = <0x1>; + interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>; + + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l15b_1p8>; + + pinctrl-0 = <&ts0_default>; + pinctrl-names = "default"; + }; +}; + +&lpass_tlmm { + spkr_01_sd_n_active: spkr-01-sd-n-active-state { + pins = "gpio12"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; + + spkr_23_sd_n_active: spkr-23-sd-n-active-state { + pins = "gpio13"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; +}; + +&lpass_vamacro { + pinctrl-0 = <&dmic01_default>, <&dmic23_default>; + pinctrl-names = "default"; + + vdd-micb-supply = <&vreg_l1b_1p8>; + qcom,dmic-sample-rate = <4800000>; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dp3 { + compatible = "qcom,x1e80100-dp"; + /delete-property/ #sound-dai-cells; + + status = "okay"; + + aux-bus { + panel { + compatible = "samsung,atna45af01", "samsung,atna33xc20"; + enable-gpios = <&pmc8380_3_gpios 4 GPIO_ACTIVE_HIGH>; + power-supply = <&vreg_edp_3p3>; + + pinctrl-0 = <&edp_bl_en>; + pinctrl-names = "default"; + + port { + edp_panel_in: endpoint { + remote-endpoint = <&mdss_dp3_out>; + }; + }; + }; + }; + + ports { + port@1 { + reg = <1>; + mdss_dp3_out: endpoint { + data-lanes = <0 1 2 3>; + link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; + + remote-endpoint = <&edp_panel_in>; + }; + }; + }; +}; + +&mdss_dp3_phy { + vdda-phy-supply = <&vreg_l3j_0p8>; + vdda-pll-supply = <&vreg_l2j_1p2>; + + status = "okay"; +}; + +&pcie4 { + perst-gpios = <&tlmm 146 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>; + + pinctrl-0 = <&pcie4_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie4_phy { + vdda-phy-supply = <&vreg_l3i_0p8>; + vdda-pll-supply = <&vreg_l3e_1p2>; + + status = "okay"; +}; + +&pcie5 { + perst-gpios = <&tlmm 149 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>; + + vddpe-3v3-supply = <&vreg_wwan>; + + pinctrl-0 = <&pcie5_default>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&pcie5_phy { + vdda-phy-supply = <&vreg_l3i_0p8>; + vdda-pll-supply = <&vreg_l3e_1p2>; + + status = "okay"; +}; + +&pcie6a { + perst-gpios = <&tlmm 152 GPIO_ACTIVE_LOW>; + wake-gpios = <&tlmm 154 GPIO_ACTIVE_LOW>; + + vddpe-3v3-supply = <&vreg_nvme>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie6a_default>; + + status = "okay"; +}; + +&pcie6a_phy { + vdda-phy-supply = <&vreg_l1d_0p8>; + vdda-pll-supply = <&vreg_l2j_1p2>; + + status = "okay"; +}; + +&pm8550ve_8_gpios { + misc_3p3_reg_en: misc-3p3-reg-en-state { + pins = "gpio6"; + function = "normal"; + bias-disable; + input-disable; + output-enable; + drive-push-pull; + power-source = <1>; /* 1.8 V */ + qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>; + }; +}; + +&pmc8380_3_gpios { + edp_bl_en: edp-bl-en-state { + pins = "gpio4"; + function = "normal"; + power-source = <1>; /* 1.8V */ + input-disable; + output-enable; + }; +}; + +&qupv3_0 { + status = "okay"; +}; + +&qupv3_1 { + status = "okay"; +}; + +&qupv3_2 { + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/x1e80100/adsp.mbn", + "qcom/x1e80100/adsp_dtb.mbn"; + + status = "okay"; +}; + +&remoteproc_cdsp { + firmware-name = "qcom/x1e80100/cdsp.mbn", + "qcom/x1e80100/cdsp_dtb.mbn"; + + status = "okay"; +}; + +&smb2360_0 { + status = "okay"; +}; + +&smb2360_0_eusb2_repeater { + vdd18-supply = <&vreg_l3d_1p8>; + vdd3-supply = <&vreg_l2b_3p0>; +}; + +&smb2360_1 { + status = "okay"; +}; + +&smb2360_1_eusb2_repeater { + vdd18-supply = <&vreg_l3d_1p8>; + vdd3-supply = <&vreg_l14b_3p0>; +}; + +&smb2360_2 { + status = "okay"; +}; + +&smb2360_2_eusb2_repeater { + vdd18-supply = <&vreg_l3d_1p8>; + vdd3-supply = <&vreg_l8b_3p0>; +}; + +&swr0 { + status = "okay"; + + pinctrl-0 = <&wsa_swr_active>, <&spkr_01_sd_n_active>; + pinctrl-names = "default"; + + /* WSA8845, Left Woofer */ + left_woofer: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "WooferLeft"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; + }; + + /* WSA8845, Left Tweeter */ + left_tweeter: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + reset-gpios = <&lpass_tlmm 12 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "TweeterLeft"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; + }; +}; + +&swr1 { + status = "okay"; + + /* WCD9385 RX */ + wcd_rx: codec@0,4 { + compatible = "sdw20217010d00"; + reg = <0 4>; + qcom,rx-port-mapping = <1 2 3 4 5>; + }; +}; + +&swr2 { + status = "okay"; + + /* WCD9385 TX */ + wcd_tx: codec@0,3 { + compatible = "sdw20217010d00"; + reg = <0 3>; + qcom,tx-port-mapping = <2 2 3 4>; + }; +}; + +&swr3 { + status = "okay"; + + pinctrl-0 = <&wsa2_swr_active>, <&spkr_23_sd_n_active>; + pinctrl-names = "default"; + + /* WSA8845, Right Woofer */ + right_woofer: speaker@0,0 { + compatible = "sdw20217020400"; + reg = <0 0>; + reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "WooferRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <1 2 3 7 10 13>; + }; + + /* WSA8845, Right Tweeter */ + right_tweeter: speaker@0,1 { + compatible = "sdw20217020400"; + reg = <0 1>; + reset-gpios = <&lpass_tlmm 13 GPIO_ACTIVE_LOW>; + #sound-dai-cells = <0>; + sound-name-prefix = "TweeterRight"; + vdd-1p8-supply = <&vreg_l15b_1p8>; + vdd-io-supply = <&vreg_l12b_1p2>; + qcom,port-mapping = <4 5 6 7 11 13>; + }; +}; + +&tlmm { + gpio-reserved-ranges = <34 2>, /* Unused */ + <44 4>, /* SPI (TPM) */ + <238 1>; /* UFS Reset */ + + edp_reg_en: edp-reg-en-state { + pins = "gpio70"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + }; + + hall_int_n_default: hall-int-n-state { + pins = "gpio92"; + function = "gpio"; + bias-disable; + }; + + kybd_default: kybd-default-state { + pins = "gpio67"; + function = "gpio"; + bias-disable; + }; + + nvme_reg_en: nvme-reg-en-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + pcie4_default: pcie4-default-state { + clkreq-n-pins { + pins = "gpio147"; + function = "pcie4_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio146"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio148"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie5_default: pcie5-default-state { + clkreq-n-pins { + pins = "gpio150"; + function = "pcie5_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio149"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio151"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + pcie6a_default: pcie6a-default-state { + clkreq-n-pins { + pins = "gpio153"; + function = "pcie6a_clk"; + drive-strength = <2>; + bias-pull-up; + }; + + perst-n-pins { + pins = "gpio152"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + + wake-n-pins { + pins = "gpio154"; + function = "gpio"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + tpad_default: tpad-default-state { + pins = "gpio3"; + function = "gpio"; + bias-disable; + }; + + ts0_default: ts0-default-state { + int-n-pins { + pins = "gpio51"; + function = "gpio"; + bias-disable; + }; + + reset-n-pins { + pins = "gpio48"; + function = "gpio"; + output-high; + drive-strength = <16>; + }; + }; + + wcd_default: wcd-reset-n-active-state { + pins = "gpio191"; + function = "gpio"; + drive-strength = <16>; + bias-disable; + output-low; + }; + + wwan_sw_en: wwan-sw-en-state { + pins = "gpio221"; + function = "gpio"; + drive-strength = <4>; + bias-disable; + }; +}; + +&uart21 { + compatible = "qcom,geni-debug-uart"; + status = "okay"; +}; + +&usb_1_ss0_hsphy { + vdd-supply = <&vreg_l3j_0p8>; + vdda12-supply = <&vreg_l2j_1p2>; + + phys = <&smb2360_0_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss0_qmpphy { + vdda-phy-supply = <&vreg_l2j_1p2>; + vdda-pll-supply = <&vreg_l1j_0p8>; + + status = "okay"; +}; + +&usb_1_ss0 { + status = "okay"; +}; + +&usb_1_ss0_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss0_dwc3_hs { + remote-endpoint = <&pmic_glink_ss0_hs_in>; +}; + +&usb_1_ss0_qmpphy_out { + remote-endpoint = <&pmic_glink_ss0_ss_in>; +}; + +&usb_1_ss1_hsphy { + vdd-supply = <&vreg_l3j_0p8>; + vdda12-supply = <&vreg_l2j_1p2>; + + phys = <&smb2360_1_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss1_qmpphy { + vdda-phy-supply = <&vreg_l2j_1p2>; + vdda-pll-supply = <&vreg_l2d_0p9>; + + status = "okay"; +}; + +&usb_1_ss1 { + status = "okay"; +}; + +&usb_1_ss1_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss1_dwc3_hs { + remote-endpoint = <&pmic_glink_ss1_hs_in>; +}; + +&usb_1_ss1_qmpphy_out { + remote-endpoint = <&pmic_glink_ss1_ss_in>; +}; + +&usb_1_ss2_hsphy { + vdd-supply = <&vreg_l3j_0p8>; + vdda12-supply = <&vreg_l2j_1p2>; + + phys = <&smb2360_2_eusb2_repeater>; + + status = "okay"; +}; + +&usb_1_ss2_qmpphy { + vdda-phy-supply = <&vreg_l2j_1p2>; + vdda-pll-supply = <&vreg_l2d_0p9>; + + status = "okay"; +}; + +&usb_1_ss2 { + status = "okay"; +}; + +&usb_1_ss2_dwc3 { + dr_mode = "host"; +}; + +&usb_1_ss2_dwc3_hs { + remote-endpoint = <&pmic_glink_ss2_hs_in>; +}; + +&usb_1_ss2_qmpphy_out { + remote-endpoint = <&pmic_glink_ss2_ss_in>; +};
arch/arm64/boot/dts/qcom/x1e80100-crd.dts +3 -1267
1,281 lines not on this page · raw message
arch/arm64/boot/dts/qcom/x1e80100.dtsi +1 -1
@@ -3748,7 +3748,7 @@ gpu: gpu@3d00000 { status = "disabled"; - zap-shader { + gpu_zap_shader: zap-shader { memory-region = <&gpu_microcode_mem>; };
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 241/263 arm64: dts: qcom: x1e80100-crd: mark l12b and l15b always-on
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit abf89bc4bb09c16a53d693b09ea85225cf57ff39 ]
The l12b and l15b supplies are used by components that are not (fully) described (and some never will be) and must never be disabled.
Mark the regulators as always-on to prevent them from being disabled, for example, when consumers probe defer or suspend.
--- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/qcom/x1-crd.dtsi +2 -0
@@ -434,6 +434,7 @@ vreg_l12b_1p2: ldo12 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + regulator-always-on; }; vreg_l13b_3p0: ldo13 {
@@ -455,6 +456,7 @@ vreg_l15b_1p8: ldo15 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + regulator-always-on; }; vreg_l16b_2p9: ldo16 {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 242/263 arm64: dts: qcom: x1e78100-t14s: mark l12b and l15b always-on
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
[ Upstream commit 673fa129e558c5f1196adb27d97ac90ddfe4f19c ]
The l12b and l15b supplies are used by components that are not (fully) described (and some never will be) and must never be disabled.
Mark the regulators as always-on to prevent them from being disabled, for example, when consumers probe defer or suspend.
--- arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts +2 -0
@@ -344,6 +344,7 @@ vreg_l12b_1p2: ldo12 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + regulator-always-on; }; vreg_l13b_3p0: ldo13 {
@@ -365,6 +366,7 @@ vreg_l15b_1p8: ldo15 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; + regulator-always-on; }; vreg_l17b_2p5: ldo17 {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 243/263 arm64: dts: qcom: x1-crd: Fix vreg_l2j_1p2 voltage
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
[ Upstream commit 5ce920e6a8db40e4b094c0d863cbd19fdcfbbb7a ]
In the ACPI DSDT table, PPP_RESOURCE_ID_LDO2_J is configured with 1256000 uV instead of the 1200000 uV we have currently in the device tree. Use the same for consistency and correctness.
--- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/x1-crd.dtsi +2 -2
@@ -674,8 +674,8 @@ vreg_l1j_0p8: ldo1 { vreg_l2j_1p2: ldo2 { regulator-name = "vreg_l2j_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; + regulator-min-microvolt = <1256000>; + regulator-max-microvolt = <1256000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; };
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 244/263 crypto: powerpc/poly1305 - add depends on BROKEN for now
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
[ Upstream commit bc8169003b41e89fe7052e408cf9fdbecb4017fe ]
As discussed in the thread containing
https://lore.kernel.org/linux-crypto/20250510053308.GB505731@sol/, the Power10-optimized Poly1305 code is currently not safe to call in softirq context. Disable it for now. It can be re-enabled once it is fixed.
--- arch/powerpc/crypto/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/crypto/Kconfig +1 -0
@@ -110,6 +110,7 @@ config CRYPTO_CHACHA20_P10 config CRYPTO_POLY1305_P10 tristate "Hash functions: Poly1305 (P10 or later)" depends on PPC64 && CPU_LITTLE_ENDIAN && VSX + depends on BROKEN # Needs to be fixed to work in softirq context select CRYPTO_HASH select CRYPTO_LIB_POLY1305_GENERIC help
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 245/263 drm/amdgpu/mes: add missing locking in helper functions
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 40f970ba7a4ab77be2ffe6d50a70416c8876496a ]
We need to take the MES lock.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +16 -0
@@ -836,7 +836,9 @@ int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev, queue_input.mqd_addr =amdgpu_bo_gpu_offset (ring->mqd_obj); queue_input.wptr_addr = ring->wptr_gpu_addr; +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->map_legacy_queue (&adev->mes, &queue_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to map legacy queue\n" );
@@ -859,7 +861,9 @@ int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev, queue_input.trail_fence_addr = gpu_addr; queue_input.trail_fence_data = seq; +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->unmap_legacy_queue (&adev->mes, &queue_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to unmap legacy queue\n" );
@@ -886,7 +890,9 @@ int amdgpu_mes_reset_legacy_queue(struct amdgpu_device *adev, queue_input.vmid = vmid; queue_input.use_mmio = use_mmio; +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->reset_legacy_queue (&adev->mes, &queue_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to reset legacy queue\n" );
@@ -916,7 +922,9 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg) goto error; } +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->misc_op (&adev->mes, &op_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to read reg (0x%x)\n" , reg);else
@@ -944,7 +952,9 @@ int amdgpu_mes_wreg(struct amdgpu_device *adev, goto error; } +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->misc_op (&adev->mes, &op_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to write reg (0x%x)\n" , reg);
@@ -971,7 +981,9 @@ int amdgpu_mes_reg_write_reg_wait(struct amdgpu_device *adev, goto error; } +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->misc_op (&adev->mes, &op_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to reg_write_reg_wait\n" );
@@ -996,7 +1008,9 @@ int amdgpu_mes_reg_wait(struct amdgpu_device *adev, uint32_t reg, goto error; } +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->misc_op (&adev->mes, &op_input); +amdgpu_mes_unlock (&adev->mes);if (r)DRM_ERROR ("failed to reg_write_reg_wait\n" );
@@ -1687,7 +1701,9 @@ static int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, goto error; } +amdgpu_mes_lock (&adev->mes); r = adev->mes.funcs->misc_op (&adev->mes, &op_input); +amdgpu_mes_unlock (&adev->mes);if (r)dev_err (adev->dev,"failed to change_config.\n" );
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 246/263 arm64: dts: qcom: x1e78100-t14s: fix missing HID supplies
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
[ Upstream commit 55e52d055393f11ba0193975d3db87af36f4b273 ]
Add the missing HID supplies to avoid relying on other consumers to keep them on.
This also avoids the following warnings on boot:
i2c_hid_of 0-0010: supply vdd not found, using dummy regulator i2c_hid_of 0-0010: supply vddl not found, using dummy regulator i2c_hid_of 1-0015: supply vdd not found, using dummy regulator i2c_hid_of 1-002c: supply vdd not found, using dummy regulator i2c_hid_of 1-0015: supply vddl not found, using dummy regulator i2c_hid_of 1-002c: supply vddl not found, using dummy regulator i2c_hid_of 1-003a: supply vdd not found, using dummy regulator i2c_hid_of 1-003a: supply vddl not found, using dummy regulator
Note that VCC3B is also used for things like the modem which are not yet described so mark the regulator as always-on for now.
--- .../qcom/x1e78100-lenovo-thinkpad-t14s.dts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+)
arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts +43 -0
@@ -9,6 +9,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/gpio-keys.h> #include <dt-bindings/input/input.h> +#include <dt-bindings/pinctrl/qcom,pmic-gpio.h> #include <dt-bindings/regulator/qcom,rpmh-regulator.h> #include "x1e80100.dtsi"
@@ -153,6 +154,23 @@ vreg_edp_3p3: regulator-edp-3p3 { regulator-boot-on; }; + vreg_misc_3p3: regulator-misc-3p3 { + compatible = "regulator-fixed"; + + regulator-name = "VCC3B"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pm8550ve_8_gpios 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + + pinctrl-0 = <&misc_3p3_reg_en>; + pinctrl-names = "default"; + + regulator-boot-on; + regulator-always-on; + }; + vreg_nvme: regulator-nvme { compatible = "regulator-fixed";
@@ -580,6 +598,9 @@ touchpad@15 { hid-descr-addr = <0x1>; interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l12b_1p2>; + wakeup-source; };
@@ -591,6 +612,9 @@ touchpad@2c { hid-descr-addr = <0x20>; interrupts-extended = <&tlmm 3 IRQ_TYPE_LEVEL_LOW>; + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l12b_1p2>; + wakeup-source; };
@@ -602,6 +626,9 @@ keyboard@3a { hid-descr-addr = <0x1>; interrupts-extended = <&tlmm 67 IRQ_TYPE_LEVEL_LOW>; + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l15b_1p8>; + pinctrl-0 = <&kybd_default>; pinctrl-names = "default";
@@ -670,6 +697,9 @@ touchscreen@10 { hid-descr-addr = <0x1>; interrupts-extended = <&tlmm 51 IRQ_TYPE_LEVEL_LOW>; + vdd-supply = <&vreg_misc_3p3>; + vddl-supply = <&vreg_l15b_1p8>; + pinctrl-0 = <&ts0_default>; pinctrl-names = "default"; };
@@ -789,6 +819,19 @@ edp_bl_en: edp-bl-en-state { }; }; +&pm8550ve_8_gpios { + misc_3p3_reg_en: misc-3p3-reg-en-state { + pins = "gpio6"; + function = "normal"; + bias-disable; + drive-push-pull; + input-disable; + output-enable; + power-source = <1>; /* 1.8 V */ + qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>; + }; +}; + &qupv3_0 { status = "okay"; };
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 247/263 sched_ext: Make scx_group_set_weight() always update tg->scx.weight
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
[ Upstream commit c50784e99f0e7199cdb12dbddf02229b102744ef ]
Otherwise, tg->scx.weight can go out of sync while scx_cgroup is not enabled and ops.cgroup_init() may be called with a stale weight value.
--- kernel/sched/ext.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/sched/ext.c +6 -6
@@ -4074,12 +4074,12 @@ void scx_group_set_weight(struct task_group *tg, unsigned long weight) {percpu_down_read (&scx_cgroup_rwsem); -if (scx_cgroup_enabled && tg->scx_weight != weight) { -if (SCX_HAS_OP (cgroup_set_weight)) -SCX_CALL_OP (SCX_KF_UNLOCKED , cgroup_set_weight,NULL , -tg_cgrp (tg), weight); - tg->scx_weight = weight; - } +if (scx_cgroup_enabled &&SCX_HAS_OP (cgroup_set_weight) && + tg->scx_weight != weight) +SCX_CALL_OP (SCX_KF_UNLOCKED , cgroup_set_weight,NULL , +tg_cgrp (tg), weight); + + tg->scx_weight = weight;percpu_up_read (&scx_cgroup_rwsem); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 248/263 drm/amd/display: Add early 8b/10b channel equalization test pattern sequence
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Strauss <[email protected]>
[ Upstream commit 8989cb919b27cd0d2aadb7f1d144cedbb12e6fca ]
[WHY]
Early EQ pattern sequence is required for some LTTPR + old dongle combinations.
[HOW]
If DP_EARLY_8B10B_TPS2 chip cap is set, this new sequence programs phy to output TPS2 before initiating link training and writes TPS1 to LTTPR training pattern register as instructed by vendor.
Add function to get embedded LTTPR target address offset.
--- .../dc/link/protocols/link_dp_capability.c | 8 +++ .../dc/link/protocols/link_dp_capability.h | 3 ++ .../dc/link/protocols/link_dp_training.c | 1 - .../link/protocols/link_dp_training_8b_10b.c | 52 +++++++++++++++++-- .../amd/display/include/link_service_types.h | 2 + 5 files changed, 62 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +8 -0
@@ -158,6 +158,14 @@ uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count)return 0 ;// invalid value } +uint32_t dp_get_closest_lttpr_offset (uint8_t lttpr_count) +{ +/* Calculate offset for LTTPR closest to DPTX which is highest in the chain +* Offset is 0 for single LTTPR cases as base LTTPR DPCD addresses target LTTPR 1 +*/ +return DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE * (lttpr_count -1 ); +} +uint32_t link_bw_kbps_from_raw_frl_link_rate_data (uint8_t bw) {switch (bw) {
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h +3 -0
@@ -48,6 +48,9 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link);/* Convert PHY repeater count read from DPCD uint8_t. */ uint8_t dp_parse_lttpr_repeater_count (uint8_t lttpr_repeater_count); +/* Calculate embedded LTTPR address offset for vendor-specific behaviour */ +uint32_t dp_get_closest_lttpr_offset (uint8_t lttpr_count); +bool dp_is_sink_present (struct dc_link *link);bool dp_is_lttpr_present (struct dc_link *link);
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +0 -1
@@ -785,7 +785,6 @@ void override_training_settings( lt_settings->lttpr_mode =LTTPR_MODE_NON_LTTPR ;dp_get_lttpr_mode_override (link, <_settings->lttpr_mode); - } enum dc_dp_training_pattern decide_cr_training_pattern(
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +49 -3
82 lines not on this page · raw message
drivers/gpu/drm/amd/display/include/link_service_types.h +2 -0
@@ -89,6 +89,8 @@ struct link_training_settings {bool enhanced_framing;enum lttpr_mode lttpr_mode; +bool lttpr_early_tps2; +/* disallow different lanes to have different lane settings */ bool disallow_per_lane_settings;/* dpcd lane settings will always use the same hw lane settings
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 249/263 drm/amd/display: Get LTTPR IEEE OUI/Device ID From Closest LTTPR To Host
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Strauss <[email protected]>
[ Upstream commit d358a51444c88bcc995e471dc8cc840f19e4b374 ]
[WHY]
These fields are read for the explicit purpose of detecting embedded LTTPRs (i.e. between host ASIC and the user-facing port), and thus need to calculate the correct DPCD address offset based on LTTPR count to target the appropriate LTTPR's DPCD register space with these queries.
[HOW]
Cascaded LTTPRs in a link each snoop and increment LTTPR count when queried via DPCD read, so an LTTPR embedded in a source device (e.g. USB4 port on a laptop) will always be addressible using the max LTTPR count seen by the host. Therefore we simply need to use a recently added helper function to calculate the correct DPCD address to target potentially embedded LTTPRs based on the received LTTPR count.
--- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 4 +- .../dc/link/protocols/link_dp_capability.c | 38 +++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/display/dc/dc_dp_types.h +2 -2
@@ -1157,8 +1157,8 @@ struct dc_lttpr_caps {union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;union dp_alpm_lttpr_cap alpm;uint8_t aux_rd_interval[MAX_REPEATER_CNT -1 ]; -uint8_t lttpr_ieee_oui[3 ]; -uint8_t lttpr_device_id[6 ]; +uint8_t lttpr_ieee_oui[3 ];// Always read from closest LTTPR to host +uint8_t lttpr_device_id[6 ];// Always read from closest LTTPR to host };struct dc_dongle_dfp_cap_ext {
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +31 -7
@@ -385,9 +385,15 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)bool dp_is_lttpr_present (struct dc_link *link) {/* Some sink devices report invalid LTTPR revision, so don't validate against that cap */ -return (dp_parse_lttpr_repeater_count (link->dpcd_caps.lttpr_caps.phy_repeater_cnt) !=0 && +uint32_t lttpr_count =dp_parse_lttpr_repeater_count (link->dpcd_caps.lttpr_caps.phy_repeater_cnt); +bool is_lttpr_present = (lttpr_count >0 && link->dpcd_caps.lttpr_caps.max_lane_count >0 && link->dpcd_caps.lttpr_caps.max_lane_count <=4 ); + +if (lttpr_count >0 && !is_lttpr_present) +DC_LOG_ERROR ("LTTPR count is nonzero but invalid lane count reported. Assuming no LTTPR present.\n" ); + +return is_lttpr_present; }/* in DP compliance test, DPR-120 may have
@@ -1551,6 +1557,8 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)uint8_t lttpr_dpcd_data[10 ] = {0 };enum dc_status status;bool is_lttpr_present; +uint32_t lttpr_count; +uint32_t closest_lttpr_offset;/* Logic to determine LTTPR support*/ bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
@@ -1602,20 +1610,22 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES -DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV ]; + lttpr_count =dp_parse_lttpr_repeater_count (link->dpcd_caps.lttpr_caps.phy_repeater_cnt); +/* If this chip cap is set, at least one retimer must exist in the chain * Override count to 1 if we receive a known bad count (0 or an invalid value) */ if (((link->chip_caps &AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK ) ==AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN ) && - (dp_parse_lttpr_repeater_count (link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ==0 )) { + lttpr_count ==0 ) {/* If you see this message consistently, either the host platform has FIXED_VS flag * incorrectly configured or the sink device is returning an invalid count. */ DC_LOG_ERROR ("lttpr_caps phy_repeater_cnt is 0x%x, forcing it to 0x80." , link->dpcd_caps.lttpr_caps.phy_repeater_cnt); link->dpcd_caps.lttpr_caps.phy_repeater_cnt =0x80 ; + lttpr_count =1 ;DC_LOG_DC ("lttpr_caps forced phy_repeater_cnt = %d\n" , link->dpcd_caps.lttpr_caps.phy_repeater_cnt); } -/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ is_lttpr_present =dp_is_lttpr_present (link);DC_LOG_DC ("is_lttpr_present = %d\n" , is_lttpr_present);
@@ -1623,11 +1633,25 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)if (is_lttpr_present) {CONN_DATA_DETECT (link, lttpr_dpcd_data,sizeof (lttpr_dpcd_data),"LTTPR Caps: " ); -core_link_read_dpcd (link,DP_LTTPR_IEEE_OUI , link->dpcd_caps.lttpr_caps.lttpr_ieee_oui,sizeof (link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); -CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui,sizeof (link->dpcd_caps.lttpr_caps.lttpr_ieee_oui),"LTTPR IEEE OUI: " ); +// Identify closest LTTPR to determine if workarounds required for known embedded LTTPR + closest_lttpr_offset =dp_get_closest_lttpr_offset (lttpr_count); -core_link_read_dpcd (link,DP_LTTPR_DEVICE_ID , link->dpcd_caps.lttpr_caps.lttpr_device_id,sizeof (link->dpcd_caps.lttpr_caps.lttpr_device_id)); -CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_device_id,sizeof (link->dpcd_caps.lttpr_caps.lttpr_device_id),"LTTPR Device ID: " ); +core_link_read_dpcd (link, (DP_LTTPR_IEEE_OUI + closest_lttpr_offset), + link->dpcd_caps.lttpr_caps.lttpr_ieee_oui,sizeof (link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); +core_link_read_dpcd (link, (DP_LTTPR_DEVICE_ID + closest_lttpr_offset), + link->dpcd_caps.lttpr_caps.lttpr_device_id,sizeof (link->dpcd_caps.lttpr_caps.lttpr_device_id)); + +if (lttpr_count >1 ) { +CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui,sizeof (link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), +"Closest LTTPR To Host's IEEE OUI: " ); +CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_device_id,sizeof (link->dpcd_caps.lttpr_caps.lttpr_device_id), +"Closest LTTPR To Host's LTTPR Device ID: " ); + }else { +CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui,sizeof (link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), +"LTTPR IEEE OUI: " ); +CONN_DATA_DETECT (link, link->dpcd_caps.lttpr_caps.lttpr_device_id,sizeof (link->dpcd_caps.lttpr_caps.lttpr_device_id), +"LTTPR Device ID: " ); + } }return status;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 250/263 drm/amd/display: Fix default DC and AC levels
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit 8b5f3a229a70d242322b78c8e13744ca00212def ]
[Why]
DC and AC levels are advertised in a percentage, not a luminance.
[How]
Scale DC and AC levels to supported values.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +8 -3
@@ -4834,6 +4834,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)struct backlight_properties props = {0 };struct amdgpu_dm_backlight_caps caps = {0 };char bl_name[16 ]; +int min, max;if (aconnector->bl_idx ==-1 )return ;
@@ -4846,11 +4847,15 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) }amdgpu_acpi_get_backlight_caps (&caps); -if (caps.caps_valid) { +if (caps.caps_valid &&get_brightness_range (&caps, &min, &max)) {if (power_supply_is_system_supplied () >0 ) - props.brightness = caps.ac_level; + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.ac_level,100 );else - props.brightness = caps.dc_level; + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.dc_level,100 ); +/* min is zero, so max needs to be adjusted */ + props.max_brightness = max - min; +drm_dbg (drm,"Backlight caps: min: %d, max: %d, ac %d, dc %d\n" , min, max, + caps.ac_level, caps.dc_level); }else props.brightness =AMDGPU_MAX_BL_LEVEL ;
Signature · 1 line
2.39.5
Re: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
Quoted 7 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]
This is actually 8b5f3a229a70d242322b78c8e13744ca00212def squashed with 4b61b8a390511a1864f26cc42bab72881e93468d -- why?
Quoted 48 lines
[Why]
DC and AC levels are advertised in a percentage, not a luminance.[How]
Scale DC and AC levels to supported values.Reviewed-by Alex Hung <[email protected]>Signed-off-by Mario Limonciello <[email protected]>Signed-off-by Wayne Lin <[email protected]>Tested-by Daniel Wheeler <[email protected]>Signed-off-by Alex Deucher <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +8
-3@@ -4834,6 +4834,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)struct backlight_properties props = {0 };struct amdgpu_dm_backlight_caps caps = {0 };char bl_name[16 ]; +int min, max;if (aconnector->bl_idx ==-1 )return ;@@ -4846,11 +4847,15 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) }amdgpu_acpi_get_backlight_caps (&caps); -if (caps.caps_valid) { +if (caps.caps_valid &&get_brightness_range (&caps, &min, &max)) {if (power_supply_is_system_supplied () >0 ) - props.brightness = caps.ac_level; + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.ac_level,100 );else - props.brightness = caps.dc_level; + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.dc_level,100 ); +/* min is zero, so max needs to be adjusted */ + props.max_brightness = max - min; +drm_dbg (drm,"Backlight caps: min: %d, max: %d, ac %d, dc %d\n" , min, max, + caps.ac_level, caps.dc_level); }else props.brightness =AMDGPU_MAX_BL_LEVEL ;
Signature · 2 lines
js suse labs
Greg Kroah-Hartman
maintainerRe: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
Quoted 11 lines · Jiri Slaby
Quoted 7 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]This is actually
8b5f3a229a70d242322b78c8e13744ca00212defsquashed with4b61b8a390511a1864f26cc42bab72881e93468d-- why?
Ick, I don't know. Let me go drop it now, good catch! Let me go verify these other drm backports too, the drm stable patch mess is never fun...
Yeah, something went wrong with Sasha's backports, some of these didn't even have an upstream commit id in them :(
I've dropped this one, and the ones after this as they weren't correct, thanks for the review!
greg k-h
Re: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
Quoted 13 lines · Greg Kroah-Hartman
Quoted 11 lines · Jiri Slaby
Quoted 7 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]This is actually
8b5f3a229a70d242322b78c8e13744ca00212defsquashed with4b61b8a390511a1864f26cc42bab72881e93468d-- why?
Quoted 8 lines
Ick, I don't know. Let me go drop it now, good catch! Let me go verify these other drm backports too, the drm stable patch mess is never fun...
Yeah, something went wrong with Sasha's backports, some of these didn't even have an upstream commit id in them :(
I've dropped this one, and the ones after this as they weren't correct, thanks for the review!
Actually, we have the two (8b5f3a229a+4b61b8a39) in our tree as they fix:
https://bugzilla.suse.com/show_bug.cgi?id=1236415
So dropping them is not a good idea after all ;). Just desquash...
thanks,
Signature · 2 lines
js suse labs
Re: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
Quoted 17 lines · Jiri Slaby
Quoted 16 lines · Greg Kroah-Hartman
Quoted 11 lines · Jiri Slaby
Quoted 7 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]This is actually
8b5f3a229a70d242322b78c8e13744ca00212defsquashed with4b61b8a390511a1864f26cc42bab72881e93468d-- why?Ick, I don't know. Let me go drop it now, good catch! Let me go verify these other drm backports too, the drm stable patch mess is never fun...
Quoted 8 lines
Quoted 5 lines
Yeah, something went wrong with Sasha's backports, some of these didn't even have an upstream commit id in them :(
I've dropped this one, and the ones after this as they weren't correct, thanks for the review!
Actually, we have the two (8b5f3a229a+4b61b8a39) in our tree as they fix:
https://bugzilla.suse.com/show_bug.cgi?id=1236415
No, this one:
https://bugzilla.suse.com/show_bug.cgi?id=1240650
Quoted 3 lines
So dropping them is not a good idea after all ;). Just desquash...
thanks,
Signature · 2 lines
js suse labs
Greg Kroah-Hartman
maintainerRe: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
Quoted 22 lines · Jiri Slaby
Quoted 21 lines · Jiri Slaby
Quoted 20 lines · Greg Kroah-Hartman
Quoted 4 lines · Jiri Slaby
Quoted 3 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
Quoted 8 lines
Quoted 5 lines
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]This is actually
8b5f3a229a70d242322b78c8e13744ca00212defsquashed with4b61b8a390511a1864f26cc42bab72881e93468d-- why?Ick, I don't know. Let me go drop it now, good catch! Let me go verify these other drm backports too, the drm stable patch mess is never fun...
Yeah, something went wrong with Sasha's backports, some of these didn't even have an upstream commit id in them :(
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
I've dropped this one, and the ones after this as they weren't correct, thanks for the review!
Actually, we have the two (8b5f3a229a+4b61b8a39) in our tree as they fix:
https://bugzilla.suse.com/show_bug.cgi?id=1236415No, this one:
https://bugzilla.suse.com/show_bug.cgi?id=1240650
Thanks, now both added, and I figured out the others that Sasha had applied without git ids and then added yet-another-fix for those that was also needed.
I'll go push out a -rc2 soon with all of these in them, thanks.
greg k-h
Greg Kroah-Hartman
maintainerRe: [PATCH 6.15 250/263] drm/amd/display: Fix default DC and AC levels
In reply to Jiri SlabyQuoted 20 lines · Jiri Slaby
Quoted 19 lines · Greg Kroah-Hartman
Quoted 11 lines · Jiri Slaby
Quoted 7 lines · Greg Kroah-Hartman
6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit
8b5f3a229a70d242322b78c8e13744ca00212def]This is actually
8b5f3a229a70d242322b78c8e13744ca00212defsquashed with4b61b8a390511a1864f26cc42bab72881e93468d-- why?Ick, I don't know. Let me go drop it now, good catch! Let me go verify these other drm backports too, the drm stable patch mess is never fun...
Yeah, something went wrong with Sasha's backports, some of these didn't even have an upstream commit id in them :(
Quoted 7 lines
Quoted 2 lines
I've dropped this one, and the ones after this as they weren't correct, thanks for the review!
Actually, we have the two (8b5f3a229a+4b61b8a39) in our tree as they fix:
https://bugzilla.suse.com/show_bug.cgi?id=1236415So dropping them is not a good idea after all ;). Just desquash...
Ah. Ok, I've applied them individually and that worked. Let me try to figure out what the ones that Sasha added that had no git id were from...
greg k-h
Greg Kroah-Hartman
maintainerPATCH 251/263 drm/amd/display: Only read ACPI backlight caps once
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit ffcaed1d7ecef31198000dfbbea791f30f7ca437 ]
[WHY]
Backlight caps are read already in amdgpu_dm_update_backlight_caps(). They may be updated by update_connector_ext_caps(). Reading again when registering backlight device may cause wrong values to be used.
[HOW]
Use backlight caps already registered to the dm.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +7 -7
@@ -4832,7 +4832,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)struct drm_device *drm = aconnector->base.dev;struct amdgpu_display_manager *dm = &drm_to_adev (drm)->dm;struct backlight_properties props = {0 }; -struct amdgpu_dm_backlight_caps caps = {0 }; +struct amdgpu_dm_backlight_caps *caps;char bl_name[16 ];int min, max;
@@ -4846,20 +4846,20 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)return ; } -amdgpu_acpi_get_backlight_caps (&caps); -if (caps.caps_valid &&get_brightness_range (&caps, &min, &max)) { + caps = &dm->backlight_caps[aconnector->bl_idx]; +if (get_brightness_range (caps, &min, &max)) {if (power_supply_is_system_supplied () >0 ) - props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.ac_level,100 ); + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps->ac_level,100 );else - props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps.dc_level,100 ); + props.brightness = (max - min) *DIV_ROUND_CLOSEST (caps->dc_level,100 );/* min is zero, so max needs to be adjusted */ props.max_brightness = max - min;drm_dbg (drm,"Backlight caps: min: %d, max: %d, ac %d, dc %d\n" , min, max, - caps.ac_level, caps.dc_level); + caps->ac_level, caps->dc_level); }else props.brightness =AMDGPU_MAX_BL_LEVEL ; -if (caps.data_points && !(amdgpu_dc_debug_mask &DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE )) +if (caps->data_points && !(amdgpu_dc_debug_mask &DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE ))drm_info (drm,"Using custom brightness curve\n" ); props.max_brightness =AMDGPU_MAX_BL_LEVEL ; props.type =BACKLIGHT_RAW ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 252/263 drm/amd/display: Optimize custom brightness curve
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[Why]
When BIOS includes a lot of custom brightness data points, walking the entire list can be time consuming. This is most noticed when dragging a power slider. The "higher" values are "slower" to drag around.
[How]
Move custom brightness calculation loop into a static function. Before starting the loop check the "half way" data point to see how it compares to the input. If greater than the half way data point use that as the starting point instead.
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +33 -20
@@ -4655,41 +4655,54 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,return 1 ; } -static u32 convert_brightness_from_user (const struct amdgpu_dm_backlight_caps *caps, -uint32_t brightness) +static void convert_custom_brightness (const struct amdgpu_dm_backlight_caps *caps, +uint32_t *brightness) { -unsigned int min, max;u8 prev_signal =0 , prev_lum =0 ; +int i =0 ; -if (!get_brightness_range (caps, &min, &max)) -return brightness; - -for (int i =0 ; i < caps->data_points; i++) { -u8 signal, lum; +if (amdgpu_dc_debug_mask &DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE ) +return ; -if (amdgpu_dc_debug_mask &DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE ) -break ; +if (!caps->data_points) +return ; - signal = caps->luminance_data[i].input_signal; - lum = caps->luminance_data[i].luminance; +/* choose start to run less interpolation steps */ +if (caps->luminance_data[caps->data_points/2 ].input_signal > *brightness) + i = caps->data_points/2 ; +do { +u8 signal = caps->luminance_data[i].input_signal; +u8 lum = caps->luminance_data[i].luminance;/* * brightness == signal: luminance is percent numerator * brightness < signal: interpolate between previous and current luminance numerator * brightness > signal: find next data point */ -if (brightness < signal) - lum = prev_lum +DIV_ROUND_CLOSEST ((lum - prev_lum) * - (brightness - prev_signal), - signal - prev_signal); -else if (brightness > signal) { +if (*brightness > signal) { prev_signal = signal; prev_lum = lum; + i++;continue ; } - brightness =DIV_ROUND_CLOSEST (lum * brightness,101 ); -break ; - } +if (*brightness < signal) + lum = prev_lum +DIV_ROUND_CLOSEST ((lum - prev_lum) * + (*brightness - prev_signal), + signal - prev_signal); + *brightness =DIV_ROUND_CLOSEST (lum * *brightness,101 ); +return ; + }while (i < caps->data_points); +} + +static u32 convert_brightness_from_user (const struct amdgpu_dm_backlight_caps *caps, +uint32_t brightness) +{ +unsigned int min, max; + +if (!get_brightness_range (caps, &min, &max)) +return brightness; + +convert_custom_brightness (caps, &brightness);// Rescale 0..255 to min..max return min + DIV_ROUND_CLOSEST((max - min) * brightness,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 253/263 drm/amd/display: Export full brightness range to userspace
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[WHY]
Userspace currently is offered a range from 0-0xFF but the PWM is programmed from 0-0xFFFF. This can be limiting to some software that wants to apply greater granularity.
[HOW]
Convert internally to firmware values only when mapping custom brightness curves because these are in 0-0xFF range. Advertise full PWM range to userspace.
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +27 -14
@@ -4655,9 +4655,23 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,return 1 ; } +/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */ +static inline u32 scale_input_to_fw (int min,int max,u64 input) +{ +return DIV_ROUND_CLOSEST_ULL (input *AMDGPU_MAX_BL_LEVEL , max - min); +} + +/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */ +static inline u32 scale_fw_to_input (int min,int max,u64 input) +{ +return min +DIV_ROUND_CLOSEST_ULL (input * (max - min),AMDGPU_MAX_BL_LEVEL ); +} +static void convert_custom_brightness (const struct amdgpu_dm_backlight_caps *caps, -uint32_t *brightness) +unsigned int min,unsigned int max, +uint32_t *user_brightness) { +u32 brightness =scale_input_to_fw (min, max, *user_brightness);u8 prev_signal =0 , prev_lum =0 ;int i =0 ;
@@ -4668,7 +4682,7 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *capreturn ;/* choose start to run less interpolation steps */ -if (caps->luminance_data[caps->data_points/2 ].input_signal > *brightness) +if (caps->luminance_data[caps->data_points/2 ].input_signal > brightness) i = caps->data_points/2 ; do { u8 signal = caps->luminance_data[i].input_signal;
@@ -4679,17 +4693,18 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap* brightness < signal: interpolate between previous and current luminance numerator * brightness > signal: find next data point */ -if (*brightness > signal) { +if (brightness > signal) { prev_signal = signal; prev_lum = lum; i++;continue ; } -if (*brightness < signal) +if (brightness < signal) lum = prev_lum +DIV_ROUND_CLOSEST ((lum - prev_lum) * - (*brightness - prev_signal), + (brightness - prev_signal), signal - prev_signal); - *brightness =DIV_ROUND_CLOSEST (lum * *brightness,101 ); + *user_brightness =scale_fw_to_input (min, max, +DIV_ROUND_CLOSEST (lum * brightness,101 ));return ; }while (i < caps->data_points); }
@@ -4702,11 +4717,10 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *cif (!get_brightness_range (caps, &min, &max))return brightness; -convert_custom_brightness (caps, &brightness); +convert_custom_brightness (caps, min, max, &brightness); -// Rescale 0..255 to min..max -return min +DIV_ROUND_CLOSEST ((max - min) * brightness, -AMDGPU_MAX_BL_LEVEL ); +// Rescale 0..max to min..max +return min +DIV_ROUND_CLOSEST_ULL ((u64)(max - min) * brightness, max); } static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
@@ -4719,8 +4733,8 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *capif (brightness < min)return 0 ; -// Rescale min..max to 0..255 -return DIV_ROUND_CLOSEST (AMDGPU_MAX_BL_LEVEL * (brightness - min), +// Rescale min..max to 0..max +return DIV_ROUND_CLOSEST_ULL ((u64 )max * (brightness - min), max - min); }
@@ -4870,11 +4884,10 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)drm_dbg (drm,"Backlight caps: min: %d, max: %d, ac %d, dc %d\n" , min, max, caps->ac_level, caps->dc_level); }else - props.brightness =AMDGPU_MAX_BL_LEVEL ; + props.brightness = props.max_brightness =AMDGPU_MAX_BL_LEVEL ;if (caps->data_points && !(amdgpu_dc_debug_mask &DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE ))drm_info (drm,"Using custom brightness curve\n" ); - props.max_brightness =AMDGPU_MAX_BL_LEVEL ; props.type =BACKLIGHT_RAW ; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 254/263 rust: completion: implement initial abstraction
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
commit 1b56e765bf8990f1f60e124926c11fc4ac63d752 upstream.
Implement a minimal abstraction for the completion synchronization primitive.
This initial abstraction only adds complete_all() and wait_for_completion(), since that is what is required for the subsequent Devres patch.
--- rust/bindings/bindings_helper.h | 1 rust/helpers/completion.c | 8 ++ rust/helpers/helpers.c | 1 rust/kernel/sync.rs | 2 rust/kernel/sync/completion.rs | 112 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 rust/helpers/completion.c create mode 100644 rust/kernel/sync/completion.rs
rust/bindings/bindings_helper.h +1 -0
@@ -10,6 +10,7 @@#include <linux/blk-mq.h> #include <linux/blk_types.h> #include <linux/blkdev.h> +#include <linux/completion.h> #include <linux/cpumask.h> #include <linux/cred.h> #include <linux/device/faux.h>
rust/helpers/completion.c new file +8 -0
@@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/completion.h> + +void rust_helper_init_completion (struct completion *x) +{ +init_completion (x); +}
rust/helpers/helpers.c +1 -0
@@ -11,6 +11,7 @@#include "bug.c" #include "build_assert.c" #include "build_bug.c" +#include "completion.c" #include "cpumask.c" #include "cred.c" #include "device.c"
rust/kernel/sync.rs +2 -0
@@ -10,6 +10,7 @@ use crate::types::Opaque;use pin_init;mod arc; +pub mod completion;mod condvar;pub mod lock;mod locked_by;
@@ -17,6 +18,7 @@ pub mod poll;pub mod rcu;pub use arc::{Arc ,ArcBorrow ,UniqueArc }; +pub use completion::Completion ;pub use condvar::{new_condvar,CondVar ,CondVarTimeoutResult };pub use lock::global::{global_lock,GlobalGuard ,GlobalLock ,GlobalLockBackend ,GlobalLockedBy };pub use lock::mutex::{new_mutex,Mutex ,MutexGuard };
rust/kernel/sync/completion.rs new file +112 -0
112 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 255/263 rust: revocable: indicate whether `data` has been revoked already
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
commit 4b76fafb20dd4a2becb94949d78e86bc88006509 upstream.
Return a boolean from Revocable::revoke() and Revocable::revoke_nosync() to indicate whether the data has been revoked already.
Return true if the data hasn't been revoked yet (i.e. this call revoked the data), false otherwise.
This is required by Devres in order to synchronize the completion of the revoke process.
--- rust/kernel/revocable.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
rust/kernel/revocable.rs +14 -4
@@ -126,8 +126,10 @@ impl<T> Revocable<T> {/// # Safety /// /// Callers must ensure that there are no more concurrent users of the revocable object. -unsafe fn revoke_internal <const SYNC :bool >(&self) { -if self.is_available.swap (false ,Ordering ::Relaxed ) { +unsafe fn revoke_internal <const SYNC :bool >(&self) ->bool { +let revoke = self.is_available.swap (false ,Ordering ::Relaxed ); + +if revoke {if SYNC {// SAFETY: Just an FFI call, there are no further requirements. unsafe { bindings::synchronize_rcu () };
@@ -137,6 +139,8 @@ impl<T> Revocable<T> {// `compare_exchange` above that takes `is_available` from `true` to `false`. unsafe {drop_in_place (self.data.get ()) }; } + + revoke }/// Revokes access to and drops the wrapped object.
@@ -144,10 +148,13 @@ impl<T> Revocable<T> {/// Access to the object is revoked immediately to new callers of [`Revocable::try_access`], /// expecting that there are no concurrent users of the object. /// +/// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked +/// already. +/// /// # Safety /// /// Callers must ensure that there are no more concurrent users of the revocable object. -pub unsafe fn revoke_nosync (&self) { +pub unsafe fn revoke_nosync (&self) ->bool {// SAFETY: By the safety requirement of this function, the caller ensures that nobody is // accessing the data anymore and hence we don't have to wait for the grace period to // finish.
@@ -161,7 +168,10 @@ impl<T> Revocable<T> {/// If there are concurrent users of the object (i.e., ones that called /// [`Revocable::try_access`] beforehand and still haven't dropped the returned guard), this /// function waits for the concurrent access to complete before dropping the wrapped object. -pub fn revoke (&self) { +/// +/// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked +/// already. +pub fn revoke (&self) ->bool {// SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to // finish. unsafe { self.revoke_internal ::<true >() }
Greg Kroah-Hartman
maintainerPATCH 256/263 rust: devres: fix race in Devres::drop()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
commit f744201c6159fc7323c40936fd079525f7063598 upstream.
In Devres::drop() we first remove the devres action and then drop the wrapped device resource.
The design goal is to give the owner of a Devres object control over when the device resource is dropped, but limit the overall scope to the corresponding device being bound to a driver.
However, there's a race that was introduced with commit 8ff656643d30 ("rust: devres: remove action in Devres::drop"), but also has been (partially) present from the initial version on.
In Devres::drop(), the devres action is removed successfully and subsequently the destructor of the wrapped device resource runs. However, there is no guarantee that the destructor of the wrapped device resource completes before the driver core is done unbinding the corresponding device.
If in Devres::drop(), the devres action can't be removed, it means that the devres callback has been executed already, or is still running concurrently. In case of the latter, either Devres::drop() wins revoking the Revocable or the devres callback wins revoking the Revocable. If Devres::drop() wins, we (again) have no guarantee that the destructor of the wrapped device resource completes before the driver core is done unbinding the corresponding device.
CPU0 CPU1
------------------------------------------------------------------------Devres::drop() { Devres::devres_callback() {
self.data.revoke() { this.data.revoke() {
is_available.swap() == true
is_available.swap == false
}
}
// [...]
// device fully unbound
drop_in_place() {
// release device resource
} }
}
Depending on the specific device resource, this can potentially lead to user-after-free bugs.
In order to fix this, implement the following logic.
In the devres callback, we're always good when we get to revoke the device resource ourselves, i.e. Revocable::revoke() returns true.
If Revocable::revoke() returns false, it means that Devres::drop(), concurrently, already drops the device resource and we have to wait for Devres::drop() to signal that it finished dropping the device resource.
Note that if we hit the case where we need to wait for the completion of Devres::drop() in the devres callback, it means that we're actually racing with a concurrent Devres::drop() call, which already started revoking the device resource for us. This is rather unlikely and means that the concurrent Devres::drop() already started doing our work and we just need to wait for it to complete it for us. Hence, there should not be any additional overhead from that.
(Actually, for now it's even better if Devres::drop() does the work for us, since it can bypass the synchronize_rcu() call implied by Revocable::revoke(), but this goes away anyways once I get to implement the split devres callback approach, which allows us to first flip the atomics of all registered Devres objects of a certain device, execute a single synchronize_rcu() and then drop all revocable objects.)
In Devres::drop() we try to revoke the device resource. If that is *not* successful, it means that the devres callback already did and we're good.
Otherwise, we try to remove the devres action, which, if successful, means that we're good, since the device resource has just been revoked by us *before* we removed the devres action successfully.
If the devres action could not be removed, it means that the devres callback must be running concurrently, hence we signal that the device resource has been revoked by us, using the completion.
This makes it safe to drop a Devres object from any task and at any point of time, which is one of the design goals.
--- rust/kernel/devres.rs | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-)
rust/kernel/devres.rs +29 -8
@@ -13,7 +13,7 @@ use crate::{ ffi::c_void, prelude::*, revocable::Revocable, - sync::Arc, + sync::{Arc, Completion}, types::ARef, };
@@ -25,13 +25,17 @@ struct DevresInner<T> { callback: unsafe extern "C" fn(*mut c_void),#[pin] data: Revocable<T>, +#[pin] + revoke: Completion, }/// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to /// manage their lifetime. /// /// [`Device`] bound resources should be freed when either the resource goes out of scope or the -/// [`Device`] is unbound respectively, depending on what happens first. +/// [`Device`] is unbound respectively, depending on what happens first. In any case, it is always +/// guaranteed that revoking the device resource is completed before the corresponding [`Device`] +/// is unbound. /// /// To achieve that [`Devres`] registers a devres callback on creation, which is called once the /// [`Device`] is unbound, revoking access to the encapsulated resource (see also [`Revocable`]).
@@ -105,6 +109,7 @@ impl<T> DevresInner<T> { dev: dev.into(), callback: Self::devres_callback, data <- Revocable::new(data), + revoke <- Completion::new(), }), flags, )?;
@@ -133,26 +138,28 @@ impl<T> DevresInner<T> { selfas _ } -fn remove_action (this: &Arc <Self >) { +fn remove_action (this: &Arc <Self >) ->bool {// SAFETY: // - `self.inner.dev` is a valid `Device`, // - the `action` and `data` pointers are the exact same ones as given to devm_add_action() // previously, // - `self` is always valid, even if the action has been released already. -let ret =unsafe { +let success =unsafe { bindings::devm_remove_action_nowarn ( this.dev.as_raw (),Some (this.callback), this.as_ptr ()as _ , ) - }; + } ==0 ; -if ret ==0 { +if success {// SAFETY: We leaked an `Arc` reference to devm_add_action() in `DevresInner::new`; if // devm_remove_action_nowarn() was successful we can (and have to) claim back ownership // of this reference. let _ =unsafe {Arc ::from_raw (this.as_ptr ()) }; } + + success }#[allow(clippy::missing_safety_doc)]
@@ -164,7 +171,12 @@ impl<T> DevresInner<T> {// `DevresInner::new`. let inner =unsafe {Arc ::from_raw (ptr) }; - inner.data.revoke (); +if !inner.data.revoke () { +// If `revoke()` returns false, it means that `Devres::drop` already started revoking +// `inner.data` for us. Hence we have to wait until `Devres::drop()` signals that it +// completed revoking `inner.data`. + inner.revoke.wait_for_completion (); + } } }
@@ -196,6 +208,15 @@ impl<T> Deref for Devres<T> {impl <T >Drop for Devres <T > {fn drop (&mut self) { -DevresInner ::remove_action (&self.0 ); +// SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data +// anymore, hence it is safe not to wait for the grace period to finish. +if unsafe { self.revoke_nosync () } { +// We revoked `self.0.data` before the devres action did, hence try to remove it. +if !DevresInner ::remove_action (&self.0 ) { +// We could not remove the devres action, which means that it now runs concurrently, +// hence signal that `self.0.data` has been revoked successfully. + self.0 .revoke.complete_all (); + } + } } }
Greg Kroah-Hartman
maintainerPATCH 257/263 rust: devres: do not dereference to the internal Revocable
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
commit 20c96ed278e362ae4e324ed7d8c69fb48c508d3c upstream.
We can't expose direct access to the internal Revocable, since this allows users to directly revoke the internal Revocable without Devres having the chance to synchronize with the devres callback -- we have to guarantee that the internal Revocable has been fully revoked before the device is fully unbound.
Hence, remove the corresponding Deref implementation and, instead, provide indirect accessors for the internal Revocable.
Note that we can still support Devres::revoke() by implementing the required synchronization (which would be almost identical to the synchronization in Devres::drop()).
--- rust/kernel/devres.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
rust/kernel/devres.rs +10 -10
@@ -12,13 +12,11 @@ use crate::{ error::{Error, Result}, ffi::c_void, prelude::*, - revocable::Revocable, - sync::{Arc, Completion}, + revocable::{Revocable, RevocableGuard}, + sync::{rcu, Arc, Completion}, types::ARef, }; -use core::ops::Deref ; -#[pin_data] struct DevresInner <T > { dev:ARef <Device >,
@@ -196,13 +194,15 @@ impl<T> Devres<T> {Ok (()) } -} -impl <T >Deref for Devres <T > { -type Target =Revocable <T >; +/// [`Devres`] accessor for [`Revocable::try_access`]. +pub fn try_access (&self) ->Option <RevocableGuard <'_,T >> { + self.0 .data.try_access () + } -fn deref (&self) -> &Self ::Target { - &self.0 .data +/// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. +pub fn try_access_with_guard <'a>(&'a self, guard: &'a rcu::Guard ) ->Option <&'aT > { + self.0 .data.try_access_with_guard (guard) } }
@@ -210,7 +210,7 @@ impl<T> Drop for Devres<T> {fn drop (&mut self) {// SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data // anymore, hence it is safe not to wait for the grace period to finish. -if unsafe { self.revoke_nosync () } { +if unsafe { self.0 .data.revoke_nosync () } {// We revoked `self.0.data` before the devres action did, hence try to remove it. if !DevresInner ::remove_action (&self.0 ) {// We could not remove the devres action, which means that it now runs concurrently,
Greg Kroah-Hartman
maintainerPATCH 258/263 x86/fpu: Refactor xfeature bitmask update code for sigframe XSAVE
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chang S. Bae <[email protected]>
commit 64e54461ab6e8524a8de4e63b7d1a3e4481b5cf3 upstream.
Currently, saving register states in the signal frame, the legacy feature bits are always set in xregs_state->header->xfeatures. This code sequence can be generalized for reuse in similar cases.
Refactor the logic to ensure a consistent approach across similar usages.
--- arch/x86/kernel/fpu/signal.c | 11 +---------- arch/x86/kernel/fpu/xstate.h | 13 +++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-)
arch/x86/kernel/fpu/signal.c +1 -10
@@ -114,7 +114,6 @@ static inline bool save_xstate_epilog(vo {struct xregs_state __user *x = buf;struct _fpx_sw_bytes sw_bytes = {}; -u32 xfeatures;int err;/* Setup the bytes not touched by the [f]xsave and reserved for SW. */
@@ -128,12 +127,6 @@ static inline bool save_xstate_epilog(vo (__u32 __user *)(buf + fpstate->user_size));/* -* Read the xfeatures which we copied (directly from the cpu or -* from the state in task struct) to the user buffers. -*/ - err |=__get_user (xfeatures, (__u32 __user *)&x->header.xfeatures); - -/* * For legacy compatible, we always set FP/SSE bits in the bit * vector while saving the state to the user context. This will * enable us capturing any changes(during sigreturn) to
@@ -144,9 +137,7 @@ static inline bool save_xstate_epilog(vo* header as well as change any contents in the memory layout. * xrestore as part of sigreturn will capture all the changes. */ - xfeatures |=XFEATURE_MASK_FPSSE ; - - err |=__put_user (xfeatures, (__u32 __user *)&x->header.xfeatures); + err |=set_xfeature_in_sigframe (x,XFEATURE_MASK_FPSSE );return !err; }
arch/x86/kernel/fpu/xstate.h +13 -0
@@ -69,6 +69,19 @@ static inline u64 xfeatures_mask_indepenreturn fpu_kernel_cfg.independent_features; } +static inline int set_xfeature_in_sigframe (struct xregs_state __user *xbuf,u64 mask) +{ +u64 xfeatures; +int err; + +/* Read the xfeatures value already saved in the user buffer */ + err =__get_user (xfeatures, &xbuf->header.xfeatures); + xfeatures |= mask; + err |=__put_user (xfeatures, &xbuf->header.xfeatures); + +return err; +} +/* * Update the value of PKRU register that was already pushed onto the signal frame. */
Greg Kroah-Hartman
maintainerPATCH 259/263 x86/pkeys: Simplify PKRU update in signal frame
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chang S. Bae <[email protected]>
commit d1e420772cd1eb0afe5858619c73ce36f3e781a1 upstream.
The signal delivery logic was modified to always set the PKRU bit in xregs_state->header->xfeatures by this commit:
ae6012d72fa6 ("x86/pkeys: Ensure updated PKRU value is XRSTOR'd")
However, the change derives the bitmask value using XGETBV(1), rather than simply updating the buffer that already holds the value. Thus, this approach induces an unnecessary dependency on XGETBV1 for PKRU handling.
Eliminate the dependency by using the established helper function. Subsequently, remove the now-unused 'mask' argument.
--- arch/x86/kernel/fpu/xstate.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/x86/kernel/fpu/xstate.h +3 -6
@@ -85,18 +85,15 @@ static inline int set_xfeature_in_sigfra/* * Update the value of PKRU register that was already pushed onto the signal frame. */ -static inline int update_pkru_in_sigframe (struct xregs_state __user *buf,u64 mask,u32 pkru) +static inline int update_pkru_in_sigframe (struct xregs_state __user *buf,u32 pkru) { -u64 xstate_bv;int err;if (unlikely (!cpu_feature_enabled (X86_FEATURE_OSPKE )))return 0 ;/* Mark PKRU as in-use so that it is restored correctly. */ - xstate_bv = (mask &xfeatures_in_use ()) |XFEATURE_MASK_PKRU ; - - err =__put_user (xstate_bv, &buf->header.xfeatures); + err =set_xfeature_in_sigframe (buf,XFEATURE_MASK_PKRU );if (err)return err;
@@ -320,7 +317,7 @@ static inline int xsave_to_user_sigframeclac ();if (!err) - err =update_pkru_in_sigframe (buf, mask, pkru); + err =update_pkru_in_sigframe (buf, pkru);return err; }
Greg Kroah-Hartman
maintainerPATCH 260/263 s390/ptrace: Fix pointer dereferencing in regs_get_kernel_stack_nth()
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
commit 7f8073cfb04a97842fe891ca50dad60afd1e3121 upstream.
The recent change which added READ_ONCE_NOCHECK() to read the nth entry from the kernel stack incorrectly dropped dereferencing of the stack pointer in order to read the requested entry.
In result the address of the entry is returned instead of its content.
Dereference the pointer again to fix this.
--- arch/s390/kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/ptrace.c +1 -1
@@ -1574,5 +1574,5 @@ unsigned long regs_get_kernel_stack_nth( addr =kernel_stack_pointer (regs) + n *sizeof (long );if (!regs_within_kernel_stack (regs, addr))return 0 ; -return READ_ONCE_NOCHECK (addr); +return READ_ONCE_NOCHECK (*(unsigned long *)addr); }
Greg Kroah-Hartman
maintainerPATCH 261/263 io_uring/kbuf: flag partial buffer mappings
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
Commit 178b8ff66ff827c41b4fa105e9aabb99a0b5c537 upstream.
A previous commit aborted mapping more for a non-incremental ring for bundle peeking, but depending on where in the process this peeking happened, it would not necessarily prevent a retry by the user. That can create gaps in the received/read data.
Add struct buf_sel_arg->partial_map, which can pass this information back. The networking side can then map that to internal state and use it to gate retry as well.
Since this necessitates a new flag, change io_sr_msg->retry to a retry_flags member, and store both the retry and partial map condition in there.
--- io_uring/kbuf.c | 1 + io_uring/kbuf.h | 1 + io_uring/net.c | 23 +++++++++++++++-------- 3 files changed, 17 insertions(+), 8 deletions(-)
io_uring/kbuf.c +1 -0
@@ -271,6 +271,7 @@ static int io_ring_buffers_peek(struct iif (len > arg->max_len) { len = arg->max_len;if (!(bl->flags &IOBL_INC )) { + arg->partial_map =1 ;if (iov != arg->iovs)break ; buf->len = len;
io_uring/kbuf.h +1 -0
@@ -55,6 +55,7 @@ struct buf_sel_arg {size_t max_len;unsigned short nr_iovs;unsigned short mode; +unsigned short partial_map; }; void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
io_uring/net.c +15 -8
@@ -76,12 +76,17 @@ struct io_sr_msg {u16 flags;/* initialised and used only by !msg send variants */ u16 buf_group; -bool retry; +unsigned short retry_flags;void __user *msg_control;/* used only for send zerocopy */ struct io_kiocb *notif; }; +enum sr_retry_flags { +IO_SR_MSG_RETRY =1 , +IO_SR_MSG_PARTIAL_MAP =2 , +}; +/* * Number of times we'll try and do receives if there's more data. If we * exceed this limit, then add us to the back of the queue and retry from
@@ -188,7 +193,7 @@ static inline void io_mshot_prep_retry(s req->flags &= ~REQ_F_BL_EMPTY ; sr->done_io =0 ; - sr->retry = false; + sr->retry_flags =0 ; sr->len =0 ;/* get from the provided buffer */ req->buf_index = sr->buf_group; }
@@ -401,7 +406,7 @@ int io_sendmsg_prep(struct io_kiocb *req struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); sr->done_io =0 ; - sr->retry = false; + sr->retry_flags =0 ; sr->len =READ_ONCE (sqe->len); sr->flags =READ_ONCE (sqe->ioprio);if (sr->flags & ~SENDMSG_FLAGS )
@@ -759,7 +764,7 @@ int io_recvmsg_prep(struct io_kiocb *req struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); sr->done_io =0 ; - sr->retry = false; + sr->retry_flags =0 ;if (unlikely (sqe->file_index || sqe->addr2))return -EINVAL ;
@@ -831,7 +836,7 @@ static inline bool io_recv_finish(struct cflags |=io_put_kbufs (req, this_ret,io_bundle_nbufs (kmsg, this_ret), issue_flags); -if (sr->retry) +if (sr->retry_flags &IO_SR_MSG_RETRY ) cflags = req->cqe.flags | (cflags &CQE_F_MASK );/* bundle with no more immediate buffers, we're done */ if (req->flags &REQ_F_BL_EMPTY )
@@ -840,12 +845,12 @@ static inline bool io_recv_finish(struct* If more is available AND it was a full transfer, retry and * append to this one */ -if (!sr->retry && kmsg->msg.msg_inq >1 && this_ret >0 && +if (!sr->retry_flags && kmsg->msg.msg_inq >1 && this_ret >0 && !iov_iter_count (&kmsg->msg.msg_iter)) { req->cqe.flags = cflags & ~CQE_F_MASK ; sr->len = kmsg->msg.msg_inq; sr->done_io += this_ret; - sr->retry = true; + sr->retry_flags |=IO_SR_MSG_RETRY ;return false; } }else {
@@ -1089,6 +1094,8 @@ static int io_recv_buf_select(struct io_ kmsg->vec.iovec = arg.iovs; req->flags |=REQ_F_NEED_CLEANUP ; } +if (arg.partial_map) + sr->retry_flags |=IO_SR_MSG_PARTIAL_MAP ;/* special case 1 vec, can be a fast path */ if (ret ==1 ) {
@@ -1285,7 +1292,7 @@ int io_send_zc_prep(struct io_kiocb *reqint ret; zc->done_io =0 ; - zc->retry = false; + zc->retry_flags =0 ;if (unlikely (READ_ONCE (sqe->__pad2[0 ]) ||READ_ONCE (sqe->addr3)))return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 262/263 io_uring: gate REQ_F_ISREG on !S_ANON_INODE as well
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
commit 6f11adcc6f36ffd8f33dbdf5f5ce073368975bc3 upstream.
io_uring marks a request as dealing with a regular file on S_ISREG. This drives things like retries on short reads or writes, which is generally not expected on a regular file (or bdev). Applications tend to not expect that, so io_uring tries hard to ensure it doesn't deliver short IO on regular files.
However, a recent commit added S_IFREG to anonymous inodes. When io_uring is used to read from various things that are backed by anon inodes, like eventfd, timerfd, etc, then it'll now all of a sudden wait for more data when rather than deliver what was read or written in a single operation. This breaks applications that issue reads on anon inodes, if they ask for more data than a single read delivers.
Add a check for !S_ANON_INODE as well before setting REQ_F_ISREG to prevent that.
--- io_uring/io_uring.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
io_uring/io_uring.c +2 -1
@@ -1647,11 +1647,12 @@ static void io_iopoll_req_issued(structio_req_flags_t io_file_get_flags (struct file *file) { +struct inode *inode =file_inode (file);io_req_flags_t res =0 ;BUILD_BUG_ON (REQ_F_ISREG_BIT !=REQ_F_SUPPORT_NOWAIT_BIT +1 ); -if (S_ISREG (file_inode (file)->i_mode)) +if (S_ISREG (inode->i_mode) && !(inode->i_flags &S_ANON_INODE )) res |=REQ_F_ISREG ;if ((file->f_flags &O_NONBLOCK ) || (file->f_mode &FMODE_NOWAIT )) res |=REQ_F_SUPPORT_NOWAIT ;
Greg Kroah-Hartman
maintainerPATCH 263/263 riscv: uaccess: Only restore the CSR_STATUS SUM bit
In reply to Greg Kroah-Hartman6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cyril Bur <[email protected]>
commit 265d6aba165c500389c80d394ac247460c443ef5 upstream.
During switch to csrs will OR the value of the register into the corresponding csr. In this case we're only interested in restoring the SUM bit not the entire register.
--- arch/riscv/include/asm/processor.h | 2 +- arch/riscv/kernel/asm-offsets.c | 6 +++--- arch/riscv/kernel/entry.S | 9 +++++---- 3 files changed, 9 insertions(+), 8 deletions(-)
arch/riscv/include/asm/processor.h +1 -1
@@ -103,7 +103,7 @@ struct thread_struct {struct __riscv_d_ext_state fstate;unsigned long bad_cause;unsigned long envcfg; -unsigned long status; +unsigned long sum;u32 riscv_v_flags;u32 vstate_ctrl;struct __riscv_v_ext_state vstate;
arch/riscv/kernel/asm-offsets.c +3 -3
@@ -34,7 +34,7 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S9 , task_struct, thread.s[9 ]);OFFSET (TASK_THREAD_S10 , task_struct, thread.s[10 ]);OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]); -OFFSET (TASK_THREAD_STATUS , task_struct, thread.status); +OFFSET (TASK_THREAD_SUM , task_struct, thread.sum);OFFSET (TASK_TI_CPU , task_struct, thread_info.cpu);OFFSET (TASK_TI_PREEMPT_COUNT , task_struct, thread_info.preempt_count);
@@ -347,8 +347,8 @@ void asm_offsets(void) offsetof(struct task_struct, thread.s[11]) - offsetof(struct task_struct, thread.ra) ); -DEFINE (TASK_THREAD_STATUS_RA , - offsetof(struct task_struct, thread.status) +DEFINE (TASK_THREAD_SUM_RA , + offsetof(struct task_struct, thread.sum) - offsetof(struct task_struct, thread.ra) );
arch/riscv/kernel/entry.S +5 -4
@@ -399,14 +399,15 @@ SYM_FUNC_START(__switch_to) REG_S s11, TASK_THREAD_S11_RA(a3) /* save the user space access flag */ - li s0, SR_SUM - csrr s1, CSR_STATUS - REG_S s1, TASK_THREAD_STATUS_RA(a3) + csrr s0, CSR_STATUS + REG_S s0, TASK_THREAD_SUM_RA(a3) /* Save the kernel shadow call stack pointer */ scs_save_current /* Restore context from next->thread */ - REG_L s0, TASK_THREAD_STATUS_RA(a4) + REG_L s0, TASK_THREAD_SUM_RA(a4) + li s1, SR_SUM + and s0, s0, s1 csrs CSR_STATUS, s0 REG_L ra, TASK_THREAD_RA_RA(a4) REG_L sp, TASK_THREAD_SP_RA(a4)
Hi
no regressions here on x86_64 (RKL, Intel 11th Gen. CPU)
Thanks
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Quoted 7 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
Tested on a ThinkPad E14 Gen 3 with a AMD Ryzen 5 5500U CPU and on a Framework Desktop.
The kernel, bpf tool, and perf tool builds fine for v6.15.5-rc1 on x86 and arm64 Azure VM.
Kernel binary size for x86 build:
text data bss dec hex filename 31999332 14279706 6250496 52529534 321897e vmlinux
Kernel binary size for arm64 build:
text data bss dec hex filename 37335764 15435073 1038480 53809317 33510a5 vmlinux
Thanks,
Hardik
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
[2025-07-03 16:38] Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Compiles fine for x86_64 with GCC 15.1.1, and runs fine on various physical Intel machines (Ivy Bridge, Haswell, Kaby Lake, Coffee Lake) and in a Skylake VM.
Regards
Pascal
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.thanks,
greg k-h
Build-tested on all Alpine architectures and boot-tested on x86_64. Thanks!
Greg Kroah-Hartman
maintainerQuoted 15 lines · Achill Gilgenast
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.
Quoted 9 lines
Quoted 3 lines
thanks,
greg k-h
Tested-by Achill Gilgenast <[email protected]>Build-tested on all Alpine architectures and boot-tested on
x86_64. Thanks!
Thanks for testing and letting me know,
greg k-h
Hi Greg
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.15.5 release. There are 263 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 05 Jul 2025 14:39:10 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.15.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.15.y
and the diffstat can be found below.thanks,
greg k-h
6.15.5-rc1 tested.
Build successfully completed.
Boot successfully completed.
No dmesg regressions.
Video output normal.
Sound output normal.
Lenovo ThinkPad X1 Carbon Gen10(Intel i7-1260P(x86_64) arch linux)
[ 0.000000] Linux version 6.15.5-rc1rv-gd5e6f0c9ca48
(takeshi@ThinkPadX1Gen10J0764) (gcc (GCC) 15.1.1 20250425, GNU ld (GNU Binutils) 2.44.0) #1 SMP PREEMPT_DYNAMIC Fri Jul 4 18:24:44 JST 2025
Thanks