--- /dev/null
+From 4ba89f611b0bec08769d7a16521ed9a90c3a03c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 18:09:14 +0800
+Subject: bpf: Fix wrong copied_seq calculation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jiayuan Chen <mrpre@163.com>
+
+[ Upstream commit 36b62df5683c315ba58c950f1a9c771c796c30ec ]
+
+'sk->copied_seq' was updated in the tcp_eat_skb() function when the action
+of a BPF program was SK_REDIRECT. For other actions, like SK_PASS, the
+update logic for 'sk->copied_seq' was moved to tcp_bpf_recvmsg_parser()
+to ensure the accuracy of the 'fionread' feature.
+
+It works for a single stream_verdict scenario, as it also modified
+sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb
+to remove updating 'sk->copied_seq'.
+
+However, for programs where both stream_parser and stream_verdict are
+active (strparser purpose), tcp_read_sock() was used instead of
+tcp_read_skb() (sk_data_ready->strp_data_ready->tcp_read_sock).
+tcp_read_sock() now still updates 'sk->copied_seq', leading to duplicate
+updates.
+
+In summary, for strparser + SK_PASS, copied_seq is redundantly calculated
+in both tcp_read_sock() and tcp_bpf_recvmsg_parser().
+
+The issue causes incorrect copied_seq calculations, which prevent
+correct data reads from the recv() interface in user-land.
+
+We do not want to add new proto_ops to implement a new version of
+tcp_read_sock, as this would introduce code complexity [1].
+
+We could have added noack and copied_seq to desc, and then called
+ops->read_sock. However, unfortunately, other modules didn’t fully
+initialize desc to zero. So, for now, we are directly calling
+tcp_read_sock_noack() in tcp_bpf.c.
+
+[1]: https://lore.kernel.org/bpf/20241218053408.437295-1-mrpre@163.com
+
+Fixes: e5c6de5fa025 ("bpf, sockmap: Incorrectly handling copied_seq")
+Suggested-by: Jakub Sitnicki <jakub@cloudflare.com>
+Signed-off-by: Jiayuan Chen <mrpre@163.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://patch.msgid.link/20250122100917.49845-3-mrpre@163.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/skmsg.h | 2 ++
+ include/net/tcp.h | 8 ++++++++
+ net/core/skmsg.c | 7 +++++++
+ net/ipv4/tcp.c | 29 ++++++++++++++++++++++++-----
+ net/ipv4/tcp_bpf.c | 36 ++++++++++++++++++++++++++++++++++++
+ 5 files changed, 77 insertions(+), 5 deletions(-)
+
+diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
+index 6ccfd9236387c..32bbebf5b71e3 100644
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -87,6 +87,8 @@ struct sk_psock {
+ struct sk_psock_progs progs;
+ #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
+ struct strparser strp;
++ u32 copied_seq;
++ u32 ingress_bytes;
+ #endif
+ struct sk_buff_head ingress_skb;
+ struct list_head ingress_msg;
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 14a00cdd31f42..83e0362e3b721 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -700,6 +700,9 @@ void tcp_get_info(struct sock *, struct tcp_info *);
+ /* Read 'sendfile()'-style from a TCP socket */
+ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor);
++int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor, bool noack,
++ u32 *copied_seq);
+ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
+ struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off);
+ void tcp_read_done(struct sock *sk, size_t len);
+@@ -2351,6 +2354,11 @@ struct sk_psock;
+ struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock);
+ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
+ void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
++#ifdef CONFIG_BPF_STREAM_PARSER
++struct strparser;
++int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor);
++#endif /* CONFIG_BPF_STREAM_PARSER */
+ #endif /* CONFIG_BPF_SYSCALL */
+
+ #ifdef CONFIG_INET
+diff --git a/net/core/skmsg.c b/net/core/skmsg.c
+index 65764952bc681..5a790cd1121b1 100644
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -547,6 +547,9 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
+ return num_sge;
+ }
+
++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
++ psock->ingress_bytes += len;
++#endif
+ copied = len;
+ msg->sg.start = 0;
+ msg->sg.size = copied;
+@@ -1140,6 +1143,10 @@ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
+ if (!ret)
+ sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED);
+
++ if (sk_is_tcp(sk)) {
++ psock->strp.cb.read_sock = tcp_bpf_strp_read_sock;
++ psock->copied_seq = tcp_sk(sk)->copied_seq;
++ }
+ return ret;
+ }
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index e27a9a9bb1623..7d591a0cf0c70 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1699,12 +1699,13 @@ EXPORT_SYMBOL(tcp_recv_skb);
+ * or for 'peeking' the socket using this routine
+ * (although both would be easy to implement).
+ */
+-int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+- sk_read_actor_t recv_actor)
++static int __tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor, bool noack,
++ u32 *copied_seq)
+ {
+ struct sk_buff *skb;
+ struct tcp_sock *tp = tcp_sk(sk);
+- u32 seq = tp->copied_seq;
++ u32 seq = *copied_seq;
+ u32 offset;
+ int copied = 0;
+
+@@ -1758,9 +1759,12 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ tcp_eat_recv_skb(sk, skb);
+ if (!desc->count)
+ break;
+- WRITE_ONCE(tp->copied_seq, seq);
++ WRITE_ONCE(*copied_seq, seq);
+ }
+- WRITE_ONCE(tp->copied_seq, seq);
++ WRITE_ONCE(*copied_seq, seq);
++
++ if (noack)
++ goto out;
+
+ tcp_rcv_space_adjust(sk);
+
+@@ -1769,10 +1773,25 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ tcp_recv_skb(sk, seq, &offset);
+ tcp_cleanup_rbuf(sk, copied);
+ }
++out:
+ return copied;
+ }
++
++int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor)
++{
++ return __tcp_read_sock(sk, desc, recv_actor, false,
++ &tcp_sk(sk)->copied_seq);
++}
+ EXPORT_SYMBOL(tcp_read_sock);
+
++int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor, bool noack,
++ u32 *copied_seq)
++{
++ return __tcp_read_sock(sk, desc, recv_actor, noack, copied_seq);
++}
++
+ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
+ {
+ struct sk_buff *skb;
+diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
+index a8db010e9e611..bf10fa3c37b76 100644
+--- a/net/ipv4/tcp_bpf.c
++++ b/net/ipv4/tcp_bpf.c
+@@ -691,6 +691,42 @@ static int tcp_bpf_assert_proto_ops(struct proto *ops)
+ ops->sendpage == tcp_sendpage ? 0 : -ENOTSUPP;
+ }
+
++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
++int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor)
++{
++ struct sock *sk = strp->sk;
++ struct sk_psock *psock;
++ struct tcp_sock *tp;
++ int copied = 0;
++
++ tp = tcp_sk(sk);
++ rcu_read_lock();
++ psock = sk_psock(sk);
++ if (WARN_ON_ONCE(!psock)) {
++ desc->error = -EINVAL;
++ goto out;
++ }
++
++ psock->ingress_bytes = 0;
++ copied = tcp_read_sock_noack(sk, desc, recv_actor, true,
++ &psock->copied_seq);
++ if (copied < 0)
++ goto out;
++ /* recv_actor may redirect skb to another socket (SK_REDIRECT) or
++ * just put skb into ingress queue of current socket (SK_PASS).
++ * For SK_REDIRECT, we need to ack the frame immediately but for
++ * SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser().
++ */
++ tp->copied_seq = psock->copied_seq - psock->ingress_bytes;
++ tcp_rcv_space_adjust(sk);
++ __tcp_cleanup_rbuf(sk, copied - psock->ingress_bytes);
++out:
++ rcu_read_unlock();
++ return copied;
++}
++#endif /* CONFIG_BPF_STREAM_PARSER */
++
+ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
+ {
+ int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
+--
+2.39.5
+
--- /dev/null
+From b4441f8c3e8c14e3028a04061157e310b925cbdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 23:22:35 -0800
+Subject: bpf: skip non exist keys in generic_map_lookup_batch
+
+From: Yan Zhai <yan@cloudflare.com>
+
+[ Upstream commit 5644c6b50ffee0a56c1e01430a8c88e34decb120 ]
+
+The generic_map_lookup_batch currently returns EINTR if it fails with
+ENOENT and retries several times on bpf_map_copy_value. The next batch
+would start from the same location, presuming it's a transient issue.
+This is incorrect if a map can actually have "holes", i.e.
+"get_next_key" can return a key that does not point to a valid value. At
+least the array of maps type may contain such holes legitly. Right now
+these holes show up, generic batch lookup cannot proceed any more. It
+will always fail with EINTR errors.
+
+Rather, do not retry in generic_map_lookup_batch. If it finds a non
+existing element, skip to the next key. This simple solution comes with
+a price that transient errors may not be recovered, and the iteration
+might cycle back to the first key under parallel deletion. For example,
+Hou Tao <houtao@huaweicloud.com> pointed out a following scenario:
+
+For LPM trie map:
+(1) ->map_get_next_key(map, prev_key, key) returns a valid key
+
+(2) bpf_map_copy_value() return -ENOMENT
+It means the key must be deleted concurrently.
+
+(3) goto next_key
+It swaps the prev_key and key
+
+(4) ->map_get_next_key(map, prev_key, key) again
+prev_key points to a non-existing key, for LPM trie it will treat just
+like prev_key=NULL case, the returned key will be duplicated.
+
+With the retry logic, the iteration can continue to the key next to the
+deleted one. But if we directly skip to the next key, the iteration loop
+would restart from the first key for the lpm_trie type.
+
+However, not all races may be recovered. For example, if current key is
+deleted after instead of before bpf_map_copy_value, or if the prev_key
+also gets deleted, then the loop will still restart from the first key
+for lpm_tire anyway. For generic lookup it might be better to stay
+simple, i.e. just skip to the next key. To guarantee that the output
+keys are not duplicated, it is better to implement map type specific
+batch operations, which can properly lock the trie and synchronize with
+concurrent mutators.
+
+Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
+Closes: https://lore.kernel.org/bpf/Z6JXtA1M5jAZx8xD@debian.debian/
+Signed-off-by: Yan Zhai <yan@cloudflare.com>
+Acked-by: Hou Tao <houtao1@huawei.com>
+Link: https://lore.kernel.org/r/85618439eea75930630685c467ccefeac0942e2b.1739171594.git.yan@cloudflare.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/syscall.c | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index cfb361f4b00ea..7a4004f09bae7 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -1713,8 +1713,6 @@ int generic_map_update_batch(struct bpf_map *map,
+ return err;
+ }
+
+-#define MAP_LOOKUP_RETRIES 3
+-
+ int generic_map_lookup_batch(struct bpf_map *map,
+ const union bpf_attr *attr,
+ union bpf_attr __user *uattr)
+@@ -1724,8 +1722,8 @@ int generic_map_lookup_batch(struct bpf_map *map,
+ void __user *values = u64_to_user_ptr(attr->batch.values);
+ void __user *keys = u64_to_user_ptr(attr->batch.keys);
+ void *buf, *buf_prevkey, *prev_key, *key, *value;
+- int err, retry = MAP_LOOKUP_RETRIES;
+ u32 value_size, cp, max_count;
++ int err;
+
+ if (attr->batch.elem_flags & ~BPF_F_LOCK)
+ return -EINVAL;
+@@ -1771,14 +1769,8 @@ int generic_map_lookup_batch(struct bpf_map *map,
+ err = bpf_map_copy_value(map, key, value,
+ attr->batch.elem_flags);
+
+- if (err == -ENOENT) {
+- if (retry) {
+- retry--;
+- continue;
+- }
+- err = -EINTR;
+- break;
+- }
++ if (err == -ENOENT)
++ goto next_key;
+
+ if (err)
+ goto free_buf;
+@@ -1793,12 +1785,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
+ goto free_buf;
+ }
+
++ cp++;
++next_key:
+ if (!prev_key)
+ prev_key = buf_prevkey;
+
+ swap(prev_key, key);
+- retry = MAP_LOOKUP_RETRIES;
+- cp++;
+ cond_resched();
+ }
+
+--
+2.39.5
+
--- /dev/null
+From c059a561f85a2ee9662e56feeaf8bc3484520f14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 00:06:42 +0900
+Subject: bpf, test_run: Fix use-after-free issue in eth_skb_pkt_type()
+
+From: Shigeru Yoshida <syoshida@redhat.com>
+
+[ Upstream commit 6b3d638ca897e099fa99bd6d02189d3176f80a47 ]
+
+KMSAN reported a use-after-free issue in eth_skb_pkt_type()[1]. The
+cause of the issue was that eth_skb_pkt_type() accessed skb's data
+that didn't contain an Ethernet header. This occurs when
+bpf_prog_test_run_xdp() passes an invalid value as the user_data
+argument to bpf_test_init().
+
+Fix this by returning an error when user_data is less than ETH_HLEN in
+bpf_test_init(). Additionally, remove the check for "if (user_size >
+size)" as it is unnecessary.
+
+[1]
+BUG: KMSAN: use-after-free in eth_skb_pkt_type include/linux/etherdevice.h:627 [inline]
+BUG: KMSAN: use-after-free in eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165
+ eth_skb_pkt_type include/linux/etherdevice.h:627 [inline]
+ eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165
+ __xdp_build_skb_from_frame+0x5a8/0xa50 net/core/xdp.c:635
+ xdp_recv_frames net/bpf/test_run.c:272 [inline]
+ xdp_test_run_batch net/bpf/test_run.c:361 [inline]
+ bpf_test_run_xdp_live+0x2954/0x3330 net/bpf/test_run.c:390
+ bpf_prog_test_run_xdp+0x148e/0x1b10 net/bpf/test_run.c:1318
+ bpf_prog_test_run+0x5b7/0xa30 kernel/bpf/syscall.c:4371
+ __sys_bpf+0x6a6/0xe20 kernel/bpf/syscall.c:5777
+ __do_sys_bpf kernel/bpf/syscall.c:5866 [inline]
+ __se_sys_bpf kernel/bpf/syscall.c:5864 [inline]
+ __x64_sys_bpf+0xa4/0xf0 kernel/bpf/syscall.c:5864
+ x64_sys_call+0x2ea0/0x3d90 arch/x86/include/generated/asm/syscalls_64.h:322
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xd9/0x1d0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Uninit was created at:
+ free_pages_prepare mm/page_alloc.c:1056 [inline]
+ free_unref_page+0x156/0x1320 mm/page_alloc.c:2657
+ __free_pages+0xa3/0x1b0 mm/page_alloc.c:4838
+ bpf_ringbuf_free kernel/bpf/ringbuf.c:226 [inline]
+ ringbuf_map_free+0xff/0x1e0 kernel/bpf/ringbuf.c:235
+ bpf_map_free kernel/bpf/syscall.c:838 [inline]
+ bpf_map_free_deferred+0x17c/0x310 kernel/bpf/syscall.c:862
+ process_one_work kernel/workqueue.c:3229 [inline]
+ process_scheduled_works+0xa2b/0x1b60 kernel/workqueue.c:3310
+ worker_thread+0xedf/0x1550 kernel/workqueue.c:3391
+ kthread+0x535/0x6b0 kernel/kthread.c:389
+ ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+CPU: 1 UID: 0 PID: 17276 Comm: syz.1.16450 Not tainted 6.12.0-05490-g9bb88c659673 #8
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014
+
+Fixes: be3d72a2896c ("bpf: move user_size out of bpf_test_init")
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Suggested-by: Martin KaFai Lau <martin.lau@linux.dev>
+Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://patch.msgid.link/20250121150643.671650-1-syoshida@redhat.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bpf/test_run.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
+index 64be562f0fe32..77b386b76d463 100644
+--- a/net/bpf/test_run.c
++++ b/net/bpf/test_run.c
+@@ -768,12 +768,9 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,
+ void __user *data_in = u64_to_user_ptr(kattr->test.data_in);
+ void *data;
+
+- if (size < ETH_HLEN || size > PAGE_SIZE - headroom - tailroom)
++ if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom)
+ return ERR_PTR(-EINVAL);
+
+- if (user_size > size)
+- return ERR_PTR(-EMSGSIZE);
+-
+ size = SKB_DATA_ALIGN(size);
+ data = kzalloc(size + headroom + tailroom, GFP_USER);
+ if (!data)
+--
+2.39.5
+
--- /dev/null
+From 6fdd147fbbeaba75054c07587f90649ff8a189a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Feb 2025 00:19:32 +0100
+Subject: drm/msm/dpu: Don't leak bits_per_component into random DSC_ENC fields
+
+From: Marijn Suijten <marijn.suijten@somainline.org>
+
+[ Upstream commit 144429831f447223253a0e4376489f84ff37d1a7 ]
+
+What used to be the input_10_bits boolean - feeding into the lowest
+bit of DSC_ENC - on MSM downstream turned into an accidental OR with
+the full bits_per_component number when it was ported to the upstream
+kernel.
+
+On typical bpc=8 setups we don't notice this because line_buf_depth is
+always an odd value (it contains bpc+1) and will also set the 4th bit
+after left-shifting by 3 (hence this |= bits_per_component is a no-op).
+
+Now that guards are being removed to allow more bits_per_component
+values besides 8 (possible since commit 49fd30a7153b ("drm/msm/dsi: use
+DRM DSC helpers for DSC setup")), a bpc of 10 will instead clash with
+the 5th bit which is convert_rgb. This is "fortunately" also always set
+to true by MSM's dsi_populate_dsc_params() already, but once a bpc of 12
+starts being used it'll write into simple_422 which is normally false.
+
+To solve all these overlaps, simply replicate downstream code and only
+set this lowest bit if bits_per_component is equal to 10. It is unclear
+why DSC requires this only for bpc=10 but not bpc=12, and also notice
+that this lowest bit wasn't set previously despite having a panel and
+patch on the list using it without any mentioned issues.
+
+Fixes: c110cfd1753e ("drm/msm/disp/dpu1: Add support for DSC")
+Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/636311/
+Link: https://lore.kernel.org/r/20250211-dsc-10-bit-v1-1-1c85a9430d9a@somainline.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+index c8f14555834a8..70a6dfe94faa5 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+@@ -46,6 +46,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ u32 slice_last_group_size;
+ u32 det_thresh_flatness;
+ bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
++ bool input_10_bits = dsc->bits_per_component == 10;
+
+ DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+@@ -62,7 +63,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ data |= (dsc->line_buf_depth << 3);
+ data |= (dsc->simple_422 << 2);
+ data |= (dsc->convert_rgb << 1);
+- data |= dsc->bits_per_component;
++ data |= input_10_bits;
+
+ DPU_REG_WRITE(c, DSC_ENC, data);
+
+--
+2.39.5
+
--- /dev/null
+From a27fddcdeed6b8198026182cf6f0af3296ea1c8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Dec 2024 07:31:35 +0200
+Subject: drm/rcar-du: dsi: Fix PHY lock bit check
+
+From: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
+
+[ Upstream commit 6389e616fae8a101ce00068f7690461ab57b29d8 ]
+
+The driver checks for bit 16 (using CLOCKSET1_LOCK define) in CLOCKSET1
+register when waiting for the PPI clock. However, the right bit to check
+is bit 17 (CLOCKSET1_LOCK_PHY define). Not only that, but there's
+nothing in the documents for bit 16 for V3U nor V4H.
+
+So, fix the check to use bit 17, and drop the define for bit 16.
+
+Fixes: 155358310f01 ("drm: rcar-du: Add R-Car DSI driver")
+Fixes: 11696c5e8924 ("drm: Place Renesas drivers in a separate dir")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241217-rcar-gh-dsi-v5-1-e77421093c05@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 2 +-
+ drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 1 -
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
+index a7f2b7f66a176..9ec9c43971dfb 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
++++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c
+@@ -396,7 +396,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
+ for (timeout = 10; timeout > 0; --timeout) {
+ if ((rcar_mipi_dsi_read(dsi, PPICLSR) & PPICLSR_STPST) &&
+ (rcar_mipi_dsi_read(dsi, PPIDLSR) & PPIDLSR_STPST) &&
+- (rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK))
++ (rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK_PHY))
+ break;
+
+ usleep_range(1000, 2000);
+diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
+index 2eaca54636f3d..1f1eb46c721fe 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
++++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h
+@@ -141,7 +141,6 @@
+
+ #define CLOCKSET1 0x101c
+ #define CLOCKSET1_LOCK_PHY (1 << 17)
+-#define CLOCKSET1_LOCK (1 << 16)
+ #define CLOCKSET1_CLKSEL (1 << 8)
+ #define CLOCKSET1_CLKINSEL_EXTAL (0 << 2)
+ #define CLOCKSET1_CLKINSEL_DIG (1 << 2)
+--
+2.39.5
+
--- /dev/null
+From 7cb0236996b50bb54fd1c5f2944484af3ef72eca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Nov 2023 09:38:00 +0200
+Subject: drm/tidss: Add simple K2G manual reset
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 576d96c5c896221b5bc8feae473739469a92e144 ]
+
+K2G display controller does not support soft reset, but we can do the
+most important steps manually: mask the IRQs and disable the VPs.
+
+Reviewed-by: Aradhya Bhatia <a-bhatia1@ti.com>
+Link: https://lore.kernel.org/r/20231109-tidss-probe-v2-7-ac91b5ea35c0@ideasonboard.com
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Stable-dep-of: a9a73f2661e6 ("drm/tidss: Fix race condition while handling interrupt registers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tidss/tidss_dispc.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
+index c986d432af507..d3e57e6de5dbb 100644
+--- a/drivers/gpu/drm/tidss/tidss_dispc.c
++++ b/drivers/gpu/drm/tidss/tidss_dispc.c
+@@ -2655,14 +2655,28 @@ static void dispc_init_errata(struct dispc_device *dispc)
+ }
+ }
+
++/*
++ * K2G display controller does not support soft reset, so we do a basic manual
++ * reset here: make sure the IRQs are masked and VPs are disabled.
++ */
++static void dispc_softreset_k2g(struct dispc_device *dispc)
++{
++ dispc_set_irqenable(dispc, 0);
++ dispc_read_and_clear_irqstatus(dispc);
++
++ for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx)
++ VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
++}
++
+ static int dispc_softreset(struct dispc_device *dispc)
+ {
+ u32 val;
+ int ret = 0;
+
+- /* K2G display controller does not support soft reset */
+- if (dispc->feat->subrev == DISPC_K2G)
++ if (dispc->feat->subrev == DISPC_K2G) {
++ dispc_softreset_k2g(dispc);
+ return 0;
++ }
+
+ /* Soft reset */
+ REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1);
+--
+2.39.5
+
--- /dev/null
+From bc7cb75e89f1d34ec723d228aab68caa73defaee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 17:07:50 +0300
+Subject: drm/tidss: Fix race condition while handling interrupt registers
+
+From: Devarsh Thakkar <devarsht@ti.com>
+
+[ Upstream commit a9a73f2661e6f625d306c9b0ef082e4593f45a21 ]
+
+The driver has a spinlock for protecting the irq_masks field and irq
+enable registers. However, the driver misses protecting the irq status
+registers which can lead to races.
+
+Take the spinlock when accessing irqstatus too.
+
+Fixes: 32a1795f57ee ("drm/tidss: New driver for TI Keystone platform Display SubSystem")
+Cc: stable@vger.kernel.org
+Signed-off-by: Devarsh Thakkar <devarsht@ti.com>
+[Tomi: updated the desc]
+Reviewed-by: Jonathan Cormier <jcormier@criticallink.com>
+Tested-by: Jonathan Cormier <jcormier@criticallink.com>
+Reviewed-by: Aradhya Bhatia <aradhya.bhatia@linux.dev>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241021-tidss-irq-fix-v1-6-82ddaec94e4a@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tidss/tidss_dispc.c | 4 ++++
+ drivers/gpu/drm/tidss/tidss_irq.c | 2 ++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
+index d3e57e6de5dbb..38b2ae0d7ec1d 100644
+--- a/drivers/gpu/drm/tidss/tidss_dispc.c
++++ b/drivers/gpu/drm/tidss/tidss_dispc.c
+@@ -2661,8 +2661,12 @@ static void dispc_init_errata(struct dispc_device *dispc)
+ */
+ static void dispc_softreset_k2g(struct dispc_device *dispc)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dispc->tidss->wait_lock, flags);
+ dispc_set_irqenable(dispc, 0);
+ dispc_read_and_clear_irqstatus(dispc);
++ spin_unlock_irqrestore(&dispc->tidss->wait_lock, flags);
+
+ for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx)
+ VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
+diff --git a/drivers/gpu/drm/tidss/tidss_irq.c b/drivers/gpu/drm/tidss/tidss_irq.c
+index 0c681c7600bcb..f13c7e434f8ed 100644
+--- a/drivers/gpu/drm/tidss/tidss_irq.c
++++ b/drivers/gpu/drm/tidss/tidss_irq.c
+@@ -60,7 +60,9 @@ static irqreturn_t tidss_irq_handler(int irq, void *arg)
+ unsigned int id;
+ dispc_irq_t irqstatus;
+
++ spin_lock(&tidss->wait_lock);
+ irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc);
++ spin_unlock(&tidss->wait_lock);
+
+ for (id = 0; id < tidss->num_crtcs; id++) {
+ struct drm_crtc *crtc = tidss->crtcs[id];
+--
+2.39.5
+
--- /dev/null
+From e1a2d23ebf31af7b08094651f1e09ca36af1b42f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2025 19:15:23 +0100
+Subject: nouveau/svm: fix missing folio unlock + put after
+ make_device_exclusive_range()
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit b3fefbb30a1691533cb905006b69b2a474660744 ]
+
+In case we have to retry the loop, we are missing to unlock+put the
+folio. In that case, we will keep failing make_device_exclusive_range()
+because we cannot grab the folio lock, and even return from the function
+with the folio locked and referenced, effectively never succeeding the
+make_device_exclusive_range().
+
+While at it, convert the other unlock+put to use a folio as well.
+
+This was found by code inspection.
+
+Fixes: 8f187163eb89 ("nouveau/svm: implement atomic SVM access")
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Alistair Popple <apopple@nvidia.com>
+Tested-by: Alistair Popple <apopple@nvidia.com>
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250124181524.3584236-2-david@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/nouveau/nouveau_svm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
+index be6674fb1af71..d0bff13ac758d 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
+@@ -592,6 +592,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
+ unsigned long timeout =
+ jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+ struct mm_struct *mm = svmm->notifier.mm;
++ struct folio *folio;
+ struct page *page;
+ unsigned long start = args->p.addr;
+ unsigned long notifier_seq;
+@@ -618,12 +619,16 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
+ ret = -EINVAL;
+ goto out;
+ }
++ folio = page_folio(page);
+
+ mutex_lock(&svmm->mutex);
+ if (!mmu_interval_read_retry(¬ifier->notifier,
+ notifier_seq))
+ break;
+ mutex_unlock(&svmm->mutex);
++
++ folio_unlock(folio);
++ folio_put(folio);
+ }
+
+ /* Map the page on the GPU. */
+@@ -639,8 +644,8 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
+ ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
+ mutex_unlock(&svmm->mutex);
+
+- unlock_page(page);
+- put_page(page);
++ folio_unlock(folio);
++ folio_put(folio);
+
+ out:
+ mmu_interval_notifier_remove(¬ifier->notifier);
+--
+2.39.5
+
--- /dev/null
+From 4ea9cc2308e84d7aa68cb92a0b01fa55577f5459 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Feb 2025 10:05:14 -0700
+Subject: nvme/ioctl: add missing space in err message
+
+From: Caleb Sander Mateos <csander@purestorage.com>
+
+[ Upstream commit 487a3ea7b1b8ba2ca7d2c2bb3c3594dc360d6261 ]
+
+nvme_validate_passthru_nsid() logs an err message whose format string is
+split over 2 lines. There is a missing space between the two pieces,
+resulting in log lines like "... does not match nsid (1)of namespace".
+Add the missing space between ")" and "of". Also combine the format
+string pieces onto a single line to make the err message easier to grep.
+
+Fixes: e7d4b5493a2d ("nvme: factor out a nvme_validate_passthru_nsid helper")
+Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/ioctl.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
+index a02873792890e..acf73a91e87e7 100644
+--- a/drivers/nvme/host/ioctl.c
++++ b/drivers/nvme/host/ioctl.c
+@@ -262,8 +262,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
+ {
+ if (ns && nsid != ns->head->ns_id) {
+ dev_err(ctrl->device,
+- "%s: nsid (%u) in cmd does not match nsid (%u)"
+- "of namespace\n",
++ "%s: nsid (%u) in cmd does not match nsid (%u) of namespace\n",
+ current->comm, nsid, ns->head->ns_id);
+ return false;
+ }
+--
+2.39.5
+
--- /dev/null
+From 5164d7c34a07028686a0539463c3887a0a667057 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Jan 2025 09:00:34 +0000
+Subject: power: supply: da9150-fg: fix potential overflow
+
+From: Andrey Vatoropin <a.vatoropin@crpt.ru>
+
+[ Upstream commit 3fb3cb4350befc4f901c54e0cb4a2a47b1302e08 ]
+
+Size of variable sd_gain equals four bytes - DA9150_QIF_SD_GAIN_SIZE.
+Size of variable shunt_val equals two bytes - DA9150_QIF_SHUNT_VAL_SIZE.
+
+The expression sd_gain * shunt_val is currently being evaluated using
+32-bit arithmetic. So during the multiplication an overflow may occur.
+
+As the value of type 'u64' is used as storage for the eventual result, put
+ULL variable at the first position of each expression in order to give the
+compiler complete information about the proper arithmetic to use. According
+to C99 the guaranteed width for a variable of type 'unsigned long long' >=
+64 bits.
+
+Remove the explicit cast to u64 as it is meaningless.
+
+Just for the sake of consistency, perform the similar trick with another
+expression concerning 'iavg'.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: a419b4fd9138 ("power: Add support for DA9150 Fuel-Gauge")
+Signed-off-by: Andrey Vatoropin <a.vatoropin@crpt.ru>
+Link: https://lore.kernel.org/r/20250130090030.53422-1-a.vatoropin@crpt.ru
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/da9150-fg.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/power/supply/da9150-fg.c b/drivers/power/supply/da9150-fg.c
+index 8c5e2c49d6c1c..9d0a6ab698f58 100644
+--- a/drivers/power/supply/da9150-fg.c
++++ b/drivers/power/supply/da9150-fg.c
+@@ -248,9 +248,9 @@ static int da9150_fg_current_avg(struct da9150_fg *fg,
+ DA9150_QIF_SD_GAIN_SIZE);
+ da9150_fg_read_sync_end(fg);
+
+- div = (u64) (sd_gain * shunt_val * 65536ULL);
++ div = 65536ULL * sd_gain * shunt_val;
+ do_div(div, 1000000);
+- res = (u64) (iavg * 1000000ULL);
++ res = 1000000ULL * iavg;
+ do_div(res, div);
+
+ val->intval = (int) res;
+--
+2.39.5
+
arp-switch-to-dev_getbyhwaddr-in-arp_req_set_public.patch
net-axienet-set-mac_managed_pm.patch
tcp-drop-secpath-at-the-same-time-as-we-currently-dr.patch
+drm-tidss-add-simple-k2g-manual-reset.patch
+drm-tidss-fix-race-condition-while-handling-interrup.patch
+drm-rcar-du-dsi-fix-phy-lock-bit-check.patch
+bpf-test_run-fix-use-after-free-issue-in-eth_skb_pkt.patch
+strparser-add-read_sock-callback.patch
+bpf-fix-wrong-copied_seq-calculation.patch
+power-supply-da9150-fg-fix-potential-overflow.patch
+nouveau-svm-fix-missing-folio-unlock-put-after-make_.patch
+drm-msm-dpu-don-t-leak-bits_per_component-into-rando.patch
+nvme-ioctl-add-missing-space-in-err-message.patch
+bpf-skip-non-exist-keys-in-generic_map_lookup_batch.patch
--- /dev/null
+From 52e655997539477f3d168b08659ffdb121523230 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 18:09:13 +0800
+Subject: strparser: Add read_sock callback
+
+From: Jiayuan Chen <mrpre@163.com>
+
+[ Upstream commit 0532a79efd68a4d9686b0385e4993af4b130ff82 ]
+
+Added a new read_sock handler, allowing users to customize read operations
+instead of relying on the native socket's read_sock.
+
+Signed-off-by: Jiayuan Chen <mrpre@163.com>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://patch.msgid.link/20250122100917.49845-2-mrpre@163.com
+Stable-dep-of: 36b62df5683c ("bpf: Fix wrong copied_seq calculation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/networking/strparser.rst | 9 ++++++++-
+ include/net/strparser.h | 2 ++
+ net/strparser/strparser.c | 11 +++++++++--
+ 3 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/networking/strparser.rst b/Documentation/networking/strparser.rst
+index 6cab1f74ae05a..7f623d1db72aa 100644
+--- a/Documentation/networking/strparser.rst
++++ b/Documentation/networking/strparser.rst
+@@ -112,7 +112,7 @@ Functions
+ Callbacks
+ =========
+
+-There are six callbacks:
++There are seven callbacks:
+
+ ::
+
+@@ -182,6 +182,13 @@ There are six callbacks:
+ the length of the message. skb->len - offset may be greater
+ then full_len since strparser does not trim the skb.
+
++ ::
++
++ int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor);
++
++ The read_sock callback is used by strparser instead of
++ sock->ops->read_sock, if provided.
+ ::
+
+ int (*read_sock_done)(struct strparser *strp, int err);
+diff --git a/include/net/strparser.h b/include/net/strparser.h
+index 41e2ce9e9e10f..0a83010b3a64a 100644
+--- a/include/net/strparser.h
++++ b/include/net/strparser.h
+@@ -43,6 +43,8 @@ struct strparser;
+ struct strp_callbacks {
+ int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
+ void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
++ int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
++ sk_read_actor_t recv_actor);
+ int (*read_sock_done)(struct strparser *strp, int err);
+ void (*abort_parser)(struct strparser *strp, int err);
+ void (*lock)(struct strparser *strp);
+diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c
+index 8299ceb3e3739..95696f42647ec 100644
+--- a/net/strparser/strparser.c
++++ b/net/strparser/strparser.c
+@@ -347,7 +347,10 @@ static int strp_read_sock(struct strparser *strp)
+ struct socket *sock = strp->sk->sk_socket;
+ read_descriptor_t desc;
+
+- if (unlikely(!sock || !sock->ops || !sock->ops->read_sock))
++ if (unlikely(!sock || !sock->ops))
++ return -EBUSY;
++
++ if (unlikely(!strp->cb.read_sock && !sock->ops->read_sock))
+ return -EBUSY;
+
+ desc.arg.data = strp;
+@@ -355,7 +358,10 @@ static int strp_read_sock(struct strparser *strp)
+ desc.count = 1; /* give more than one skb per call */
+
+ /* sk should be locked here, so okay to do read_sock */
+- sock->ops->read_sock(strp->sk, &desc, strp_recv);
++ if (strp->cb.read_sock)
++ strp->cb.read_sock(strp, &desc, strp_recv);
++ else
++ sock->ops->read_sock(strp->sk, &desc, strp_recv);
+
+ desc.error = strp->cb.read_sock_done(strp, desc.error);
+
+@@ -468,6 +474,7 @@ int strp_init(struct strparser *strp, struct sock *sk,
+ strp->cb.unlock = cb->unlock ? : strp_sock_unlock;
+ strp->cb.rcv_msg = cb->rcv_msg;
+ strp->cb.parse_msg = cb->parse_msg;
++ strp->cb.read_sock = cb->read_sock;
+ strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done;
+ strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp;
+
+--
+2.39.5
+