+++ /dev/null
-From 4e7817c3190175d02a107405205be715d8ddebbd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:28 -0700
-Subject: af_unix: Annodate data-races around sk->sk_state for writers.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 942238f9735a4a4ebf8274b218d9a910158941d1 ]
-
-sk->sk_state is changed under unix_state_lock(), but it's read locklessly
-in many places.
-
-This patch adds WRITE_ONCE() on the writer side.
-
-We will add READ_ONCE() to the lockless readers in the following patches.
-
-Fixes: 83301b5367a9 ("af_unix: Set TCP_ESTABLISHED for datagram sockets too")
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 14 ++++++++------
- 1 file changed, 8 insertions(+), 6 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 914e40697f00a..616d6c34d6102 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -542,7 +542,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
- u->path.dentry = NULL;
- u->path.mnt = NULL;
- state = sk->sk_state;
-- sk->sk_state = TCP_CLOSE;
-+ WRITE_ONCE(sk->sk_state, TCP_CLOSE);
-
- skpair = unix_peer(sk);
- unix_peer(sk) = NULL;
-@@ -664,7 +664,8 @@ static int unix_listen(struct socket *sock, int backlog)
- if (backlog > sk->sk_max_ack_backlog)
- wake_up_interruptible_all(&u->peer_wait);
- sk->sk_max_ack_backlog = backlog;
-- sk->sk_state = TCP_LISTEN;
-+ WRITE_ONCE(sk->sk_state, TCP_LISTEN);
-+
- /* set credentials so connect can copy them */
- init_peercred(sk);
- err = 0;
-@@ -1254,7 +1255,8 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- if (err)
- goto out_unlock;
-
-- sk->sk_state = other->sk_state = TCP_ESTABLISHED;
-+ WRITE_ONCE(sk->sk_state, TCP_ESTABLISHED);
-+ WRITE_ONCE(other->sk_state, TCP_ESTABLISHED);
- } else {
- /*
- * 1003.1g breaking connected state with AF_UNSPEC
-@@ -1271,7 +1273,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
-
- unix_peer(sk) = other;
- if (!other)
-- sk->sk_state = TCP_CLOSE;
-+ WRITE_ONCE(sk->sk_state, TCP_CLOSE);
- unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer);
-
- unix_state_double_unlock(sk, other);
-@@ -1484,7 +1486,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- copy_peercred(sk, other);
-
- sock->state = SS_CONNECTED;
-- sk->sk_state = TCP_ESTABLISHED;
-+ WRITE_ONCE(sk->sk_state, TCP_ESTABLISHED);
- sock_hold(newsk);
-
- smp_mb__after_atomic(); /* sock_hold() does an atomic_inc() */
-@@ -1880,7 +1882,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- unix_peer(sk) = NULL;
- unix_dgram_peer_wake_disconnect_wakeup(sk, other);
-
-- sk->sk_state = TCP_CLOSE;
-+ WRITE_ONCE(sk->sk_state, TCP_CLOSE);
- unix_state_unlock(sk);
-
- unix_dgram_disconnected(sk, other);
---
-2.43.0
-
+++ /dev/null
-From d0211af6e254986091d952cd861d1ec9517ca5cf Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:37 -0700
-Subject: af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit bd9f2d05731f6a112d0c7391a0d537bfc588dbe6 ]
-
-net->unx.sysctl_max_dgram_qlen is exposed as a sysctl knob and can be
-changed concurrently.
-
-Let's use READ_ONCE() in unix_create1().
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index c6d3a19956004..5c4318f64d253 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -888,7 +888,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
-
- sk->sk_allocation = GFP_KERNEL_ACCOUNT;
- sk->sk_write_space = unix_write_space;
-- sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
-+ sk->sk_max_ack_backlog = READ_ONCE(net->unx.sysctl_max_dgram_qlen);
- sk->sk_destruct = unix_sock_destructor;
- u = unix_sk(sk);
- u->inflight = 0;
---
-2.43.0
-
+++ /dev/null
-From 94dccc65b7d84333cead9dfbd69fd322a517704d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:41 -0700
-Subject: af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit efaf24e30ec39ebbea9112227485805a48b0ceb1 ]
-
-While dumping sockets via UNIX_DIAG, we do not hold unix_state_lock().
-
-Let's use READ_ONCE() to read sk->sk_shutdown.
-
-Fixes: e4e541a84863 ("sock-diag: Report shutdown for inet and unix sockets (v2)")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/diag.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/diag.c b/net/unix/diag.c
-index 63a0040e9fb45..86b3401dcc000 100644
---- a/net/unix/diag.c
-+++ b/net/unix/diag.c
-@@ -165,7 +165,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
- sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
- goto out_nlmsg_trim;
-
-- if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, sk->sk_shutdown))
-+ if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, READ_ONCE(sk->sk_shutdown)))
- goto out_nlmsg_trim;
-
- if ((req->udiag_show & UDIAG_SHOW_UID) &&
---
-2.43.0
-
+++ /dev/null
-From 606ac2707f4c4f563be7f791560647cbac5c339c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:29 -0700
-Subject: af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 3a0f38eb285c8c2eead4b3230c7ac2983707599d ]
-
-ioctl(SIOCINQ) calls unix_inq_len() that checks sk->sk_state first
-and returns -EINVAL if it's TCP_LISTEN.
-
-Then, for SOCK_STREAM sockets, unix_inq_len() returns the number of
-bytes in recvq.
-
-However, unix_inq_len() does not hold unix_state_lock(), and the
-concurrent listen() might change the state after checking sk->sk_state.
-
-If the race occurs, 0 is returned for the listener, instead of -EINVAL,
-because the length of skb with embryo is 0.
-
-We could hold unix_state_lock() in unix_inq_len(), but it's overkill
-given the result is true for pre-listen() TCP_CLOSE state.
-
-So, let's use READ_ONCE() for sk->sk_state in unix_inq_len().
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 616d6c34d6102..18e2dea699720 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -2957,7 +2957,7 @@ long unix_inq_len(struct sock *sk)
- struct sk_buff *skb;
- long amount = 0;
-
-- if (sk->sk_state == TCP_LISTEN)
-+ if (READ_ONCE(sk->sk_state) == TCP_LISTEN)
- return -EINVAL;
-
- spin_lock(&sk->sk_receive_queue.lock);
---
-2.43.0
-
+++ /dev/null
-From aeec58466a73081c275584e95c683b252b99a215 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:31 -0700
-Subject: af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit a9bf9c7dc6a5899c01cb8f6e773a66315a5cd4b7 ]
-
-As small optimisation, unix_stream_connect() prefetches the client's
-sk->sk_state without unix_state_lock() and checks if it's TCP_CLOSE.
-
-Later, sk->sk_state is checked again under unix_state_lock().
-
-Let's use READ_ONCE() for the first check and TCP_CLOSE directly for
-the second check.
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 9800d255a8bc7..628b3fcc74227 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -1371,7 +1371,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- struct sk_buff *skb = NULL;
- long timeo;
- int err;
-- int st;
-
- err = unix_validate_addr(sunaddr, addr_len);
- if (err)
-@@ -1455,9 +1454,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-
- Well, and we have to recheck the state after socket locked.
- */
-- st = sk->sk_state;
--
-- switch (st) {
-+ switch (READ_ONCE(sk->sk_state)) {
- case TCP_CLOSE:
- /* This is ok... continue with connect */
- break;
-@@ -1472,7 +1469,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-
- unix_state_lock_nested(sk, U_LOCK_SECOND);
-
-- if (sk->sk_state != st) {
-+ if (sk->sk_state != TCP_CLOSE) {
- unix_state_unlock(sk);
- unix_state_unlock(other);
- sock_put(other);
---
-2.43.0
-
+++ /dev/null
-From 342e27acc53fd2f8a50a957f7c82bf1445299273 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:34 -0700
-Subject: af_unix: Annotate data-race of sk->sk_state in
- unix_stream_read_skb().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit af4c733b6b1aded4dc808fafece7dfe6e9d2ebb3 ]
-
-unix_stream_read_skb() is called from sk->sk_data_ready() context
-where unix_state_lock() is not held.
-
-Let's use READ_ONCE() there.
-
-Fixes: 77462de14a43 ("af_unix: Add read_sock for stream socket types")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index d00d781f777be..c6d3a19956004 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -2642,7 +2642,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
- static int unix_stream_read_sock(struct sock *sk, read_descriptor_t *desc,
- sk_read_actor_t recv_actor)
- {
-- if (unlikely(sk->sk_state != TCP_ESTABLISHED))
-+ if (unlikely(READ_ONCE(sk->sk_state) != TCP_ESTABLISHED))
- return -ENOTCONN;
-
- return unix_read_sock(sk, desc, recv_actor);
---
-2.43.0
-
+++ /dev/null
-From 00d7a1aca3c596b90e6bd71e005335419ed7f4fb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:33 -0700
-Subject: af_unix: Annotate data-races around sk->sk_state in sendmsg() and
- recvmsg().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 8a34d4e8d9742a24f74998f45a6a98edd923319b ]
-
-The following functions read sk->sk_state locklessly and proceed only if
-the state is TCP_ESTABLISHED.
-
- * unix_stream_sendmsg
- * unix_stream_read_generic
- * unix_seqpacket_sendmsg
- * unix_seqpacket_recvmsg
-
-Let's use READ_ONCE() there.
-
-Fixes: a05d2ad1c1f3 ("af_unix: Only allow recv on connected seqpacket sockets.")
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 628b3fcc74227..d00d781f777be 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -2093,7 +2093,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
- }
-
- if (msg->msg_namelen) {
-- err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
-+ err = READ_ONCE(sk->sk_state) == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
- goto out_err;
- } else {
- err = -ENOTCONN;
-@@ -2305,7 +2305,7 @@ static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,
- if (err)
- return err;
-
-- if (sk->sk_state != TCP_ESTABLISHED)
-+ if (READ_ONCE(sk->sk_state) != TCP_ESTABLISHED)
- return -ENOTCONN;
-
- if (msg->msg_namelen)
-@@ -2319,7 +2319,7 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
- {
- struct sock *sk = sock->sk;
-
-- if (sk->sk_state != TCP_ESTABLISHED)
-+ if (READ_ONCE(sk->sk_state) != TCP_ESTABLISHED)
- return -ENOTCONN;
-
- return unix_dgram_recvmsg(sock, msg, size, flags);
-@@ -2666,7 +2666,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
- size_t size = state->size;
- unsigned int last_len;
-
-- if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
-+ if (unlikely(READ_ONCE(sk->sk_state) != TCP_ESTABLISHED)) {
- err = -EINVAL;
- goto out;
- }
---
-2.43.0
-
+++ /dev/null
-From b2efe08af840020f292ef96693445bd9feffa196 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:30 -0700
-Subject: af_unix: Annotate data-races around sk->sk_state in
- unix_write_space() and poll().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit eb0718fb3e97ad0d6f4529b810103451c90adf94 ]
-
-unix_poll() and unix_dgram_poll() read sk->sk_state locklessly and
-calls unix_writable() which also reads sk->sk_state without holding
-unix_state_lock().
-
-Let's use READ_ONCE() in unix_poll() and unix_dgram_poll() and pass
-it to unix_writable().
-
-While at it, we remove TCP_SYN_SENT check in unix_dgram_poll() as
-that state does not exist for AF_UNIX socket since the code was added.
-
-Fixes: 1586a5877db9 ("af_unix: do not report POLLOUT on listeners")
-Fixes: 3c73419c09a5 ("af_unix: fix 'poll for write'/ connected DGRAM sockets")
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 25 ++++++++++++-------------
- 1 file changed, 12 insertions(+), 13 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 18e2dea699720..73b287b7a1154 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -455,9 +455,9 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
- return 0;
- }
-
--static int unix_writable(const struct sock *sk)
-+static int unix_writable(const struct sock *sk, unsigned char state)
- {
-- return sk->sk_state != TCP_LISTEN &&
-+ return state != TCP_LISTEN &&
- (refcount_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
- }
-
-@@ -466,7 +466,7 @@ static void unix_write_space(struct sock *sk)
- struct socket_wq *wq;
-
- rcu_read_lock();
-- if (unix_writable(sk)) {
-+ if (unix_writable(sk, READ_ONCE(sk->sk_state))) {
- wq = rcu_dereference(sk->sk_wq);
- if (skwq_has_sleeper(wq))
- wake_up_interruptible_sync_poll(&wq->wait,
-@@ -3069,12 +3069,14 @@ static int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
- static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wait)
- {
- struct sock *sk = sock->sk;
-+ unsigned char state;
- __poll_t mask;
- u8 shutdown;
-
- sock_poll_wait(file, sock, wait);
- mask = 0;
- shutdown = READ_ONCE(sk->sk_shutdown);
-+ state = READ_ONCE(sk->sk_state);
-
- /* exceptional events? */
- if (sk->sk_err)
-@@ -3096,14 +3098,14 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
-
- /* Connection-based need to check for termination and startup */
- if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) &&
-- sk->sk_state == TCP_CLOSE)
-+ state == TCP_CLOSE)
- mask |= EPOLLHUP;
-
- /*
- * we set writable also when the other side has shut down the
- * connection. This prevents stuck sockets.
- */
-- if (unix_writable(sk))
-+ if (unix_writable(sk, state))
- mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
-
- return mask;
-@@ -3114,12 +3116,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
- {
- struct sock *sk = sock->sk, *other;
- unsigned int writable;
-+ unsigned char state;
- __poll_t mask;
- u8 shutdown;
-
- sock_poll_wait(file, sock, wait);
- mask = 0;
- shutdown = READ_ONCE(sk->sk_shutdown);
-+ state = READ_ONCE(sk->sk_state);
-
- /* exceptional events? */
- if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
-@@ -3138,19 +3142,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
- mask |= EPOLLIN | EPOLLRDNORM;
-
- /* Connection-based need to check for termination and startup */
-- if (sk->sk_type == SOCK_SEQPACKET) {
-- if (sk->sk_state == TCP_CLOSE)
-- mask |= EPOLLHUP;
-- /* connection hasn't started yet? */
-- if (sk->sk_state == TCP_SYN_SENT)
-- return mask;
-- }
-+ if (sk->sk_type == SOCK_SEQPACKET && state == TCP_CLOSE)
-+ mask |= EPOLLHUP;
-
- /* No write status requested, avoid expensive OUT tests. */
- if (!(poll_requested_events(wait) & (EPOLLWRBAND|EPOLLWRNORM|EPOLLOUT)))
- return mask;
-
-- writable = unix_writable(sk);
-+ writable = unix_writable(sk, state);
- if (writable) {
- unix_state_lock(sk);
-
---
-2.43.0
-
+++ /dev/null
-From 3e7745374f5d333d3c29dd950a845f1990da2cb9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:35 -0700
-Subject: af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 0aa3be7b3e1f8f997312cc4705f8165e02806f8f ]
-
-While dumping AF_UNIX sockets via UNIX_DIAG, sk->sk_state is read
-locklessly.
-
-Let's use READ_ONCE() there.
-
-Note that the result could be inconsistent if the socket is dumped
-during the state change. This is common for other SOCK_DIAG and
-similar interfaces.
-
-Fixes: c9da99e6475f ("unix_diag: Fixup RQLEN extension report")
-Fixes: 2aac7a2cb0d9 ("unix_diag: Pending connections IDs NLA")
-Fixes: 45a96b9be6ec ("unix_diag: Dumping all sockets core")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/diag.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/net/unix/diag.c b/net/unix/diag.c
-index 15aaeabb1363b..94c8f509261d0 100644
---- a/net/unix/diag.c
-+++ b/net/unix/diag.c
-@@ -65,7 +65,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
- u32 *buf;
- int i;
-
-- if (sk->sk_state == TCP_LISTEN) {
-+ if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
- spin_lock(&sk->sk_receive_queue.lock);
-
- attr = nla_reserve(nlskb, UNIX_DIAG_ICONS,
-@@ -103,7 +103,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
- {
- struct unix_diag_rqlen rql;
-
-- if (sk->sk_state == TCP_LISTEN) {
-+ if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
- rql.udiag_rqueue = sk->sk_receive_queue.qlen;
- rql.udiag_wqueue = sk->sk_max_ack_backlog;
- } else {
-@@ -136,7 +136,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
- rep = nlmsg_data(nlh);
- rep->udiag_family = AF_UNIX;
- rep->udiag_type = sk->sk_type;
-- rep->udiag_state = sk->sk_state;
-+ rep->udiag_state = READ_ONCE(sk->sk_state);
- rep->pad = 0;
- rep->udiag_ino = sk_ino;
- sock_diag_save_cookie(sk, rep->udiag_cookie);
-@@ -219,7 +219,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
- continue;
- if (num < s_num)
- goto next;
-- if (!(req->udiag_states & (1 << sk->sk_state)))
-+ if (!(req->udiag_states & (1 << READ_ONCE(sk->sk_state))))
- goto next;
- if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk),
- NETLINK_CB(cb->skb).portid,
---
-2.43.0
-
+++ /dev/null
-From d67e0043413caa1b66c8d9bb708330ddeebf7fa3 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 15 Mar 2023 20:57:46 +0000
-Subject: af_unix: annotate lockless accesses to sk->sk_err
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit cc04410af7de348234ac36a5f50c4ce416efdb4b ]
-
-unix_poll() and unix_dgram_poll() read sk->sk_err
-without any lock held.
-
-Add relevant READ_ONCE()/WRITE_ONCE() annotations.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: 83690b82d228 ("af_unix: Use skb_queue_empty_lockless() in unix_release_sock().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 3fa86d70467c2..85b1c0d7c287a 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -500,7 +500,7 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
- * when peer was not connected to us.
- */
- if (!sock_flag(other, SOCK_DEAD) && unix_peer(other) == sk) {
-- other->sk_err = ECONNRESET;
-+ WRITE_ONCE(other->sk_err, ECONNRESET);
- sk_error_report(other);
- }
- }
-@@ -571,7 +571,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
- /* No more writes */
- WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
- if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
-- skpair->sk_err = ECONNRESET;
-+ WRITE_ONCE(skpair->sk_err, ECONNRESET);
- unix_state_unlock(skpair);
- skpair->sk_state_change(skpair);
- sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
-@@ -3108,7 +3108,7 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
- state = READ_ONCE(sk->sk_state);
-
- /* exceptional events? */
-- if (sk->sk_err)
-+ if (READ_ONCE(sk->sk_err))
- mask |= EPOLLERR;
- if (shutdown == SHUTDOWN_MASK)
- mask |= EPOLLHUP;
-@@ -3155,7 +3155,8 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
- state = READ_ONCE(sk->sk_state);
-
- /* exceptional events? */
-- if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
-+ if (READ_ONCE(sk->sk_err) ||
-+ !skb_queue_empty_lockless(&sk->sk_error_queue))
- mask |= EPOLLERR |
- (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
-
---
-2.43.0
-
+++ /dev/null
-From 871f1d52052c897d94a9ed0573e073d4fe7ff7e0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 21 Jun 2022 10:19:08 -0700
-Subject: af_unix: Clean up some sock_net() uses.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 340c3d337119ea177a98338be2e3bc62ee87ac80 ]
-
-Some functions define a net pointer only for one-shot use. Others call
-sock_net() redundantly even when a net pointer is available. Let's fix
-these and make the code simpler.
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 33 ++++++++++++++-------------------
- net/unix/diag.c | 3 +--
- 2 files changed, 15 insertions(+), 21 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index a848e777e448c..9800d255a8bc7 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -903,7 +903,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
- memset(&u->scm_stat, 0, sizeof(struct scm_stat));
- unix_insert_socket(unix_sockets_unbound(sk), sk);
-
-- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-+ sock_prot_inuse_add(net, sk->sk_prot, 1);
-
- return sk;
-
-@@ -1247,9 +1247,8 @@ static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
- static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- int alen, int flags)
- {
-- struct sock *sk = sock->sk;
-- struct net *net = sock_net(sk);
- struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
-+ struct sock *sk = sock->sk;
- struct sock *other;
- int err;
-
-@@ -1270,7 +1269,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- }
-
- restart:
-- other = unix_find_other(net, sunaddr, alen, sock->type);
-+ other = unix_find_other(sock_net(sk), sunaddr, alen, sock->type);
- if (IS_ERR(other)) {
- err = PTR_ERR(other);
- goto out;
-@@ -1366,15 +1365,13 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags)
- {
- struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
-- struct sock *sk = sock->sk;
-- struct net *net = sock_net(sk);
-+ struct sock *sk = sock->sk, *newsk = NULL, *other = NULL;
- struct unix_sock *u = unix_sk(sk), *newu, *otheru;
-- struct sock *newsk = NULL;
-- struct sock *other = NULL;
-+ struct net *net = sock_net(sk);
- struct sk_buff *skb = NULL;
-- int st;
-- int err;
- long timeo;
-+ int err;
-+ int st;
-
- err = unix_validate_addr(sunaddr, addr_len);
- if (err)
-@@ -1394,7 +1391,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- */
-
- /* create new sock for complete connection */
-- newsk = unix_create1(sock_net(sk), NULL, 0, sock->type);
-+ newsk = unix_create1(net, NULL, 0, sock->type);
- if (IS_ERR(newsk)) {
- err = PTR_ERR(newsk);
- newsk = NULL;
-@@ -1803,17 +1800,15 @@ static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
- static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- size_t len)
- {
-- struct sock *sk = sock->sk;
-- struct net *net = sock_net(sk);
-- struct unix_sock *u = unix_sk(sk);
- DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
-- struct sock *other = NULL;
-- int err;
-- struct sk_buff *skb;
-- long timeo;
-+ struct sock *sk = sock->sk, *other = NULL;
-+ struct unix_sock *u = unix_sk(sk);
- struct scm_cookie scm;
-+ struct sk_buff *skb;
- int data_len = 0;
- int sk_locked;
-+ long timeo;
-+ int err;
-
- wait_for_unix_gc();
- err = scm_send(sock, msg, &scm, false);
-@@ -1880,7 +1875,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- if (sunaddr == NULL)
- goto out_free;
-
-- other = unix_find_other(net, sunaddr, msg->msg_namelen,
-+ other = unix_find_other(sock_net(sk), sunaddr, msg->msg_namelen,
- sk->sk_type);
- if (IS_ERR(other)) {
- err = PTR_ERR(other);
-diff --git a/net/unix/diag.c b/net/unix/diag.c
-index 006438e2e07a2..15aaeabb1363b 100644
---- a/net/unix/diag.c
-+++ b/net/unix/diag.c
-@@ -312,7 +312,6 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
- static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
- {
- int hdrlen = sizeof(struct unix_diag_req);
-- struct net *net = sock_net(skb->sk);
-
- if (nlmsg_len(h) < hdrlen)
- return -EINVAL;
-@@ -321,7 +320,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
- struct netlink_dump_control c = {
- .dump = unix_diag_dump,
- };
-- return netlink_dump_start(net->diag_nlsk, skb, h, &c);
-+ return netlink_dump_start(sock_net(skb->sk)->diag_nlsk, skb, h, &c);
- } else
- return unix_diag_get_exact(skb, h, nlmsg_data(h));
- }
---
-2.43.0
-
+++ /dev/null
-From a521bba7af6be404371346310d94ccd7c1e8c224 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:24 +0900
-Subject: af_unix: Copy unix_mkname() into unix_find_(bsd|abstract)().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit d2d8c9fddb1c11ccfa73bf0ad2b1e6b4ea7afdaf ]
-
-We should not call unix_mkname() before unix_find_other() and instead do
-the same thing where necessary based on the address type:
-
- - terminating the address with '\0' in unix_find_bsd()
- - calculating the hash in unix_find_abstract().
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 63 ++++++++++++++++++----------------------------
- 1 file changed, 25 insertions(+), 38 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 8aeafe66e6115..a848e777e448c 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -239,19 +239,25 @@ static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
- return 0;
- }
-
-+static void unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
-+{
-+ /* This may look like an off by one error but it is a bit more
-+ * subtle. 108 is the longest valid AF_UNIX path for a binding.
-+ * sun_path[108] doesn't as such exist. However in kernel space
-+ * we are guaranteed that it is a valid memory location in our
-+ * kernel address buffer because syscall functions always pass
-+ * a pointer of struct sockaddr_storage which has a bigger buffer
-+ * than 108.
-+ */
-+ ((char *)sunaddr)[addr_len] = 0;
-+}
-+
- static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
- {
- *hashp = 0;
-
- if (sunaddr->sun_path[0]) {
-- /*
-- * This may look like an off by one error but it is a bit more
-- * subtle. 108 is the longest valid AF_UNIX path for a binding.
-- * sun_path[108] doesn't as such exist. However in kernel space
-- * we are guaranteed that it is a valid memory location in our
-- * kernel address buffer.
-- */
-- ((char *)sunaddr)[len] = 0;
-+ unix_mkname_bsd(sunaddr, len);
- len = strlen(sunaddr->sun_path) +
- offsetof(struct sockaddr_un, sun_path) + 1;
- return len;
-@@ -959,13 +965,14 @@ static int unix_release(struct socket *sock)
- }
-
- static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
-- int type)
-+ int addr_len, int type)
- {
- struct inode *inode;
- struct path path;
- struct sock *sk;
- int err;
-
-+ unix_mkname_bsd(sunaddr, addr_len);
- err = kern_path(sunaddr->sun_path, LOOKUP_FOLLOW, &path);
- if (err)
- goto fail;
-@@ -1003,9 +1010,9 @@ static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
-
- static struct sock *unix_find_abstract(struct net *net,
- struct sockaddr_un *sunaddr,
-- int addr_len, int type,
-- unsigned int hash)
-+ int addr_len, int type)
- {
-+ unsigned int hash = unix_hash_fold(csum_partial(sunaddr, addr_len, 0));
- struct dentry *dentry;
- struct sock *sk;
-
-@@ -1022,15 +1029,14 @@ static struct sock *unix_find_abstract(struct net *net,
-
- static struct sock *unix_find_other(struct net *net,
- struct sockaddr_un *sunaddr,
-- int addr_len, int type,
-- unsigned int hash)
-+ int addr_len, int type)
- {
- struct sock *sk;
-
- if (sunaddr->sun_path[0])
-- sk = unix_find_bsd(net, sunaddr, type);
-+ sk = unix_find_bsd(net, sunaddr, addr_len, type);
- else
-- sk = unix_find_abstract(net, sunaddr, addr_len, type, hash);
-+ sk = unix_find_abstract(net, sunaddr, addr_len, type);
-
- return sk;
- }
-@@ -1245,7 +1251,6 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- struct net *net = sock_net(sk);
- struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;
- struct sock *other;
-- unsigned int hash;
- int err;
-
- err = -EINVAL;
-@@ -1257,11 +1262,6 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- if (err)
- goto out;
-
-- err = unix_mkname(sunaddr, alen, &hash);
-- if (err < 0)
-- goto out;
-- alen = err;
--
- if (test_bit(SOCK_PASSCRED, &sock->flags) &&
- !unix_sk(sk)->addr) {
- err = unix_autobind(sk);
-@@ -1270,7 +1270,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- }
-
- restart:
-- other = unix_find_other(net, sunaddr, alen, sock->type, hash);
-+ other = unix_find_other(net, sunaddr, alen, sock->type);
- if (IS_ERR(other)) {
- err = PTR_ERR(other);
- goto out;
-@@ -1372,7 +1372,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- struct sock *newsk = NULL;
- struct sock *other = NULL;
- struct sk_buff *skb = NULL;
-- unsigned int hash;
- int st;
- int err;
- long timeo;
-@@ -1381,11 +1380,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- if (err)
- goto out;
-
-- err = unix_mkname(sunaddr, addr_len, &hash);
-- if (err < 0)
-- goto out;
-- addr_len = err;
--
- if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr) {
- err = unix_autobind(sk);
- if (err)
-@@ -1416,7 +1410,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-
- restart:
- /* Find listening sock. */
-- other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash);
-+ other = unix_find_other(net, sunaddr, addr_len, sk->sk_type);
- if (IS_ERR(other)) {
- err = PTR_ERR(other);
- other = NULL;
-@@ -1814,9 +1808,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- struct unix_sock *u = unix_sk(sk);
- DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
- struct sock *other = NULL;
-- int namelen = 0; /* fake GCC */
- int err;
-- unsigned int hash;
- struct sk_buff *skb;
- long timeo;
- struct scm_cookie scm;
-@@ -1836,11 +1828,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- err = unix_validate_addr(sunaddr, msg->msg_namelen);
- if (err)
- goto out;
--
-- err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
-- if (err < 0)
-- goto out;
-- namelen = err;
- } else {
- sunaddr = NULL;
- err = -ENOTCONN;
-@@ -1893,8 +1880,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- if (sunaddr == NULL)
- goto out_free;
-
-- other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
-- hash);
-+ other = unix_find_other(net, sunaddr, msg->msg_namelen,
-+ sk->sk_type);
- if (IS_ERR(other)) {
- err = PTR_ERR(other);
- other = NULL;
---
-2.43.0
-
+++ /dev/null
-From 66094a2eae821c3437f6bee8337b83adbd0663a4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:23 +0900
-Subject: af_unix: Cut unix_validate_addr() out of unix_mkname().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit b8a58aa6fccc5b2940f0da18c7f02e8a1deb693a ]
-
-unix_mkname() tests socket address length and family and does some
-processing based on the address type. It is called in the early stage,
-and therefore some instructions are redundant and can end up in vain.
-
-The address length/family tests are done twice in unix_bind(). Also, the
-address type is rechecked later in unix_bind() and unix_find_other(), where
-we can do the same processing. Moreover, in the BSD address case, the hash
-is set to 0 but never used and confusing.
-
-This patch moves the address tests out of unix_mkname(), and the following
-patches move the other part into appropriate places and remove
-unix_mkname() finally.
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 40 ++++++++++++++++++++++++++++++----------
- 1 file changed, 30 insertions(+), 10 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 0a1258b417a9d..8aeafe66e6115 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -227,15 +227,22 @@ static inline void unix_release_addr(struct unix_address *addr)
- * - if started by zero, it is abstract name.
- */
-
-+static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
-+{
-+ if (addr_len <= offsetof(struct sockaddr_un, sun_path) ||
-+ addr_len > sizeof(*sunaddr))
-+ return -EINVAL;
-+
-+ if (sunaddr->sun_family != AF_UNIX)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
- static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
- {
- *hashp = 0;
-
-- if (len <= offsetof(struct sockaddr_un, sun_path) ||
-- len > sizeof(*sunaddr))
-- return -EINVAL;
-- if (!sunaddr || sunaddr->sun_family != AF_UNIX)
-- return -EINVAL;
- if (sunaddr->sun_path[0]) {
- /*
- * This may look like an off by one error but it is a bit more
-@@ -1178,13 +1185,14 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- unsigned int hash;
- struct unix_address *addr;
-
-- if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
-- sunaddr->sun_family != AF_UNIX)
-- return -EINVAL;
--
-- if (addr_len == offsetof(struct sockaddr_un, sun_path))
-+ if (addr_len == offsetof(struct sockaddr_un, sun_path) &&
-+ sunaddr->sun_family == AF_UNIX)
- return unix_autobind(sk);
-
-+ err = unix_validate_addr(sunaddr, addr_len);
-+ if (err)
-+ return err;
-+
- err = unix_mkname(sunaddr, addr_len, &hash);
- if (err < 0)
- return err;
-@@ -1245,6 +1253,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- goto out;
-
- if (addr->sa_family != AF_UNSPEC) {
-+ err = unix_validate_addr(sunaddr, alen);
-+ if (err)
-+ goto out;
-+
- err = unix_mkname(sunaddr, alen, &hash);
- if (err < 0)
- goto out;
-@@ -1365,6 +1377,10 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- int err;
- long timeo;
-
-+ err = unix_validate_addr(sunaddr, addr_len);
-+ if (err)
-+ goto out;
-+
- err = unix_mkname(sunaddr, addr_len, &hash);
- if (err < 0)
- goto out;
-@@ -1817,6 +1833,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- goto out;
-
- if (msg->msg_namelen) {
-+ err = unix_validate_addr(sunaddr, msg->msg_namelen);
-+ if (err)
-+ goto out;
-+
- err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
- if (err < 0)
- goto out;
---
-2.43.0
-
+++ /dev/null
-From 37f21e3bf98191271a970d44f8437110434cf447 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:21 +0900
-Subject: af_unix: Factorise unix_find_other() based on address types.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit fa39ef0e472961baef49ddb0e6f7b8ebb555bd8f ]
-
-As done in the commit fa42d910a38e ("unix_bind(): take BSD and abstract
-address cases into new helpers"), this patch moves BSD and abstract address
-cases from unix_find_other() into unix_find_bsd() and unix_find_abstract().
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 136 +++++++++++++++++++++++++++------------------
- 1 file changed, 81 insertions(+), 55 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 1fc3022510093..20a7be3effe83 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -951,6 +951,87 @@ static int unix_release(struct socket *sock)
- return 0;
- }
-
-+static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
-+ int type, int *error)
-+{
-+ struct inode *inode;
-+ struct path path;
-+ struct sock *sk;
-+ int err;
-+
-+ err = kern_path(sunaddr->sun_path, LOOKUP_FOLLOW, &path);
-+ if (err)
-+ goto fail;
-+
-+ err = path_permission(&path, MAY_WRITE);
-+ if (err)
-+ goto path_put;
-+
-+ err = -ECONNREFUSED;
-+ inode = d_backing_inode(path.dentry);
-+ if (!S_ISSOCK(inode->i_mode))
-+ goto path_put;
-+
-+ sk = unix_find_socket_byinode(inode);
-+ if (!sk)
-+ goto path_put;
-+
-+ err = -EPROTOTYPE;
-+ if (sk->sk_type == type)
-+ touch_atime(&path);
-+ else
-+ goto sock_put;
-+
-+ path_put(&path);
-+
-+ return sk;
-+
-+sock_put:
-+ sock_put(sk);
-+path_put:
-+ path_put(&path);
-+fail:
-+ *error = err;
-+ return NULL;
-+}
-+
-+static struct sock *unix_find_abstract(struct net *net,
-+ struct sockaddr_un *sunaddr,
-+ int addr_len, int type,
-+ unsigned int hash, int *error)
-+{
-+ struct dentry *dentry;
-+ struct sock *sk;
-+
-+ sk = unix_find_socket_byname(net, sunaddr, addr_len, type ^ hash);
-+ if (!sk) {
-+ *error = -ECONNREFUSED;
-+ return NULL;
-+ }
-+
-+ dentry = unix_sk(sk)->path.dentry;
-+ if (dentry)
-+ touch_atime(&unix_sk(sk)->path);
-+
-+ return sk;
-+}
-+
-+static struct sock *unix_find_other(struct net *net,
-+ struct sockaddr_un *sunaddr,
-+ int addr_len, int type,
-+ unsigned int hash, int *error)
-+{
-+ struct sock *sk;
-+
-+ if (sunaddr->sun_path[0])
-+ sk = unix_find_bsd(net, sunaddr, type, error);
-+ else
-+ sk = unix_find_abstract(net, sunaddr, addr_len, type, hash,
-+ error);
-+
-+ return sk;
-+}
-+
- static int unix_autobind(struct sock *sk)
- {
- struct unix_sock *u = unix_sk(sk);
-@@ -1009,61 +1090,6 @@ out: mutex_unlock(&u->bindlock);
- return err;
- }
-
--static struct sock *unix_find_other(struct net *net,
-- struct sockaddr_un *sunname, int len,
-- int type, unsigned int hash, int *error)
--{
-- struct sock *u;
-- struct path path;
-- int err = 0;
--
-- if (sunname->sun_path[0]) {
-- struct inode *inode;
-- err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
-- if (err)
-- goto fail;
-- inode = d_backing_inode(path.dentry);
-- err = path_permission(&path, MAY_WRITE);
-- if (err)
-- goto put_fail;
--
-- err = -ECONNREFUSED;
-- if (!S_ISSOCK(inode->i_mode))
-- goto put_fail;
-- u = unix_find_socket_byinode(inode);
-- if (!u)
-- goto put_fail;
--
-- if (u->sk_type == type)
-- touch_atime(&path);
--
-- path_put(&path);
--
-- err = -EPROTOTYPE;
-- if (u->sk_type != type) {
-- sock_put(u);
-- goto fail;
-- }
-- } else {
-- err = -ECONNREFUSED;
-- u = unix_find_socket_byname(net, sunname, len, type ^ hash);
-- if (u) {
-- struct dentry *dentry;
-- dentry = unix_sk(u)->path.dentry;
-- if (dentry)
-- touch_atime(&unix_sk(u)->path);
-- } else
-- goto fail;
-- }
-- return u;
--
--put_fail:
-- path_put(&path);
--fail:
-- *error = err;
-- return NULL;
--}
--
- static int unix_bind_bsd(struct sock *sk, struct unix_address *addr)
- {
- struct unix_sock *u = unix_sk(sk);
---
-2.43.0
-
+++ /dev/null
-From 6e28b0638dc4a6110a6b56646b3b62d9619a0076 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:20 +0900
-Subject: af_unix: Pass struct sock to unix_autobind().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit f7ed31f4615f4e1d97c0e4325c5b8a240e10073c ]
-
-We do not use struct socket in unix_autobind() and pass struct sock to
-unix_bind_bsd() and unix_bind_abstract(). Let's pass it to unix_autobind()
-as well.
-
-Also, this patch fixes these errors by checkpatch.pl.
-
- ERROR: do not use assignment in if condition
- #1795: FILE: net/unix/af_unix.c:1795:
- + if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
-
- CHECK: Logical continuations should be on the previous line
- #1796: FILE: net/unix/af_unix.c:1796:
- + if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
- + && (err = unix_autobind(sock)) != 0)
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 36 +++++++++++++++++++++---------------
- 1 file changed, 21 insertions(+), 15 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 7d58067ffd3f8..1fc3022510093 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -951,15 +951,13 @@ static int unix_release(struct socket *sock)
- return 0;
- }
-
--static int unix_autobind(struct socket *sock)
-+static int unix_autobind(struct sock *sk)
- {
-- struct sock *sk = sock->sk;
-- struct net *net = sock_net(sk);
- struct unix_sock *u = unix_sk(sk);
-- static u32 ordernum = 1;
- struct unix_address *addr;
-- int err;
- unsigned int retries = 0;
-+ static u32 ordernum = 1;
-+ int err;
-
- err = mutex_lock_interruptible(&u->bindlock);
- if (err)
-@@ -986,7 +984,8 @@ static int unix_autobind(struct socket *sock)
- spin_lock(&unix_table_lock);
- ordernum = (ordernum+1)&0xFFFFF;
-
-- if (__unix_find_socket_byname(net, addr->name, addr->len, addr->hash)) {
-+ if (__unix_find_socket_byname(sock_net(sk), addr->name, addr->len,
-+ addr->hash)) {
- spin_unlock(&unix_table_lock);
- /*
- * __unix_find_socket_byname() may take long time if many names
-@@ -1162,7 +1161,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- return -EINVAL;
-
- if (addr_len == offsetof(struct sockaddr_un, sun_path))
-- return unix_autobind(sock);
-+ return unix_autobind(sk);
-
- err = unix_mkname(sunaddr, addr_len, &hash);
- if (err < 0)
-@@ -1230,8 +1229,11 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- alen = err;
-
- if (test_bit(SOCK_PASSCRED, &sock->flags) &&
-- !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
-- goto out;
-+ !unix_sk(sk)->addr) {
-+ err = unix_autobind(sk);
-+ if (err)
-+ goto out;
-+ }
-
- restart:
- other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
-@@ -1344,9 +1346,11 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- goto out;
- addr_len = err;
-
-- if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
-- (err = unix_autobind(sock)) != 0)
-- goto out;
-+ if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr) {
-+ err = unix_autobind(sk);
-+ if (err)
-+ goto out;
-+ }
-
- timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
-
-@@ -1798,9 +1802,11 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- goto out;
- }
-
-- if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
-- && (err = unix_autobind(sock)) != 0)
-- goto out;
-+ if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr) {
-+ err = unix_autobind(sk);
-+ if (err)
-+ goto out;
-+ }
-
- err = -EMSGSIZE;
- if (len > sk->sk_sndbuf - 32)
---
-2.43.0
-
+++ /dev/null
-From 8d66d269fbdf2e746bb696f4723f626698608dee Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:22 +0900
-Subject: af_unix: Return an error as a pointer in unix_find_other().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit aed26f557bbc94f0c778f63d7dfe86af99208f68 ]
-
-We can return an error as a pointer and need not pass an additional
-argument to unix_find_other().
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 40 ++++++++++++++++++++++------------------
- 1 file changed, 22 insertions(+), 18 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 20a7be3effe83..0a1258b417a9d 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -952,7 +952,7 @@ static int unix_release(struct socket *sock)
- }
-
- static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
-- int type, int *error)
-+ int type)
- {
- struct inode *inode;
- struct path path;
-@@ -991,23 +991,20 @@ static struct sock *unix_find_bsd(struct net *net, struct sockaddr_un *sunaddr,
- path_put:
- path_put(&path);
- fail:
-- *error = err;
-- return NULL;
-+ return ERR_PTR(err);
- }
-
- static struct sock *unix_find_abstract(struct net *net,
- struct sockaddr_un *sunaddr,
- int addr_len, int type,
-- unsigned int hash, int *error)
-+ unsigned int hash)
- {
- struct dentry *dentry;
- struct sock *sk;
-
- sk = unix_find_socket_byname(net, sunaddr, addr_len, type ^ hash);
-- if (!sk) {
-- *error = -ECONNREFUSED;
-- return NULL;
-- }
-+ if (!sk)
-+ return ERR_PTR(-ECONNREFUSED);
-
- dentry = unix_sk(sk)->path.dentry;
- if (dentry)
-@@ -1019,15 +1016,14 @@ static struct sock *unix_find_abstract(struct net *net,
- static struct sock *unix_find_other(struct net *net,
- struct sockaddr_un *sunaddr,
- int addr_len, int type,
-- unsigned int hash, int *error)
-+ unsigned int hash)
- {
- struct sock *sk;
-
- if (sunaddr->sun_path[0])
-- sk = unix_find_bsd(net, sunaddr, type, error);
-+ sk = unix_find_bsd(net, sunaddr, type);
- else
-- sk = unix_find_abstract(net, sunaddr, addr_len, type, hash,
-- error);
-+ sk = unix_find_abstract(net, sunaddr, addr_len, type, hash);
-
- return sk;
- }
-@@ -1262,9 +1258,11 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
- }
-
- restart:
-- other = unix_find_other(net, sunaddr, alen, sock->type, hash, &err);
-- if (!other)
-+ other = unix_find_other(net, sunaddr, alen, sock->type, hash);
-+ if (IS_ERR(other)) {
-+ err = PTR_ERR(other);
- goto out;
-+ }
-
- unix_state_double_lock(sk, other);
-
-@@ -1402,9 +1400,12 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-
- restart:
- /* Find listening sock. */
-- other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
-- if (!other)
-+ other = unix_find_other(net, sunaddr, addr_len, sk->sk_type, hash);
-+ if (IS_ERR(other)) {
-+ err = PTR_ERR(other);
-+ other = NULL;
- goto out;
-+ }
-
- /* Latch state of peer */
- unix_state_lock(other);
-@@ -1873,9 +1874,12 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
- goto out_free;
-
- other = unix_find_other(net, sunaddr, namelen, sk->sk_type,
-- hash, &err);
-- if (other == NULL)
-+ hash);
-+ if (IS_ERR(other)) {
-+ err = PTR_ERR(other);
-+ other = NULL;
- goto out_free;
-+ }
- }
-
- if (sk_filter(other, skb) < 0) {
---
-2.43.0
-
+++ /dev/null
-From afe6f203c22c6b2ebb197c34f902211d748b58f3 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:27 -0700
-Subject: af_unix: Set sk->sk_state under unix_state_lock() for truly
- disconencted peer.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 26bfb8b57063f52b867f9b6c8d1742fcb5bd656c ]
-
-When a SOCK_DGRAM socket connect()s to another socket, the both sockets'
-sk->sk_state are changed to TCP_ESTABLISHED so that we can register them
-to BPF SOCKMAP.
-
-When the socket disconnects from the peer by connect(AF_UNSPEC), the state
-is set back to TCP_CLOSE.
-
-Then, the peer's state is also set to TCP_CLOSE, but the update is done
-locklessly and unconditionally.
-
-Let's say socket A connect()ed to B, B connect()ed to C, and A disconnects
-from B.
-
-After the first two connect()s, all three sockets' sk->sk_state are
-TCP_ESTABLISHED:
-
- $ ss -xa
- Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
- u_dgr ESTAB 0 0 @A 641 * 642
- u_dgr ESTAB 0 0 @B 642 * 643
- u_dgr ESTAB 0 0 @C 643 * 0
-
-And after the disconnect, B's state is TCP_CLOSE even though it's still
-connected to C and C's state is TCP_ESTABLISHED.
-
- $ ss -xa
- Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
- u_dgr UNCONN 0 0 @A 641 * 0
- u_dgr UNCONN 0 0 @B 642 * 643
- u_dgr ESTAB 0 0 @C 643 * 0
-
-In this case, we cannot register B to SOCKMAP.
-
-So, when a socket disconnects from the peer, we should not set TCP_CLOSE to
-the peer if the peer is connected to yet another socket, and this must be
-done under unix_state_lock().
-
-Note that we use WRITE_ONCE() for sk->sk_state as there are many lockless
-readers. These data-races will be fixed in the following patches.
-
-Fixes: 83301b5367a9 ("af_unix: Set TCP_ESTABLISHED for datagram sockets too")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 80f91b5ab4012..914e40697f00a 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -495,7 +495,6 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
- sk_error_report(other);
- }
- }
-- other->sk_state = TCP_CLOSE;
- }
-
- static void unix_sock_destructor(struct sock *sk)
-@@ -1277,8 +1276,15 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
-
- unix_state_double_unlock(sk, other);
-
-- if (other != old_peer)
-+ if (other != old_peer) {
- unix_dgram_disconnected(sk, old_peer);
-+
-+ unix_state_lock(old_peer);
-+ if (!unix_peer(old_peer))
-+ WRITE_ONCE(old_peer->sk_state, TCP_CLOSE);
-+ unix_state_unlock(old_peer);
-+ }
-+
- sock_put(old_peer);
- } else {
- unix_peer(sk) = other;
---
-2.43.0
-
+++ /dev/null
-From 9f19d9848e020c6dd48d37bfff3428f2376e72dc Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 24 Nov 2021 11:14:19 +0900
-Subject: af_unix: Use offsetof() instead of sizeof().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit 755662ce78d14c1a9118df921c528b1f992ded2e ]
-
-The length of the AF_UNIX socket address contains an offset to the member
-sun_path of struct sockaddr_un.
-
-Currently, the preceding member is just sun_family, and its type is
-sa_family_t and resolved to short. Therefore, the offset is represented by
-sizeof(short). However, it is not clear and fragile to changes in struct
-sockaddr_storage or sockaddr_un.
-
-This commit makes it clear and robust by rewriting sizeof() with
-offsetof().
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 19 ++++++++++++-------
- net/unix/diag.c | 3 ++-
- 2 files changed, 14 insertions(+), 8 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 262aeaea9861c..7d58067ffd3f8 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -231,7 +231,8 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp
- {
- *hashp = 0;
-
-- if (len <= sizeof(short) || len > sizeof(*sunaddr))
-+ if (len <= offsetof(struct sockaddr_un, sun_path) ||
-+ len > sizeof(*sunaddr))
- return -EINVAL;
- if (!sunaddr || sunaddr->sun_family != AF_UNIX)
- return -EINVAL;
-@@ -244,7 +245,8 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp
- * kernel address buffer.
- */
- ((char *)sunaddr)[len] = 0;
-- len = strlen(sunaddr->sun_path)+1+sizeof(short);
-+ len = strlen(sunaddr->sun_path) +
-+ offsetof(struct sockaddr_un, sun_path) + 1;
- return len;
- }
-
-@@ -967,7 +969,8 @@ static int unix_autobind(struct socket *sock)
- goto out;
-
- err = -ENOMEM;
-- addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
-+ addr = kzalloc(sizeof(*addr) +
-+ offsetof(struct sockaddr_un, sun_path) + 16, GFP_KERNEL);
- if (!addr)
- goto out;
-
-@@ -975,7 +978,8 @@ static int unix_autobind(struct socket *sock)
- refcount_set(&addr->refcnt, 1);
-
- retry:
-- addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
-+ addr->len = sprintf(addr->name->sun_path + 1, "%05x", ordernum) +
-+ offsetof(struct sockaddr_un, sun_path) + 1;
- addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
- addr->hash ^= sk->sk_type;
-
-@@ -1157,7 +1161,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- sunaddr->sun_family != AF_UNIX)
- return -EINVAL;
-
-- if (addr_len == sizeof(short))
-+ if (addr_len == offsetof(struct sockaddr_un, sun_path))
- return unix_autobind(sock);
-
- err = unix_mkname(sunaddr, addr_len, &hash);
-@@ -1607,7 +1611,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
- if (!addr) {
- sunaddr->sun_family = AF_UNIX;
- sunaddr->sun_path[0] = 0;
-- err = sizeof(short);
-+ err = offsetof(struct sockaddr_un, sun_path);
- } else {
- err = addr->len;
- memcpy(sunaddr, addr->name, addr->len);
-@@ -3271,7 +3275,8 @@ static int unix_seq_show(struct seq_file *seq, void *v)
- seq_putc(seq, ' ');
-
- i = 0;
-- len = u->addr->len - sizeof(short);
-+ len = u->addr->len -
-+ offsetof(struct sockaddr_un, sun_path);
- if (!UNIX_ABSTRACT(s))
- len--;
- else {
-diff --git a/net/unix/diag.c b/net/unix/diag.c
-index daef19932f780..006438e2e07a2 100644
---- a/net/unix/diag.c
-+++ b/net/unix/diag.c
-@@ -19,7 +19,8 @@ static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
- if (!addr)
- return 0;
-
-- return nla_put(nlskb, UNIX_DIAG_NAME, addr->len - sizeof(short),
-+ return nla_put(nlskb, UNIX_DIAG_NAME,
-+ addr->len - offsetof(struct sockaddr_un, sun_path),
- addr->name->sun_path);
- }
-
---
-2.43.0
-
+++ /dev/null
-From 0d596d22aae72b7ca666d21a079b8f63449f0407 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:39 -0700
-Subject: af_unix: Use skb_queue_empty_lockless() in unix_release_sock().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 83690b82d228b3570565ebd0b41873933238b97f ]
-
-If the socket type is SOCK_STREAM or SOCK_SEQPACKET, unix_release_sock()
-checks the length of the peer socket's recvq under unix_state_lock().
-
-However, unix_stream_read_generic() calls skb_unlink() after releasing
-the lock. Also, for SOCK_SEQPACKET, __skb_try_recv_datagram() unlinks
-skb without unix_state_lock().
-
-Thues, unix_state_lock() does not protect qlen.
-
-Let's use skb_queue_empty_lockless() in unix_release_sock().
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 85b1c0d7c287a..12099b06d7e88 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -570,7 +570,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
- unix_state_lock(skpair);
- /* No more writes */
- WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK);
-- if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
-+ if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || embrion)
- WRITE_ONCE(skpair->sk_err, ECONNRESET);
- unix_state_unlock(skpair);
- skpair->sk_state_change(skpair);
---
-2.43.0
-
+++ /dev/null
-From 27be04be4ebc9fca755aeeec004c4367ae4dc3eb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:40 -0700
-Subject: af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 5d915e584d8408211d4567c22685aae8820bfc55 ]
-
-We can dump the socket queue length via UNIX_DIAG by specifying
-UDIAG_SHOW_RQLEN.
-
-If sk->sk_state is TCP_LISTEN, we return the recv queue length,
-but here we do not hold recvq lock.
-
-Let's use skb_queue_len_lockless() in sk_diag_show_rqlen().
-
-Fixes: c9da99e6475f ("unix_diag: Fixup RQLEN extension report")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/diag.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/unix/diag.c b/net/unix/diag.c
-index 94c8f509261d0..63a0040e9fb45 100644
---- a/net/unix/diag.c
-+++ b/net/unix/diag.c
-@@ -104,7 +104,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
- struct unix_diag_rqlen rql;
-
- if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
-- rql.udiag_rqueue = sk->sk_receive_queue.qlen;
-+ rql.udiag_rqueue = skb_queue_len_lockless(&sk->sk_receive_queue);
- rql.udiag_wqueue = sk->sk_max_ack_backlog;
- } else {
- rql.udiag_rqueue = (u32) unix_inq_len(sk);
---
-2.43.0
-
+++ /dev/null
-From 17eb75b26b34dcf7b81ff17b71e88f908abe9198 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 09:52:38 -0700
-Subject: af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
-
-From: Kuniyuki Iwashima <kuniyu@amazon.com>
-
-[ Upstream commit 45d872f0e65593176d880ec148f41ad7c02e40a7 ]
-
-Once sk->sk_state is changed to TCP_LISTEN, it never changes.
-
-unix_accept() takes advantage of this characteristics; it does not
-hold the listener's unix_state_lock() and only acquires recvq lock
-to pop one skb.
-
-It means unix_state_lock() does not prevent the queue length from
-changing in unix_stream_connect().
-
-Thus, we need to use unix_recvq_full_lockless() to avoid data-race.
-
-Now we remove unix_recvq_full() as no one uses it.
-
-Note that we can remove READ_ONCE() for sk->sk_max_ack_backlog in
-unix_recvq_full_lockless() because of the following reasons:
-
- (1) For SOCK_DGRAM, it is a written-once field in unix_create1()
-
- (2) For SOCK_STREAM and SOCK_SEQPACKET, it is changed under the
- listener's unix_state_lock() in unix_listen(), and we hold
- the lock in unix_stream_connect()
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 10 ++--------
- 1 file changed, 2 insertions(+), 8 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 5c4318f64d253..3fa86d70467c2 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -190,15 +190,9 @@ static inline int unix_may_send(struct sock *sk, struct sock *osk)
- return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
- }
-
--static inline int unix_recvq_full(const struct sock *sk)
--{
-- return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
--}
--
- static inline int unix_recvq_full_lockless(const struct sock *sk)
- {
-- return skb_queue_len_lockless(&sk->sk_receive_queue) >
-- READ_ONCE(sk->sk_max_ack_backlog);
-+ return skb_queue_len_lockless(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
- }
-
- struct sock *unix_peer_get(struct sock *s)
-@@ -1429,7 +1423,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- if (other->sk_shutdown & RCV_SHUTDOWN)
- goto out_unlock;
-
-- if (unix_recvq_full(other)) {
-+ if (unix_recvq_full_lockless(other)) {
- err = -EAGAIN;
- if (!timeo)
- goto out_unlock;
---
-2.43.0
-
+++ /dev/null
-From 98c19c5237cadc9efec6b16923140e860e0ce0dd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 2 Aug 2023 08:56:29 +0200
-Subject: Bluetooth: btqca: Add WCN3988 support
-
-From: Luca Weiss <luca.weiss@fairphone.com>
-
-[ Upstream commit f904feefe60c28b6852d5625adc4a2c39426a2d9 ]
-
-Add support for the Bluetooth chip codenamed APACHE which is part of
-WCN3988.
-
-The firmware for this chip has a slightly different naming scheme
-compared to most others. For ROM Version 0x0200 we need to use
-apbtfw10.tlv + apnv10.bin and for ROM version 0x201 apbtfw11.tlv +
-apnv11.bin
-
-Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/btqca.c | 13 +++++++++++--
- drivers/bluetooth/btqca.h | 12 ++++++++++--
- drivers/bluetooth/hci_qca.c | 12 ++++++++++++
- 3 files changed, 33 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
-index b850b5de9f862..6ae806b9e77f2 100644
---- a/drivers/bluetooth/btqca.c
-+++ b/drivers/bluetooth/btqca.c
-@@ -595,11 +595,17 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- /* Firmware files to download are based on ROM version.
- * ROM version is derived from last two bytes of soc_ver.
- */
-- rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f);
-+ if (soc_type == QCA_WCN3988)
-+ rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f);
-+ else
-+ rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f);
-
- /* Download rampatch file */
- config.type = TLV_TYPE_PATCH;
-- if (qca_is_wcn399x(soc_type)) {
-+ if (soc_type == QCA_WCN3988) {
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/apbtfw%02x.tlv", rom_ver);
-+ } else if (qca_is_wcn399x(soc_type)) {
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/crbtfw%02x.tlv", rom_ver);
- } else if (soc_type == QCA_QCA6390) {
-@@ -634,6 +640,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- if (firmware_name)
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/%s", firmware_name);
-+ else if (soc_type == QCA_WCN3988)
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/apnv%02x.bin", rom_ver);
- else if (qca_is_wcn399x(soc_type)) {
- if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
- snprintf(config.fwname, sizeof(config.fwname),
-diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
-index b83bf202ea604..104bb12c88adf 100644
---- a/drivers/bluetooth/btqca.h
-+++ b/drivers/bluetooth/btqca.h
-@@ -140,6 +140,7 @@ enum qca_btsoc_type {
- QCA_INVALID = -1,
- QCA_AR3002,
- QCA_ROME,
-+ QCA_WCN3988,
- QCA_WCN3990,
- QCA_WCN3998,
- QCA_WCN3991,
-@@ -160,8 +161,15 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
- int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
- static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
- {
-- return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3991 ||
-- soc_type == QCA_WCN3998;
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ return true;
-+ default:
-+ return false;
-+ }
- }
- static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type)
- {
-diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
-index 1c2bd292ecb7c..3e67e07161969 100644
---- a/drivers/bluetooth/hci_qca.c
-+++ b/drivers/bluetooth/hci_qca.c
-@@ -1834,6 +1834,17 @@ static const struct hci_uart_proto qca_proto = {
- .dequeue = qca_dequeue,
- };
-
-+static const struct qca_device_data qca_soc_data_wcn3988 __maybe_unused = {
-+ .soc_type = QCA_WCN3988,
-+ .vregs = (struct qca_vreg []) {
-+ { "vddio", 15000 },
-+ { "vddxo", 80000 },
-+ { "vddrf", 300000 },
-+ { "vddch0", 450000 },
-+ },
-+ .num_vregs = 4,
-+};
-+
- static const struct qca_device_data qca_soc_data_wcn3990 __maybe_unused = {
- .soc_type = QCA_WCN3990,
- .vregs = (struct qca_vreg []) {
-@@ -2359,6 +2370,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = {
- { .compatible = "qcom,qca6174-bt" },
- { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
- { .compatible = "qcom,qca9377-bt" },
-+ { .compatible = "qcom,wcn3988-bt", .data = &qca_soc_data_wcn3988},
- { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},
- { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},
- { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998},
---
-2.43.0
-
+++ /dev/null
-From 3323f172de3ed2953633009e6517363a8d748667 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 19 May 2023 18:43:23 +0800
-Subject: Bluetooth: btqca: use le32_to_cpu for ver.soc_id
-
-From: Min-Hua Chen <minhuadotchen@gmail.com>
-
-[ Upstream commit 8153b738bc547878a017889d2b1cf8dd2de0e0c6 ]
-
-Use le32_to_cpu for ver.soc_id to fix the following
-sparse warning.
-
-drivers/bluetooth/btqca.c:640:24: sparse: warning: restricted
-__le32 degrades to integer
-
-Signed-off-by: Min-Hua Chen <minhuadotchen@gmail.com>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/btqca.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
-index d4ae33a5f805e..b850b5de9f862 100644
---- a/drivers/bluetooth/btqca.c
-+++ b/drivers/bluetooth/btqca.c
-@@ -635,7 +635,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/%s", firmware_name);
- else if (qca_is_wcn399x(soc_type)) {
-- if (ver.soc_id == QCA_WCN3991_SOC_ID) {
-+ if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/crnv%02xu.bin", rom_ver);
- } else {
---
-2.43.0
-
+++ /dev/null
-From 391192635689b4cde600c4d5be334134929a0e79 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 11 Mar 2023 12:13:53 +0100
-Subject: Bluetooth: hci_qca: mark OF related data as maybe unused
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-
-[ Upstream commit 44fac8a2fd2f72ee98ee41e6bc9ecc7765b5d3cc ]
-
-The driver can be compile tested with !CONFIG_OF making certain data
-unused:
-
- drivers/bluetooth/hci_qca.c:1869:37: error: ‘qca_soc_data_wcn6750’
- defined but not used [-Werror=unused-const-variable=]
- drivers/bluetooth/hci_qca.c:1853:37: error: ‘qca_soc_data_wcn3998’
- defined but not used [-Werror=unused-const-variable=]
- drivers/bluetooth/hci_qca.c:1841:37: error: ‘qca_soc_data_wcn3991’
- defined but not used [-Werror=unused-const-variable=]
- drivers/bluetooth/hci_qca.c:1830:37: error: ‘qca_soc_data_wcn3990’
- defined but not used [-Werror=unused-const-variable=]
-
-Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/hci_qca.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
-index fb71caa31daa7..1c2bd292ecb7c 100644
---- a/drivers/bluetooth/hci_qca.c
-+++ b/drivers/bluetooth/hci_qca.c
-@@ -1834,7 +1834,7 @@ static const struct hci_uart_proto qca_proto = {
- .dequeue = qca_dequeue,
- };
-
--static const struct qca_device_data qca_soc_data_wcn3990 = {
-+static const struct qca_device_data qca_soc_data_wcn3990 __maybe_unused = {
- .soc_type = QCA_WCN3990,
- .vregs = (struct qca_vreg []) {
- { "vddio", 15000 },
-@@ -1845,7 +1845,7 @@ static const struct qca_device_data qca_soc_data_wcn3990 = {
- .num_vregs = 4,
- };
-
--static const struct qca_device_data qca_soc_data_wcn3991 = {
-+static const struct qca_device_data qca_soc_data_wcn3991 __maybe_unused = {
- .soc_type = QCA_WCN3991,
- .vregs = (struct qca_vreg []) {
- { "vddio", 15000 },
-@@ -1857,7 +1857,7 @@ static const struct qca_device_data qca_soc_data_wcn3991 = {
- .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
- };
-
--static const struct qca_device_data qca_soc_data_wcn3998 = {
-+static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
- .soc_type = QCA_WCN3998,
- .vregs = (struct qca_vreg []) {
- { "vddio", 10000 },
-@@ -1868,13 +1868,13 @@ static const struct qca_device_data qca_soc_data_wcn3998 = {
- .num_vregs = 4,
- };
-
--static const struct qca_device_data qca_soc_data_qca6390 = {
-+static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
- .soc_type = QCA_QCA6390,
- .num_vregs = 0,
- .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
- };
-
--static const struct qca_device_data qca_soc_data_wcn6750 = {
-+static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = {
- .soc_type = QCA_WCN6750,
- .vregs = (struct qca_vreg []) {
- { "vddio", 5000 },
---
-2.43.0
-
+++ /dev/null
-From 2bb103505fb2d3ef1afb539e814575d11df48336 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 12 Sep 2023 17:39:57 +0800
-Subject: Bluetooth: qca: add support for QCA2066
-
-From: Tim Jiang <quic_tjiang@quicinc.com>
-
-[ Upstream commit a7f8dedb4be2cc930a29af24427b885405ecd15d ]
-
-This patch adds support for QCA2066 firmware patch and NVM downloading.
-as the RF performance of QCA2066 SOC chip from different foundries may
-vary. Therefore we use different NVM to configure them based on board ID.
-
-Changes in v2
- - optimize the function qca_generate_hsp_nvm_name
- - remove redundant debug code for function qca_read_fw_board_id
-
-Signed-off-by: Tim Jiang <quic_tjiang@quicinc.com>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/btqca.c | 68 +++++++++++++++++++++++++++++++++++++
- drivers/bluetooth/btqca.h | 5 ++-
- drivers/bluetooth/hci_qca.c | 11 ++++++
- 3 files changed, 83 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
-index b14201b7bcd04..abd621d224667 100644
---- a/drivers/bluetooth/btqca.c
-+++ b/drivers/bluetooth/btqca.c
-@@ -160,6 +160,44 @@ static int qca_send_reset(struct hci_dev *hdev)
- return 0;
- }
-
-+static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
-+{
-+ u8 cmd;
-+ struct sk_buff *skb;
-+ struct edl_event_hdr *edl;
-+ int err = 0;
-+
-+ cmd = EDL_GET_BID_REQ_CMD;
-+ skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
-+ &cmd, 0, HCI_INIT_TIMEOUT);
-+ if (IS_ERR(skb)) {
-+ err = PTR_ERR(skb);
-+ bt_dev_err(hdev, "Reading QCA board ID failed (%d)", err);
-+ return err;
-+ }
-+
-+ edl = skb_pull_data(skb, sizeof(*edl));
-+ if (!edl) {
-+ bt_dev_err(hdev, "QCA read board ID with no header");
-+ err = -EILSEQ;
-+ goto out;
-+ }
-+
-+ if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
-+ edl->rtype != EDL_GET_BID_REQ_CMD) {
-+ bt_dev_err(hdev, "QCA Wrong packet: %d %d", edl->cresp, edl->rtype);
-+ err = -EIO;
-+ goto out;
-+ }
-+
-+ *bid = (edl->data[1] << 8) + edl->data[2];
-+ bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
-+
-+out:
-+ kfree_skb(skb);
-+ return err;
-+}
-+
- int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
- {
- struct sk_buff *skb;
-@@ -575,6 +613,23 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
- }
- EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
-
-+static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
-+ struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
-+{
-+ const char *variant;
-+
-+ /* hsp gf chip */
-+ if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
-+ variant = "g";
-+ else
-+ variant = "";
-+
-+ if (bid == 0x0)
-+ snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant);
-+ else
-+ snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
-+}
-+
- int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
- const char *firmware_name)
-@@ -583,6 +638,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- int err;
- u8 rom_ver = 0;
- u32 soc_ver;
-+ u16 boardid = 0;
-
- bt_dev_dbg(hdev, "QCA setup on UART");
-
-@@ -613,6 +669,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/apbtfw%02x.tlv", rom_ver);
- break;
-+ case QCA_QCA2066:
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/hpbtfw%02x.tlv", rom_ver);
-+ break;
- case QCA_QCA6390:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/htbtfw%02x.tlv", rom_ver);
-@@ -643,6 +703,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- /* Give the controller some time to get ready to receive the NVM */
- msleep(10);
-
-+ if (soc_type == QCA_QCA2066)
-+ qca_read_fw_board_id(hdev, &boardid);
-+
- /* Download NVM configuration */
- config.type = TLV_TYPE_NVM;
- if (firmware_name) {
-@@ -665,6 +728,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/apnv%02x.bin", rom_ver);
- break;
-+ case QCA_QCA2066:
-+ qca_generate_hsp_nvm_name(config.fwname,
-+ sizeof(config.fwname), ver, rom_ver, boardid);
-+ break;
- case QCA_QCA6390:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/htnv%02x.bin", rom_ver);
-@@ -692,6 +759,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-
- switch (soc_type) {
- case QCA_WCN3991:
-+ case QCA_QCA2066:
- case QCA_QCA6390:
- case QCA_WCN6750:
- case QCA_WCN6855:
-diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
-index fa77c07daecf5..d69ecfdef2a20 100644
---- a/drivers/bluetooth/btqca.h
-+++ b/drivers/bluetooth/btqca.h
-@@ -12,6 +12,7 @@
- #define EDL_PATCH_VER_REQ_CMD (0x19)
- #define EDL_PATCH_TLV_REQ_CMD (0x1E)
- #define EDL_GET_BUILD_INFO_CMD (0x20)
-+#define EDL_GET_BID_REQ_CMD (0x23)
- #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
- #define MAX_SIZE_PER_TLV_SEGMENT (243)
- #define QCA_PRE_SHUTDOWN_CMD (0xFC08)
-@@ -45,7 +46,8 @@
- ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
-
- #define QCA_FW_BUILD_VER_LEN 255
--
-+#define QCA_HSP_GF_SOC_ID 0x1200
-+#define QCA_HSP_GF_SOC_MASK 0x0000ff00
-
- enum qca_baudrate {
- QCA_BAUDRATE_115200 = 0,
-@@ -144,6 +146,7 @@ enum qca_btsoc_type {
- QCA_WCN3990,
- QCA_WCN3998,
- QCA_WCN3991,
-+ QCA_QCA2066,
- QCA_QCA6390,
- QCA_WCN6750,
- QCA_WCN6855,
-diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
-index 62491e7610384..0800f6e62b7f0 100644
---- a/drivers/bluetooth/hci_qca.c
-+++ b/drivers/bluetooth/hci_qca.c
-@@ -1801,6 +1801,10 @@ static int qca_setup(struct hci_uart *hu)
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
-
- switch (soc_type) {
-+ case QCA_QCA2066:
-+ soc_name = "qca2066";
-+ break;
-+
- case QCA_WCN3988:
- case QCA_WCN3990:
- case QCA_WCN3991:
-@@ -1981,6 +1985,11 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
- .num_vregs = 4,
- };
-
-+static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
-+ .soc_type = QCA_QCA2066,
-+ .num_vregs = 0,
-+};
-+
- static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
- .soc_type = QCA_QCA6390,
- .num_vregs = 0,
-@@ -2492,6 +2501,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);
-
- #ifdef CONFIG_OF
- static const struct of_device_id qca_bluetooth_of_match[] = {
-+ { .compatible = "qcom,qca2066-bt", .data = &qca_soc_data_qca2066},
- { .compatible = "qcom,qca6174-bt" },
- { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
- { .compatible = "qcom,qca9377-bt" },
-@@ -2508,6 +2518,7 @@ MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
-
- #ifdef CONFIG_ACPI
- static const struct acpi_device_id qca_bluetooth_acpi_match[] = {
-+ { "QCOM2066", (kernel_ulong_t)&qca_soc_data_qca2066 },
- { "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 },
- { "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
- { "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
---
-2.43.0
-
+++ /dev/null
-From 9a92c309f6ebee38d42f674015c7ad8270d8d690 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 1 May 2024 14:34:52 +0200
-Subject: Bluetooth: qca: fix info leak when fetching fw build id
-
-From: Johan Hovold <johan+linaro@kernel.org>
-
-[ Upstream commit cda0d6a198e2a7ec6f176c36173a57bdd8af7af2 ]
-
-Add the missing sanity checks and move the 255-byte build-id buffer off
-the stack to avoid leaking stack data through debugfs in case the
-build-info reply is malformed.
-
-Fixes: c0187b0bd3e9 ("Bluetooth: btqca: Add support to read FW build version for WCN3991 BTSoC")
-Cc: stable@vger.kernel.org # 5.12
-Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/btqca.c | 25 +++++++++++++++++++++----
- drivers/bluetooth/btqca.h | 1 -
- 2 files changed, 21 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
-index abd621d224667..7011151420e48 100644
---- a/drivers/bluetooth/btqca.c
-+++ b/drivers/bluetooth/btqca.c
-@@ -98,7 +98,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
- {
- struct sk_buff *skb;
- struct edl_event_hdr *edl;
-- char cmd, build_label[QCA_FW_BUILD_VER_LEN];
-+ char *build_label;
-+ char cmd;
- int build_lbl_len, err = 0;
-
- bt_dev_dbg(hdev, "QCA read fw build info");
-@@ -113,6 +114,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
- return err;
- }
-
-+ if (skb->len < sizeof(*edl)) {
-+ err = -EILSEQ;
-+ goto out;
-+ }
-+
- edl = (struct edl_event_hdr *)(skb->data);
- if (!edl) {
- bt_dev_err(hdev, "QCA read fw build info with no header");
-@@ -128,14 +134,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
- goto out;
- }
-
-+ if (skb->len < sizeof(*edl) + 1) {
-+ err = -EILSEQ;
-+ goto out;
-+ }
-+
- build_lbl_len = edl->data[0];
-- if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
-- memcpy(build_label, edl->data + 1, build_lbl_len);
-- *(build_label + build_lbl_len) = '\0';
-+
-+ if (skb->len < sizeof(*edl) + 1 + build_lbl_len) {
-+ err = -EILSEQ;
-+ goto out;
- }
-
-+ build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
-+ if (!build_label)
-+ goto out;
-+
- hci_set_fw_info(hdev, "%s", build_label);
-
-+ kfree(build_label);
- out:
- kfree_skb(skb);
- return err;
-diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
-index d69ecfdef2a20..6a6a286bc8547 100644
---- a/drivers/bluetooth/btqca.h
-+++ b/drivers/bluetooth/btqca.h
-@@ -45,7 +45,6 @@
- #define get_soc_ver(soc_id, rom_ver) \
- ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
-
--#define QCA_FW_BUILD_VER_LEN 255
- #define QCA_HSP_GF_SOC_ID 0x1200
- #define QCA_HSP_GF_SOC_MASK 0x0000ff00
-
---
-2.43.0
-
+++ /dev/null
-From ff36c600c800a4cbeb2ae58251e1465104807b29 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 16 Aug 2023 10:06:47 +0200
-Subject: Bluetooth: qca: use switch case for soc type behavior
-
-From: Neil Armstrong <neil.armstrong@linaro.org>
-
-[ Upstream commit 691d54d0f7cb14baac1ff4af210d13c0e4897e27 ]
-
-Use switch/case to handle soc type specific behaviour,
-the permit dropping the qca_is_xxx() inline functions
-and make the code clearer and easier to update for new
-SoCs.
-
-Suggested-by: Konrad Dybcio <konrad.dybcio@linaro.org>
-Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
-Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/bluetooth/btqca.c | 87 +++++++++-----
- drivers/bluetooth/btqca.h | 36 ------
- drivers/bluetooth/hci_qca.c | 233 +++++++++++++++++++++++++++---------
- 3 files changed, 236 insertions(+), 120 deletions(-)
-
-diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
-index 6ae806b9e77f2..b14201b7bcd04 100644
---- a/drivers/bluetooth/btqca.c
-+++ b/drivers/bluetooth/btqca.c
-@@ -602,26 +602,34 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-
- /* Download rampatch file */
- config.type = TLV_TYPE_PATCH;
-- if (soc_type == QCA_WCN3988) {
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/apbtfw%02x.tlv", rom_ver);
-- } else if (qca_is_wcn399x(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/crbtfw%02x.tlv", rom_ver);
-- } else if (soc_type == QCA_QCA6390) {
-+ break;
-+ case QCA_WCN3988:
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/apbtfw%02x.tlv", rom_ver);
-+ break;
-+ case QCA_QCA6390:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/htbtfw%02x.tlv", rom_ver);
-- } else if (soc_type == QCA_WCN6750) {
-+ break;
-+ case QCA_WCN6750:
- /* Choose mbn file by default.If mbn file is not found
- * then choose tlv file
- */
- config.type = ELF_TYPE_PATCH;
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/msbtfw%02x.mbn", rom_ver);
-- } else if (soc_type == QCA_WCN6855) {
-+ break;
-+ case QCA_WCN6855:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/hpbtfw%02x.tlv", rom_ver);
-- } else {
-+ break;
-+ default:
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/rampatch_%08x.bin", soc_ver);
- }
-@@ -637,33 +645,44 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-
- /* Download NVM configuration */
- config.type = TLV_TYPE_NVM;
-- if (firmware_name)
-+ if (firmware_name) {
- snprintf(config.fwname, sizeof(config.fwname),
- "qca/%s", firmware_name);
-- else if (soc_type == QCA_WCN3988)
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/apnv%02x.bin", rom_ver);
-- else if (qca_is_wcn399x(soc_type)) {
-- if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
-+ } else {
-+ switch (soc_type) {
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) {
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/crnv%02xu.bin", rom_ver);
-+ } else {
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/crnv%02x.bin", rom_ver);
-+ }
-+ break;
-+ case QCA_WCN3988:
- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/crnv%02xu.bin", rom_ver);
-- } else {
-+ "qca/apnv%02x.bin", rom_ver);
-+ break;
-+ case QCA_QCA6390:
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/htnv%02x.bin", rom_ver);
-+ break;
-+ case QCA_WCN6750:
- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/crnv%02x.bin", rom_ver);
-+ "qca/msnv%02x.bin", rom_ver);
-+ break;
-+ case QCA_WCN6855:
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/hpnv%02x.bin", rom_ver);
-+ break;
-+
-+ default:
-+ snprintf(config.fwname, sizeof(config.fwname),
-+ "qca/nvm_%08x.bin", soc_ver);
- }
- }
-- else if (soc_type == QCA_QCA6390)
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/htnv%02x.bin", rom_ver);
-- else if (soc_type == QCA_WCN6750)
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/msnv%02x.bin", rom_ver);
-- else if (soc_type == QCA_WCN6855)
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/hpnv%02x.bin", rom_ver);
-- else
-- snprintf(config.fwname, sizeof(config.fwname),
-- "qca/nvm_%08x.bin", soc_ver);
-
- err = qca_download_firmware(hdev, &config, soc_type, rom_ver);
- if (err < 0) {
-@@ -671,16 +690,24 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
- return err;
- }
-
-- if (soc_type >= QCA_WCN3991) {
-+ switch (soc_type) {
-+ case QCA_WCN3991:
-+ case QCA_QCA6390:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- err = qca_disable_soc_logging(hdev);
- if (err < 0)
- return err;
-+ break;
-+ default:
-+ break;
- }
-
- /* WCN399x and WCN6750 supports the Microsoft vendor extension with 0xFD70 as the
- * VsMsftOpCode.
- */
- switch (soc_type) {
-+ case QCA_WCN3988:
- case QCA_WCN3990:
- case QCA_WCN3991:
- case QCA_WCN3998:
-diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
-index 104bb12c88adf..fa77c07daecf5 100644
---- a/drivers/bluetooth/btqca.h
-+++ b/drivers/bluetooth/btqca.h
-@@ -159,27 +159,6 @@ int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
- enum qca_btsoc_type);
- int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
- int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
--static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
--{
-- switch (soc_type) {
-- case QCA_WCN3988:
-- case QCA_WCN3990:
-- case QCA_WCN3991:
-- case QCA_WCN3998:
-- return true;
-- default:
-- return false;
-- }
--}
--static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type)
--{
-- return soc_type == QCA_WCN6750;
--}
--static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type)
--{
-- return soc_type == QCA_WCN6855;
--}
--
- #else
-
- static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
-@@ -207,21 +186,6 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
- return -EOPNOTSUPP;
- }
-
--static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
--{
-- return false;
--}
--
--static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type)
--{
-- return false;
--}
--
--static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type)
--{
-- return false;
--}
--
- static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
- {
- return -EOPNOTSUPP;
-diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
-index 3e67e07161969..62491e7610384 100644
---- a/drivers/bluetooth/hci_qca.c
-+++ b/drivers/bluetooth/hci_qca.c
-@@ -606,9 +606,18 @@ static int qca_open(struct hci_uart *hu)
- if (hu->serdev) {
- qcadev = serdev_device_get_drvdata(hu->serdev);
-
-- if (qca_is_wcn399x(qcadev->btsoc_type) ||
-- qca_is_wcn6750(qcadev->btsoc_type))
-+ switch (qcadev->btsoc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
- hu->init_speed = qcadev->init_speed;
-+ break;
-+
-+ default:
-+ break;
-+ }
-
- if (qcadev->oper_speed)
- hu->oper_speed = qcadev->oper_speed;
-@@ -1314,12 +1323,19 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
- msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
-
- /* Give the controller time to process the request */
-- if (qca_is_wcn399x(qca_soc_type(hu)) ||
-- qca_is_wcn6750(qca_soc_type(hu)) ||
-- qca_is_wcn6855(qca_soc_type(hu)))
-+ switch (qca_soc_type(hu)) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- usleep_range(1000, 10000);
-- else
-+ break;
-+
-+ default:
- msleep(300);
-+ }
-
- return 0;
- }
-@@ -1392,13 +1408,19 @@ static unsigned int qca_get_speed(struct hci_uart *hu,
-
- static int qca_check_speeds(struct hci_uart *hu)
- {
-- if (qca_is_wcn399x(qca_soc_type(hu)) ||
-- qca_is_wcn6750(qca_soc_type(hu)) ||
-- qca_is_wcn6855(qca_soc_type(hu))) {
-+ switch (qca_soc_type(hu)) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- if (!qca_get_speed(hu, QCA_INIT_SPEED) &&
- !qca_get_speed(hu, QCA_OPER_SPEED))
- return -EINVAL;
-- } else {
-+ break;
-+
-+ default:
- if (!qca_get_speed(hu, QCA_INIT_SPEED) ||
- !qca_get_speed(hu, QCA_OPER_SPEED))
- return -EINVAL;
-@@ -1427,14 +1449,28 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
- /* Disable flow control for wcn3990 to deassert RTS while
- * changing the baudrate of chip and host.
- */
-- if (qca_is_wcn399x(soc_type) ||
-- qca_is_wcn6750(soc_type) ||
-- qca_is_wcn6855(soc_type))
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- hci_uart_set_flow_control(hu, true);
-+ break;
-
-- if (soc_type == QCA_WCN3990) {
-+ default:
-+ break;
-+ }
-+
-+ switch (soc_type) {
-+ case QCA_WCN3990:
- reinit_completion(&qca->drop_ev_comp);
- set_bit(QCA_DROP_VENDOR_EVENT, &qca->flags);
-+ break;
-+
-+ default:
-+ break;
- }
-
- qca_baudrate = qca_get_baudrate_value(speed);
-@@ -1446,12 +1482,22 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
- host_set_baudrate(hu, speed);
-
- error:
-- if (qca_is_wcn399x(soc_type) ||
-- qca_is_wcn6750(soc_type) ||
-- qca_is_wcn6855(soc_type))
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- hci_uart_set_flow_control(hu, false);
-+ break;
-
-- if (soc_type == QCA_WCN3990) {
-+ default:
-+ break;
-+ }
-+
-+ switch (soc_type) {
-+ case QCA_WCN3990:
- /* Wait for the controller to send the vendor event
- * for the baudrate change command.
- */
-@@ -1463,6 +1509,10 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
- }
-
- clear_bit(QCA_DROP_VENDOR_EVENT, &qca->flags);
-+ break;
-+
-+ default:
-+ break;
- }
- }
-
-@@ -1627,12 +1677,20 @@ static int qca_regulator_init(struct hci_uart *hu)
- }
- }
-
-- if (qca_is_wcn399x(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
- /* Forcefully enable wcn399x to enter in to boot mode. */
- host_set_baudrate(hu, 2400);
- ret = qca_send_power_pulse(hu, false);
- if (ret)
- return ret;
-+ break;
-+
-+ default:
-+ break;
- }
-
- /* For wcn6750 need to enable gpio bt_en */
-@@ -1649,10 +1707,18 @@ static int qca_regulator_init(struct hci_uart *hu)
-
- qca_set_speed(hu, QCA_INIT_SPEED);
-
-- if (qca_is_wcn399x(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
- ret = qca_send_power_pulse(hu, true);
- if (ret)
- return ret;
-+ break;
-+
-+ default:
-+ break;
- }
-
- /* Now the device is in ready state to communicate with host.
-@@ -1686,11 +1752,17 @@ static int qca_power_on(struct hci_dev *hdev)
- if (!hu->serdev)
- return 0;
-
-- if (qca_is_wcn399x(soc_type) ||
-- qca_is_wcn6750(soc_type) ||
-- qca_is_wcn6855(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- ret = qca_regulator_init(hu);
-- } else {
-+ break;
-+
-+ default:
- qcadev = serdev_device_get_drvdata(hu->serdev);
- if (qcadev->bt_en) {
- gpiod_set_value_cansleep(qcadev->bt_en, 1);
-@@ -1713,6 +1785,7 @@ static int qca_setup(struct hci_uart *hu)
- const char *firmware_name = qca_get_firmware_name(hu);
- int ret;
- struct qca_btsoc_version ver;
-+ const char *soc_name;
-
- ret = qca_check_speeds(hu);
- if (ret)
-@@ -1727,10 +1800,26 @@ static int qca_setup(struct hci_uart *hu)
- */
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
-
-- bt_dev_info(hdev, "setting up %s",
-- qca_is_wcn399x(soc_type) ? "wcn399x" :
-- (soc_type == QCA_WCN6750) ? "wcn6750" :
-- (soc_type == QCA_WCN6855) ? "wcn6855" : "ROME/QCA6390");
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ soc_name = "wcn399x";
-+ break;
-+
-+ case QCA_WCN6750:
-+ soc_name = "wcn6750";
-+ break;
-+
-+ case QCA_WCN6855:
-+ soc_name = "wcn6855";
-+ break;
-+
-+ default:
-+ soc_name = "ROME/QCA6390";
-+ }
-+ bt_dev_info(hdev, "setting up %s", soc_name);
-
- qca->memdump_state = QCA_MEMDUMP_IDLE;
-
-@@ -1741,15 +1830,21 @@ static int qca_setup(struct hci_uart *hu)
-
- clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
-
-- if (qca_is_wcn399x(soc_type) ||
-- qca_is_wcn6750(soc_type) ||
-- qca_is_wcn6855(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
-
- ret = qca_read_soc_version(hdev, &ver, soc_type);
- if (ret)
- goto out;
-- } else {
-+ break;
-+
-+ default:
- qca_set_speed(hu, QCA_INIT_SPEED);
- }
-
-@@ -1763,9 +1858,16 @@ static int qca_setup(struct hci_uart *hu)
- qca_baudrate = qca_get_baudrate_value(speed);
- }
-
-- if (!(qca_is_wcn399x(soc_type) ||
-- qca_is_wcn6750(soc_type) ||
-- qca_is_wcn6855(soc_type))) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
-+ break;
-+
-+ default:
- /* Get QCA version information */
- ret = qca_read_soc_version(hdev, &ver, soc_type);
- if (ret)
-@@ -1941,11 +2043,18 @@ static void qca_power_shutdown(struct hci_uart *hu)
-
- qcadev = serdev_device_get_drvdata(hu->serdev);
-
-- if (qca_is_wcn399x(soc_type)) {
-+ switch (soc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
- host_set_baudrate(hu, 2400);
- qca_send_power_pulse(hu, false);
- qca_regulator_disable(qcadev);
-- } else if (soc_type == QCA_WCN6750 || soc_type == QCA_WCN6855) {
-+ break;
-+
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- gpiod_set_value_cansleep(qcadev->bt_en, 0);
- msleep(100);
- qca_regulator_disable(qcadev);
-@@ -1953,7 +2062,9 @@ static void qca_power_shutdown(struct hci_uart *hu)
- sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl);
- bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state);
- }
-- } else if (qcadev->bt_en) {
-+ break;
-+
-+ default:
- gpiod_set_value_cansleep(qcadev->bt_en, 0);
- }
-
-@@ -2078,11 +2189,18 @@ static int qca_serdev_probe(struct serdev_device *serdev)
- if (!qcadev->oper_speed)
- BT_DBG("UART will pick default operating speed");
-
-- if (data &&
-- (qca_is_wcn399x(data->soc_type) ||
-- qca_is_wcn6750(data->soc_type) ||
-- qca_is_wcn6855(data->soc_type))) {
-+ if (data)
- qcadev->btsoc_type = data->soc_type;
-+ else
-+ qcadev->btsoc_type = QCA_ROME;
-+
-+ switch (qcadev->btsoc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
- qcadev->bt_power = devm_kzalloc(&serdev->dev,
- sizeof(struct qca_power),
- GFP_KERNEL);
-@@ -2126,12 +2244,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
- BT_ERR("wcn3990 serdev registration failed");
- return err;
- }
-- } else {
-- if (data)
-- qcadev->btsoc_type = data->soc_type;
-- else
-- qcadev->btsoc_type = QCA_ROME;
-+ break;
-
-+ default:
- qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
- GPIOD_OUT_LOW);
- if (IS_ERR(qcadev->bt_en)) {
-@@ -2187,13 +2302,23 @@ static void qca_serdev_remove(struct serdev_device *serdev)
- struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
- struct qca_power *power = qcadev->bt_power;
-
-- if ((qca_is_wcn399x(qcadev->btsoc_type) ||
-- qca_is_wcn6750(qcadev->btsoc_type) ||
-- qca_is_wcn6855(qcadev->btsoc_type)) &&
-- power->vregs_on)
-- qca_power_shutdown(&qcadev->serdev_hu);
-- else if (qcadev->susclk)
-- clk_disable_unprepare(qcadev->susclk);
-+ switch (qcadev->btsoc_type) {
-+ case QCA_WCN3988:
-+ case QCA_WCN3990:
-+ case QCA_WCN3991:
-+ case QCA_WCN3998:
-+ case QCA_WCN6750:
-+ case QCA_WCN6855:
-+ if (power->vregs_on) {
-+ qca_power_shutdown(&qcadev->serdev_hu);
-+ break;
-+ }
-+ fallthrough;
-+
-+ default:
-+ if (qcadev->susclk)
-+ clk_disable_unprepare(qcadev->susclk);
-+ }
-
- hci_uart_unregister_device(&qcadev->serdev_hu);
- }
---
-2.43.0
-
+++ /dev/null
-From ee021c76a34f6d96be17d94e197d8b14a4d4b5d1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 17:00:24 +0200
-Subject: bpf: Set run context for rawtp test_run callback
-
-From: Jiri Olsa <jolsa@kernel.org>
-
-[ Upstream commit d0d1df8ba18abc57f28fb3bc053b2bf319367f2c ]
-
-syzbot reported crash when rawtp program executed through the
-test_run interface calls bpf_get_attach_cookie helper or any
-other helper that touches task->bpf_ctx pointer.
-
-Setting the run context (task->bpf_ctx pointer) for test_run
-callback.
-
-Fixes: 7adfc6c9b315 ("bpf: Add bpf_get_attach_cookie() BPF helper to access bpf_cookie value")
-Reported-by: syzbot+3ab78ff125b7979e45f9@syzkaller.appspotmail.com
-Signed-off-by: Jiri Olsa <jolsa@kernel.org>
-Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
-Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-Closes: https://syzkaller.appspot.com/bug?extid=3ab78ff125b7979e45f9
-Link: https://lore.kernel.org/bpf/20240604150024.359247-1-jolsa@kernel.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/bpf/test_run.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
-index 11d254ce3581c..a0d75c33b5d6a 100644
---- a/net/bpf/test_run.c
-+++ b/net/bpf/test_run.c
-@@ -326,10 +326,16 @@ static void
- __bpf_prog_test_run_raw_tp(void *data)
- {
- struct bpf_raw_tp_test_run_info *info = data;
-+ struct bpf_trace_run_ctx run_ctx = {};
-+ struct bpf_run_ctx *old_run_ctx;
-+
-+ old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
-
- rcu_read_lock();
- info->retval = bpf_prog_run(info->prog, info->ctx);
- rcu_read_unlock();
-+
-+ bpf_reset_run_ctx(old_run_ctx);
- }
-
- int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
---
-2.43.0
-
+++ /dev/null
-From e889b0b319a8f077d83a493209c9a0ff93c16830 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 3 Jun 2024 12:49:08 +0100
-Subject: btrfs: fix leak of qgroup extent records after transaction abort
-
-From: Filipe Manana <fdmanana@suse.com>
-
-[ Upstream commit fb33eb2ef0d88e75564983ef057b44c5b7e4fded ]
-
-Qgroup extent records are created when delayed ref heads are created and
-then released after accounting extents at btrfs_qgroup_account_extents(),
-called during the transaction commit path.
-
-If a transaction is aborted we free the qgroup records by calling
-btrfs_qgroup_destroy_extent_records() at btrfs_destroy_delayed_refs(),
-unless we don't have delayed references. We are incorrectly assuming
-that no delayed references means we don't have qgroup extents records.
-
-We can currently have no delayed references because we ran them all
-during a transaction commit and the transaction was aborted after that
-due to some error in the commit path.
-
-So fix this by ensuring we btrfs_qgroup_destroy_extent_records() at
-btrfs_destroy_delayed_refs() even if we don't have any delayed references.
-
-Reported-by: syzbot+0fecc032fa134afd49df@syzkaller.appspotmail.com
-Link: https://lore.kernel.org/linux-btrfs/0000000000004e7f980619f91835@google.com/
-Fixes: 81f7eb00ff5b ("btrfs: destroy qgroup extent records on transaction abort")
-CC: stable@vger.kernel.org # 6.1+
-Reviewed-by: Josef Bacik <josef@toxicpanda.com>
-Reviewed-by: Qu Wenruo <wqu@suse.com>
-Signed-off-by: Filipe Manana <fdmanana@suse.com>
-Signed-off-by: David Sterba <dsterba@suse.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/btrfs/disk-io.c | 10 +---------
- 1 file changed, 1 insertion(+), 9 deletions(-)
-
-diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
-index c1dfde886b1e3..092ebed754b0c 100644
---- a/fs/btrfs/disk-io.c
-+++ b/fs/btrfs/disk-io.c
-@@ -4707,19 +4707,11 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
- struct btrfs_fs_info *fs_info)
- {
- struct rb_node *node;
-- struct btrfs_delayed_ref_root *delayed_refs;
-+ struct btrfs_delayed_ref_root *delayed_refs = &trans->delayed_refs;
- struct btrfs_delayed_ref_node *ref;
- int ret = 0;
-
-- delayed_refs = &trans->delayed_refs;
--
- spin_lock(&delayed_refs->lock);
-- if (atomic_read(&delayed_refs->num_entries) == 0) {
-- spin_unlock(&delayed_refs->lock);
-- btrfs_debug(fs_info, "delayed_refs has NO entry");
-- return ret;
-- }
--
- while ((node = rb_first_cached(&delayed_refs->href_root)) != NULL) {
- struct btrfs_delayed_ref_head *head;
- struct rb_node *n;
---
-2.43.0
-
+++ /dev/null
-From ad9e4137a36db6cf7391c2f51b2fe9cd6ab0911a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 22 Mar 2022 14:43:17 -0700
-Subject: cma: factor out minimum alignment requirement
-
-From: David Hildenbrand <david@redhat.com>
-
-[ Upstream commit e16faf26780fc0c8dd693ea9ee8420a7706cb2f5 ]
-
-Patch series "mm: enforce pageblock_order < MAX_ORDER".
-
-Having pageblock_order >= MAX_ORDER seems to be able to happen in corner
-cases and some parts of the kernel are not prepared for it.
-
-For example, Aneesh has shown [1] that such kernels can be compiled on
-ppc64 with 64k base pages by setting FORCE_MAX_ZONEORDER=8, which will
-run into a WARN_ON_ONCE(order >= MAX_ORDER) in comapction code right
-during boot.
-
-We can get pageblock_order >= MAX_ORDER when the default hugetlb size is
-bigger than the maximum allocation granularity of the buddy, in which
-case we are no longer talking about huge pages but instead gigantic
-pages.
-
-Having pageblock_order >= MAX_ORDER can only make alloc_contig_range()
-of such gigantic pages more likely to succeed.
-
-Reliable use of gigantic pages either requires boot time allcoation or
-CMA, no need to overcomplicate some places in the kernel to optimize for
-corner cases that are broken in other areas of the kernel.
-
-This patch (of 2):
-
-Let's enforce pageblock_order < MAX_ORDER and simplify.
-
-Especially patch #1 can be regarded a cleanup before:
- [PATCH v5 0/6] Use pageblock_order for cma and alloc_contig_range
- alignment. [2]
-
-[1] https://lkml.kernel.org/r/87r189a2ks.fsf@linux.ibm.com
-[2] https://lkml.kernel.org/r/20220211164135.1803616-1-zi.yan@sent.com
-
-Link: https://lkml.kernel.org/r/20220214174132.219303-2-david@redhat.com
-Signed-off-by: David Hildenbrand <david@redhat.com>
-Reviewed-by: Zi Yan <ziy@nvidia.com>
-Acked-by: Rob Herring <robh@kernel.org>
-Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
-Cc: Michael Ellerman <mpe@ellerman.id.au>
-Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-Cc: Paul Mackerras <paulus@samba.org>
-Cc: Frank Rowand <frowand.list@gmail.com>
-Cc: Michael S. Tsirkin <mst@redhat.com>
-Cc: Christoph Hellwig <hch@lst.de>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Robin Murphy <robin.murphy@arm.com>
-Cc: Minchan Kim <minchan@kernel.org>
-Cc: Vlastimil Babka <vbabka@suse.cz>
-Cc: John Garry via iommu <iommu@lists.linux-foundation.org>
-
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-Stable-dep-of: b174f139bdc8 ("mm/cma: drop incorrect alignment check in cma_init_reserved_mem")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/powerpc/include/asm/fadump-internal.h | 5 -----
- arch/powerpc/kernel/fadump.c | 2 +-
- drivers/of/of_reserved_mem.c | 9 +++------
- include/linux/cma.h | 9 +++++++++
- kernel/dma/contiguous.c | 4 +---
- mm/cma.c | 20 +++++---------------
- 6 files changed, 19 insertions(+), 30 deletions(-)
-
-diff --git a/arch/powerpc/include/asm/fadump-internal.h b/arch/powerpc/include/asm/fadump-internal.h
-index 8d61c8f3fec47..d06b2be645326 100644
---- a/arch/powerpc/include/asm/fadump-internal.h
-+++ b/arch/powerpc/include/asm/fadump-internal.h
-@@ -19,11 +19,6 @@
-
- #define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
-
--/* Alignment per CMA requirement. */
--#define FADUMP_CMA_ALIGNMENT (PAGE_SIZE << \
-- max_t(unsigned long, MAX_ORDER - 1, \
-- pageblock_order))
--
- /* FAD commands */
- #define FADUMP_REGISTER 1
- #define FADUMP_UNREGISTER 2
-diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
-index d496dc5151aa1..35b142ad0e40e 100644
---- a/arch/powerpc/kernel/fadump.c
-+++ b/arch/powerpc/kernel/fadump.c
-@@ -544,7 +544,7 @@ int __init fadump_reserve_mem(void)
- if (!fw_dump.nocma) {
- fw_dump.boot_memory_size =
- ALIGN(fw_dump.boot_memory_size,
-- FADUMP_CMA_ALIGNMENT);
-+ CMA_MIN_ALIGNMENT_BYTES);
- }
- #endif
-
-diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
-index 9e949ddcb1464..6ec668ae2d6fa 100644
---- a/drivers/of/of_reserved_mem.c
-+++ b/drivers/of/of_reserved_mem.c
-@@ -22,6 +22,7 @@
- #include <linux/slab.h>
- #include <linux/memblock.h>
- #include <linux/kmemleak.h>
-+#include <linux/cma.h>
-
- #include "of_private.h"
-
-@@ -117,12 +118,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
- if (IS_ENABLED(CONFIG_CMA)
- && of_flat_dt_is_compatible(node, "shared-dma-pool")
- && of_get_flat_dt_prop(node, "reusable", NULL)
-- && !nomap) {
-- unsigned long order =
-- max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
--
-- align = max(align, (phys_addr_t)PAGE_SIZE << order);
-- }
-+ && !nomap)
-+ align = max_t(phys_addr_t, align, CMA_MIN_ALIGNMENT_BYTES);
-
- prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
- if (prop) {
-diff --git a/include/linux/cma.h b/include/linux/cma.h
-index 53fd8c3cdbd04..1b302e204c09b 100644
---- a/include/linux/cma.h
-+++ b/include/linux/cma.h
-@@ -20,6 +20,15 @@
-
- #define CMA_MAX_NAME 64
-
-+/*
-+ * TODO: once the buddy -- especially pageblock merging and alloc_contig_range()
-+ * -- can deal with only some pageblocks of a higher-order page being
-+ * MIGRATE_CMA, we can use pageblock_nr_pages.
-+ */
-+#define CMA_MIN_ALIGNMENT_PAGES max_t(phys_addr_t, MAX_ORDER_NR_PAGES, \
-+ pageblock_nr_pages)
-+#define CMA_MIN_ALIGNMENT_BYTES (PAGE_SIZE * CMA_MIN_ALIGNMENT_PAGES)
-+
- struct cma;
-
- extern unsigned long totalcma_pages;
-diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
-index 3d63d91cba5cf..6ea80ae426228 100644
---- a/kernel/dma/contiguous.c
-+++ b/kernel/dma/contiguous.c
-@@ -399,8 +399,6 @@ static const struct reserved_mem_ops rmem_cma_ops = {
-
- static int __init rmem_cma_setup(struct reserved_mem *rmem)
- {
-- phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
-- phys_addr_t mask = align - 1;
- unsigned long node = rmem->fdt_node;
- bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
- struct cma *cma;
-@@ -416,7 +414,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
- of_get_flat_dt_prop(node, "no-map", NULL))
- return -EINVAL;
-
-- if ((rmem->base & mask) || (rmem->size & mask)) {
-+ if (!IS_ALIGNED(rmem->base | rmem->size, CMA_MIN_ALIGNMENT_BYTES)) {
- pr_err("Reserved memory: incorrect alignment of CMA region\n");
- return -EINVAL;
- }
-diff --git a/mm/cma.c b/mm/cma.c
-index 26967c70e9c73..5208aee4f45ad 100644
---- a/mm/cma.c
-+++ b/mm/cma.c
-@@ -169,7 +169,6 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
- struct cma **res_cma)
- {
- struct cma *cma;
-- phys_addr_t alignment;
-
- /* Sanity checks */
- if (cma_area_count == ARRAY_SIZE(cma_areas)) {
-@@ -180,15 +179,12 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
- if (!size || !memblock_is_region_reserved(base, size))
- return -EINVAL;
-
-- /* ensure minimal alignment required by mm core */
-- alignment = PAGE_SIZE <<
-- max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
--
- /* alignment should be aligned with order_per_bit */
-- if (!IS_ALIGNED(alignment >> PAGE_SHIFT, 1 << order_per_bit))
-+ if (!IS_ALIGNED(CMA_MIN_ALIGNMENT_PAGES, 1 << order_per_bit))
- return -EINVAL;
-
-- if (ALIGN(base, alignment) != base || ALIGN(size, alignment) != size)
-+ /* ensure minimal alignment required by mm core */
-+ if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
- return -EINVAL;
-
- /*
-@@ -263,14 +259,8 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
- if (alignment && !is_power_of_2(alignment))
- return -EINVAL;
-
-- /*
-- * Sanitise input arguments.
-- * Pages both ends in CMA area could be merged into adjacent unmovable
-- * migratetype page by page allocator's buddy algorithm. In the case,
-- * you couldn't get a contiguous memory, which is not what we want.
-- */
-- alignment = max(alignment, (phys_addr_t)PAGE_SIZE <<
-- max_t(unsigned long, MAX_ORDER - 1, pageblock_order));
-+ /* Sanitise input arguments. */
-+ alignment = max_t(phys_addr_t, alignment, CMA_MIN_ALIGNMENT_BYTES);
- if (fixed && base & (alignment - 1)) {
- ret = -EINVAL;
- pr_err("Region at %pa must be aligned to %pa bytes\n",
---
-2.43.0
-
+++ /dev/null
-From aa5d2fb014aac47ef4182aca7ff801989be6f6a0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 26 Jul 2022 15:25:55 +0800
-Subject: drm/amd/display: Clean up some inconsistent indenting
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
-
-[ Upstream commit 1da2fcc435114ea5a65d7e15fc31b4d0ce11113c ]
-
-Eliminate the follow smatch warning:
-
-drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_srv.c:622
-dmub_srv_cmd_execute() warn: inconsistent indenting.
-
-Reported-by: Abaci Robot <abaci@linux.alibaba.com>
-Reviewed-by: Christian König <christian.koenig@amd.com>
-Signed-off-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-Stable-dep-of: 892b41b16f61 ("drm/amd/display: Fix incorrect DSC instance for MST")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 72 +++++++++----------
- 1 file changed, 36 insertions(+), 36 deletions(-)
-
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-index ed2f6802b0e20..fc0f6b0089ba0 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-@@ -1315,9 +1315,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -1421,9 +1421,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx || !pipe_ctx->stream)
-@@ -1506,9 +1506,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -1610,9 +1610,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx || !pipe_ctx->stream)
-@@ -1695,9 +1695,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -1799,9 +1799,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx || !pipe_ctx->stream)
-@@ -1880,9 +1880,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -1981,9 +1981,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx || !pipe_ctx->stream)
-@@ -2060,9 +2060,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -2121,9 +2121,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -2197,9 +2197,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
-@@ -2273,9 +2273,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-- break;
-+ if (pipe_ctx && pipe_ctx->stream &&
-+ pipe_ctx->stream->link == aconnector->dc_link)
-+ break;
- }
-
- if (!pipe_ctx) {
---
-2.43.0
-
+++ /dev/null
-From d0bfe387038bc7b99948146c0ed1e5dccf9c366d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 27 Dec 2022 20:04:15 +0300
-Subject: drm/amd/display: drop unnecessary NULL checks in debugfs
-
-From: Alexey Kodanev <aleksei.kodanev@bell-sw.com>
-
-[ Upstream commit f8e12e770e8049917f82387033b3cf44bc43b915 ]
-
-pipe_ctx pointer cannot be NULL when getting the address of
-an element of the pipe_ctx array. Moreover, the MAX_PIPES is
-defined as 6, so pipe_ctx is not NULL after the loop either.
-
-Detected using the static analysis tool - Svace.
-
-Signed-off-by: Alexey Kodanev <aleksei.kodanev@bell-sw.com>
-Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-Stable-dep-of: 892b41b16f61 ("drm/amd/display: Fix incorrect DSC instance for MST")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 72 +++++--------------
- 1 file changed, 16 insertions(+), 56 deletions(-)
-
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-index fc0f6b0089ba0..939734eecf709 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-@@ -1315,16 +1315,11 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -1421,12 +1416,12 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx || !pipe_ctx->stream)
-+ if (!pipe_ctx->stream)
- goto done;
-
- // Get CRTC state
-@@ -1506,16 +1501,11 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -1610,12 +1600,12 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx || !pipe_ctx->stream)
-+ if (!pipe_ctx->stream)
- goto done;
-
- // Safely get CRTC state
-@@ -1695,16 +1685,11 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -1799,12 +1784,12 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx || !pipe_ctx->stream)
-+ if (!pipe_ctx->stream)
- goto done;
-
- // Get CRTC state
-@@ -1880,16 +1865,11 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -1981,12 +1961,12 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx || !pipe_ctx->stream)
-+ if (!pipe_ctx->stream)
- goto done;
-
- // Get CRTC state
-@@ -2060,16 +2040,11 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -2121,16 +2096,11 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -2197,16 +2167,11 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
-@@ -2273,16 +2238,11 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
-- if (pipe_ctx && pipe_ctx->stream &&
-+ if (pipe_ctx->stream &&
- pipe_ctx->stream->link == aconnector->dc_link)
- break;
- }
-
-- if (!pipe_ctx) {
-- kfree(rd_buf);
-- return -ENXIO;
-- }
--
- dsc = pipe_ctx->stream_res.dsc;
- if (dsc)
- dsc->funcs->dsc_read_state(dsc, &dsc_state);
---
-2.43.0
-
+++ /dev/null
-From 961b1d2a069a0595b8b3afd8b7094469d9ca1308 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 13 Feb 2024 14:26:06 -0500
-Subject: drm/amd/display: Fix incorrect DSC instance for MST
-
-From: Hersen Wu <hersenxs.wu@amd.com>
-
-[ Upstream commit 892b41b16f6163e6556545835abba668fcab4eea ]
-
-[Why] DSC debugfs, such as dp_dsc_clock_en_read,
-use aconnector->dc_link to find pipe_ctx for display.
-Displays connected to MST hub share the same dc_link.
-DSC instance is from pipe_ctx. This causes incorrect
-DSC instance for display connected to MST hub.
-
-[How] Add aconnector->sink check to find pipe_ctx.
-
-CC: stable@vger.kernel.org
-Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
-Signed-off-by: Hersen Wu <hersenxs.wu@amd.com>
-Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 48 ++++++++++++++-----
- 1 file changed, 36 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-index 939734eecf709..8ccd43ec68829 100644
---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
-@@ -1316,7 +1316,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1417,7 +1419,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1502,7 +1506,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1601,7 +1607,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1686,7 +1694,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1785,7 +1795,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1866,7 +1878,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -1962,7 +1976,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -2041,7 +2057,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -2097,7 +2115,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -2168,7 +2188,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
-@@ -2239,7 +2261,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
- for (i = 0; i < MAX_PIPES; i++) {
- pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx->stream &&
-- pipe_ctx->stream->link == aconnector->dc_link)
-+ pipe_ctx->stream->link == aconnector->dc_link &&
-+ pipe_ctx->stream->sink &&
-+ pipe_ctx->stream->sink == aconnector->dc_sink)
- break;
- }
-
---
-2.43.0
-
+++ /dev/null
-From ae2b75cf1443bc3a0d7f3bcbf705251d594ad09c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 16 Sep 2021 19:55:39 -0400
-Subject: drm/amd/display: Handle Y carry-over in VCP X.Y calculation
-
-From: George Shen <george.shen@amd.com>
-
-[ Upstream commit 3626a6aebe62ce7067cdc460c0c644e9445386bb ]
-
-[Why/How]
-Theoretically rare corner case where ceil(Y) results in rounding
-up to an integer. If this happens, the 1 should be carried over to
-the X value.
-
-Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
-Acked-by: Anson Jacob <Anson.Jacob@amd.com>
-Signed-off-by: George Shen <george.shen@amd.com>
-Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
-index cf364ae931386..d0799c426a84d 100644
---- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
-+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
-@@ -644,6 +644,12 @@ void enc1_stream_encoder_set_throttled_vcp_size(
- x),
- 26));
-
-+ // If y rounds up to integer, carry it over to x.
-+ if (y >> 26) {
-+ x += 1;
-+ y = 0;
-+ }
-+
- REG_SET_2(DP_MSE_RATE_CNTL, 0,
- DP_MSE_RATE_X, x,
- DP_MSE_RATE_Y, y);
---
-2.43.0
-
+++ /dev/null
-From e8887fbea9da99ad55188ba9a0829f88c1d44ef0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 10 May 2024 03:28:59 +0800
-Subject: ftrace: Fix possible use-after-free issue in ftrace_location()
-
-From: Zheng Yejian <zhengyejian1@huawei.com>
-
-[ Upstream commit e60b613df8b6253def41215402f72986fee3fc8d ]
-
-KASAN reports a bug:
-
- BUG: KASAN: use-after-free in ftrace_location+0x90/0x120
- Read of size 8 at addr ffff888141d40010 by task insmod/424
- CPU: 8 PID: 424 Comm: insmod Tainted: G W 6.9.0-rc2+
- [...]
- Call Trace:
- <TASK>
- dump_stack_lvl+0x68/0xa0
- print_report+0xcf/0x610
- kasan_report+0xb5/0xe0
- ftrace_location+0x90/0x120
- register_kprobe+0x14b/0xa40
- kprobe_init+0x2d/0xff0 [kprobe_example]
- do_one_initcall+0x8f/0x2d0
- do_init_module+0x13a/0x3c0
- load_module+0x3082/0x33d0
- init_module_from_file+0xd2/0x130
- __x64_sys_finit_module+0x306/0x440
- do_syscall_64+0x68/0x140
- entry_SYSCALL_64_after_hwframe+0x71/0x79
-
-The root cause is that, in lookup_rec(), ftrace record of some address
-is being searched in ftrace pages of some module, but those ftrace pages
-at the same time is being freed in ftrace_release_mod() as the
-corresponding module is being deleted:
-
- CPU1 | CPU2
- register_kprobes() { | delete_module() {
- check_kprobe_address_safe() { |
- arch_check_ftrace_location() { |
- ftrace_location() { |
- lookup_rec() // USE! | ftrace_release_mod() // Free!
-
-To fix this issue:
- 1. Hold rcu lock as accessing ftrace pages in ftrace_location_range();
- 2. Use ftrace_location_range() instead of lookup_rec() in
- ftrace_location();
- 3. Call synchronize_rcu() before freeing any ftrace pages both in
- ftrace_process_locs()/ftrace_release_mod()/ftrace_free_mem().
-
-Link: https://lore.kernel.org/linux-trace-kernel/20240509192859.1273558-1-zhengyejian1@huawei.com
-
-Cc: stable@vger.kernel.org
-Cc: <mhiramat@kernel.org>
-Cc: <mark.rutland@arm.com>
-Cc: <mathieu.desnoyers@efficios.com>
-Fixes: ae6aa16fdc16 ("kprobes: introduce ftrace based optimization")
-Suggested-by: Steven Rostedt <rostedt@goodmis.org>
-Signed-off-by: Zheng Yejian <zhengyejian1@huawei.com>
-Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- kernel/trace/ftrace.c | 39 +++++++++++++++++++++++----------------
- 1 file changed, 23 insertions(+), 16 deletions(-)
-
-diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
-index 3dce1a107a7c7..780f1c0563f58 100644
---- a/kernel/trace/ftrace.c
-+++ b/kernel/trace/ftrace.c
-@@ -1566,12 +1566,15 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
- unsigned long ftrace_location_range(unsigned long start, unsigned long end)
- {
- struct dyn_ftrace *rec;
-+ unsigned long ip = 0;
-
-+ rcu_read_lock();
- rec = lookup_rec(start, end);
- if (rec)
-- return rec->ip;
-+ ip = rec->ip;
-+ rcu_read_unlock();
-
-- return 0;
-+ return ip;
- }
-
- /**
-@@ -1584,25 +1587,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
- */
- unsigned long ftrace_location(unsigned long ip)
- {
-- struct dyn_ftrace *rec;
-+ unsigned long loc;
- unsigned long offset;
- unsigned long size;
-
-- rec = lookup_rec(ip, ip);
-- if (!rec) {
-+ loc = ftrace_location_range(ip, ip);
-+ if (!loc) {
- if (!kallsyms_lookup_size_offset(ip, &size, &offset))
- goto out;
-
- /* map sym+0 to __fentry__ */
- if (!offset)
-- rec = lookup_rec(ip, ip + size - 1);
-+ loc = ftrace_location_range(ip, ip + size - 1);
- }
-
-- if (rec)
-- return rec->ip;
--
- out:
-- return 0;
-+ return loc;
- }
-
- /**
-@@ -6325,6 +6325,8 @@ static int ftrace_process_locs(struct module *mod,
- /* We should have used all pages unless we skipped some */
- if (pg_unuse) {
- WARN_ON(!skipped);
-+ /* Need to synchronize with ftrace_location_range() */
-+ synchronize_rcu();
- ftrace_free_pages(pg_unuse);
- }
- return ret;
-@@ -6507,6 +6509,9 @@ void ftrace_release_mod(struct module *mod)
- out_unlock:
- mutex_unlock(&ftrace_lock);
-
-+ /* Need to synchronize with ftrace_location_range() */
-+ if (tmp_page)
-+ synchronize_rcu();
- for (pg = tmp_page; pg; pg = tmp_page) {
-
- /* Needs to be called outside of ftrace_lock */
-@@ -6829,6 +6834,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
- unsigned long start = (unsigned long)(start_ptr);
- unsigned long end = (unsigned long)(end_ptr);
- struct ftrace_page **last_pg = &ftrace_pages_start;
-+ struct ftrace_page *tmp_page = NULL;
- struct ftrace_page *pg;
- struct dyn_ftrace *rec;
- struct dyn_ftrace key;
-@@ -6872,12 +6878,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
- ftrace_update_tot_cnt--;
- if (!pg->index) {
- *last_pg = pg->next;
-- if (pg->records) {
-- free_pages((unsigned long)pg->records, pg->order);
-- ftrace_number_of_pages -= 1 << pg->order;
-- }
-- ftrace_number_of_groups--;
-- kfree(pg);
-+ pg->next = tmp_page;
-+ tmp_page = pg;
- pg = container_of(last_pg, struct ftrace_page, next);
- if (!(*last_pg))
- ftrace_pages = pg;
-@@ -6894,6 +6896,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
- clear_func_from_hashes(func);
- kfree(func);
- }
-+ /* Need to synchronize with ftrace_location_range() */
-+ if (tmp_page) {
-+ synchronize_rcu();
-+ ftrace_free_pages(tmp_page);
-+ }
- }
-
- void __init ftrace_free_init_mem(void)
---
-2.43.0
-
+++ /dev/null
-From d4c7d1bb33b84b3c22d3f68f53d01f37f26edcb7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 13 Mar 2024 11:16:32 +1300
-Subject: i2c: acpi: Unbind mux adapters before delete
-
-From: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
-
-[ Upstream commit 3f858bbf04dbac934ac279aaee05d49eb9910051 ]
-
-There is an issue with ACPI overlay table removal specifically related
-to I2C multiplexers.
-
-Consider an ACPI SSDT Overlay that defines a PCA9548 I2C mux on an
-existing I2C bus. When this table is loaded we see the creation of a
-device for the overall PCA9548 chip and 8 further devices - one
-i2c_adapter each for the mux channels. These are all bound to their
-ACPI equivalents via an eventual invocation of acpi_bind_one().
-
-When we unload the SSDT overlay we run into the problem. The ACPI
-devices are deleted as normal via acpi_device_del_work_fn() and the
-acpi_device_del_list.
-
-However, the following warning and stack trace is output as the
-deletion does not go smoothly:
-------------[ cut here ]------------
-kernfs: can not remove 'physical_node', no directory
-WARNING: CPU: 1 PID: 11 at fs/kernfs/dir.c:1674 kernfs_remove_by_name_ns+0xb9/0xc0
-Modules linked in:
-CPU: 1 PID: 11 Comm: kworker/u128:0 Not tainted 6.8.0-rc6+ #1
-Hardware name: congatec AG conga-B7E3/conga-B7E3, BIOS 5.13 05/16/2023
-Workqueue: kacpi_hotplug acpi_device_del_work_fn
-RIP: 0010:kernfs_remove_by_name_ns+0xb9/0xc0
-Code: e4 00 48 89 ef e8 07 71 db ff 5b b8 fe ff ff ff 5d 41 5c 41 5d e9 a7 55 e4 00 0f 0b eb a6 48 c7 c7 f0 38 0d 9d e8 97 0a d5 ff <0f> 0b eb dc 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
-RSP: 0018:ffff9f864008fb28 EFLAGS: 00010286
-RAX: 0000000000000000 RBX: ffff8ef90a8d4940 RCX: 0000000000000000
-RDX: ffff8f000e267d10 RSI: ffff8f000e25c780 RDI: ffff8f000e25c780
-RBP: ffff8ef9186f9870 R08: 0000000000013ffb R09: 00000000ffffbfff
-R10: 00000000ffffbfff R11: ffff8f000e0a0000 R12: ffff9f864008fb50
-R13: ffff8ef90c93dd60 R14: ffff8ef9010d0958 R15: ffff8ef9186f98c8
-FS: 0000000000000000(0000) GS:ffff8f000e240000(0000) knlGS:0000000000000000
-CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
-CR2: 00007f48f5253a08 CR3: 00000003cb82e000 CR4: 00000000003506f0
-Call Trace:
- <TASK>
- ? kernfs_remove_by_name_ns+0xb9/0xc0
- ? __warn+0x7c/0x130
- ? kernfs_remove_by_name_ns+0xb9/0xc0
- ? report_bug+0x171/0x1a0
- ? handle_bug+0x3c/0x70
- ? exc_invalid_op+0x17/0x70
- ? asm_exc_invalid_op+0x1a/0x20
- ? kernfs_remove_by_name_ns+0xb9/0xc0
- ? kernfs_remove_by_name_ns+0xb9/0xc0
- acpi_unbind_one+0x108/0x180
- device_del+0x18b/0x490
- ? srso_return_thunk+0x5/0x5f
- ? srso_return_thunk+0x5/0x5f
- device_unregister+0xd/0x30
- i2c_del_adapter.part.0+0x1bf/0x250
- i2c_mux_del_adapters+0xa1/0xe0
- i2c_device_remove+0x1e/0x80
- device_release_driver_internal+0x19a/0x200
- bus_remove_device+0xbf/0x100
- device_del+0x157/0x490
- ? __pfx_device_match_fwnode+0x10/0x10
- ? srso_return_thunk+0x5/0x5f
- device_unregister+0xd/0x30
- i2c_acpi_notify+0x10f/0x140
- notifier_call_chain+0x58/0xd0
- blocking_notifier_call_chain+0x3a/0x60
- acpi_device_del_work_fn+0x85/0x1d0
- process_one_work+0x134/0x2f0
- worker_thread+0x2f0/0x410
- ? __pfx_worker_thread+0x10/0x10
- kthread+0xe3/0x110
- ? __pfx_kthread+0x10/0x10
- ret_from_fork+0x2f/0x50
- ? __pfx_kthread+0x10/0x10
- ret_from_fork_asm+0x1b/0x30
- </TASK>
----[ end trace 0000000000000000 ]---
-...
-repeated 7 more times, 1 for each channel of the mux
-...
-
-The issue is that the binding of the ACPI devices to their peer I2C
-adapters is not correctly cleaned up. Digging deeper into the issue we
-see that the deletion order is such that the ACPI devices matching the
-mux channel i2c adapters are deleted first during the SSDT overlay
-removal. For each of the channels we see a call to i2c_acpi_notify()
-with ACPI_RECONFIG_DEVICE_REMOVE but, because these devices are not
-actually i2c_clients, nothing is done for them.
-
-Later on, after each of the mux channels has been dealt with, we come
-to delete the i2c_client representing the PCA9548 device. This is the
-call stack we see above, whereby the kernel cleans up the i2c_client
-including destruction of the mux and its channel adapters. At this
-point we do attempt to unbind from the ACPI peers but those peers no
-longer exist and so we hit the kernfs errors.
-
-The fix is to augment i2c_acpi_notify() to handle i2c_adapters. But,
-given that the life cycle of the adapters is linked to the i2c_client,
-instead of deleting the i2c_adapters during the i2c_acpi_notify(), we
-just trigger unbinding of the ACPI device from the adapter device, and
-allow the clean up of the adapter to continue in the way it always has.
-
-Signed-off-by: Hamish Martin <hamish.martin@alliedtelesis.co.nz>
-Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
-Fixes: 525e6fabeae2 ("i2c / ACPI: add support for ACPI reconfigure notifications")
-Cc: <stable@vger.kernel.org> # v4.8+
-Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/i2c/i2c-core-acpi.c | 19 +++++++++++++++----
- 1 file changed, 15 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
-index 29a482abf1eed..6ce05441178a3 100644
---- a/drivers/i2c/i2c-core-acpi.c
-+++ b/drivers/i2c/i2c-core-acpi.c
-@@ -424,6 +424,11 @@ static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
- return i2c_find_device_by_fwnode(acpi_fwnode_handle(adev));
- }
-
-+static struct i2c_adapter *i2c_acpi_find_adapter_by_adev(struct acpi_device *adev)
-+{
-+ return i2c_find_adapter_by_fwnode(acpi_fwnode_handle(adev));
-+}
-+
- static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
- void *arg)
- {
-@@ -450,11 +455,17 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
- break;
-
- client = i2c_acpi_find_client_by_adev(adev);
-- if (!client)
-- break;
-+ if (client) {
-+ i2c_unregister_device(client);
-+ put_device(&client->dev);
-+ }
-+
-+ adapter = i2c_acpi_find_adapter_by_adev(adev);
-+ if (adapter) {
-+ acpi_unbind_one(&adapter->dev);
-+ put_device(&adapter->dev);
-+ }
-
-- i2c_unregister_device(client);
-- put_device(&client->dev);
- break;
- }
-
---
-2.43.0
-
+++ /dev/null
-From 6b51c4fd816685f533c92a285f28dd79b97699c4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Jan 2023 10:54:21 +0000
-Subject: i2c: add fwnode APIs
-
-From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-
-[ Upstream commit 373c612d72461ddaea223592df31e62c934aae61 ]
-
-Add fwnode APIs for finding and getting I2C adapters, which will be
-used by the SFP code. These are passed the fwnode corresponding to
-the adapter, and return the I2C adapter. It is the responsibility of
-the caller to find the appropriate fwnode.
-
-We keep the DT and ACPI interfaces, but where appropriate, recode them
-to use the fwnode interfaces internally.
-
-Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-Signed-off-by: Wolfram Sang <wsa@kernel.org>
-Stable-dep-of: 3f858bbf04db ("i2c: acpi: Unbind mux adapters before delete")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/i2c/i2c-core-acpi.c | 13 +----
- drivers/i2c/i2c-core-base.c | 98 +++++++++++++++++++++++++++++++++++++
- drivers/i2c/i2c-core-of.c | 66 -------------------------
- include/linux/i2c.h | 24 +++++++--
- 4 files changed, 120 insertions(+), 81 deletions(-)
-
-diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
-index 546cc935e035a..29a482abf1eed 100644
---- a/drivers/i2c/i2c-core-acpi.c
-+++ b/drivers/i2c/i2c-core-acpi.c
-@@ -421,18 +421,7 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle);
-
- static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
- {
-- struct device *dev;
-- struct i2c_client *client;
--
-- dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
-- if (!dev)
-- return NULL;
--
-- client = i2c_verify_client(dev);
-- if (!client)
-- put_device(dev);
--
-- return client;
-+ return i2c_find_device_by_fwnode(acpi_fwnode_handle(adev));
- }
-
- static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
-diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
-index 1810a994c07ca..505eebbc98a09 100644
---- a/drivers/i2c/i2c-core-base.c
-+++ b/drivers/i2c/i2c-core-base.c
-@@ -1009,6 +1009,35 @@ void i2c_unregister_device(struct i2c_client *client)
- }
- EXPORT_SYMBOL_GPL(i2c_unregister_device);
-
-+/**
-+ * i2c_find_device_by_fwnode() - find an i2c_client for the fwnode
-+ * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_client
-+ *
-+ * Look up and return the &struct i2c_client corresponding to the @fwnode.
-+ * If no client can be found, or @fwnode is NULL, this returns NULL.
-+ *
-+ * The user must call put_device(&client->dev) once done with the i2c client.
-+ */
-+struct i2c_client *i2c_find_device_by_fwnode(struct fwnode_handle *fwnode)
-+{
-+ struct i2c_client *client;
-+ struct device *dev;
-+
-+ if (!fwnode)
-+ return NULL;
-+
-+ dev = bus_find_device_by_fwnode(&i2c_bus_type, fwnode);
-+ if (!dev)
-+ return NULL;
-+
-+ client = i2c_verify_client(dev);
-+ if (!client)
-+ put_device(dev);
-+
-+ return client;
-+}
-+EXPORT_SYMBOL(i2c_find_device_by_fwnode);
-+
-
- static const struct i2c_device_id dummy_id[] = {
- { "dummy", 0 },
-@@ -1764,6 +1793,75 @@ int devm_i2c_add_adapter(struct device *dev, struct i2c_adapter *adapter)
- }
- EXPORT_SYMBOL_GPL(devm_i2c_add_adapter);
-
-+static int i2c_dev_or_parent_fwnode_match(struct device *dev, const void *data)
-+{
-+ if (dev_fwnode(dev) == data)
-+ return 1;
-+
-+ if (dev->parent && dev_fwnode(dev->parent) == data)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * i2c_find_adapter_by_fwnode() - find an i2c_adapter for the fwnode
-+ * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter
-+ *
-+ * Look up and return the &struct i2c_adapter corresponding to the @fwnode.
-+ * If no adapter can be found, or @fwnode is NULL, this returns NULL.
-+ *
-+ * The user must call put_device(&adapter->dev) once done with the i2c adapter.
-+ */
-+struct i2c_adapter *i2c_find_adapter_by_fwnode(struct fwnode_handle *fwnode)
-+{
-+ struct i2c_adapter *adapter;
-+ struct device *dev;
-+
-+ if (!fwnode)
-+ return NULL;
-+
-+ dev = bus_find_device(&i2c_bus_type, NULL, fwnode,
-+ i2c_dev_or_parent_fwnode_match);
-+ if (!dev)
-+ return NULL;
-+
-+ adapter = i2c_verify_adapter(dev);
-+ if (!adapter)
-+ put_device(dev);
-+
-+ return adapter;
-+}
-+EXPORT_SYMBOL(i2c_find_adapter_by_fwnode);
-+
-+/**
-+ * i2c_get_adapter_by_fwnode() - find an i2c_adapter for the fwnode
-+ * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter
-+ *
-+ * Look up and return the &struct i2c_adapter corresponding to the @fwnode,
-+ * and increment the adapter module's use count. If no adapter can be found,
-+ * or @fwnode is NULL, this returns NULL.
-+ *
-+ * The user must call i2c_put_adapter(adapter) once done with the i2c adapter.
-+ * Note that this is different from i2c_find_adapter_by_node().
-+ */
-+struct i2c_adapter *i2c_get_adapter_by_fwnode(struct fwnode_handle *fwnode)
-+{
-+ struct i2c_adapter *adapter;
-+
-+ adapter = i2c_find_adapter_by_fwnode(fwnode);
-+ if (!adapter)
-+ return NULL;
-+
-+ if (!try_module_get(adapter->owner)) {
-+ put_device(&adapter->dev);
-+ adapter = NULL;
-+ }
-+
-+ return adapter;
-+}
-+EXPORT_SYMBOL(i2c_get_adapter_by_fwnode);
-+
- static void i2c_parse_timing(struct device *dev, char *prop_name, u32 *cur_val_p,
- u32 def_val, bool use_def)
- {
-diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
-index 3ed74aa4b44bb..bce6b796e04c2 100644
---- a/drivers/i2c/i2c-core-of.c
-+++ b/drivers/i2c/i2c-core-of.c
-@@ -113,72 +113,6 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
- of_node_put(bus);
- }
-
--static int of_dev_or_parent_node_match(struct device *dev, const void *data)
--{
-- if (dev->of_node == data)
-- return 1;
--
-- if (dev->parent)
-- return dev->parent->of_node == data;
--
-- return 0;
--}
--
--/* must call put_device() when done with returned i2c_client device */
--struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
--{
-- struct device *dev;
-- struct i2c_client *client;
--
-- dev = bus_find_device_by_of_node(&i2c_bus_type, node);
-- if (!dev)
-- return NULL;
--
-- client = i2c_verify_client(dev);
-- if (!client)
-- put_device(dev);
--
-- return client;
--}
--EXPORT_SYMBOL(of_find_i2c_device_by_node);
--
--/* must call put_device() when done with returned i2c_adapter device */
--struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
--{
-- struct device *dev;
-- struct i2c_adapter *adapter;
--
-- dev = bus_find_device(&i2c_bus_type, NULL, node,
-- of_dev_or_parent_node_match);
-- if (!dev)
-- return NULL;
--
-- adapter = i2c_verify_adapter(dev);
-- if (!adapter)
-- put_device(dev);
--
-- return adapter;
--}
--EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
--
--/* must call i2c_put_adapter() when done with returned i2c_adapter device */
--struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
--{
-- struct i2c_adapter *adapter;
--
-- adapter = of_find_i2c_adapter_by_node(node);
-- if (!adapter)
-- return NULL;
--
-- if (!try_module_get(adapter->owner)) {
-- put_device(&adapter->dev);
-- adapter = NULL;
-- }
--
-- return adapter;
--}
--EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
--
- static const struct of_device_id*
- i2c_of_match_device_sysfs(const struct of_device_id *matches,
- struct i2c_client *client)
-diff --git a/include/linux/i2c.h b/include/linux/i2c.h
-index 2ce3efbe9198a..f071a121ed914 100644
---- a/include/linux/i2c.h
-+++ b/include/linux/i2c.h
-@@ -954,15 +954,33 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr);
-
- #endif /* I2C */
-
-+/* must call put_device() when done with returned i2c_client device */
-+struct i2c_client *i2c_find_device_by_fwnode(struct fwnode_handle *fwnode);
-+
-+/* must call put_device() when done with returned i2c_adapter device */
-+struct i2c_adapter *i2c_find_adapter_by_fwnode(struct fwnode_handle *fwnode);
-+
-+/* must call i2c_put_adapter() when done with returned i2c_adapter device */
-+struct i2c_adapter *i2c_get_adapter_by_fwnode(struct fwnode_handle *fwnode);
-+
- #if IS_ENABLED(CONFIG_OF)
- /* must call put_device() when done with returned i2c_client device */
--struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
-+static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
-+{
-+ return i2c_find_device_by_fwnode(of_fwnode_handle(node));
-+}
-
- /* must call put_device() when done with returned i2c_adapter device */
--struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
-+static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
-+{
-+ return i2c_find_adapter_by_fwnode(of_fwnode_handle(node));
-+}
-
- /* must call i2c_put_adapter() when done with returned i2c_adapter device */
--struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node);
-+static inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
-+{
-+ return i2c_get_adapter_by_fwnode(of_fwnode_handle(node));
-+}
-
- const struct of_device_id
- *i2c_of_match_device(const struct of_device_id *matches,
---
-2.43.0
-
+++ /dev/null
-From 5ec1f0816a672a4ab79c27ec0ab1f6d269ccb84a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 26 Mar 2024 12:37:00 +0100
-Subject: iio: accel: mxc4005: Reset chip on probe() and resume()
-
-From: Hans de Goede <hdegoede@redhat.com>
-
-[ Upstream commit 6b8cffdc4a31e4a72f75ecd1bc13fbf0dafee390 ]
-
-On some designs the chip is not properly reset when powered up at boot or
-after a suspend/resume cycle.
-
-Use the sw-reset feature to ensure that the chip is in a clean state
-after probe() / resume() and in the case of resume() restore the settings
-(scale, trigger-enabled).
-
-Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218578
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Link: https://lore.kernel.org/r/20240326113700.56725-3-hdegoede@redhat.com
-Cc: <Stable@vger.kernel.org>
-Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/iio/accel/mxc4005.c | 68 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 68 insertions(+)
-
-diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
-index ffae30e5eb5be..8db5611134da4 100644
---- a/drivers/iio/accel/mxc4005.c
-+++ b/drivers/iio/accel/mxc4005.c
-@@ -5,6 +5,7 @@
- * Copyright (c) 2014, Intel Corporation.
- */
-
-+#include <linux/delay.h>
- #include <linux/module.h>
- #include <linux/i2c.h>
- #include <linux/iio/iio.h>
-@@ -36,6 +37,7 @@
-
- #define MXC4005_REG_INT_CLR1 0x01
- #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
-+#define MXC4005_REG_INT_CLR1_SW_RST 0x10
-
- #define MXC4005_REG_CONTROL 0x0D
- #define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5)
-@@ -43,6 +45,9 @@
-
- #define MXC4005_REG_DEVICE_ID 0x0E
-
-+/* Datasheet does not specify a reset time, this is a conservative guess */
-+#define MXC4005_RESET_TIME_US 2000
-+
- enum mxc4005_axis {
- AXIS_X,
- AXIS_Y,
-@@ -66,6 +71,8 @@ struct mxc4005_data {
- s64 timestamp __aligned(8);
- } scan;
- bool trigger_enabled;
-+ unsigned int control;
-+ unsigned int int_mask1;
- };
-
- /*
-@@ -349,6 +356,7 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
- return ret;
- }
-
-+ data->int_mask1 = val;
- data->trigger_enabled = state;
- mutex_unlock(&data->mutex);
-
-@@ -384,6 +392,13 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
-
- dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
-
-+ ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
-+ MXC4005_REG_INT_CLR1_SW_RST);
-+ if (ret < 0)
-+ return dev_err_probe(data->dev, ret, "resetting chip\n");
-+
-+ fsleep(MXC4005_RESET_TIME_US);
-+
- ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
- if (ret < 0)
- return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
-@@ -480,6 +495,58 @@ static int mxc4005_probe(struct i2c_client *client,
- return devm_iio_device_register(&client->dev, indio_dev);
- }
-
-+static int mxc4005_suspend(struct device *dev)
-+{
-+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
-+ struct mxc4005_data *data = iio_priv(indio_dev);
-+ int ret;
-+
-+ /* Save control to restore it on resume */
-+ ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
-+ if (ret < 0)
-+ dev_err(data->dev, "failed to read reg_control\n");
-+
-+ return ret;
-+}
-+
-+static int mxc4005_resume(struct device *dev)
-+{
-+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
-+ struct mxc4005_data *data = iio_priv(indio_dev);
-+ int ret;
-+
-+ ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
-+ MXC4005_REG_INT_CLR1_SW_RST);
-+ if (ret) {
-+ dev_err(data->dev, "failed to reset chip: %d\n", ret);
-+ return ret;
-+ }
-+
-+ fsleep(MXC4005_RESET_TIME_US);
-+
-+ ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
-+ if (ret) {
-+ dev_err(data->dev, "failed to restore control register\n");
-+ return ret;
-+ }
-+
-+ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
-+ if (ret) {
-+ dev_err(data->dev, "failed to restore interrupt 0 mask\n");
-+ return ret;
-+ }
-+
-+ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
-+ if (ret) {
-+ dev_err(data->dev, "failed to restore interrupt 1 mask\n");
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
-+
- static const struct acpi_device_id mxc4005_acpi_match[] = {
- {"MXC4005", 0},
- {"MXC6655", 0},
-@@ -498,6 +565,7 @@ static struct i2c_driver mxc4005_driver = {
- .driver = {
- .name = MXC4005_DRV_NAME,
- .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
-+ .pm = pm_sleep_ptr(&mxc4005_pm_ops),
- },
- .probe = mxc4005_probe,
- .id_table = mxc4005_id,
---
-2.43.0
-
+++ /dev/null
-From 04c9445b5ceb19ca07135611ecd02104fb94ff93 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 19:35:49 +0000
-Subject: ipv6: fix possible race in __fib6_drop_pcpu_from()
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit b01e1c030770ff3b4fe37fc7cc6bca03f594133f ]
-
-syzbot found a race in __fib6_drop_pcpu_from() [1]
-
-If compiler reads more than once (*ppcpu_rt),
-second read could read NULL, if another cpu clears
-the value in rt6_get_pcpu_route().
-
-Add a READ_ONCE() to prevent this race.
-
-Also add rcu_read_lock()/rcu_read_unlock() because
-we rely on RCU protection while dereferencing pcpu_rt.
-
-[1]
-
-Oops: general protection fault, probably for non-canonical address 0xdffffc0000000012: 0000 [#1] PREEMPT SMP KASAN PTI
-KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097]
-CPU: 0 PID: 7543 Comm: kworker/u8:17 Not tainted 6.10.0-rc1-syzkaller-00013-g2bfcfd584ff5 #0
-Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024
-Workqueue: netns cleanup_net
- RIP: 0010:__fib6_drop_pcpu_from.part.0+0x10a/0x370 net/ipv6/ip6_fib.c:984
-Code: f8 48 c1 e8 03 80 3c 28 00 0f 85 16 02 00 00 4d 8b 3f 4d 85 ff 74 31 e8 74 a7 fa f7 49 8d bf 90 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 1e 02 00 00 49 8b 87 90 00 00 00 48 8b 0c 24 48
-RSP: 0018:ffffc900040df070 EFLAGS: 00010206
-RAX: 0000000000000012 RBX: 0000000000000001 RCX: ffffffff89932e16
-RDX: ffff888049dd1e00 RSI: ffffffff89932d7c RDI: 0000000000000091
-RBP: dffffc0000000000 R08: 0000000000000005 R09: 0000000000000007
-R10: 0000000000000001 R11: 0000000000000006 R12: ffff88807fa080b8
-R13: fffffbfff1a9a07d R14: ffffed100ff41022 R15: 0000000000000001
-FS: 0000000000000000(0000) GS:ffff8880b9200000(0000) knlGS:0000000000000000
-CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
-CR2: 0000001b32c26000 CR3: 000000005d56e000 CR4: 00000000003526f0
-DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
-DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
-Call Trace:
- <TASK>
- __fib6_drop_pcpu_from net/ipv6/ip6_fib.c:966 [inline]
- fib6_drop_pcpu_from net/ipv6/ip6_fib.c:1027 [inline]
- fib6_purge_rt+0x7f2/0x9f0 net/ipv6/ip6_fib.c:1038
- fib6_del_route net/ipv6/ip6_fib.c:1998 [inline]
- fib6_del+0xa70/0x17b0 net/ipv6/ip6_fib.c:2043
- fib6_clean_node+0x426/0x5b0 net/ipv6/ip6_fib.c:2205
- fib6_walk_continue+0x44f/0x8d0 net/ipv6/ip6_fib.c:2127
- fib6_walk+0x182/0x370 net/ipv6/ip6_fib.c:2175
- fib6_clean_tree+0xd7/0x120 net/ipv6/ip6_fib.c:2255
- __fib6_clean_all+0x100/0x2d0 net/ipv6/ip6_fib.c:2271
- rt6_sync_down_dev net/ipv6/route.c:4906 [inline]
- rt6_disable_ip+0x7ed/0xa00 net/ipv6/route.c:4911
- addrconf_ifdown.isra.0+0x117/0x1b40 net/ipv6/addrconf.c:3855
- addrconf_notify+0x223/0x19e0 net/ipv6/addrconf.c:3778
- notifier_call_chain+0xb9/0x410 kernel/notifier.c:93
- call_netdevice_notifiers_info+0xbe/0x140 net/core/dev.c:1992
- call_netdevice_notifiers_extack net/core/dev.c:2030 [inline]
- call_netdevice_notifiers net/core/dev.c:2044 [inline]
- dev_close_many+0x333/0x6a0 net/core/dev.c:1585
- unregister_netdevice_many_notify+0x46d/0x19f0 net/core/dev.c:11193
- unregister_netdevice_many net/core/dev.c:11276 [inline]
- default_device_exit_batch+0x85b/0xae0 net/core/dev.c:11759
- ops_exit_list+0x128/0x180 net/core/net_namespace.c:178
- cleanup_net+0x5b7/0xbf0 net/core/net_namespace.c:640
- process_one_work+0x9fb/0x1b60 kernel/workqueue.c:3231
- process_scheduled_works kernel/workqueue.c:3312 [inline]
- worker_thread+0x6c8/0xf70 kernel/workqueue.c:3393
- kthread+0x2c1/0x3a0 kernel/kthread.c:389
- ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
- ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
-
-Fixes: d52d3997f843 ("ipv6: Create percpu rt6_info")
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Cc: Martin KaFai Lau <kafai@fb.com>
-Link: https://lore.kernel.org/r/20240604193549.981839-1-edumazet@google.com
-Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/ipv6/ip6_fib.c | 6 +++++-
- net/ipv6/route.c | 1 +
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
-index c0ff5ee490e7b..7d09193c14445 100644
---- a/net/ipv6/ip6_fib.c
-+++ b/net/ipv6/ip6_fib.c
-@@ -961,6 +961,7 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,
- if (!fib6_nh->rt6i_pcpu)
- return;
-
-+ rcu_read_lock();
- /* release the reference to this fib entry from
- * all of its cached pcpu routes
- */
-@@ -969,7 +970,9 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,
- struct rt6_info *pcpu_rt;
-
- ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu);
-- pcpu_rt = *ppcpu_rt;
-+
-+ /* Paired with xchg() in rt6_get_pcpu_route() */
-+ pcpu_rt = READ_ONCE(*ppcpu_rt);
-
- /* only dropping the 'from' reference if the cached route
- * is using 'match'. The cached pcpu_rt->from only changes
-@@ -983,6 +986,7 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,
- fib6_info_release(from);
- }
- }
-+ rcu_read_unlock();
- }
-
- struct fib6_nh_pcpu_arg {
-diff --git a/net/ipv6/route.c b/net/ipv6/route.c
-index 3bc3a30363e19..2c60270c5798b 100644
---- a/net/ipv6/route.c
-+++ b/net/ipv6/route.c
-@@ -1398,6 +1398,7 @@ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
- struct rt6_info *prev, **p;
-
- p = this_cpu_ptr(res->nh->rt6i_pcpu);
-+ /* Paired with READ_ONCE() in __fib6_drop_pcpu_from() */
- prev = xchg(p, NULL);
- if (prev) {
- dst_dev_put(&prev->dst);
---
-2.43.0
-
+++ /dev/null
-From 93568aa9547731c6c2711c5caa0d7a8c76e3787f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 31 May 2024 13:26:34 +0000
-Subject: ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit c0b98ac1cc104f48763cdb27b1e9ac25fd81fc90 ]
-
-As explained in commit 1378817486d6 ("tipc: block BH
-before using dst_cache"), net/core/dst_cache.c
-helpers need to be called with BH disabled.
-
-Disabling preemption in seg6_output_core() is not good enough,
-because seg6_output_core() is called from process context,
-lwtunnel_output() only uses rcu_read_lock().
-
-We might be interrupted by a softirq, re-enter seg6_output_core()
-and corrupt dst_cache data structures.
-
-Fix the race by using local_bh_disable() instead of
-preempt_disable().
-
-Apply a similar change in seg6_input_core().
-
-Fixes: fa79581ea66c ("ipv6: sr: fix several BUGs when preemption is enabled")
-Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels")
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Cc: David Lebrun <dlebrun@google.com>
-Acked-by: Paolo Abeni <pabeni@redhat.com>
-Link: https://lore.kernel.org/r/20240531132636.2637995-4-edumazet@google.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/ipv6/seg6_iptunnel.c | 14 ++++++--------
- 1 file changed, 6 insertions(+), 8 deletions(-)
-
-diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
-index f98bb719190be..135712649d25f 100644
---- a/net/ipv6/seg6_iptunnel.c
-+++ b/net/ipv6/seg6_iptunnel.c
-@@ -332,9 +332,8 @@ static int seg6_input_core(struct net *net, struct sock *sk,
-
- slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
-
-- preempt_disable();
-+ local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
-- preempt_enable();
-
- skb_dst_drop(skb);
-
-@@ -342,14 +341,13 @@ static int seg6_input_core(struct net *net, struct sock *sk,
- ip6_route_input(skb);
- dst = skb_dst(skb);
- if (!dst->error) {
-- preempt_disable();
- dst_cache_set_ip6(&slwt->cache, dst,
- &ipv6_hdr(skb)->saddr);
-- preempt_enable();
- }
- } else {
- skb_dst_set(skb, dst);
- }
-+ local_bh_enable();
-
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
-@@ -405,9 +403,9 @@ static int seg6_output_core(struct net *net, struct sock *sk,
-
- slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
-
-- preempt_disable();
-+ local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
-- preempt_enable();
-+ local_bh_enable();
-
- if (unlikely(!dst)) {
- struct ipv6hdr *hdr = ipv6_hdr(skb);
-@@ -427,9 +425,9 @@ static int seg6_output_core(struct net *net, struct sock *sk,
- goto drop;
- }
-
-- preempt_disable();
-+ local_bh_disable();
- dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
-- preempt_enable();
-+ local_bh_enable();
- }
-
- skb_dst_drop(skb);
---
-2.43.0
-
+++ /dev/null
-From 667d7657871bd1a717461173de1518aac7a9233c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 11 Oct 2023 09:18:27 +0200
-Subject: misc/pvpanic: deduplicate common code
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Thomas Weißschuh <linux@weissschuh.net>
-
-[ Upstream commit c1426d392aebc51da4944d950d89e483e43f6f14 ]
-
-pvpanic-mmio.c and pvpanic-pci.c share a lot of code.
-Refactor it into pvpanic.c where it doesn't have to be kept in sync
-manually and where the core logic can be understood more easily.
-
-No functional change.
-
-Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
-Link: https://lore.kernel.org/r/20231011-pvpanic-cleanup-v2-1-4b21d56f779f@weissschuh.net
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: ee59be35d7a8 ("misc/pvpanic-pci: register attributes via pci_driver")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/misc/pvpanic/pvpanic-mmio.c | 58 +---------------------
- drivers/misc/pvpanic/pvpanic-pci.c | 58 +---------------------
- drivers/misc/pvpanic/pvpanic.c | 76 ++++++++++++++++++++++++++++-
- drivers/misc/pvpanic/pvpanic.h | 10 +---
- 4 files changed, 80 insertions(+), 122 deletions(-)
-
-diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c
-index eb97167c03fb4..9715798acce3d 100644
---- a/drivers/misc/pvpanic/pvpanic-mmio.c
-+++ b/drivers/misc/pvpanic/pvpanic-mmio.c
-@@ -24,52 +24,9 @@ MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
- MODULE_DESCRIPTION("pvpanic-mmio device driver");
- MODULE_LICENSE("GPL");
-
--static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%x\n", pi->capability);
--}
--static DEVICE_ATTR_RO(capability);
--
--static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%x\n", pi->events);
--}
--
--static ssize_t events_store(struct device *dev, struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-- unsigned int tmp;
-- int err;
--
-- err = kstrtouint(buf, 16, &tmp);
-- if (err)
-- return err;
--
-- if ((tmp & pi->capability) != tmp)
-- return -EINVAL;
--
-- pi->events = tmp;
--
-- return count;
--}
--static DEVICE_ATTR_RW(events);
--
--static struct attribute *pvpanic_mmio_dev_attrs[] = {
-- &dev_attr_capability.attr,
-- &dev_attr_events.attr,
-- NULL
--};
--ATTRIBUTE_GROUPS(pvpanic_mmio_dev);
--
- static int pvpanic_mmio_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-- struct pvpanic_instance *pi;
- struct resource *res;
- void __iomem *base;
-
-@@ -92,18 +49,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev)
- return -EINVAL;
- }
-
-- pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
-- if (!pi)
-- return -ENOMEM;
--
-- pi->base = base;
-- pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
--
-- /* initialize capability by RDPT */
-- pi->capability &= ioread8(base);
-- pi->events = pi->capability;
--
-- return devm_pvpanic_probe(dev, pi);
-+ return devm_pvpanic_probe(dev, base);
- }
-
- static const struct of_device_id pvpanic_mmio_match[] = {
-@@ -123,7 +69,7 @@ static struct platform_driver pvpanic_mmio_driver = {
- .name = "pvpanic-mmio",
- .of_match_table = pvpanic_mmio_match,
- .acpi_match_table = pvpanic_device_ids,
-- .dev_groups = pvpanic_mmio_dev_groups,
-+ .dev_groups = pvpanic_dev_groups,
- },
- .probe = pvpanic_mmio_probe,
- };
-diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
-index 07eddb5ea30fa..689af4c28c2a9 100644
---- a/drivers/misc/pvpanic/pvpanic-pci.c
-+++ b/drivers/misc/pvpanic/pvpanic-pci.c
-@@ -22,51 +22,8 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
- MODULE_DESCRIPTION("pvpanic device driver");
- MODULE_LICENSE("GPL");
-
--static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%x\n", pi->capability);
--}
--static DEVICE_ATTR_RO(capability);
--
--static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
--
-- return sysfs_emit(buf, "%x\n", pi->events);
--}
--
--static ssize_t events_store(struct device *dev, struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-- unsigned int tmp;
-- int err;
--
-- err = kstrtouint(buf, 16, &tmp);
-- if (err)
-- return err;
--
-- if ((tmp & pi->capability) != tmp)
-- return -EINVAL;
--
-- pi->events = tmp;
--
-- return count;
--}
--static DEVICE_ATTR_RW(events);
--
--static struct attribute *pvpanic_pci_dev_attrs[] = {
-- &dev_attr_capability.attr,
-- &dev_attr_events.attr,
-- NULL
--};
--ATTRIBUTE_GROUPS(pvpanic_pci_dev);
--
- static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
-- struct pvpanic_instance *pi;
- void __iomem *base;
- int ret;
-
-@@ -78,18 +35,7 @@ static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
- if (!base)
- return -ENOMEM;
-
-- pi = devm_kmalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
-- if (!pi)
-- return -ENOMEM;
--
-- pi->base = base;
-- pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
--
-- /* initlize capability by RDPT */
-- pi->capability &= ioread8(base);
-- pi->events = pi->capability;
--
-- return devm_pvpanic_probe(&pdev->dev, pi);
-+ return devm_pvpanic_probe(&pdev->dev, base);
- }
-
- static const struct pci_device_id pvpanic_pci_id_tbl[] = {
-@@ -103,7 +49,7 @@ static struct pci_driver pvpanic_pci_driver = {
- .id_table = pvpanic_pci_id_tbl,
- .probe = pvpanic_pci_probe,
- .driver = {
-- .dev_groups = pvpanic_pci_dev_groups,
-+ .dev_groups = pvpanic_dev_groups,
- },
- };
- module_pci_driver(pvpanic_pci_driver);
-diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c
-index 049a120063489..305b367e0ce34 100644
---- a/drivers/misc/pvpanic/pvpanic.c
-+++ b/drivers/misc/pvpanic/pvpanic.c
-@@ -7,6 +7,7 @@
- * Copyright (C) 2021 Oracle.
- */
-
-+#include <linux/device.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/kexec.h>
-@@ -26,6 +27,13 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
- MODULE_DESCRIPTION("pvpanic device driver");
- MODULE_LICENSE("GPL");
-
-+struct pvpanic_instance {
-+ void __iomem *base;
-+ unsigned int capability;
-+ unsigned int events;
-+ struct list_head list;
-+};
-+
- static struct list_head pvpanic_list;
- static spinlock_t pvpanic_lock;
-
-@@ -81,11 +89,75 @@ static void pvpanic_remove(void *param)
- spin_unlock(&pvpanic_lock);
- }
-
--int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi)
-+static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct pvpanic_instance *pi = dev_get_drvdata(dev);
-+
-+ return sysfs_emit(buf, "%x\n", pi->capability);
-+}
-+static DEVICE_ATTR_RO(capability);
-+
-+static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct pvpanic_instance *pi = dev_get_drvdata(dev);
-+
-+ return sysfs_emit(buf, "%x\n", pi->events);
-+}
-+
-+static ssize_t events_store(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct pvpanic_instance *pi = dev_get_drvdata(dev);
-+ unsigned int tmp;
-+ int err;
-+
-+ err = kstrtouint(buf, 16, &tmp);
-+ if (err)
-+ return err;
-+
-+ if ((tmp & pi->capability) != tmp)
-+ return -EINVAL;
-+
-+ pi->events = tmp;
-+
-+ return count;
-+}
-+static DEVICE_ATTR_RW(events);
-+
-+static struct attribute *pvpanic_dev_attrs[] = {
-+ &dev_attr_capability.attr,
-+ &dev_attr_events.attr,
-+ NULL
-+};
-+
-+static const struct attribute_group pvpanic_dev_group = {
-+ .attrs = pvpanic_dev_attrs,
-+};
-+
-+const struct attribute_group *pvpanic_dev_groups[] = {
-+ &pvpanic_dev_group,
-+ NULL
-+};
-+EXPORT_SYMBOL_GPL(pvpanic_dev_groups);
-+
-+int devm_pvpanic_probe(struct device *dev, void __iomem *base)
- {
-- if (!pi || !pi->base)
-+ struct pvpanic_instance *pi;
-+
-+ if (!base)
- return -EINVAL;
-
-+ pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
-+ if (!pi)
-+ return -ENOMEM;
-+
-+ pi->base = base;
-+ pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
-+
-+ /* initlize capability by RDPT */
-+ pi->capability &= ioread8(base);
-+ pi->events = pi->capability;
-+
- spin_lock(&pvpanic_lock);
- list_add(&pi->list, &pvpanic_list);
- spin_unlock(&pvpanic_lock);
-diff --git a/drivers/misc/pvpanic/pvpanic.h b/drivers/misc/pvpanic/pvpanic.h
-index 4935459517548..46ffb10438adf 100644
---- a/drivers/misc/pvpanic/pvpanic.h
-+++ b/drivers/misc/pvpanic/pvpanic.h
-@@ -8,13 +8,7 @@
- #ifndef PVPANIC_H_
- #define PVPANIC_H_
-
--struct pvpanic_instance {
-- void __iomem *base;
-- unsigned int capability;
-- unsigned int events;
-- struct list_head list;
--};
--
--int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi);
-+int devm_pvpanic_probe(struct device *dev, void __iomem *base);
-+extern const struct attribute_group *pvpanic_dev_groups[];
-
- #endif /* PVPANIC_H_ */
---
-2.43.0
-
+++ /dev/null
-From d12d57cd2c7be519b412445578f9d583ff77f91a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 11 Apr 2024 23:33:51 +0200
-Subject: misc/pvpanic-pci: register attributes via pci_driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Thomas Weißschuh <linux@weissschuh.net>
-
-[ Upstream commit ee59be35d7a8be7fcaa2d61fb89734ab5c25e4ee ]
-
-In __pci_register_driver(), the pci core overwrites the dev_groups field of
-the embedded struct device_driver with the dev_groups from the outer
-struct pci_driver unconditionally.
-
-Set dev_groups in the pci_driver to make sure it is used.
-
-This was broken since the introduction of pvpanic-pci.
-
-Fixes: db3a4f0abefd ("misc/pvpanic: add PCI driver")
-Cc: stable@vger.kernel.org
-Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
-Fixes: ded13b9cfd59 ("PCI: Add support for dev_groups to struct pci_driver")
-Link: https://lore.kernel.org/r/20240411-pvpanic-pci-dev-groups-v1-1-db8cb69f1b09@weissschuh.net
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/misc/pvpanic/pvpanic-pci.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
-diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
-index 689af4c28c2a9..2494725dfacfa 100644
---- a/drivers/misc/pvpanic/pvpanic-pci.c
-+++ b/drivers/misc/pvpanic/pvpanic-pci.c
-@@ -48,8 +48,6 @@ static struct pci_driver pvpanic_pci_driver = {
- .name = "pvpanic-pci",
- .id_table = pvpanic_pci_id_tbl,
- .probe = pvpanic_pci_probe,
-- .driver = {
-- .dev_groups = pvpanic_dev_groups,
-- },
-+ .dev_groups = pvpanic_dev_groups,
- };
- module_pci_driver(pvpanic_pci_driver);
---
-2.43.0
-
+++ /dev/null
-From 6f73cf81e6438c334ae03321c915e9d376501fd8 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 9 May 2022 18:20:50 -0700
-Subject: mm: avoid unnecessary flush on change_huge_pmd()
-
-From: Nadav Amit <namit@vmware.com>
-
-[ Upstream commit 4f83145721f362c2f4d312edc4755269a2069488 ]
-
-Calls to change_protection_range() on THP can trigger, at least on x86,
-two TLB flushes for one page: one immediately, when pmdp_invalidate() is
-called by change_huge_pmd(), and then another one later (that can be
-batched) when change_protection_range() finishes.
-
-The first TLB flush is only necessary to prevent the dirty bit (and with a
-lesser importance the access bit) from changing while the PTE is modified.
-However, this is not necessary as the x86 CPUs set the dirty-bit
-atomically with an additional check that the PTE is (still) present. One
-caveat is Intel's Knights Landing that has a bug and does not do so.
-
-Leverage this behavior to eliminate the unnecessary TLB flush in
-change_huge_pmd(). Introduce a new arch specific pmdp_invalidate_ad()
-that only invalidates the access and dirty bit from further changes.
-
-Link: https://lkml.kernel.org/r/20220401180821.1986781-4-namit@vmware.com
-Signed-off-by: Nadav Amit <namit@vmware.com>
-Cc: Andrea Arcangeli <aarcange@redhat.com>
-Cc: Andrew Cooper <andrew.cooper3@citrix.com>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: Peter Xu <peterx@redhat.com>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Will Deacon <will@kernel.org>
-Cc: Yu Zhao <yuzhao@google.com>
-Cc: Nick Piggin <npiggin@gmail.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: 3a5a8d343e1c ("mm: fix race between __split_huge_pmd_locked() and GUP-fast")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/x86/include/asm/pgtable.h | 5 +++++
- arch/x86/mm/pgtable.c | 10 ++++++++++
- include/linux/pgtable.h | 20 ++++++++++++++++++++
- mm/huge_memory.c | 4 ++--
- mm/pgtable-generic.c | 8 ++++++++
- 5 files changed, 45 insertions(+), 2 deletions(-)
-
-diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
-index 448cd01eb3ecb..c04be133a6cd7 100644
---- a/arch/x86/include/asm/pgtable.h
-+++ b/arch/x86/include/asm/pgtable.h
-@@ -1146,6 +1146,11 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
- }
- }
- #endif
-+
-+#define __HAVE_ARCH_PMDP_INVALIDATE_AD
-+extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
-+ unsigned long address, pmd_t *pmdp);
-+
- /*
- * Page table pages are page-aligned. The lower half of the top
- * level is used for userspace and the top half for the kernel.
-diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
-index 3481b35cb4ec7..f16059e9a85e7 100644
---- a/arch/x86/mm/pgtable.c
-+++ b/arch/x86/mm/pgtable.c
-@@ -608,6 +608,16 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
-
- return young;
- }
-+
-+pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
-+ pmd_t *pmdp)
-+{
-+ /*
-+ * No flush is necessary. Once an invalid PTE is established, the PTE's
-+ * access and dirty bits cannot be updated.
-+ */
-+ return pmdp_establish(vma, address, pmdp, pmd_mkinvalid(*pmdp));
-+}
- #endif
-
- /**
-diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
-index d468efcf48f45..952969aa19ec1 100644
---- a/include/linux/pgtable.h
-+++ b/include/linux/pgtable.h
-@@ -562,6 +562,26 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pmd_t *pmdp);
- #endif
-
-+#ifndef __HAVE_ARCH_PMDP_INVALIDATE_AD
-+
-+/*
-+ * pmdp_invalidate_ad() invalidates the PMD while changing a transparent
-+ * hugepage mapping in the page tables. This function is similar to
-+ * pmdp_invalidate(), but should only be used if the access and dirty bits would
-+ * not be cleared by the software in the new PMD value. The function ensures
-+ * that hardware changes of the access and dirty bits updates would not be lost.
-+ *
-+ * Doing so can allow in certain architectures to avoid a TLB flush in most
-+ * cases. Yet, another TLB flush might be necessary later if the PMD update
-+ * itself requires such flush (e.g., if protection was set to be stricter). Yet,
-+ * even when a TLB flush is needed because of the update, the caller may be able
-+ * to batch these TLB flushing operations, so fewer TLB flush operations are
-+ * needed.
-+ */
-+extern pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma,
-+ unsigned long address, pmd_t *pmdp);
-+#endif
-+
- #ifndef __HAVE_ARCH_PTE_SAME
- static inline int pte_same(pte_t pte_a, pte_t pte_b)
- {
-diff --git a/mm/huge_memory.c b/mm/huge_memory.c
-index 8ab6316d85391..265ef8d1393c5 100644
---- a/mm/huge_memory.c
-+++ b/mm/huge_memory.c
-@@ -1798,10 +1798,10 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
- * The race makes MADV_DONTNEED miss the huge pmd and don't clear it
- * which may break userspace.
- *
-- * pmdp_invalidate() is required to make sure we don't miss
-+ * pmdp_invalidate_ad() is required to make sure we don't miss
- * dirty/young flags set by hardware.
- */
-- oldpmd = pmdp_invalidate(vma, addr, pmd);
-+ oldpmd = pmdp_invalidate_ad(vma, addr, pmd);
-
- entry = pmd_modify(oldpmd, newprot);
- if (preserve_write)
-diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
-index 4e640baf97948..b0ce6c7391bf4 100644
---- a/mm/pgtable-generic.c
-+++ b/mm/pgtable-generic.c
-@@ -200,6 +200,14 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- }
- #endif
-
-+#ifndef __HAVE_ARCH_PMDP_INVALIDATE_AD
-+pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
-+ pmd_t *pmdp)
-+{
-+ return pmdp_invalidate(vma, address, pmdp);
-+}
-+#endif
-+
- #ifndef pmdp_collapse_flush
- pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
- pmd_t *pmdp)
---
-2.43.0
-
+++ /dev/null
-From f3f649041a190cda4c4b0f15f9898ad8f6653c30 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Apr 2024 16:25:14 +0000
-Subject: mm/cma: drop incorrect alignment check in cma_init_reserved_mem
-
-From: Frank van der Linden <fvdl@google.com>
-
-[ Upstream commit b174f139bdc8aaaf72f5b67ad1bd512c4868a87e ]
-
-cma_init_reserved_mem uses IS_ALIGNED to check if the size represented by
-one bit in the cma allocation bitmask is aligned with
-CMA_MIN_ALIGNMENT_BYTES (pageblock size).
-
-However, this is too strict, as this will fail if order_per_bit >
-pageblock_order, which is a valid configuration.
-
-We could check IS_ALIGNED both ways, but since both numbers are powers of
-two, no check is needed at all.
-
-Link: https://lkml.kernel.org/r/20240404162515.527802-1-fvdl@google.com
-Fixes: de9e14eebf33 ("drivers: dma-contiguous: add initialization from device tree")
-Signed-off-by: Frank van der Linden <fvdl@google.com>
-Acked-by: David Hildenbrand <david@redhat.com>
-Cc: Marek Szyprowski <m.szyprowski@samsung.com>
-Cc: Muchun Song <muchun.song@linux.dev>
-Cc: Roman Gushchin <roman.gushchin@linux.dev>
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- mm/cma.c | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/mm/cma.c b/mm/cma.c
-index 5208aee4f45ad..88fbd4f8124d3 100644
---- a/mm/cma.c
-+++ b/mm/cma.c
-@@ -179,10 +179,6 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
- if (!size || !memblock_is_region_reserved(base, size))
- return -EINVAL;
-
-- /* alignment should be aligned with order_per_bit */
-- if (!IS_ALIGNED(CMA_MIN_ALIGNMENT_PAGES, 1 << order_per_bit))
-- return -EINVAL;
--
- /* ensure minimal alignment required by mm core */
- if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
- return -EINVAL;
---
-2.43.0
-
+++ /dev/null
-From dca09ad288fc1dd6652c82f0aa90f993a357f4f8 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 1 May 2024 15:33:10 +0100
-Subject: mm: fix race between __split_huge_pmd_locked() and GUP-fast
-
-From: Ryan Roberts <ryan.roberts@arm.com>
-
-[ Upstream commit 3a5a8d343e1cf96eb9971b17cbd4b832ab19b8e7 ]
-
-__split_huge_pmd_locked() can be called for a present THP, devmap or
-(non-present) migration entry. It calls pmdp_invalidate() unconditionally
-on the pmdp and only determines if it is present or not based on the
-returned old pmd. This is a problem for the migration entry case because
-pmd_mkinvalid(), called by pmdp_invalidate() must only be called for a
-present pmd.
-
-On arm64 at least, pmd_mkinvalid() will mark the pmd such that any future
-call to pmd_present() will return true. And therefore any lockless
-pgtable walker could see the migration entry pmd in this state and start
-interpretting the fields as if it were present, leading to BadThings (TM).
-GUP-fast appears to be one such lockless pgtable walker.
-
-x86 does not suffer the above problem, but instead pmd_mkinvalid() will
-corrupt the offset field of the swap entry within the swap pte. See link
-below for discussion of that problem.
-
-Fix all of this by only calling pmdp_invalidate() for a present pmd. And
-for good measure let's add a warning to all implementations of
-pmdp_invalidate[_ad](). I've manually reviewed all other
-pmdp_invalidate[_ad]() call sites and believe all others to be conformant.
-
-This is a theoretical bug found during code review. I don't have any test
-case to trigger it in practice.
-
-Link: https://lkml.kernel.org/r/20240501143310.1381675-1-ryan.roberts@arm.com
-Link: https://lore.kernel.org/all/0dd7827a-6334-439a-8fd0-43c98e6af22b@arm.com/
-Fixes: 84c3fc4e9c56 ("mm: thp: check pmd migration entry in common path")
-Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
-Reviewed-by: Zi Yan <ziy@nvidia.com>
-Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
-Acked-by: David Hildenbrand <david@redhat.com>
-Cc: Andreas Larsson <andreas@gaisler.com>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
-Cc: Borislav Petkov (AMD) <bp@alien8.de>
-Cc: Catalin Marinas <catalin.marinas@arm.com>
-Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
-Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
-Cc: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: "David S. Miller" <davem@davemloft.net>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: Jonathan Corbet <corbet@lwn.net>
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Naveen N. Rao <naveen.n.rao@linux.ibm.com>
-Cc: Nicholas Piggin <npiggin@gmail.com>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Sven Schnelle <svens@linux.ibm.com>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Will Deacon <will@kernel.org>
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- Documentation/vm/arch_pgtable_helpers.rst | 6 ++-
- arch/powerpc/mm/book3s64/pgtable.c | 1 +
- arch/s390/include/asm/pgtable.h | 4 +-
- arch/sparc/mm/tlb.c | 1 +
- arch/x86/mm/pgtable.c | 2 +
- mm/huge_memory.c | 49 ++++++++++++-----------
- mm/pgtable-generic.c | 2 +
- 7 files changed, 39 insertions(+), 26 deletions(-)
-
-diff --git a/Documentation/vm/arch_pgtable_helpers.rst b/Documentation/vm/arch_pgtable_helpers.rst
-index 552567d863b86..b8ae5d040b998 100644
---- a/Documentation/vm/arch_pgtable_helpers.rst
-+++ b/Documentation/vm/arch_pgtable_helpers.rst
-@@ -134,7 +134,8 @@ PMD Page Table Helpers
- +---------------------------+--------------------------------------------------+
- | pmd_swp_clear_soft_dirty | Clears a soft dirty swapped PMD |
- +---------------------------+--------------------------------------------------+
--| pmd_mkinvalid | Invalidates a mapped PMD [1] |
-+| pmd_mkinvalid | Invalidates a present PMD; do not call for |
-+| | non-present PMD [1] |
- +---------------------------+--------------------------------------------------+
- | pmd_set_huge | Creates a PMD huge mapping |
- +---------------------------+--------------------------------------------------+
-@@ -190,7 +191,8 @@ PUD Page Table Helpers
- +---------------------------+--------------------------------------------------+
- | pud_mkdevmap | Creates a ZONE_DEVICE mapped PUD |
- +---------------------------+--------------------------------------------------+
--| pud_mkinvalid | Invalidates a mapped PUD [1] |
-+| pud_mkinvalid | Invalidates a present PUD; do not call for |
-+| | non-present PUD [1] |
- +---------------------------+--------------------------------------------------+
- | pud_set_huge | Creates a PUD huge mapping |
- +---------------------------+--------------------------------------------------+
-diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
-index da15f28c7b13a..3a22e7d970f33 100644
---- a/arch/powerpc/mm/book3s64/pgtable.c
-+++ b/arch/powerpc/mm/book3s64/pgtable.c
-@@ -115,6 +115,7 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- {
- unsigned long old_pmd;
-
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
- old_pmd = pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, _PAGE_INVALID);
- flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
- return __pmd(old_pmd);
-diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
-index b61426c9ef178..b65ce0c90dd0e 100644
---- a/arch/s390/include/asm/pgtable.h
-+++ b/arch/s390/include/asm/pgtable.h
-@@ -1625,8 +1625,10 @@ static inline pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma,
- static inline pmd_t pmdp_invalidate(struct vm_area_struct *vma,
- unsigned long addr, pmd_t *pmdp)
- {
-- pmd_t pmd = __pmd(pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID);
-+ pmd_t pmd;
-
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
-+ pmd = __pmd(pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID);
- return pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd);
- }
-
-diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
-index 9a725547578e8..946f33c1b032f 100644
---- a/arch/sparc/mm/tlb.c
-+++ b/arch/sparc/mm/tlb.c
-@@ -245,6 +245,7 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- {
- pmd_t old, entry;
-
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
- entry = __pmd(pmd_val(*pmdp) & ~_PAGE_VALID);
- old = pmdp_establish(vma, address, pmdp, entry);
- flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
-diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
-index f16059e9a85e7..5c2be867a2ed9 100644
---- a/arch/x86/mm/pgtable.c
-+++ b/arch/x86/mm/pgtable.c
-@@ -612,6 +612,8 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
- pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
- pmd_t *pmdp)
- {
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
-+
- /*
- * No flush is necessary. Once an invalid PTE is established, the PTE's
- * access and dirty bits cannot be updated.
-diff --git a/mm/huge_memory.c b/mm/huge_memory.c
-index 265ef8d1393c5..99d38f712863b 100644
---- a/mm/huge_memory.c
-+++ b/mm/huge_memory.c
-@@ -2024,32 +2024,11 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
- return __split_huge_zero_page_pmd(vma, haddr, pmd);
- }
-
-- /*
-- * Up to this point the pmd is present and huge and userland has the
-- * whole access to the hugepage during the split (which happens in
-- * place). If we overwrite the pmd with the not-huge version pointing
-- * to the pte here (which of course we could if all CPUs were bug
-- * free), userland could trigger a small page size TLB miss on the
-- * small sized TLB while the hugepage TLB entry is still established in
-- * the huge TLB. Some CPU doesn't like that.
-- * See http://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf, Erratum
-- * 383 on page 105. Intel should be safe but is also warns that it's
-- * only safe if the permission and cache attributes of the two entries
-- * loaded in the two TLB is identical (which should be the case here).
-- * But it is generally safer to never allow small and huge TLB entries
-- * for the same virtual address to be loaded simultaneously. So instead
-- * of doing "pmd_populate(); flush_pmd_tlb_range();" we first mark the
-- * current pmd notpresent (atomically because here the pmd_trans_huge
-- * must remain set at all times on the pmd until the split is complete
-- * for this pmd), then we flush the SMP TLB and finally we write the
-- * non-huge version of the pmd entry with pmd_populate.
-- */
-- old_pmd = pmdp_invalidate(vma, haddr, pmd);
--
-- pmd_migration = is_pmd_migration_entry(old_pmd);
-+ pmd_migration = is_pmd_migration_entry(*pmd);
- if (unlikely(pmd_migration)) {
- swp_entry_t entry;
-
-+ old_pmd = *pmd;
- entry = pmd_to_swp_entry(old_pmd);
- page = pfn_swap_entry_to_page(entry);
- write = is_writable_migration_entry(entry);
-@@ -2057,6 +2036,30 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
- soft_dirty = pmd_swp_soft_dirty(old_pmd);
- uffd_wp = pmd_swp_uffd_wp(old_pmd);
- } else {
-+ /*
-+ * Up to this point the pmd is present and huge and userland has
-+ * the whole access to the hugepage during the split (which
-+ * happens in place). If we overwrite the pmd with the not-huge
-+ * version pointing to the pte here (which of course we could if
-+ * all CPUs were bug free), userland could trigger a small page
-+ * size TLB miss on the small sized TLB while the hugepage TLB
-+ * entry is still established in the huge TLB. Some CPU doesn't
-+ * like that. See
-+ * http://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf, Erratum
-+ * 383 on page 105. Intel should be safe but is also warns that
-+ * it's only safe if the permission and cache attributes of the
-+ * two entries loaded in the two TLB is identical (which should
-+ * be the case here). But it is generally safer to never allow
-+ * small and huge TLB entries for the same virtual address to be
-+ * loaded simultaneously. So instead of doing "pmd_populate();
-+ * flush_pmd_tlb_range();" we first mark the current pmd
-+ * notpresent (atomically because here the pmd_trans_huge must
-+ * remain set at all times on the pmd until the split is
-+ * complete for this pmd), then we flush the SMP TLB and finally
-+ * we write the non-huge version of the pmd entry with
-+ * pmd_populate.
-+ */
-+ old_pmd = pmdp_invalidate(vma, haddr, pmd);
- page = pmd_page(old_pmd);
- if (pmd_dirty(old_pmd))
- SetPageDirty(page);
-diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
-index b0ce6c7391bf4..cc8b11724cf5a 100644
---- a/mm/pgtable-generic.c
-+++ b/mm/pgtable-generic.c
-@@ -194,6 +194,7 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
- pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pmd_t *pmdp)
- {
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
- pmd_t old = pmdp_establish(vma, address, pmdp, pmd_mkinvalid(*pmdp));
- flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
- return old;
-@@ -204,6 +205,7 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
- pmd_t pmdp_invalidate_ad(struct vm_area_struct *vma, unsigned long address,
- pmd_t *pmdp)
- {
-+ VM_WARN_ON_ONCE(!pmd_present(*pmdp));
- return pmdp_invalidate(vma, address, pmdp);
- }
- #endif
---
-2.43.0
-
+++ /dev/null
-From 2031c117202f5d2e11b95194e0012d36553e6e78 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 9 May 2022 18:20:50 -0700
-Subject: mm/mprotect: do not flush when not required architecturally
-
-From: Nadav Amit <namit@vmware.com>
-
-[ Upstream commit c9fe66560bf2dc7d109754414e309888cb8c9ba9 ]
-
-Currently, using mprotect() to unprotect a memory region or uffd to
-unprotect a memory region causes a TLB flush. However, in such cases the
-PTE is often not modified (i.e., remain RO) and therefore not TLB flush is
-needed.
-
-Add an arch-specific pte_needs_flush() which tells whether a TLB flush is
-needed based on the old PTE and the new one. Implement an x86
-pte_needs_flush().
-
-Always flush the TLB when it is architecturally needed even when skipping
-a TLB flush might only result in a spurious page-faults by skipping the
-flush.
-
-Even with such conservative manner, we can in the future further refine
-the checks to test whether a PTE is present by only considering the
-architectural _PAGE_PRESENT flag instead of {pte|pmd}_preesnt(). For not
-be careful and use the latter.
-
-Link: https://lkml.kernel.org/r/20220401180821.1986781-3-namit@vmware.com
-Signed-off-by: Nadav Amit <namit@vmware.com>
-Cc: Andrea Arcangeli <aarcange@redhat.com>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Will Deacon <will@kernel.org>
-Cc: Yu Zhao <yuzhao@google.com>
-Cc: Nick Piggin <npiggin@gmail.com>
-Cc: Andrew Cooper <andrew.cooper3@citrix.com>
-Cc: Peter Xu <peterx@redhat.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: 3a5a8d343e1c ("mm: fix race between __split_huge_pmd_locked() and GUP-fast")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/x86/include/asm/pgtable_types.h | 2 +
- arch/x86/include/asm/tlbflush.h | 97 ++++++++++++++++++++++++++++
- include/asm-generic/tlb.h | 14 ++++
- mm/huge_memory.c | 9 +--
- mm/mprotect.c | 3 +-
- 5 files changed, 120 insertions(+), 5 deletions(-)
-
-diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
-index 28e59576c75be..de9e3c635618e 100644
---- a/arch/x86/include/asm/pgtable_types.h
-+++ b/arch/x86/include/asm/pgtable_types.h
-@@ -110,9 +110,11 @@
- #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
- #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX)
- #define _PAGE_DEVMAP (_AT(u64, 1) << _PAGE_BIT_DEVMAP)
-+#define _PAGE_SOFTW4 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW4)
- #else
- #define _PAGE_NX (_AT(pteval_t, 0))
- #define _PAGE_DEVMAP (_AT(pteval_t, 0))
-+#define _PAGE_SOFTW4 (_AT(pteval_t, 0))
- #endif
-
- #define _PAGE_PROTNONE (_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
-diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
-index b587a9ee9cb25..8be1ff9081728 100644
---- a/arch/x86/include/asm/tlbflush.h
-+++ b/arch/x86/include/asm/tlbflush.h
-@@ -259,6 +259,103 @@ static inline void arch_tlbbatch_add_mm(struct arch_tlbflush_unmap_batch *batch,
-
- extern void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch);
-
-+static inline bool pte_flags_need_flush(unsigned long oldflags,
-+ unsigned long newflags,
-+ bool ignore_access)
-+{
-+ /*
-+ * Flags that require a flush when cleared but not when they are set.
-+ * Only include flags that would not trigger spurious page-faults.
-+ * Non-present entries are not cached. Hardware would set the
-+ * dirty/access bit if needed without a fault.
-+ */
-+ const pteval_t flush_on_clear = _PAGE_DIRTY | _PAGE_PRESENT |
-+ _PAGE_ACCESSED;
-+ const pteval_t software_flags = _PAGE_SOFTW1 | _PAGE_SOFTW2 |
-+ _PAGE_SOFTW3 | _PAGE_SOFTW4;
-+ const pteval_t flush_on_change = _PAGE_RW | _PAGE_USER | _PAGE_PWT |
-+ _PAGE_PCD | _PAGE_PSE | _PAGE_GLOBAL | _PAGE_PAT |
-+ _PAGE_PAT_LARGE | _PAGE_PKEY_BIT0 | _PAGE_PKEY_BIT1 |
-+ _PAGE_PKEY_BIT2 | _PAGE_PKEY_BIT3 | _PAGE_NX;
-+ unsigned long diff = oldflags ^ newflags;
-+
-+ BUILD_BUG_ON(flush_on_clear & software_flags);
-+ BUILD_BUG_ON(flush_on_clear & flush_on_change);
-+ BUILD_BUG_ON(flush_on_change & software_flags);
-+
-+ /* Ignore software flags */
-+ diff &= ~software_flags;
-+
-+ if (ignore_access)
-+ diff &= ~_PAGE_ACCESSED;
-+
-+ /*
-+ * Did any of the 'flush_on_clear' flags was clleared set from between
-+ * 'oldflags' and 'newflags'?
-+ */
-+ if (diff & oldflags & flush_on_clear)
-+ return true;
-+
-+ /* Flush on modified flags. */
-+ if (diff & flush_on_change)
-+ return true;
-+
-+ /* Ensure there are no flags that were left behind */
-+ if (IS_ENABLED(CONFIG_DEBUG_VM) &&
-+ (diff & ~(flush_on_clear | software_flags | flush_on_change))) {
-+ VM_WARN_ON_ONCE(1);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+/*
-+ * pte_needs_flush() checks whether permissions were demoted and require a
-+ * flush. It should only be used for userspace PTEs.
-+ */
-+static inline bool pte_needs_flush(pte_t oldpte, pte_t newpte)
-+{
-+ /* !PRESENT -> * ; no need for flush */
-+ if (!(pte_flags(oldpte) & _PAGE_PRESENT))
-+ return false;
-+
-+ /* PFN changed ; needs flush */
-+ if (pte_pfn(oldpte) != pte_pfn(newpte))
-+ return true;
-+
-+ /*
-+ * check PTE flags; ignore access-bit; see comment in
-+ * ptep_clear_flush_young().
-+ */
-+ return pte_flags_need_flush(pte_flags(oldpte), pte_flags(newpte),
-+ true);
-+}
-+#define pte_needs_flush pte_needs_flush
-+
-+/*
-+ * huge_pmd_needs_flush() checks whether permissions were demoted and require a
-+ * flush. It should only be used for userspace huge PMDs.
-+ */
-+static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd)
-+{
-+ /* !PRESENT -> * ; no need for flush */
-+ if (!(pmd_flags(oldpmd) & _PAGE_PRESENT))
-+ return false;
-+
-+ /* PFN changed ; needs flush */
-+ if (pmd_pfn(oldpmd) != pmd_pfn(newpmd))
-+ return true;
-+
-+ /*
-+ * check PMD flags; do not ignore access-bit; see
-+ * pmdp_clear_flush_young().
-+ */
-+ return pte_flags_need_flush(pmd_flags(oldpmd), pmd_flags(newpmd),
-+ false);
-+}
-+#define huge_pmd_needs_flush huge_pmd_needs_flush
-+
- #endif /* !MODULE */
-
- #endif /* _ASM_X86_TLBFLUSH_H */
-diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
-index c99710b3027a0..7afde1eff2398 100644
---- a/include/asm-generic/tlb.h
-+++ b/include/asm-generic/tlb.h
-@@ -662,6 +662,20 @@ static inline void tlb_flush_p4d_range(struct mmu_gather *tlb,
- } while (0)
- #endif
-
-+#ifndef pte_needs_flush
-+static inline bool pte_needs_flush(pte_t oldpte, pte_t newpte)
-+{
-+ return true;
-+}
-+#endif
-+
-+#ifndef huge_pmd_needs_flush
-+static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd)
-+{
-+ return true;
-+}
-+#endif
-+
- #endif /* CONFIG_MMU */
-
- #endif /* _ASM_GENERIC__TLB_H */
-diff --git a/mm/huge_memory.c b/mm/huge_memory.c
-index 661dd29642ebc..8ab6316d85391 100644
---- a/mm/huge_memory.c
-+++ b/mm/huge_memory.c
-@@ -1726,7 +1726,7 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
- {
- struct mm_struct *mm = vma->vm_mm;
- spinlock_t *ptl;
-- pmd_t entry;
-+ pmd_t oldpmd, entry;
- bool preserve_write;
- int ret;
- bool prot_numa = cp_flags & MM_CP_PROT_NUMA;
-@@ -1801,9 +1801,9 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
- * pmdp_invalidate() is required to make sure we don't miss
- * dirty/young flags set by hardware.
- */
-- entry = pmdp_invalidate(vma, addr, pmd);
-+ oldpmd = pmdp_invalidate(vma, addr, pmd);
-
-- entry = pmd_modify(entry, newprot);
-+ entry = pmd_modify(oldpmd, newprot);
- if (preserve_write)
- entry = pmd_mk_savedwrite(entry);
- if (uffd_wp) {
-@@ -1820,7 +1820,8 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
- ret = HPAGE_PMD_NR;
- set_pmd_at(mm, addr, pmd, entry);
-
-- tlb_flush_pmd_range(tlb, addr, HPAGE_PMD_SIZE);
-+ if (huge_pmd_needs_flush(oldpmd, entry))
-+ tlb_flush_pmd_range(tlb, addr, HPAGE_PMD_SIZE);
-
- BUG_ON(vma_is_anonymous(vma) && !preserve_write && pmd_write(entry));
- unlock:
-diff --git a/mm/mprotect.c b/mm/mprotect.c
-index fe1196be9ca28..09c5c448b9e7c 100644
---- a/mm/mprotect.c
-+++ b/mm/mprotect.c
-@@ -141,7 +141,8 @@ static unsigned long change_pte_range(struct mmu_gather *tlb,
- ptent = pte_mkwrite(ptent);
- }
- ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent);
-- tlb_flush_pte_range(tlb, addr, PAGE_SIZE);
-+ if (pte_needs_flush(oldpte, ptent))
-+ tlb_flush_pte_range(tlb, addr, PAGE_SIZE);
- pages++;
- } else if (is_swap_pte(oldpte)) {
- swp_entry_t entry = pte_to_swp_entry(oldpte);
---
-2.43.0
-
+++ /dev/null
-From 61cba6a6dc1cc6682b9aeff3aff3114f0ff30462 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 9 May 2022 18:20:50 -0700
-Subject: mm/mprotect: use mmu_gather
-
-From: Nadav Amit <namit@vmware.com>
-
-[ Upstream commit 4a18419f71cdf9155d2d2a6c79546f720978b990 ]
-
-Patch series "mm/mprotect: avoid unnecessary TLB flushes", v6.
-
-This patchset is intended to remove unnecessary TLB flushes during
-mprotect() syscalls. Once this patch-set make it through, similar and
-further optimizations for MADV_COLD and userfaultfd would be possible.
-
-Basically, there are 3 optimizations in this patch-set:
-
-1. Use TLB batching infrastructure to batch flushes across VMAs and do
- better/fewer flushes. This would also be handy for later userfaultfd
- enhancements.
-
-2. Avoid unnecessary TLB flushes. This optimization is the one that
- provides most of the performance benefits. Unlike previous versions,
- we now only avoid flushes that would not result in spurious
- page-faults.
-
-3. Avoiding TLB flushes on change_huge_pmd() that are only needed to
- prevent the A/D bits from changing.
-
-Andrew asked for some benchmark numbers. I do not have an easy
-determinate macrobenchmark in which it is easy to show benefit. I
-therefore ran a microbenchmark: a loop that does the following on
-anonymous memory, just as a sanity check to see that time is saved by
-avoiding TLB flushes. The loop goes:
-
- mprotect(p, PAGE_SIZE, PROT_READ)
- mprotect(p, PAGE_SIZE, PROT_READ|PROT_WRITE)
- *p = 0; // make the page writable
-
-The test was run in KVM guest with 1 or 2 threads (the second thread was
-busy-looping). I measured the time (cycles) of each operation:
-
- 1 thread 2 threads
- mmots +patch mmots +patch
-PROT_READ 3494 2725 (-22%) 8630 7788 (-10%)
-PROT_READ|WRITE 3952 2724 (-31%) 9075 2865 (-68%)
-
-[ mmots = v5.17-rc6-mmots-2022-03-06-20-38 ]
-
-The exact numbers are really meaningless, but the benefit is clear. There
-are 2 interesting results though.
-
-(1) PROT_READ is cheaper, while one can expect it not to be affected.
-This is presumably due to TLB miss that is saved
-
-(2) Without memory access (*p = 0), the speedup of the patch is even
-greater. In that scenario mprotect(PROT_READ) also avoids the TLB flush.
-As a result both operations on the patched kernel take roughly ~1500
-cycles (with either 1 or 2 threads), whereas on mmotm their cost is as
-high as presented in the table.
-
-This patch (of 3):
-
-change_pXX_range() currently does not use mmu_gather, but instead
-implements its own deferred TLB flushes scheme. This both complicates the
-code, as developers need to be aware of different invalidation schemes,
-and prevents opportunities to avoid TLB flushes or perform them in finer
-granularity.
-
-The use of mmu_gather for modified PTEs has benefits in various scenarios
-even if pages are not released. For instance, if only a single page needs
-to be flushed out of a range of many pages, only that page would be
-flushed. If a THP page is flushed, on x86 a single TLB invlpg instruction
-can be used instead of 512 instructions (or a full TLB flush, which would
-Linux would actually use by default). mprotect() over multiple VMAs
-requires a single flush.
-
-Use mmu_gather in change_pXX_range(). As the pages are not released, only
-record the flushed range using tlb_flush_pXX_range().
-
-Handle THP similarly and get rid of flush_cache_range() which becomes
-redundant since tlb_start_vma() calls it when needed.
-
-Link: https://lkml.kernel.org/r/20220401180821.1986781-1-namit@vmware.com
-Link: https://lkml.kernel.org/r/20220401180821.1986781-2-namit@vmware.com
-Signed-off-by: Nadav Amit <namit@vmware.com>
-Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-Cc: Andrea Arcangeli <aarcange@redhat.com>
-Cc: Andrew Cooper <andrew.cooper3@citrix.com>
-Cc: Andy Lutomirski <luto@kernel.org>
-Cc: Dave Hansen <dave.hansen@linux.intel.com>
-Cc: Peter Xu <peterx@redhat.com>
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Will Deacon <will@kernel.org>
-Cc: Yu Zhao <yuzhao@google.com>
-Cc: Nick Piggin <npiggin@gmail.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: 3a5a8d343e1c ("mm: fix race between __split_huge_pmd_locked() and GUP-fast")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/exec.c | 6 ++-
- include/linux/huge_mm.h | 5 ++-
- include/linux/mm.h | 5 ++-
- mm/huge_memory.c | 10 ++++-
- mm/mempolicy.c | 9 +++-
- mm/mprotect.c | 92 ++++++++++++++++++++++-------------------
- mm/userfaultfd.c | 6 ++-
- 7 files changed, 82 insertions(+), 51 deletions(-)
-
-diff --git a/fs/exec.c b/fs/exec.c
-index 03516b704d8a4..3cf38e5e8b733 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -758,6 +758,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
- unsigned long stack_size;
- unsigned long stack_expand;
- unsigned long rlim_stack;
-+ struct mmu_gather tlb;
-
- #ifdef CONFIG_STACK_GROWSUP
- /* Limit stack size */
-@@ -812,8 +813,11 @@ int setup_arg_pages(struct linux_binprm *bprm,
- vm_flags |= mm->def_flags;
- vm_flags |= VM_STACK_INCOMPLETE_SETUP;
-
-- ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end,
-+ tlb_gather_mmu(&tlb, mm);
-+ ret = mprotect_fixup(&tlb, vma, &prev, vma->vm_start, vma->vm_end,
- vm_flags);
-+ tlb_finish_mmu(&tlb);
-+
- if (ret)
- goto out_unlock;
- BUG_ON(prev != vma);
-diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
-index f123e15d966e8..6cb3e6fe11e7f 100644
---- a/include/linux/huge_mm.h
-+++ b/include/linux/huge_mm.h
-@@ -36,8 +36,9 @@ int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, pud_t *pud,
- unsigned long addr);
- bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
- unsigned long new_addr, pmd_t *old_pmd, pmd_t *new_pmd);
--int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr,
-- pgprot_t newprot, unsigned long cp_flags);
-+int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
-+ pmd_t *pmd, unsigned long addr, pgprot_t newprot,
-+ unsigned long cp_flags);
- vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn,
- pgprot_t pgprot, bool write);
-
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 5692055f202cb..e05c91ea5735d 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -1899,10 +1899,11 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,
- #define MM_CP_UFFD_WP_ALL (MM_CP_UFFD_WP | \
- MM_CP_UFFD_WP_RESOLVE)
-
--extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
-+extern unsigned long change_protection(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, unsigned long start,
- unsigned long end, pgprot_t newprot,
- unsigned long cp_flags);
--extern int mprotect_fixup(struct vm_area_struct *vma,
-+extern int mprotect_fixup(struct mmu_gather *tlb, struct vm_area_struct *vma,
- struct vm_area_struct **pprev, unsigned long start,
- unsigned long end, unsigned long newflags);
-
-diff --git a/mm/huge_memory.c b/mm/huge_memory.c
-index 98ff57c8eda69..661dd29642ebc 100644
---- a/mm/huge_memory.c
-+++ b/mm/huge_memory.c
-@@ -1720,8 +1720,9 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
- * or if prot_numa but THP migration is not supported
- * - HPAGE_PMD_NR if protections changed and TLB flush necessary
- */
--int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
-- unsigned long addr, pgprot_t newprot, unsigned long cp_flags)
-+int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
-+ pmd_t *pmd, unsigned long addr, pgprot_t newprot,
-+ unsigned long cp_flags)
- {
- struct mm_struct *mm = vma->vm_mm;
- spinlock_t *ptl;
-@@ -1732,6 +1733,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
- bool uffd_wp = cp_flags & MM_CP_UFFD_WP;
- bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE;
-
-+ tlb_change_page_size(tlb, HPAGE_PMD_SIZE);
-+
- if (prot_numa && !thp_migration_supported())
- return 1;
-
-@@ -1816,6 +1819,9 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
- }
- ret = HPAGE_PMD_NR;
- set_pmd_at(mm, addr, pmd, entry);
-+
-+ tlb_flush_pmd_range(tlb, addr, HPAGE_PMD_SIZE);
-+
- BUG_ON(vma_is_anonymous(vma) && !preserve_write && pmd_write(entry));
- unlock:
- spin_unlock(ptl);
-diff --git a/mm/mempolicy.c b/mm/mempolicy.c
-index 818753635e427..c05e979fd8695 100644
---- a/mm/mempolicy.c
-+++ b/mm/mempolicy.c
-@@ -104,6 +104,7 @@
- #include <linux/swapops.h>
-
- #include <asm/tlbflush.h>
-+#include <asm/tlb.h>
- #include <linux/uaccess.h>
-
- #include "internal.h"
-@@ -634,12 +635,18 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask,
- unsigned long change_prot_numa(struct vm_area_struct *vma,
- unsigned long addr, unsigned long end)
- {
-+ struct mmu_gather tlb;
- int nr_updated;
-
-- nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA);
-+ tlb_gather_mmu(&tlb, vma->vm_mm);
-+
-+ nr_updated = change_protection(&tlb, vma, addr, end, PAGE_NONE,
-+ MM_CP_PROT_NUMA);
- if (nr_updated)
- count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
-
-+ tlb_finish_mmu(&tlb);
-+
- return nr_updated;
- }
- #else
-diff --git a/mm/mprotect.c b/mm/mprotect.c
-index ed18dc49533f6..fe1196be9ca28 100644
---- a/mm/mprotect.c
-+++ b/mm/mprotect.c
-@@ -32,12 +32,13 @@
- #include <asm/cacheflush.h>
- #include <asm/mmu_context.h>
- #include <asm/tlbflush.h>
-+#include <asm/tlb.h>
-
- #include "internal.h"
-
--static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
-- unsigned long addr, unsigned long end, pgprot_t newprot,
-- unsigned long cp_flags)
-+static unsigned long change_pte_range(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr,
-+ unsigned long end, pgprot_t newprot, unsigned long cp_flags)
- {
- pte_t *pte, oldpte;
- spinlock_t *ptl;
-@@ -48,6 +49,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
- bool uffd_wp = cp_flags & MM_CP_UFFD_WP;
- bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE;
-
-+ tlb_change_page_size(tlb, PAGE_SIZE);
-+
- /*
- * Can be called with only the mmap_lock for reading by
- * prot_numa so we must check the pmd isn't constantly
-@@ -138,6 +141,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
- ptent = pte_mkwrite(ptent);
- }
- ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent);
-+ tlb_flush_pte_range(tlb, addr, PAGE_SIZE);
- pages++;
- } else if (is_swap_pte(oldpte)) {
- swp_entry_t entry = pte_to_swp_entry(oldpte);
-@@ -219,9 +223,9 @@ static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd)
- return 0;
- }
-
--static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
-- pud_t *pud, unsigned long addr, unsigned long end,
-- pgprot_t newprot, unsigned long cp_flags)
-+static inline unsigned long change_pmd_range(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, pud_t *pud, unsigned long addr,
-+ unsigned long end, pgprot_t newprot, unsigned long cp_flags)
- {
- pmd_t *pmd;
- unsigned long next;
-@@ -261,8 +265,12 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
- if (next - addr != HPAGE_PMD_SIZE) {
- __split_huge_pmd(vma, pmd, addr, false, NULL);
- } else {
-- int nr_ptes = change_huge_pmd(vma, pmd, addr,
-- newprot, cp_flags);
-+ /*
-+ * change_huge_pmd() does not defer TLB flushes,
-+ * so no need to propagate the tlb argument.
-+ */
-+ int nr_ptes = change_huge_pmd(tlb, vma, pmd,
-+ addr, newprot, cp_flags);
-
- if (nr_ptes) {
- if (nr_ptes == HPAGE_PMD_NR) {
-@@ -276,8 +284,8 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
- }
- /* fall through, the trans huge pmd just split */
- }
-- this_pages = change_pte_range(vma, pmd, addr, next, newprot,
-- cp_flags);
-+ this_pages = change_pte_range(tlb, vma, pmd, addr, next,
-+ newprot, cp_flags);
- pages += this_pages;
- next:
- cond_resched();
-@@ -291,9 +299,9 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
- return pages;
- }
-
--static inline unsigned long change_pud_range(struct vm_area_struct *vma,
-- p4d_t *p4d, unsigned long addr, unsigned long end,
-- pgprot_t newprot, unsigned long cp_flags)
-+static inline unsigned long change_pud_range(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, p4d_t *p4d, unsigned long addr,
-+ unsigned long end, pgprot_t newprot, unsigned long cp_flags)
- {
- pud_t *pud;
- unsigned long next;
-@@ -304,16 +312,16 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma,
- next = pud_addr_end(addr, end);
- if (pud_none_or_clear_bad(pud))
- continue;
-- pages += change_pmd_range(vma, pud, addr, next, newprot,
-+ pages += change_pmd_range(tlb, vma, pud, addr, next, newprot,
- cp_flags);
- } while (pud++, addr = next, addr != end);
-
- return pages;
- }
-
--static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
-- pgd_t *pgd, unsigned long addr, unsigned long end,
-- pgprot_t newprot, unsigned long cp_flags)
-+static inline unsigned long change_p4d_range(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, pgd_t *pgd, unsigned long addr,
-+ unsigned long end, pgprot_t newprot, unsigned long cp_flags)
- {
- p4d_t *p4d;
- unsigned long next;
-@@ -324,44 +332,40 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
- next = p4d_addr_end(addr, end);
- if (p4d_none_or_clear_bad(p4d))
- continue;
-- pages += change_pud_range(vma, p4d, addr, next, newprot,
-+ pages += change_pud_range(tlb, vma, p4d, addr, next, newprot,
- cp_flags);
- } while (p4d++, addr = next, addr != end);
-
- return pages;
- }
-
--static unsigned long change_protection_range(struct vm_area_struct *vma,
-- unsigned long addr, unsigned long end, pgprot_t newprot,
-- unsigned long cp_flags)
-+static unsigned long change_protection_range(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, unsigned long addr,
-+ unsigned long end, pgprot_t newprot, unsigned long cp_flags)
- {
- struct mm_struct *mm = vma->vm_mm;
- pgd_t *pgd;
- unsigned long next;
-- unsigned long start = addr;
- unsigned long pages = 0;
-
- BUG_ON(addr >= end);
- pgd = pgd_offset(mm, addr);
-- flush_cache_range(vma, addr, end);
-- inc_tlb_flush_pending(mm);
-+ tlb_start_vma(tlb, vma);
- do {
- next = pgd_addr_end(addr, end);
- if (pgd_none_or_clear_bad(pgd))
- continue;
-- pages += change_p4d_range(vma, pgd, addr, next, newprot,
-+ pages += change_p4d_range(tlb, vma, pgd, addr, next, newprot,
- cp_flags);
- } while (pgd++, addr = next, addr != end);
-
-- /* Only flush the TLB if we actually modified any entries: */
-- if (pages)
-- flush_tlb_range(vma, start, end);
-- dec_tlb_flush_pending(mm);
-+ tlb_end_vma(tlb, vma);
-
- return pages;
- }
-
--unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
-+unsigned long change_protection(struct mmu_gather *tlb,
-+ struct vm_area_struct *vma, unsigned long start,
- unsigned long end, pgprot_t newprot,
- unsigned long cp_flags)
- {
-@@ -372,7 +376,7 @@ unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
- if (is_vm_hugetlb_page(vma))
- pages = hugetlb_change_protection(vma, start, end, newprot);
- else
-- pages = change_protection_range(vma, start, end, newprot,
-+ pages = change_protection_range(tlb, vma, start, end, newprot,
- cp_flags);
-
- return pages;
-@@ -406,8 +410,9 @@ static const struct mm_walk_ops prot_none_walk_ops = {
- };
-
- int
--mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
-- unsigned long start, unsigned long end, unsigned long newflags)
-+mprotect_fixup(struct mmu_gather *tlb, struct vm_area_struct *vma,
-+ struct vm_area_struct **pprev, unsigned long start,
-+ unsigned long end, unsigned long newflags)
- {
- struct mm_struct *mm = vma->vm_mm;
- unsigned long oldflags = vma->vm_flags;
-@@ -494,7 +499,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
- dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot);
- vma_set_page_prot(vma);
-
-- change_protection(vma, start, end, vma->vm_page_prot,
-+ change_protection(tlb, vma, start, end, vma->vm_page_prot,
- dirty_accountable ? MM_CP_DIRTY_ACCT : 0);
-
- /*
-@@ -528,6 +533,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
- const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
- const bool rier = (current->personality & READ_IMPLIES_EXEC) &&
- (prot & PROT_READ);
-+ struct mmu_gather tlb;
-
- start = untagged_addr(start);
-
-@@ -584,6 +590,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
- if (start > vma->vm_start)
- prev = vma;
-
-+ tlb_gather_mmu(&tlb, current->mm);
- for (nstart = start ; ; ) {
- unsigned long mask_off_old_flags;
- unsigned long newflags;
-@@ -610,18 +617,18 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
- /* newflags >> 4 shift VM_MAY% in place of VM_% */
- if ((newflags & ~(newflags >> 4)) & VM_ACCESS_FLAGS) {
- error = -EACCES;
-- goto out;
-+ break;
- }
-
- /* Allow architectures to sanity-check the new flags */
- if (!arch_validate_flags(newflags)) {
- error = -EINVAL;
-- goto out;
-+ break;
- }
-
- error = security_file_mprotect(vma, reqprot, prot);
- if (error)
-- goto out;
-+ break;
-
- tmp = vma->vm_end;
- if (tmp > end)
-@@ -630,27 +637,28 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
- if (vma->vm_ops && vma->vm_ops->mprotect) {
- error = vma->vm_ops->mprotect(vma, nstart, tmp, newflags);
- if (error)
-- goto out;
-+ break;
- }
-
-- error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
-+ error = mprotect_fixup(&tlb, vma, &prev, nstart, tmp, newflags);
- if (error)
-- goto out;
-+ break;
-
- nstart = tmp;
-
- if (nstart < prev->vm_end)
- nstart = prev->vm_end;
- if (nstart >= end)
-- goto out;
-+ break;
-
- vma = prev->vm_next;
- if (!vma || vma->vm_start != nstart) {
- error = -ENOMEM;
-- goto out;
-+ break;
- }
- prot = reqprot;
- }
-+ tlb_finish_mmu(&tlb);
- out:
- mmap_write_unlock(current->mm);
- return error;
-diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
-index 98a9d0ef2d917..eafdc112ac7aa 100644
---- a/mm/userfaultfd.c
-+++ b/mm/userfaultfd.c
-@@ -16,6 +16,7 @@
- #include <linux/hugetlb.h>
- #include <linux/shmem_fs.h>
- #include <asm/tlbflush.h>
-+#include <asm/tlb.h>
- #include "internal.h"
-
- static __always_inline
-@@ -698,6 +699,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
- atomic_t *mmap_changing)
- {
- struct vm_area_struct *dst_vma;
-+ struct mmu_gather tlb;
- pgprot_t newprot;
- int err;
-
-@@ -739,8 +741,10 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
- else
- newprot = vm_get_page_prot(dst_vma->vm_flags);
-
-- change_protection(dst_vma, start, start + len, newprot,
-+ tlb_gather_mmu(&tlb, dst_mm);
-+ change_protection(&tlb, dst_vma, start, start + len, newprot,
- enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
-+ tlb_finish_mmu(&tlb);
-
- err = 0;
- out_unlock:
---
-2.43.0
-
+++ /dev/null
-From db1dc85c7dd16e575bad700b7761451733db9665 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 24 Mar 2024 12:40:17 +0100
-Subject: mmc: davinci: Don't strip remove function when driver is builtin
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-
-[ Upstream commit 55c421b364482b61c4c45313a535e61ed5ae4ea3 ]
-
-Using __exit for the remove function results in the remove callback being
-discarded with CONFIG_MMC_DAVINCI=y. When such a device gets unbound (e.g.
-using sysfs or hotplug), the driver is just removed without the cleanup
-being performed. This results in resource leaks. Fix it by compiling in the
-remove callback unconditionally.
-
-This also fixes a W=1 modpost warning:
-
-WARNING: modpost: drivers/mmc/host/davinci_mmc: section mismatch in
-reference: davinci_mmcsd_driver+0x10 (section: .data) ->
-davinci_mmcsd_remove (section: .exit.text)
-
-Fixes: b4cff4549b7a ("DaVinci: MMC: MMC/SD controller driver for DaVinci family")
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-Cc: stable@vger.kernel.org
-Link: https://lore.kernel.org/r/20240324114017.231936-2-u.kleine-koenig@pengutronix.de
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/mmc/host/davinci_mmc.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
-index 36c45867eb643..e0175808c3b0d 100644
---- a/drivers/mmc/host/davinci_mmc.c
-+++ b/drivers/mmc/host/davinci_mmc.c
-@@ -1347,7 +1347,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
- return ret;
- }
-
--static void __exit davinci_mmcsd_remove(struct platform_device *pdev)
-+static void davinci_mmcsd_remove(struct platform_device *pdev)
- {
- struct mmc_davinci_host *host = platform_get_drvdata(pdev);
-
-@@ -1402,7 +1402,7 @@ static struct platform_driver davinci_mmcsd_driver = {
- .of_match_table = davinci_mmc_dt_ids,
- },
- .probe = davinci_mmcsd_probe,
-- .remove_new = __exit_p(davinci_mmcsd_remove),
-+ .remove_new = davinci_mmcsd_remove,
- .id_table = davinci_mmc_devtype,
- };
-
---
-2.43.0
-
+++ /dev/null
-From d2d80526ac7c82e3143dd7b830c6843e7acbbf7d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 27 Jul 2023 14:59:56 +0800
-Subject: mmc: davinci_mmc: Convert to platform remove callback returning void
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Yangtao Li <frank.li@vivo.com>
-
-[ Upstream commit bc1711e8332da03648d8fe1950189237e66313af ]
-
-The .remove() callback for a platform driver returns an int which makes
-many driver authors wrongly assume it's possible to do error handling by
-returning an error code. However the value returned is (mostly) ignored
-and this typically results in resource leaks. To improve here there is a
-quest to make the remove callback return void. In the first step of this
-quest all drivers are converted to .remove_new() which already returns
-void.
-
-Trivially convert this driver from always returning zero in the remove
-callback to the void returning variant.
-
-Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-Signed-off-by: Yangtao Li <frank.li@vivo.com>
-Link: https://lore.kernel.org/r/20230727070051.17778-7-frank.li@vivo.com
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-Stable-dep-of: 55c421b36448 ("mmc: davinci: Don't strip remove function when driver is builtin")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/mmc/host/davinci_mmc.c | 6 ++----
- 1 file changed, 2 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
-index 80de660027d89..36c45867eb643 100644
---- a/drivers/mmc/host/davinci_mmc.c
-+++ b/drivers/mmc/host/davinci_mmc.c
-@@ -1347,7 +1347,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev)
- return ret;
- }
-
--static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
-+static void __exit davinci_mmcsd_remove(struct platform_device *pdev)
- {
- struct mmc_davinci_host *host = platform_get_drvdata(pdev);
-
-@@ -1356,8 +1356,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
- davinci_release_dma_channels(host);
- clk_disable_unprepare(host->clk);
- mmc_free_host(host->mmc);
--
-- return 0;
- }
-
- #ifdef CONFIG_PM
-@@ -1404,7 +1402,7 @@ static struct platform_driver davinci_mmcsd_driver = {
- .of_match_table = davinci_mmc_dt_ids,
- },
- .probe = davinci_mmcsd_probe,
-- .remove = __exit_p(davinci_mmcsd_remove),
-+ .remove_new = __exit_p(davinci_mmcsd_remove),
- .id_table = davinci_mmc_devtype,
- };
-
---
-2.43.0
-
+++ /dev/null
-From 273f0826c81d3fcfcfdbcf1cd99efe2202aa4709 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 15 Nov 2021 09:11:50 -0800
-Subject: net: drop nopreempt requirement on sock_prot_inuse_add()
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit b3cb764aa1d753cf6a58858f9e2097ba71e8100b ]
-
-This is distracting really, let's make this simpler,
-because many callers had to take care of this
-by themselves, even if on x86 this adds more
-code than really needed.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/sock.h | 4 ++--
- net/ieee802154/socket.c | 4 ++--
- net/ipv4/raw.c | 2 +-
- net/ipv6/ipv6_sockglue.c | 8 ++++----
- net/netlink/af_netlink.c | 4 ----
- net/packet/af_packet.c | 4 ----
- net/sctp/socket.c | 5 -----
- net/smc/af_smc.c | 2 +-
- net/unix/af_unix.c | 4 ----
- net/xdp/xsk.c | 4 ----
- 10 files changed, 10 insertions(+), 31 deletions(-)
-
-diff --git a/include/net/sock.h b/include/net/sock.h
-index c13c284222424..146f1b9c30636 100644
---- a/include/net/sock.h
-+++ b/include/net/sock.h
-@@ -1464,11 +1464,11 @@ proto_memory_pressure(struct proto *prot)
- struct prot_inuse {
- int val[PROTO_INUSE_NR];
- };
--/* Called with local bh disabled */
-+
- static inline void sock_prot_inuse_add(const struct net *net,
- const struct proto *prot, int val)
- {
-- __this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val);
-+ this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val);
- }
- int sock_prot_inuse_get(struct net *net, struct proto *proto);
- int sock_inuse_get(struct net *net);
-diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
-index c33f46c9b6b34..586a6c4adf246 100644
---- a/net/ieee802154/socket.c
-+++ b/net/ieee802154/socket.c
-@@ -174,8 +174,8 @@ static int raw_hash(struct sock *sk)
- {
- write_lock_bh(&raw_lock);
- sk_add_node(sk, &raw_head);
-- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
- write_unlock_bh(&raw_lock);
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-
- return 0;
- }
-@@ -458,8 +458,8 @@ static int dgram_hash(struct sock *sk)
- {
- write_lock_bh(&dgram_lock);
- sk_add_node(sk, &dgram_head);
-- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
- write_unlock_bh(&dgram_lock);
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-
- return 0;
- }
-diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
-index f532589d26926..cc8e946768e43 100644
---- a/net/ipv4/raw.c
-+++ b/net/ipv4/raw.c
-@@ -99,8 +99,8 @@ int raw_hash_sk(struct sock *sk)
-
- write_lock_bh(&h->lock);
- sk_add_node(sk, head);
-- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
- write_unlock_bh(&h->lock);
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-
- return 0;
- }
-diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
-index 197e12d5607f1..2071a212a2679 100644
---- a/net/ipv6/ipv6_sockglue.c
-+++ b/net/ipv6/ipv6_sockglue.c
-@@ -471,10 +471,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
-
- if (sk->sk_protocol == IPPROTO_TCP) {
- struct inet_connection_sock *icsk = inet_csk(sk);
-- local_bh_disable();
-+
- sock_prot_inuse_add(net, sk->sk_prot, -1);
- sock_prot_inuse_add(net, &tcp_prot, 1);
-- local_bh_enable();
-+
- sk->sk_prot = &tcp_prot;
- icsk->icsk_af_ops = &ipv4_specific;
- sk->sk_socket->ops = &inet_stream_ops;
-@@ -485,10 +485,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
-
- if (sk->sk_protocol == IPPROTO_UDPLITE)
- prot = &udplite_prot;
-- local_bh_disable();
-+
- sock_prot_inuse_add(net, sk->sk_prot, -1);
- sock_prot_inuse_add(net, prot, 1);
-- local_bh_enable();
-+
- sk->sk_prot = prot;
- sk->sk_socket->ops = &inet_dgram_ops;
- sk->sk_family = PF_INET;
-diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
-index 216445dd44db9..18a38db2b27eb 100644
---- a/net/netlink/af_netlink.c
-+++ b/net/netlink/af_netlink.c
-@@ -711,9 +711,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
- if (err < 0)
- goto out_module;
-
-- local_bh_disable();
- sock_prot_inuse_add(net, &netlink_proto, 1);
-- local_bh_enable();
-
- nlk = nlk_sk(sock->sk);
- nlk->module = module;
-@@ -813,9 +811,7 @@ static int netlink_release(struct socket *sock)
- netlink_table_ungrab();
- }
-
-- local_bh_disable();
- sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
-- local_bh_enable();
- call_rcu(&nlk->rcu, deferred_put_nlk_sk);
- return 0;
- }
-diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
-index 0ab3b09f863ba..4f920502f92fe 100644
---- a/net/packet/af_packet.c
-+++ b/net/packet/af_packet.c
-@@ -3092,9 +3092,7 @@ static int packet_release(struct socket *sock)
- sk_del_node_init_rcu(sk);
- mutex_unlock(&net->packet.sklist_lock);
-
-- preempt_disable();
- sock_prot_inuse_add(net, sk->sk_prot, -1);
-- preempt_enable();
-
- spin_lock(&po->bind_lock);
- unregister_prot_hook(sk, false);
-@@ -3361,9 +3359,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
- sk_add_node_tail_rcu(sk, &net->packet.sklist);
- mutex_unlock(&net->packet.sklist_lock);
-
-- preempt_disable();
- sock_prot_inuse_add(net, &packet_proto, 1);
-- preempt_enable();
-
- return 0;
- out2:
-diff --git a/net/sctp/socket.c b/net/sctp/socket.c
-index 57acf7ed80de3..d9271ffb29781 100644
---- a/net/sctp/socket.c
-+++ b/net/sctp/socket.c
-@@ -5073,12 +5073,9 @@ static int sctp_init_sock(struct sock *sk)
-
- SCTP_DBG_OBJCNT_INC(sock);
-
-- local_bh_disable();
- sk_sockets_allocated_inc(sk);
- sock_prot_inuse_add(net, sk->sk_prot, 1);
-
-- local_bh_enable();
--
- return 0;
- }
-
-@@ -5104,10 +5101,8 @@ static void sctp_destroy_sock(struct sock *sk)
- list_del(&sp->auto_asconf_list);
- }
- sctp_endpoint_free(sp->ep);
-- local_bh_disable();
- sk_sockets_allocated_dec(sk);
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-- local_bh_enable();
- }
-
- /* Triggered when there are no references on the socket anymore */
-diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
-index 8c11eb70c0f69..bd0b3a8b95d50 100644
---- a/net/smc/af_smc.c
-+++ b/net/smc/af_smc.c
-@@ -88,8 +88,8 @@ int smc_hash_sk(struct sock *sk)
-
- write_lock_bh(&h->lock);
- sk_add_node(sk, head);
-- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
- write_unlock_bh(&h->lock);
-+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-
- return 0;
- }
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 73b287b7a1154..262aeaea9861c 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -515,9 +515,7 @@ static void unix_sock_destructor(struct sock *sk)
- unix_release_addr(u->addr);
-
- atomic_long_dec(&unix_nr_socks);
-- local_bh_disable();
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
-- local_bh_enable();
- #ifdef UNIX_REFCNT_DEBUG
- pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,
- atomic_long_read(&unix_nr_socks));
-@@ -890,9 +888,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
- memset(&u->scm_stat, 0, sizeof(struct scm_stat));
- unix_insert_socket(unix_sockets_unbound(sk), sk);
-
-- local_bh_disable();
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-- local_bh_enable();
-
- return sk;
-
-diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
-index 1f61d15b3d1d4..da31a99ce6521 100644
---- a/net/xdp/xsk.c
-+++ b/net/xdp/xsk.c
-@@ -842,9 +842,7 @@ static int xsk_release(struct socket *sock)
- sk_del_node_init_rcu(sk);
- mutex_unlock(&net->xdp.lock);
-
-- local_bh_disable();
- sock_prot_inuse_add(net, sk->sk_prot, -1);
-- local_bh_enable();
-
- xsk_delete_from_maps(xs);
- mutex_lock(&xs->mutex);
-@@ -1465,9 +1463,7 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol,
- sk_add_node_rcu(sk, &net->xdp.list);
- mutex_unlock(&net->xdp.lock);
-
-- local_bh_disable();
- sock_prot_inuse_add(net, &xsk_proto, 1);
-- local_bh_enable();
-
- return 0;
- }
---
-2.43.0
-
+++ /dev/null
-From ab981fed621a211beeedabf25d14259651bfa005 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 15 Nov 2021 09:11:47 -0800
-Subject: net: inline sock_prot_inuse_add()
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit 2a12ae5d433df3d3c3f1a930799ec09cb2b8058f ]
-
-sock_prot_inuse_add() is very small, we can inline it.
-
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: a9bf9c7dc6a5 ("af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/net/sock.h | 14 +++++++++++---
- net/core/sock.c | 11 -----------
- 2 files changed, 11 insertions(+), 14 deletions(-)
-
-diff --git a/include/net/sock.h b/include/net/sock.h
-index b8de579b916e8..c13c284222424 100644
---- a/include/net/sock.h
-+++ b/include/net/sock.h
-@@ -1460,13 +1460,21 @@ proto_memory_pressure(struct proto *prot)
-
-
- #ifdef CONFIG_PROC_FS
-+#define PROTO_INUSE_NR 64 /* should be enough for the first time */
-+struct prot_inuse {
-+ int val[PROTO_INUSE_NR];
-+};
- /* Called with local bh disabled */
--void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
-+static inline void sock_prot_inuse_add(const struct net *net,
-+ const struct proto *prot, int val)
-+{
-+ __this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val);
-+}
- int sock_prot_inuse_get(struct net *net, struct proto *proto);
- int sock_inuse_get(struct net *net);
- #else
--static inline void sock_prot_inuse_add(struct net *net, struct proto *prot,
-- int inc)
-+static inline void sock_prot_inuse_add(const struct net *net,
-+ const struct proto *prot, int val)
- {
- }
- #endif
-diff --git a/net/core/sock.c b/net/core/sock.c
-index 62e376f09f957..e79e1c7933537 100644
---- a/net/core/sock.c
-+++ b/net/core/sock.c
-@@ -3497,19 +3497,8 @@ void sk_get_meminfo(const struct sock *sk, u32 *mem)
- }
-
- #ifdef CONFIG_PROC_FS
--#define PROTO_INUSE_NR 64 /* should be enough for the first time */
--struct prot_inuse {
-- int val[PROTO_INUSE_NR];
--};
--
- static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
-
--void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
--{
-- __this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val);
--}
--EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
--
- int sock_prot_inuse_get(struct net *net, struct proto *prot)
- {
- int cpu, idx = prot->inuse_idx;
---
-2.43.0
-
+++ /dev/null
-From 26e01ee3bec1ebf251e1e9c3050de28cba208228 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 29 May 2024 14:58:55 +0800
-Subject: net/ncsi: Fix the multi thread manner of NCSI driver
-
-From: DelphineCCChiu <delphine_cc_chiu@wiwynn.com>
-
-[ Upstream commit e85e271dec0270982afed84f70dc37703fcc1d52 ]
-
-Currently NCSI driver will send several NCSI commands back to back without
-waiting the response of previous NCSI command or timeout in some state
-when NIC have multi channel. This operation against the single thread
-manner defined by NCSI SPEC(section 6.3.2.3 in DSP0222_1.1.1)
-
-According to NCSI SPEC(section 6.2.13.1 in DSP0222_1.1.1), we should probe
-one channel at a time by sending NCSI commands (Clear initial state, Get
-version ID, Get capabilities...), than repeat this steps until the max
-number of channels which we got from NCSI command (Get capabilities) has
-been probed.
-
-Fixes: e6f44ed6d04d ("net/ncsi: Package and channel management")
-Signed-off-by: DelphineCCChiu <delphine_cc_chiu@wiwynn.com>
-Link: https://lore.kernel.org/r/20240529065856.825241-1-delphine_cc_chiu@wiwynn.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/ncsi/internal.h | 2 ++
- net/ncsi/ncsi-manage.c | 73 +++++++++++++++++++++---------------------
- net/ncsi/ncsi-rsp.c | 4 ++-
- 3 files changed, 41 insertions(+), 38 deletions(-)
-
-diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
-index 374412ed780b6..ef0f8f73826f5 100644
---- a/net/ncsi/internal.h
-+++ b/net/ncsi/internal.h
-@@ -325,6 +325,7 @@ struct ncsi_dev_priv {
- spinlock_t lock; /* Protect the NCSI device */
- unsigned int package_probe_id;/* Current ID during probe */
- unsigned int package_num; /* Number of packages */
-+ unsigned int channel_probe_id;/* Current cahnnel ID during probe */
- struct list_head packages; /* List of packages */
- struct ncsi_channel *hot_channel; /* Channel was ever active */
- struct ncsi_request requests[256]; /* Request table */
-@@ -343,6 +344,7 @@ struct ncsi_dev_priv {
- bool multi_package; /* Enable multiple packages */
- bool mlx_multi_host; /* Enable multi host Mellanox */
- u32 package_whitelist; /* Packages to configure */
-+ unsigned char channel_count; /* Num of channels to probe */
- };
-
- struct ncsi_cmd_arg {
-diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
-index 734feb2352fbc..30f5502530374 100644
---- a/net/ncsi/ncsi-manage.c
-+++ b/net/ncsi/ncsi-manage.c
-@@ -510,17 +510,19 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
-
- break;
- case ncsi_dev_state_suspend_gls:
-- ndp->pending_req_num = np->channel_num;
-+ ndp->pending_req_num = 1;
-
- nca.type = NCSI_PKT_CMD_GLS;
- nca.package = np->id;
-+ nca.channel = ndp->channel_probe_id;
-+ ret = ncsi_xmit_cmd(&nca);
-+ if (ret)
-+ goto error;
-+ ndp->channel_probe_id++;
-
-- nd->state = ncsi_dev_state_suspend_dcnt;
-- NCSI_FOR_EACH_CHANNEL(np, nc) {
-- nca.channel = nc->id;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
-+ if (ndp->channel_probe_id == ndp->channel_count) {
-+ ndp->channel_probe_id = 0;
-+ nd->state = ncsi_dev_state_suspend_dcnt;
- }
-
- break;
-@@ -1340,7 +1342,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- {
- struct ncsi_dev *nd = &ndp->ndev;
- struct ncsi_package *np;
-- struct ncsi_channel *nc;
- struct ncsi_cmd_arg nca;
- unsigned char index;
- int ret;
-@@ -1418,23 +1419,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
-
- nd->state = ncsi_dev_state_probe_cis;
- break;
-- case ncsi_dev_state_probe_cis:
-- ndp->pending_req_num = NCSI_RESERVED_CHANNEL;
--
-- /* Clear initial state */
-- nca.type = NCSI_PKT_CMD_CIS;
-- nca.package = ndp->active_package->id;
-- for (index = 0; index < NCSI_RESERVED_CHANNEL; index++) {
-- nca.channel = index;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
-- }
--
-- nd->state = ncsi_dev_state_probe_gvi;
-- if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY))
-- nd->state = ncsi_dev_state_probe_keep_phy;
-- break;
- case ncsi_dev_state_probe_keep_phy:
- ndp->pending_req_num = 1;
-
-@@ -1447,14 +1431,17 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
-
- nd->state = ncsi_dev_state_probe_gvi;
- break;
-+ case ncsi_dev_state_probe_cis:
- case ncsi_dev_state_probe_gvi:
- case ncsi_dev_state_probe_gc:
- case ncsi_dev_state_probe_gls:
- np = ndp->active_package;
-- ndp->pending_req_num = np->channel_num;
-+ ndp->pending_req_num = 1;
-
-- /* Retrieve version, capability or link status */
-- if (nd->state == ncsi_dev_state_probe_gvi)
-+ /* Clear initial state Retrieve version, capability or link status */
-+ if (nd->state == ncsi_dev_state_probe_cis)
-+ nca.type = NCSI_PKT_CMD_CIS;
-+ else if (nd->state == ncsi_dev_state_probe_gvi)
- nca.type = NCSI_PKT_CMD_GVI;
- else if (nd->state == ncsi_dev_state_probe_gc)
- nca.type = NCSI_PKT_CMD_GC;
-@@ -1462,19 +1449,29 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- nca.type = NCSI_PKT_CMD_GLS;
-
- nca.package = np->id;
-- NCSI_FOR_EACH_CHANNEL(np, nc) {
-- nca.channel = nc->id;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
-- }
-+ nca.channel = ndp->channel_probe_id;
-
-- if (nd->state == ncsi_dev_state_probe_gvi)
-+ ret = ncsi_xmit_cmd(&nca);
-+ if (ret)
-+ goto error;
-+
-+ if (nd->state == ncsi_dev_state_probe_cis) {
-+ nd->state = ncsi_dev_state_probe_gvi;
-+ if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY) && ndp->channel_probe_id == 0)
-+ nd->state = ncsi_dev_state_probe_keep_phy;
-+ } else if (nd->state == ncsi_dev_state_probe_gvi) {
- nd->state = ncsi_dev_state_probe_gc;
-- else if (nd->state == ncsi_dev_state_probe_gc)
-+ } else if (nd->state == ncsi_dev_state_probe_gc) {
- nd->state = ncsi_dev_state_probe_gls;
-- else
-+ } else {
-+ nd->state = ncsi_dev_state_probe_cis;
-+ ndp->channel_probe_id++;
-+ }
-+
-+ if (ndp->channel_probe_id == ndp->channel_count) {
-+ ndp->channel_probe_id = 0;
- nd->state = ncsi_dev_state_probe_dp;
-+ }
- break;
- case ncsi_dev_state_probe_dp:
- ndp->pending_req_num = 1;
-@@ -1775,6 +1772,7 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
- ndp->requests[i].ndp = ndp;
- timer_setup(&ndp->requests[i].timer, ncsi_request_timeout, 0);
- }
-+ ndp->channel_count = NCSI_RESERVED_CHANNEL;
-
- spin_lock_irqsave(&ncsi_dev_lock, flags);
- list_add_tail_rcu(&ndp->node, &ncsi_dev_list);
-@@ -1807,6 +1805,7 @@ int ncsi_start_dev(struct ncsi_dev *nd)
-
- if (!(ndp->flags & NCSI_DEV_PROBED)) {
- ndp->package_probe_id = 0;
-+ ndp->channel_probe_id = 0;
- nd->state = ncsi_dev_state_probe;
- schedule_work(&ndp->work);
- return 0;
-diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
-index 480e80e3c2836..f22d67cb04d37 100644
---- a/net/ncsi/ncsi-rsp.c
-+++ b/net/ncsi/ncsi-rsp.c
-@@ -795,12 +795,13 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
- struct ncsi_rsp_gc_pkt *rsp;
- struct ncsi_dev_priv *ndp = nr->ndp;
- struct ncsi_channel *nc;
-+ struct ncsi_package *np;
- size_t size;
-
- /* Find the channel */
- rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
- ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
-- NULL, &nc);
-+ &np, &nc);
- if (!nc)
- return -ENODEV;
-
-@@ -835,6 +836,7 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
- */
- nc->vlan_filter.bitmap = U64_MAX;
- nc->vlan_filter.n_vids = rsp->vlan_cnt;
-+ np->ndp->channel_count = rsp->channel_cnt;
-
- return 0;
- }
---
-2.43.0
-
+++ /dev/null
-From db8e971e5aefe4855b8299f3e2aafa6081ffedcd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 14 Nov 2023 10:07:33 -0600
-Subject: net/ncsi: Simplify Kconfig/dts control flow
-
-From: Peter Delevoryas <peter@pjd.dev>
-
-[ Upstream commit c797ce168930ce3d62a9b7fc4d7040963ee6a01e ]
-
-Background:
-
-1. CONFIG_NCSI_OEM_CMD_KEEP_PHY
-
-If this is enabled, we send an extra OEM Intel command in the probe
-sequence immediately after discovering a channel (e.g. after "Clear
-Initial State").
-
-2. CONFIG_NCSI_OEM_CMD_GET_MAC
-
-If this is enabled, we send one of 3 OEM "Get MAC Address" commands from
-Broadcom, Mellanox (Nvidida), and Intel in the *configuration* sequence
-for a channel.
-
-3. mellanox,multi-host (or mlx,multi-host)
-
-Introduced by this patch:
-
-https://lore.kernel.org/all/20200108234341.2590674-1-vijaykhemka@fb.com/
-
-Which was actually originally from cosmo.chou@quantatw.com:
-
-https://github.com/facebook/openbmc-linux/commit/9f132a10ec48db84613519258cd8a317fb9c8f1b
-
-Cosmo claimed that the Nvidia ConnectX-4 and ConnectX-6 NIC's don't
-respond to Get Version ID, et. al in the probe sequence unless you send
-the Set MC Affinity command first.
-
-Problem Statement:
-
-We've been using a combination of #ifdef code blocks and IS_ENABLED()
-conditions to conditionally send these OEM commands.
-
-It makes adding any new code around these commands hard to understand.
-
-Solution:
-
-In this patch, I just want to remove the conditionally compiled blocks
-of code, and always use IS_ENABLED(...) to do dynamic control flow.
-
-I don't think the small amount of code this adds to non-users of the OEM
-Kconfigs is a big deal.
-
-Signed-off-by: Peter Delevoryas <peter@pjd.dev>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Stable-dep-of: e85e271dec02 ("net/ncsi: Fix the multi thread manner of NCSI driver")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/ncsi/ncsi-manage.c | 20 +++-----------------
- 1 file changed, 3 insertions(+), 17 deletions(-)
-
-diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
-index 7121ce2a47c0b..734feb2352fbc 100644
---- a/net/ncsi/ncsi-manage.c
-+++ b/net/ncsi/ncsi-manage.c
-@@ -689,8 +689,6 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
- return 0;
- }
-
--#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY)
--
- static int ncsi_oem_keep_phy_intel(struct ncsi_cmd_arg *nca)
- {
- unsigned char data[NCSI_OEM_INTEL_CMD_KEEP_PHY_LEN];
-@@ -716,10 +714,6 @@ static int ncsi_oem_keep_phy_intel(struct ncsi_cmd_arg *nca)
- return ret;
- }
-
--#endif
--
--#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
--
- /* NCSI OEM Command APIs */
- static int ncsi_oem_gma_handler_bcm(struct ncsi_cmd_arg *nca)
- {
-@@ -856,8 +850,6 @@ static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
- return nch->handler(nca);
- }
-
--#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
--
- /* Determine if a given channel from the channel_queue should be used for Tx */
- static bool ncsi_channel_is_tx(struct ncsi_dev_priv *ndp,
- struct ncsi_channel *nc)
-@@ -1039,20 +1031,18 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
- goto error;
- }
-
-- nd->state = ncsi_dev_state_config_oem_gma;
-+ nd->state = IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
-+ ? ncsi_dev_state_config_oem_gma
-+ : ncsi_dev_state_config_clear_vids;
- break;
- case ncsi_dev_state_config_oem_gma:
- nd->state = ncsi_dev_state_config_clear_vids;
-- ret = -1;
-
--#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
- nca.type = NCSI_PKT_CMD_OEM;
- nca.package = np->id;
- nca.channel = nc->id;
- ndp->pending_req_num = 1;
- ret = ncsi_gma_handler(&nca, nc->version.mf_id);
--#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
--
- if (ret < 0)
- schedule_work(&ndp->work);
-
-@@ -1404,7 +1394,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
-
- schedule_work(&ndp->work);
- break;
--#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
- case ncsi_dev_state_probe_mlx_gma:
- ndp->pending_req_num = 1;
-
-@@ -1429,7 +1418,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
-
- nd->state = ncsi_dev_state_probe_cis;
- break;
--#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
- case ncsi_dev_state_probe_cis:
- ndp->pending_req_num = NCSI_RESERVED_CHANNEL;
-
-@@ -1447,7 +1435,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY))
- nd->state = ncsi_dev_state_probe_keep_phy;
- break;
--#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY)
- case ncsi_dev_state_probe_keep_phy:
- ndp->pending_req_num = 1;
-
-@@ -1460,7 +1447,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
-
- nd->state = ncsi_dev_state_probe_gvi;
- break;
--#endif /* CONFIG_NCSI_OEM_CMD_KEEP_PHY */
- case ncsi_dev_state_probe_gvi:
- case ncsi_dev_state_probe_gc:
- case ncsi_dev_state_probe_gls:
---
-2.43.0
-
+++ /dev/null
-From 012580408a8964b935cf4734390a75966d84b01b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 3 Jun 2024 15:13:03 +0800
-Subject: net: sched: sch_multiq: fix possible OOB write in multiq_tune()
-
-From: Hangyu Hua <hbh25y@gmail.com>
-
-[ Upstream commit affc18fdc694190ca7575b9a86632a73b9fe043d ]
-
-q->bands will be assigned to qopt->bands to execute subsequent code logic
-after kmalloc. So the old q->bands should not be used in kmalloc.
-Otherwise, an out-of-bounds write will occur.
-
-Fixes: c2999f7fb05b ("net: sched: multiq: don't call qdisc_put() while holding tree lock")
-Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
-Acked-by: Cong Wang <cong.wang@bytedance.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/sched/sch_multiq.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
-index 8b99f07aa3a76..caa76c96b02ba 100644
---- a/net/sched/sch_multiq.c
-+++ b/net/sched/sch_multiq.c
-@@ -185,7 +185,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
-
- qopt->bands = qdisc_dev(sch)->real_num_tx_queues;
-
-- removed = kmalloc(sizeof(*removed) * (q->max_bands - q->bands),
-+ removed = kmalloc(sizeof(*removed) * (q->max_bands - qopt->bands),
- GFP_KERNEL);
- if (!removed)
- return -ENOMEM;
---
-2.43.0
-
+++ /dev/null
-From cb00efe7d5844d0eb017cce05e8791cb4c6f0650 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 18:15:11 +0000
-Subject: net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
-
-From: Eric Dumazet <edumazet@google.com>
-
-[ Upstream commit f921a58ae20852d188f70842431ce6519c4fdc36 ]
-
-If one TCA_TAPRIO_ATTR_PRIOMAP attribute has been provided,
-taprio_parse_mqprio_opt() must validate it, or userspace
-can inject arbitrary data to the kernel, the second time
-taprio_change() is called.
-
-First call (with valid attributes) sets dev->num_tc
-to a non zero value.
-
-Second call (with arbitrary mqprio attributes)
-returns early from taprio_parse_mqprio_opt()
-and bad things can happen.
-
-Fixes: a3d43c0d56f1 ("taprio: Add support adding an admin schedule")
-Reported-by: Noam Rathaus <noamr@ssd-disclosure.com>
-Signed-off-by: Eric Dumazet <edumazet@google.com>
-Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
-Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
-Link: https://lore.kernel.org/r/20240604181511.769870-1-edumazet@google.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/sched/sch_taprio.c | 15 ++++++---------
- 1 file changed, 6 insertions(+), 9 deletions(-)
-
-diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
-index e40b4425eb6b5..4a0986843fb5d 100644
---- a/net/sched/sch_taprio.c
-+++ b/net/sched/sch_taprio.c
-@@ -947,16 +947,13 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
- {
- int i, j;
-
-- if (!qopt && !dev->num_tc) {
-- NL_SET_ERR_MSG(extack, "'mqprio' configuration is necessary");
-- return -EINVAL;
-- }
--
-- /* If num_tc is already set, it means that the user already
-- * configured the mqprio part
-- */
-- if (dev->num_tc)
-+ if (!qopt) {
-+ if (!dev->num_tc) {
-+ NL_SET_ERR_MSG(extack, "'mqprio' configuration is necessary");
-+ return -EINVAL;
-+ }
- return 0;
-+ }
-
- /* Verify num_tc is not out of max range */
- if (qopt->num_tc > TC_MAX_QUEUE) {
---
-2.43.0
-
+++ /dev/null
-From 9d2b4690a8d80d81e80ac17bbfc4cf4183de4f43 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 22:42:55 +0900
-Subject: nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
-
-From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
-
-[ Upstream commit 7373a51e7998b508af7136530f3a997b286ce81c ]
-
-The error handling in nilfs_empty_dir() when a directory folio/page read
-fails is incorrect, as in the old ext2 implementation, and if the
-folio/page cannot be read or nilfs_check_folio() fails, it will falsely
-determine the directory as empty and corrupt the file system.
-
-In addition, since nilfs_empty_dir() does not immediately return on a
-failed folio/page read, but continues to loop, this can cause a long loop
-with I/O if i_size of the directory's inode is also corrupted, causing the
-log writer thread to wait and hang, as reported by syzbot.
-
-Fix these issues by making nilfs_empty_dir() immediately return a false
-value (0) if it fails to get a directory folio/page.
-
-Link: https://lkml.kernel.org/r/20240604134255.7165-1-konishi.ryusuke@gmail.com
-Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
-Reported-by: syzbot+c8166c541d3971bf6c87@syzkaller.appspotmail.com
-Closes: https://syzkaller.appspot.com/bug?extid=c8166c541d3971bf6c87
-Fixes: 2ba466d74ed7 ("nilfs2: directory entry operations")
-Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nilfs2/dir.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
-index 22f1f75a90c1a..552234ef22fe7 100644
---- a/fs/nilfs2/dir.c
-+++ b/fs/nilfs2/dir.c
-@@ -627,7 +627,7 @@ int nilfs_empty_dir(struct inode *inode)
-
- kaddr = nilfs_get_page(inode, i, &page);
- if (IS_ERR(kaddr))
-- continue;
-+ return 0;
-
- de = (struct nilfs_dir_entry *)kaddr;
- kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1);
---
-2.43.0
-
+++ /dev/null
-From ab84725bc1775d0a3ef5fd2ea6a661463a5fd832 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 17 May 2022 18:12:25 -0400
-Subject: nilfs2: Remove check for PageError
-
-From: Matthew Wilcox (Oracle) <willy@infradead.org>
-
-[ Upstream commit 79ea65563ad8aaab309d61eeb4d5019dd6cf5fa0 ]
-
-If read_mapping_page() encounters an error, it returns an errno, not a
-page with PageError set, so this test is not needed.
-
-Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-Stable-dep-of: 7373a51e7998 ("nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nilfs2/dir.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
-index eb7de9e2a384e..24cfe9db66e02 100644
---- a/fs/nilfs2/dir.c
-+++ b/fs/nilfs2/dir.c
-@@ -194,7 +194,7 @@ static struct page *nilfs_get_page(struct inode *dir, unsigned long n)
- if (!IS_ERR(page)) {
- kmap(page);
- if (unlikely(!PageChecked(page))) {
-- if (PageError(page) || !nilfs_check_page(page))
-+ if (!nilfs_check_page(page))
- goto fail;
- }
- }
---
-2.43.0
-
+++ /dev/null
-From 396dd465c29ba59fbc07ee78f1ad824e6b0a42b4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 27 Nov 2023 23:30:25 +0900
-Subject: nilfs2: return the mapped address from nilfs_get_page()
-
-From: Matthew Wilcox (Oracle) <willy@infradead.org>
-
-[ Upstream commit 09a46acb3697e50548bb265afa1d79163659dd85 ]
-
-In prepartion for switching from kmap() to kmap_local(), return the kmap
-address from nilfs_get_page() instead of having the caller look up
-page_address().
-
-[konishi.ryusuke: fixed a missing blank line after declaration]
-Link: https://lkml.kernel.org/r/20231127143036.2425-7-konishi.ryusuke@gmail.com
-Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: 7373a51e7998 ("nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- fs/nilfs2/dir.c | 57 +++++++++++++++++++++++--------------------------
- 1 file changed, 27 insertions(+), 30 deletions(-)
-
-diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
-index 24cfe9db66e02..22f1f75a90c1a 100644
---- a/fs/nilfs2/dir.c
-+++ b/fs/nilfs2/dir.c
-@@ -186,19 +186,24 @@ static bool nilfs_check_page(struct page *page)
- return false;
- }
-
--static struct page *nilfs_get_page(struct inode *dir, unsigned long n)
-+static void *nilfs_get_page(struct inode *dir, unsigned long n,
-+ struct page **pagep)
- {
- struct address_space *mapping = dir->i_mapping;
- struct page *page = read_mapping_page(mapping, n, NULL);
-+ void *kaddr;
-
-- if (!IS_ERR(page)) {
-- kmap(page);
-- if (unlikely(!PageChecked(page))) {
-- if (!nilfs_check_page(page))
-- goto fail;
-- }
-+ if (IS_ERR(page))
-+ return page;
-+
-+ kaddr = kmap(page);
-+ if (unlikely(!PageChecked(page))) {
-+ if (!nilfs_check_page(page))
-+ goto fail;
- }
-- return page;
-+
-+ *pagep = page;
-+ return kaddr;
-
- fail:
- nilfs_put_page(page);
-@@ -275,14 +280,14 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)
- for ( ; n < npages; n++, offset = 0) {
- char *kaddr, *limit;
- struct nilfs_dir_entry *de;
-- struct page *page = nilfs_get_page(inode, n);
-+ struct page *page;
-
-- if (IS_ERR(page)) {
-+ kaddr = nilfs_get_page(inode, n, &page);
-+ if (IS_ERR(kaddr)) {
- nilfs_error(sb, "bad page in #%lu", inode->i_ino);
- ctx->pos += PAGE_SIZE - offset;
- return -EIO;
- }
-- kaddr = page_address(page);
- de = (struct nilfs_dir_entry *)(kaddr + offset);
- limit = kaddr + nilfs_last_byte(inode, n) -
- NILFS_DIR_REC_LEN(1);
-@@ -345,11 +350,9 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
- start = 0;
- n = start;
- do {
-- char *kaddr;
-+ char *kaddr = nilfs_get_page(dir, n, &page);
-
-- page = nilfs_get_page(dir, n);
-- if (!IS_ERR(page)) {
-- kaddr = page_address(page);
-+ if (!IS_ERR(kaddr)) {
- de = (struct nilfs_dir_entry *)kaddr;
- kaddr += nilfs_last_byte(dir, n) - reclen;
- while ((char *) de <= kaddr) {
-@@ -387,15 +390,11 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
-
- struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
- {
-- struct page *page = nilfs_get_page(dir, 0);
-- struct nilfs_dir_entry *de = NULL;
-+ struct nilfs_dir_entry *de = nilfs_get_page(dir, 0, p);
-
-- if (!IS_ERR(page)) {
-- de = nilfs_next_entry(
-- (struct nilfs_dir_entry *)page_address(page));
-- *p = page;
-- }
-- return de;
-+ if (IS_ERR(de))
-+ return NULL;
-+ return nilfs_next_entry(de);
- }
-
- ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
-@@ -459,12 +458,11 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)
- for (n = 0; n <= npages; n++) {
- char *dir_end;
-
-- page = nilfs_get_page(dir, n);
-- err = PTR_ERR(page);
-- if (IS_ERR(page))
-+ kaddr = nilfs_get_page(dir, n, &page);
-+ err = PTR_ERR(kaddr);
-+ if (IS_ERR(kaddr))
- goto out;
- lock_page(page);
-- kaddr = page_address(page);
- dir_end = kaddr + nilfs_last_byte(dir, n);
- de = (struct nilfs_dir_entry *)kaddr;
- kaddr += PAGE_SIZE - reclen;
-@@ -627,11 +625,10 @@ int nilfs_empty_dir(struct inode *inode)
- char *kaddr;
- struct nilfs_dir_entry *de;
-
-- page = nilfs_get_page(inode, i);
-- if (IS_ERR(page))
-+ kaddr = nilfs_get_page(inode, i, &page);
-+ if (IS_ERR(kaddr))
- continue;
-
-- kaddr = page_address(page);
- de = (struct nilfs_dir_entry *)kaddr;
- kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1);
-
---
-2.43.0
-
+++ /dev/null
-From 6cbbf3cbece256826d736dea4d0ab50d3dca35cc Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 29 May 2024 20:59:44 +0530
-Subject: octeontx2-af: Always allocate PF entries from low prioriy zone
-
-From: Subbaraya Sundeep <sbhatta@marvell.com>
-
-[ Upstream commit 8b0f7410942cdc420c4557eda02bfcdf60ccec17 ]
-
-PF mcam entries has to be at low priority always so that VF
-can install longest prefix match rules at higher priority.
-This was taken care currently but when priority allocation
-wrt reference entry is requested then entries are allocated
-from mid-zone instead of low priority zone. Fix this and
-always allocate entries from low priority zone for PFs.
-
-Fixes: 7df5b4b260dd ("octeontx2-af: Allocate low priority entries for PF")
-Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
-Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 33 ++++++++++++-------
- 1 file changed, 22 insertions(+), 11 deletions(-)
-
-diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
-index c6b6d709e5908..84003243e3b75 100644
---- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
-+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
-@@ -2459,7 +2459,17 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
- * - when available free entries are less.
- * Lower priority ones out of avaialble free entries are always
- * chosen when 'high vs low' question arises.
-+ *
-+ * For a VF base MCAM match rule is set by its PF. And all the
-+ * further MCAM rules installed by VF on its own are
-+ * concatenated with the base rule set by its PF. Hence PF entries
-+ * should be at lower priority compared to VF entries. Otherwise
-+ * base rule is hit always and rules installed by VF will be of
-+ * no use. Hence if the request is from PF then allocate low
-+ * priority entries.
- */
-+ if (!(pcifunc & RVU_PFVF_FUNC_MASK))
-+ goto lprio_alloc;
-
- /* Get the search range for priority allocation request */
- if (req->priority) {
-@@ -2468,17 +2478,6 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
- goto alloc;
- }
-
-- /* For a VF base MCAM match rule is set by its PF. And all the
-- * further MCAM rules installed by VF on its own are
-- * concatenated with the base rule set by its PF. Hence PF entries
-- * should be at lower priority compared to VF entries. Otherwise
-- * base rule is hit always and rules installed by VF will be of
-- * no use. Hence if the request is from PF and NOT a priority
-- * allocation request then allocate low priority entries.
-- */
-- if (!(pcifunc & RVU_PFVF_FUNC_MASK))
-- goto lprio_alloc;
--
- /* Find out the search range for non-priority allocation request
- *
- * Get MCAM free entry count in middle zone.
-@@ -2508,6 +2507,18 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
- reverse = true;
- start = 0;
- end = mcam->bmap_entries;
-+ /* Ensure PF requests are always at bottom and if PF requests
-+ * for higher/lower priority entry wrt reference entry then
-+ * honour that criteria and start search for entries from bottom
-+ * and not in mid zone.
-+ */
-+ if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
-+ req->priority == NPC_MCAM_HIGHER_PRIO)
-+ end = req->ref_entry;
-+
-+ if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
-+ req->priority == NPC_MCAM_LOWER_PRIO)
-+ start = req->ref_entry;
- }
-
- alloc:
---
-2.43.0
-
+++ /dev/null
-From f37792d6c0c499db4e2e02e7a69d41d5e837ce08 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 14:05:27 +0200
-Subject: ptp: Fix error message on failed pin verification
-
-From: Karol Kolacinski <karol.kolacinski@intel.com>
-
-[ Upstream commit 323a359f9b077f382f4483023d096a4d316fd135 ]
-
-On failed verification of PTP clock pin, error message prints channel
-number instead of pin index after "pin", which is incorrect.
-
-Fix error message by adding channel number to the message and printing
-pin number instead of channel number.
-
-Fixes: 6092315dfdec ("ptp: introduce programmable pins.")
-Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
-Acked-by: Richard Cochran <richardcochran@gmail.com>
-Link: https://lore.kernel.org/r/20240604120555.16643-1-karol.kolacinski@intel.com
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/ptp/ptp_chardev.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
-index 9311f3d09c8fc..8eb902fe73a98 100644
---- a/drivers/ptp/ptp_chardev.c
-+++ b/drivers/ptp/ptp_chardev.c
-@@ -84,7 +84,8 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
- }
-
- if (info->verify(info, pin, func, chan)) {
-- pr_err("driver cannot use function %u on pin %u\n", func, chan);
-+ pr_err("driver cannot use function %u and channel %u on pin %u\n",
-+ func, chan, pin);
- return -EOPNOTSUPP;
- }
-
---
-2.43.0
-
+++ /dev/null
-From 06f0f18c3ad2b8622e86d452bf46b13e1f0c79f3 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 29 Aug 2021 15:43:54 +0300
-Subject: pvpanic: Indentation fixes here and there
-
-From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-
-[ Upstream commit 84b0f12a953c4feff9994b1c4583ed18b441f482 ]
-
-1) replace double spaces with single;
-2) relax line width limitation a bit.
-
-Reviewed-by: Mihai Carabas <mihai.carabas@oracle.com>
-Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Link: https://lore.kernel.org/r/20210829124354.81653-3-andriy.shevchenko@linux.intel.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: ee59be35d7a8 ("misc/pvpanic-pci: register attributes via pci_driver")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/misc/pvpanic/pvpanic-mmio.c | 7 +++----
- drivers/misc/pvpanic/pvpanic-pci.c | 12 +++++-------
- drivers/misc/pvpanic/pvpanic.c | 11 ++++-------
- 3 files changed, 12 insertions(+), 18 deletions(-)
-
-diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c
-index 61dbff5f0065c..eb97167c03fb4 100644
---- a/drivers/misc/pvpanic/pvpanic-mmio.c
-+++ b/drivers/misc/pvpanic/pvpanic-mmio.c
-@@ -24,8 +24,7 @@ MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
- MODULE_DESCRIPTION("pvpanic-mmio device driver");
- MODULE_LICENSE("GPL");
-
--static ssize_t capability_show(struct device *dev,
-- struct device_attribute *attr, char *buf)
-+static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-
-@@ -33,14 +32,14 @@ static ssize_t capability_show(struct device *dev,
- }
- static DEVICE_ATTR_RO(capability);
-
--static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
-+static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%x\n", pi->events);
- }
-
--static ssize_t events_store(struct device *dev, struct device_attribute *attr,
-+static ssize_t events_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
-index 7d1220f4c95bc..07eddb5ea30fa 100644
---- a/drivers/misc/pvpanic/pvpanic-pci.c
-+++ b/drivers/misc/pvpanic/pvpanic-pci.c
-@@ -19,11 +19,10 @@
- #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
-
- MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
--MODULE_DESCRIPTION("pvpanic device driver ");
-+MODULE_DESCRIPTION("pvpanic device driver");
- MODULE_LICENSE("GPL");
-
--static ssize_t capability_show(struct device *dev,
-- struct device_attribute *attr, char *buf)
-+static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-
-@@ -31,14 +30,14 @@ static ssize_t capability_show(struct device *dev,
- }
- static DEVICE_ATTR_RO(capability);
-
--static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
-+static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%x\n", pi->events);
- }
-
--static ssize_t events_store(struct device *dev, struct device_attribute *attr,
-+static ssize_t events_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct pvpanic_instance *pi = dev_get_drvdata(dev);
-@@ -65,8 +64,7 @@ static struct attribute *pvpanic_pci_dev_attrs[] = {
- };
- ATTRIBUTE_GROUPS(pvpanic_pci_dev);
-
--static int pvpanic_pci_probe(struct pci_dev *pdev,
-- const struct pci_device_id *ent)
-+static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- struct pvpanic_instance *pi;
- void __iomem *base;
-diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c
-index 477bf9c6b6bc5..049a120063489 100644
---- a/drivers/misc/pvpanic/pvpanic.c
-+++ b/drivers/misc/pvpanic/pvpanic.c
-@@ -23,7 +23,7 @@
- #include "pvpanic.h"
-
- MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
--MODULE_DESCRIPTION("pvpanic device driver ");
-+MODULE_DESCRIPTION("pvpanic device driver");
- MODULE_LICENSE("GPL");
-
- static struct list_head pvpanic_list;
-@@ -45,8 +45,7 @@ pvpanic_send_event(unsigned int event)
- }
-
- static int
--pvpanic_panic_notify(struct notifier_block *nb, unsigned long code,
-- void *unused)
-+pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, void *unused)
- {
- unsigned int event = PVPANIC_PANICKED;
-
-@@ -102,8 +101,7 @@ static int pvpanic_init(void)
- INIT_LIST_HEAD(&pvpanic_list);
- spin_lock_init(&pvpanic_lock);
-
-- atomic_notifier_chain_register(&panic_notifier_list,
-- &pvpanic_panic_nb);
-+ atomic_notifier_chain_register(&panic_notifier_list, &pvpanic_panic_nb);
-
- return 0;
- }
-@@ -111,8 +109,7 @@ module_init(pvpanic_init);
-
- static void pvpanic_exit(void)
- {
-- atomic_notifier_chain_unregister(&panic_notifier_list,
-- &pvpanic_panic_nb);
-+ atomic_notifier_chain_unregister(&panic_notifier_list, &pvpanic_panic_nb);
-
- }
- module_exit(pvpanic_exit);
---
-2.43.0
-
+++ /dev/null
-From 1d75229b9ef3c1ca26bf3b39c0da530ef818899d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 29 Aug 2021 15:43:52 +0300
-Subject: pvpanic: Keep single style across modules
-
-From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-
-[ Upstream commit 33a430419456991480cde9d8889e5a27f6049df4 ]
-
-We have different style on where we place module_*() and MODULE_*() macros.
-Inherit the style from the original module (now pvpanic-mmio.c).
-
-Reviewed-by: Mihai Carabas <mihai.carabas@oracle.com
-Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Link: https://lore.kernel.org/r/20210829124354.81653-1-andriy.shevchenko@linux.intel.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: ee59be35d7a8 ("misc/pvpanic-pci: register attributes via pci_driver")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/misc/pvpanic/pvpanic-pci.c | 14 ++++++--------
- drivers/misc/pvpanic/pvpanic.c | 3 +--
- 2 files changed, 7 insertions(+), 10 deletions(-)
-
-diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
-index 741116b3d9958..7d1220f4c95bc 100644
---- a/drivers/misc/pvpanic/pvpanic-pci.c
-+++ b/drivers/misc/pvpanic/pvpanic-pci.c
-@@ -22,11 +22,6 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
- MODULE_DESCRIPTION("pvpanic device driver ");
- MODULE_LICENSE("GPL");
-
--static const struct pci_device_id pvpanic_pci_id_tbl[] = {
-- { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PVPANIC)},
-- {}
--};
--
- static ssize_t capability_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
-@@ -99,6 +94,12 @@ static int pvpanic_pci_probe(struct pci_dev *pdev,
- return devm_pvpanic_probe(&pdev->dev, pi);
- }
-
-+static const struct pci_device_id pvpanic_pci_id_tbl[] = {
-+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PVPANIC)},
-+ {}
-+};
-+MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl);
-+
- static struct pci_driver pvpanic_pci_driver = {
- .name = "pvpanic-pci",
- .id_table = pvpanic_pci_id_tbl,
-@@ -107,7 +108,4 @@ static struct pci_driver pvpanic_pci_driver = {
- .dev_groups = pvpanic_pci_dev_groups,
- },
- };
--
--MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl);
--
- module_pci_driver(pvpanic_pci_driver);
-diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c
-index b9e6400a574b0..477bf9c6b6bc5 100644
---- a/drivers/misc/pvpanic/pvpanic.c
-+++ b/drivers/misc/pvpanic/pvpanic.c
-@@ -107,6 +107,7 @@ static int pvpanic_init(void)
-
- return 0;
- }
-+module_init(pvpanic_init);
-
- static void pvpanic_exit(void)
- {
-@@ -114,6 +115,4 @@ static void pvpanic_exit(void)
- &pvpanic_panic_nb);
-
- }
--
--module_init(pvpanic_init);
- module_exit(pvpanic_exit);
---
-2.43.0
-
+++ /dev/null
-From 7942fb2584daa8140ea8680021b03bf0b9c9a0d4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 21 May 2024 13:13:56 +0530
-Subject: selftests/mm: compaction_test: fix bogus test success on Aarch64
-
-From: Dev Jain <dev.jain@arm.com>
-
-[ Upstream commit d4202e66a4b1fe6968f17f9f09bbc30d08f028a1 ]
-
-Patch series "Fixes for compaction_test", v2.
-
-The compaction_test memory selftest introduces fragmentation in memory
-and then tries to allocate as many hugepages as possible. This series
-addresses some problems.
-
-On Aarch64, if nr_hugepages == 0, then the test trivially succeeds since
-compaction_index becomes 0, which is less than 3, due to no division by
-zero exception being raised. We fix that by checking for division by
-zero.
-
-Secondly, correctly set the number of hugepages to zero before trying
-to set a large number of them.
-
-Now, consider a situation in which, at the start of the test, a non-zero
-number of hugepages have been already set (while running the entire
-selftests/mm suite, or manually by the admin). The test operates on 80%
-of memory to avoid OOM-killer invocation, and because some memory is
-already blocked by hugepages, it would increase the chance of OOM-killing.
-Also, since mem_free used in check_compaction() is the value before we
-set nr_hugepages to zero, the chance that the compaction_index will
-be small is very high if the preset nr_hugepages was high, leading to a
-bogus test success.
-
-This patch (of 3):
-
-Currently, if at runtime we are not able to allocate a huge page, the test
-will trivially pass on Aarch64 due to no exception being raised on
-division by zero while computing compaction_index. Fix that by checking
-for nr_hugepages == 0. Anyways, in general, avoid a division by zero by
-exiting the program beforehand. While at it, fix a typo, and handle the
-case where the number of hugepages may overflow an integer.
-
-Link: https://lkml.kernel.org/r/20240521074358.675031-1-dev.jain@arm.com
-Link: https://lkml.kernel.org/r/20240521074358.675031-2-dev.jain@arm.com
-Fixes: bd67d5c15cc1 ("Test compaction of mlocked memory")
-Signed-off-by: Dev Jain <dev.jain@arm.com>
-Cc: Anshuman Khandual <anshuman.khandual@arm.com>
-Cc: Shuah Khan <shuah@kernel.org>
-Cc: Sri Jayaramappa <sjayaram@akamai.com>
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/testing/selftests/vm/compaction_test.c | 20 +++++++++++++-------
- 1 file changed, 13 insertions(+), 7 deletions(-)
-
-diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
-index 6aa6460b854ea..309b3750e57e1 100644
---- a/tools/testing/selftests/vm/compaction_test.c
-+++ b/tools/testing/selftests/vm/compaction_test.c
-@@ -82,12 +82,13 @@ int prereq(void)
- return -1;
- }
-
--int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-+int check_compaction(unsigned long mem_free, unsigned long hugepage_size)
- {
-+ unsigned long nr_hugepages_ul;
- int fd, ret = -1;
- int compaction_index = 0;
-- char initial_nr_hugepages[10] = {0};
-- char nr_hugepages[10] = {0};
-+ char initial_nr_hugepages[20] = {0};
-+ char nr_hugepages[20] = {0};
-
- /* We want to test with 80% of available memory. Else, OOM killer comes
- in to play */
-@@ -136,7 +137,12 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- /* We should have been able to request at least 1/3 rd of the memory in
- huge pages */
-- compaction_index = mem_free/(atoi(nr_hugepages) * hugepage_size);
-+ nr_hugepages_ul = strtoul(nr_hugepages, NULL, 10);
-+ if (!nr_hugepages_ul) {
-+ ksft_print_msg("ERROR: No memory is available as huge pages\n");
-+ goto close_fd;
-+ }
-+ compaction_index = mem_free/(nr_hugepages_ul * hugepage_size);
-
- lseek(fd, 0, SEEK_SET);
-
-@@ -147,11 +153,11 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- goto close_fd;
- }
-
-- ksft_print_msg("Number of huge pages allocated = %d\n",
-- atoi(nr_hugepages));
-+ ksft_print_msg("Number of huge pages allocated = %lu\n",
-+ nr_hugepages_ul);
-
- if (compaction_index > 3) {
-- ksft_print_msg("ERROR: Less that 1/%d of memory is available\n"
-+ ksft_print_msg("ERROR: Less than 1/%d of memory is available\n"
- "as huge pages\n", compaction_index);
- goto close_fd;
- }
---
-2.43.0
-
+++ /dev/null
-From 8122b9a1d85ed20baf5b0f0dc31e8a912e38559f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 21 May 2024 13:13:57 +0530
-Subject: selftests/mm: compaction_test: fix incorrect write of zero to
- nr_hugepages
-
-From: Dev Jain <dev.jain@arm.com>
-
-[ Upstream commit 9ad665ef55eaad1ead1406a58a34f615a7c18b5e ]
-
-Currently, the test tries to set nr_hugepages to zero, but that is not
-actually done because the file offset is not reset after read(). Fix that
-using lseek().
-
-Link: https://lkml.kernel.org/r/20240521074358.675031-3-dev.jain@arm.com
-Fixes: bd67d5c15cc1 ("Test compaction of mlocked memory")
-Signed-off-by: Dev Jain <dev.jain@arm.com>
-Cc: <stable@vger.kernel.org>
-Cc: Anshuman Khandual <anshuman.khandual@arm.com>
-Cc: Shuah Khan <shuah@kernel.org>
-Cc: Sri Jayaramappa <sjayaram@akamai.com>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/testing/selftests/vm/compaction_test.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
-index 9b420140ba2ba..55dec92e1e58c 100644
---- a/tools/testing/selftests/vm/compaction_test.c
-+++ b/tools/testing/selftests/vm/compaction_test.c
-@@ -103,6 +103,8 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- goto close_fd;
- }
-
-+ lseek(fd, 0, SEEK_SET);
-+
- /* Start with the initial condition of 0 huge pages*/
- if (write(fd, "0", sizeof(char)) != sizeof(char)) {
- perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n");
---
-2.43.0
-
+++ /dev/null
-From fc916f38ee158cfe606782f4c93fb9e349c54cd6 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 1 Jan 2024 13:36:12 +0500
-Subject: selftests/mm: conform test to TAP format output
-
-From: Muhammad Usama Anjum <usama.anjum@collabora.com>
-
-[ Upstream commit 9a21701edc41465de56f97914741bfb7bfc2517d ]
-
-Conform the layout, informational and status messages to TAP. No
-functional change is intended other than the layout of output messages.
-
-Link: https://lkml.kernel.org/r/20240101083614.1076768-1-usama.anjum@collabora.com
-Signed-off-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
-Cc: Shuah Khan <shuah@kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: d4202e66a4b1 ("selftests/mm: compaction_test: fix bogus test success on Aarch64")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/testing/selftests/vm/compaction_test.c | 91 ++++++++++----------
- 1 file changed, 44 insertions(+), 47 deletions(-)
-
-diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
-index 55dec92e1e58c..f81931c1f8386 100644
---- a/tools/testing/selftests/vm/compaction_test.c
-+++ b/tools/testing/selftests/vm/compaction_test.c
-@@ -33,7 +33,7 @@ int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize)
- FILE *cmdfile = popen(cmd, "r");
-
- if (!(fgets(buffer, sizeof(buffer), cmdfile))) {
-- perror("Failed to read meminfo\n");
-+ ksft_print_msg("Failed to read meminfo: %s\n", strerror(errno));
- return -1;
- }
-
-@@ -44,7 +44,7 @@ int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize)
- cmdfile = popen(cmd, "r");
-
- if (!(fgets(buffer, sizeof(buffer), cmdfile))) {
-- perror("Failed to read meminfo\n");
-+ ksft_print_msg("Failed to read meminfo: %s\n", strerror(errno));
- return -1;
- }
-
-@@ -62,14 +62,14 @@ int prereq(void)
- fd = open("/proc/sys/vm/compact_unevictable_allowed",
- O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
-- perror("Failed to open\n"
-- "/proc/sys/vm/compact_unevictable_allowed\n");
-+ ksft_print_msg("Failed to open /proc/sys/vm/compact_unevictable_allowed: %s\n",
-+ strerror(errno));
- return -1;
- }
-
- if (read(fd, &allowed, sizeof(char)) != sizeof(char)) {
-- perror("Failed to read from\n"
-- "/proc/sys/vm/compact_unevictable_allowed\n");
-+ ksft_print_msg("Failed to read from /proc/sys/vm/compact_unevictable_allowed: %s\n",
-+ strerror(errno));
- close(fd);
- return -1;
- }
-@@ -78,12 +78,13 @@ int prereq(void)
- if (allowed == '1')
- return 0;
-
-+ ksft_print_msg("Compaction isn't allowed\n");
- return -1;
- }
-
- int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- {
-- int fd;
-+ int fd, ret = -1;
- int compaction_index = 0;
- char initial_nr_hugepages[10] = {0};
- char nr_hugepages[10] = {0};
-@@ -94,12 +95,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK);
- if (fd < 0) {
-- perror("Failed to open /proc/sys/vm/nr_hugepages");
-+ ksft_test_result_fail("Failed to open /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- return -1;
- }
-
- if (read(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) <= 0) {
-- perror("Failed to read from /proc/sys/vm/nr_hugepages");
-+ ksft_test_result_fail("Failed to read from /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -107,7 +110,8 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- /* Start with the initial condition of 0 huge pages*/
- if (write(fd, "0", sizeof(char)) != sizeof(char)) {
-- perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n");
-+ ksft_test_result_fail("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -116,14 +120,16 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- /* Request a large number of huge pages. The Kernel will allocate
- as much as it can */
- if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
-- perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n");
-+ ksft_test_result_fail("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
- lseek(fd, 0, SEEK_SET);
-
- if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
-- perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n");
-+ ksft_test_result_fail("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -131,67 +137,58 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- huge pages */
- compaction_index = mem_free/(atoi(nr_hugepages) * hugepage_size);
-
-- if (compaction_index > 3) {
-- printf("No of huge pages allocated = %d\n",
-- (atoi(nr_hugepages)));
-- fprintf(stderr, "ERROR: Less that 1/%d of memory is available\n"
-- "as huge pages\n", compaction_index);
-- goto close_fd;
-- }
--
-- printf("No of huge pages allocated = %d\n",
-- (atoi(nr_hugepages)));
--
- lseek(fd, 0, SEEK_SET);
-
- if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
- != strlen(initial_nr_hugepages)) {
-- perror("Failed to write value to /proc/sys/vm/nr_hugepages\n");
-+ ksft_test_result_fail("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-- close(fd);
-- return 0;
-+ if (compaction_index > 3) {
-+ ksft_print_msg("ERROR: Less that 1/%d of memory is available\n"
-+ "as huge pages\n", compaction_index);
-+ ksft_test_result_fail("No of huge pages allocated = %d\n", (atoi(nr_hugepages)));
-+ goto close_fd;
-+ }
-+
-+ ksft_test_result_pass("Memory compaction succeeded. No of huge pages allocated = %d\n",
-+ (atoi(nr_hugepages)));
-+ ret = 0;
-
- close_fd:
- close(fd);
-- printf("Not OK. Compaction test failed.");
-- return -1;
-+ return ret;
- }
-
-
- int main(int argc, char **argv)
- {
- struct rlimit lim;
-- struct map_list *list, *entry;
-+ struct map_list *list = NULL, *entry;
- size_t page_size, i;
- void *map = NULL;
- unsigned long mem_free = 0;
- unsigned long hugepage_size = 0;
- long mem_fragmentable_MB = 0;
-
-- if (prereq() != 0) {
-- printf("Either the sysctl compact_unevictable_allowed is not\n"
-- "set to 1 or couldn't read the proc file.\n"
-- "Skipping the test\n");
-- return KSFT_SKIP;
-- }
-+ ksft_print_header();
-+
-+ if (prereq() != 0)
-+ return ksft_exit_pass();
-+
-+ ksft_set_plan(1);
-
- lim.rlim_cur = RLIM_INFINITY;
- lim.rlim_max = RLIM_INFINITY;
-- if (setrlimit(RLIMIT_MEMLOCK, &lim)) {
-- perror("Failed to set rlimit:\n");
-- return -1;
-- }
-+ if (setrlimit(RLIMIT_MEMLOCK, &lim))
-+ ksft_exit_fail_msg("Failed to set rlimit: %s\n", strerror(errno));
-
- page_size = getpagesize();
-
-- list = NULL;
--
-- if (read_memory_info(&mem_free, &hugepage_size) != 0) {
-- printf("ERROR: Cannot read meminfo\n");
-- return -1;
-- }
-+ if (read_memory_info(&mem_free, &hugepage_size) != 0)
-+ ksft_exit_fail_msg("Failed to get meminfo\n");
-
- mem_fragmentable_MB = mem_free * 0.8 / 1024;
-
-@@ -227,7 +224,7 @@ int main(int argc, char **argv)
- }
-
- if (check_compaction(mem_free, hugepage_size) == 0)
-- return 0;
-+ return ksft_exit_pass();
-
-- return -1;
-+ return ksft_exit_fail();
- }
---
-2.43.0
-
+++ /dev/null
-From 853c0f059d7a91d4bd850040a0da0512dbfeedda Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 9 Feb 2024 14:30:04 +0000
-Subject: selftests/mm: log a consistent test name for check_compaction
-
-From: Mark Brown <broonie@kernel.org>
-
-[ Upstream commit f3b7568c49420d2dcd251032c9ca1e069ec8a6c9 ]
-
-Every test result report in the compaction test prints a distinct log
-messae, and some of the reports print a name that varies at runtime. This
-causes problems for automation since a lot of automation software uses the
-printed string as the name of the test, if the name varies from run to run
-and from pass to fail then the automation software can't identify that a
-test changed result or that the same tests are being run.
-
-Refactor the logging to use a consistent name when printing the result of
-the test, printing the existing messages as diagnostic information instead
-so they are still available for people trying to interpret the results.
-
-Link: https://lkml.kernel.org/r/20240209-kselftest-mm-cleanup-v1-2-a3c0386496b5@kernel.org
-Signed-off-by: Mark Brown <broonie@kernel.org>
-Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>
-Cc: Ryan Roberts <ryan.roberts@arm.com>
-Cc: Shuah Khan <shuah@kernel.org>
-Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-Stable-dep-of: d4202e66a4b1 ("selftests/mm: compaction_test: fix bogus test success on Aarch64")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/testing/selftests/vm/compaction_test.c | 35 +++++++++++---------
- 1 file changed, 19 insertions(+), 16 deletions(-)
-
-diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
-index f81931c1f8386..6aa6460b854ea 100644
---- a/tools/testing/selftests/vm/compaction_test.c
-+++ b/tools/testing/selftests/vm/compaction_test.c
-@@ -95,14 +95,15 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK);
- if (fd < 0) {
-- ksft_test_result_fail("Failed to open /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-- return -1;
-+ ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
-+ ret = -1;
-+ goto out;
- }
-
- if (read(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) <= 0) {
-- ksft_test_result_fail("Failed to read from /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-+ ksft_print_msg("Failed to read from /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -110,8 +111,8 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- /* Start with the initial condition of 0 huge pages*/
- if (write(fd, "0", sizeof(char)) != sizeof(char)) {
-- ksft_test_result_fail("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-+ ksft_print_msg("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -120,16 +121,16 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
- /* Request a large number of huge pages. The Kernel will allocate
- as much as it can */
- if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
-- ksft_test_result_fail("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-+ ksft_print_msg("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
- lseek(fd, 0, SEEK_SET);
-
- if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
-- ksft_test_result_fail("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-+ ksft_print_msg("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-@@ -141,24 +142,26 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
-
- if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
- != strlen(initial_nr_hugepages)) {
-- ksft_test_result_fail("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n",
-- strerror(errno));
-+ ksft_print_msg("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n",
-+ strerror(errno));
- goto close_fd;
- }
-
-+ ksft_print_msg("Number of huge pages allocated = %d\n",
-+ atoi(nr_hugepages));
-+
- if (compaction_index > 3) {
- ksft_print_msg("ERROR: Less that 1/%d of memory is available\n"
- "as huge pages\n", compaction_index);
-- ksft_test_result_fail("No of huge pages allocated = %d\n", (atoi(nr_hugepages)));
- goto close_fd;
- }
-
-- ksft_test_result_pass("Memory compaction succeeded. No of huge pages allocated = %d\n",
-- (atoi(nr_hugepages)));
- ret = 0;
-
- close_fd:
- close(fd);
-+ out:
-+ ksft_test_result(ret == 0, "check_compaction\n");
- return ret;
- }
-
---
-2.43.0
-
+++ /dev/null
-From 8caf55f63a641ad26dbc95f25a4d9d3e1308b18b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 30 Apr 2024 16:04:30 -0400
-Subject: serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using
- prescaler
-
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-
-[ Upstream commit 8492bd91aa055907c67ef04f2b56f6dadd1f44bf ]
-
-When using a high speed clock with a low baud rate, the 4x prescaler is
-automatically selected if required. In that case, sc16is7xx_set_baud()
-properly configures the chip registers, but returns an incorrect baud
-rate by not taking into account the prescaler value. This incorrect baud
-rate is then fed to uart_update_timeout().
-
-For example, with an input clock of 80MHz, and a selected baud rate of 50,
-sc16is7xx_set_baud() will return 200 instead of 50.
-
-Fix this by first changing the prescaler variable to hold the selected
-prescaler value instead of the MCR bitfield. Then properly take into
-account the selected prescaler value in the return value computation.
-
-Also add better documentation about the divisor value computation.
-
-Fixes: dfeae619d781 ("serial: sc16is7xx")
-Cc: stable@vger.kernel.org
-Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
-Link: https://lore.kernel.org/r/20240430200431.4102923-1-hugo@hugovil.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/sc16is7xx.c | 23 ++++++++++++++++++-----
- 1 file changed, 18 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
-index 25e625c2ee74b..d274a847c6ab3 100644
---- a/drivers/tty/serial/sc16is7xx.c
-+++ b/drivers/tty/serial/sc16is7xx.c
-@@ -490,16 +490,28 @@ static bool sc16is7xx_regmap_noinc(struct device *dev, unsigned int reg)
- return reg == SC16IS7XX_RHR_REG;
- }
-
-+/*
-+ * Configure programmable baud rate generator (divisor) according to the
-+ * desired baud rate.
-+ *
-+ * From the datasheet, the divisor is computed according to:
-+ *
-+ * XTAL1 input frequency
-+ * -----------------------
-+ * prescaler
-+ * divisor = ---------------------------
-+ * baud-rate x sampling-rate
-+ */
- static int sc16is7xx_set_baud(struct uart_port *port, int baud)
- {
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- u8 lcr;
-- u8 prescaler = 0;
-+ unsigned int prescaler = 1;
- unsigned long clk = port->uartclk, div = clk / 16 / baud;
-
- if (div >= BIT(16)) {
-- prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
-- div /= 4;
-+ prescaler = 4;
-+ div /= prescaler;
- }
-
- /* In an amazing feat of design, the Enhanced Features Register shares
-@@ -534,9 +546,10 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
-
- mutex_unlock(&s->efr_lock);
-
-+ /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */
- sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
- SC16IS7XX_MCR_CLKSEL_BIT,
-- prescaler);
-+ prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
-
- /* Open the LCR divisors for configuration */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
-@@ -551,7 +564,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
- /* Put LCR back to the normal mode */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-
-- return DIV_ROUND_CLOSEST(clk / 16, div);
-+ return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
- }
-
- static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
---
-2.43.0
-
+++ /dev/null
-From 33192d74cb6f30113e61243ae4fae4f917008d94 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 21 Dec 2023 18:18:19 -0500
-Subject: serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
-
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-
-[ Upstream commit 2e57cefc4477659527f7adab1f87cdbf60ef1ae6 ]
-
-To better show why the limit is what it is, since we have only 16 bits for
-the divisor.
-
-Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
-Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
-Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Link: https://lore.kernel.org/r/20231221231823.2327894-13-hugo@hugovil.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: 8492bd91aa05 ("serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/sc16is7xx.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
-index 35f8675db1d89..25e625c2ee74b 100644
---- a/drivers/tty/serial/sc16is7xx.c
-+++ b/drivers/tty/serial/sc16is7xx.c
-@@ -497,7 +497,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
- u8 prescaler = 0;
- unsigned long clk = port->uartclk, div = clk / 16 / baud;
-
-- if (div > 0xffff) {
-+ if (div >= BIT(16)) {
- prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
- div /= 4;
- }
---
-2.43.0
-
nfs-fix-undefined-behavior-in-nfs_block_bits.patch
nfs-fix-read_plus-when-server-doesn-t-support-op_read_plus.patch
scsi-ufs-ufs-qcom-clear-qunipro_g4_sel-for-hw-major-version-5.patch
-wifi-mac80211-mesh-fix-leak-of-mesh_preq_queue-objec.patch
-wifi-mac80211-fix-deadlock-in-ieee80211_sta_ps_deliv.patch
-wifi-cfg80211-lock-wiphy-in-cfg80211_get_station.patch
-wifi-cfg80211-pmsr-use-correct-nla_get_ux-functions.patch
-wifi-iwlwifi-mvm-revert-gen2-tx-a-mpdu-size-to-64.patch
-wifi-iwlwifi-dbg_ini-move-iwl_dbg_tlv_free-outside-o.patch
-wifi-iwlwifi-mvm-check-n_ssids-before-accessing-the-.patch
-wifi-iwlwifi-mvm-don-t-read-past-the-mfuart-notifcat.patch
-wifi-mac80211-correctly-parse-spatial-reuse-paramete.patch
-net-ncsi-simplify-kconfig-dts-control-flow.patch
-net-ncsi-fix-the-multi-thread-manner-of-ncsi-driver.patch
-ipv6-sr-block-bh-in-seg6_output_core-and-seg6_input_.patch
-bpf-set-run-context-for-rawtp-test_run-callback.patch
-octeontx2-af-always-allocate-pf-entries-from-low-pri.patch
-net-sched-sch_multiq-fix-possible-oob-write-in-multi.patch
-vxlan-fix-regression-when-dropping-packets-due-to-in.patch
-tcp-count-close-wait-sockets-for-tcp_mib_currestab.patch
-net-sched-taprio-always-validate-tca_taprio_attr_pri.patch
-ptp-fix-error-message-on-failed-pin-verification.patch
-af_unix-set-sk-sk_state-under-unix_state_lock-for-tr.patch
-af_unix-annodate-data-races-around-sk-sk_state-for-w.patch
-af_unix-annotate-data-race-of-sk-sk_state-in-unix_in.patch
-af_unix-annotate-data-races-around-sk-sk_state-in-un.patch
-net-inline-sock_prot_inuse_add.patch
-net-drop-nopreempt-requirement-on-sock_prot_inuse_ad.patch
-af_unix-use-offsetof-instead-of-sizeof.patch
-af_unix-pass-struct-sock-to-unix_autobind.patch
-af_unix-factorise-unix_find_other-based-on-address-t.patch
-af_unix-return-an-error-as-a-pointer-in-unix_find_ot.patch
-af_unix-cut-unix_validate_addr-out-of-unix_mkname.patch
-af_unix-copy-unix_mkname-into-unix_find_-bsd-abstrac.patch
-af_unix-clean-up-some-sock_net-uses.patch
-af_unix-annotate-data-race-of-sk-sk_state-in-unix_st.patch
-af_unix-annotate-data-races-around-sk-sk_state-in-se.patch
-af_unix-annotate-data-race-of-sk-sk_state-in-unix_st.patch-5290
-af_unix-annotate-data-races-around-sk-sk_state-in-un.patch-6162
-af_unix-annotate-data-race-of-net-unx.sysctl_max_dgr.patch
-af_unix-use-unix_recvq_full_lockless-in-unix_stream_.patch
-af_unix-annotate-lockless-accesses-to-sk-sk_err.patch
-af_unix-use-skb_queue_empty_lockless-in-unix_release.patch
-af_unix-use-skb_queue_len_lockless-in-sk_diag_show_r.patch
-af_unix-annotate-data-race-of-sk-sk_shutdown-in-sk_d.patch
-ipv6-fix-possible-race-in-__fib6_drop_pcpu_from.patch
-usb-gadget-f_fs-use-io_data-status-consistently.patch
-usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-.patch
-iio-accel-mxc4005-reset-chip-on-probe-and-resume.patch
-drm-amd-display-handle-y-carry-over-in-vcp-x.y-calcu.patch
-drm-amd-display-clean-up-some-inconsistent-indenting.patch
-drm-amd-display-drop-unnecessary-null-checks-in-debu.patch
-drm-amd-display-fix-incorrect-dsc-instance-for-mst.patch
-pvpanic-keep-single-style-across-modules.patch
-pvpanic-indentation-fixes-here-and-there.patch
-misc-pvpanic-deduplicate-common-code.patch
-misc-pvpanic-pci-register-attributes-via-pci_driver.patch
-skbuff-introduce-skb_pull_data.patch
-bluetooth-hci_qca-mark-of-related-data-as-maybe-unus.patch
-bluetooth-btqca-use-le32_to_cpu-for-ver.soc_id.patch
-bluetooth-btqca-add-wcn3988-support.patch
-bluetooth-qca-use-switch-case-for-soc-type-behavior.patch
-bluetooth-qca-add-support-for-qca2066.patch
-bluetooth-qca-fix-info-leak-when-fetching-fw-build-i.patch
-serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch
-serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch
-x86-ibt-ftrace-search-for-__fentry__-location.patch
-ftrace-fix-possible-use-after-free-issue-in-ftrace_l.patch
-mmc-davinci_mmc-convert-to-platform-remove-callback-.patch
-mmc-davinci-don-t-strip-remove-function-when-driver-.patch
-mm-mprotect-use-mmu_gather.patch
-mm-mprotect-do-not-flush-when-not-required-architect.patch
-mm-avoid-unnecessary-flush-on-change_huge_pmd.patch
-mm-fix-race-between-__split_huge_pmd_locked-and-gup-.patch
-i2c-add-fwnode-apis.patch
-i2c-acpi-unbind-mux-adapters-before-delete.patch
-cma-factor-out-minimum-alignment-requirement.patch
-mm-cma-drop-incorrect-alignment-check-in-cma_init_re.patch
-selftests-mm-compaction_test-fix-incorrect-write-of-.patch
-selftests-mm-conform-test-to-tap-format-output.patch
-selftests-mm-log-a-consistent-test-name-for-check_co.patch
-selftests-mm-compaction_test-fix-bogus-test-success-.patch
-wifi-ath10k-store-wlan-firmware-version-in-smem-imag.patch
-wifi-ath10k-fix-qcom_smem-dependency.patch
-wifi-ath10k-fix-qcom_rproc_common-dependency.patch
-btrfs-fix-leak-of-qgroup-extent-records-after-transa.patch
-nilfs2-remove-check-for-pageerror.patch
-nilfs2-return-the-mapped-address-from-nilfs_get_page.patch
-nilfs2-fix-nilfs_empty_dir-misjudgment-and-long-loop.patch
+++ /dev/null
-From 2d4f94517222d0fa628417ac8333611548ca21fe Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 1 Dec 2021 10:54:52 -0800
-Subject: skbuff: introduce skb_pull_data
-
-From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-
-[ Upstream commit 13244cccc2b61ec715f0ac583d3037497004d4a5 ]
-
-Like skb_pull but returns the original data pointer before pulling the
-data after performing a check against sbk->len.
-
-This allows to change code that does "struct foo *p = (void *)skb->data;"
-which is hard to audit and error prone, to:
-
- p = skb_pull_data(skb, sizeof(*p));
- if (!p)
- return;
-
-Which is both safer and cleaner.
-
-Acked-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-Stable-dep-of: cda0d6a198e2 ("Bluetooth: qca: fix info leak when fetching fw build id")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- include/linux/skbuff.h | 2 ++
- net/core/skbuff.c | 24 ++++++++++++++++++++++++
- 2 files changed, 26 insertions(+)
-
-diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index 15de91c65a09a..b230c422dc3b9 100644
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -2447,6 +2447,8 @@ static inline void *skb_pull_inline(struct sk_buff *skb, unsigned int len)
- return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
- }
-
-+void *skb_pull_data(struct sk_buff *skb, size_t len);
-+
- void *__pskb_pull_tail(struct sk_buff *skb, int delta);
-
- static inline void *__pskb_pull(struct sk_buff *skb, unsigned int len)
-diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 4ec8cfd357eba..17073429cc365 100644
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -2071,6 +2071,30 @@ void *skb_pull(struct sk_buff *skb, unsigned int len)
- }
- EXPORT_SYMBOL(skb_pull);
-
-+/**
-+ * skb_pull_data - remove data from the start of a buffer returning its
-+ * original position.
-+ * @skb: buffer to use
-+ * @len: amount of data to remove
-+ *
-+ * This function removes data from the start of a buffer, returning
-+ * the memory to the headroom. A pointer to the original data in the buffer
-+ * is returned after checking if there is enough data to pull. Once the
-+ * data has been pulled future pushes will overwrite the old data.
-+ */
-+void *skb_pull_data(struct sk_buff *skb, size_t len)
-+{
-+ void *data = skb->data;
-+
-+ if (skb->len < len)
-+ return NULL;
-+
-+ skb_pull(skb, len);
-+
-+ return data;
-+}
-+EXPORT_SYMBOL(skb_pull_data);
-+
- /**
- * skb_trim - remove end from a buffer
- * @skb: buffer to alter
---
-2.43.0
-
+++ /dev/null
-From bd1a843eb8e9bc02a9d6eb451012475bcef63b78 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Jun 2024 01:02:16 +0800
-Subject: tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
-
-From: Jason Xing <kernelxing@tencent.com>
-
-[ Upstream commit a46d0ea5c94205f40ecf912d1bb7806a8a64704f ]
-
-According to RFC 1213, we should also take CLOSE-WAIT sockets into
-consideration:
-
- "tcpCurrEstab OBJECT-TYPE
- ...
- The number of TCP connections for which the current state
- is either ESTABLISHED or CLOSE- WAIT."
-
-After this, CurrEstab counter will display the total number of
-ESTABLISHED and CLOSE-WAIT sockets.
-
-The logic of counting
-When we increment the counter?
-a) if we change the state to ESTABLISHED.
-b) if we change the state from SYN-RECEIVED to CLOSE-WAIT.
-
-When we decrement the counter?
-a) if the socket leaves ESTABLISHED and will never go into CLOSE-WAIT,
-say, on the client side, changing from ESTABLISHED to FIN-WAIT-1.
-b) if the socket leaves CLOSE-WAIT, say, on the server side, changing
-from CLOSE-WAIT to LAST-ACK.
-
-Please note: there are two chances that old state of socket can be changed
-to CLOSE-WAIT in tcp_fin(). One is SYN-RECV, the other is ESTABLISHED.
-So we have to take care of the former case.
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Signed-off-by: Jason Xing <kernelxing@tencent.com>
-Reviewed-by: Eric Dumazet <edumazet@google.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/ipv4/tcp.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index 9c7998377d6bd..31c572882b41f 100644
---- a/net/ipv4/tcp.c
-+++ b/net/ipv4/tcp.c
-@@ -2619,6 +2619,10 @@ void tcp_set_state(struct sock *sk, int state)
- if (oldstate != TCP_ESTABLISHED)
- TCP_INC_STATS(sock_net(sk), TCP_MIB_CURRESTAB);
- break;
-+ case TCP_CLOSE_WAIT:
-+ if (oldstate == TCP_SYN_RECV)
-+ TCP_INC_STATS(sock_net(sk), TCP_MIB_CURRESTAB);
-+ break;
-
- case TCP_CLOSE:
- if (oldstate == TCP_CLOSE_WAIT || oldstate == TCP_ESTABLISHED)
-@@ -2630,7 +2634,7 @@ void tcp_set_state(struct sock *sk, int state)
- inet_put_port(sk);
- fallthrough;
- default:
-- if (oldstate == TCP_ESTABLISHED)
-+ if (oldstate == TCP_ESTABLISHED || oldstate == TCP_CLOSE_WAIT)
- TCP_DEC_STATS(sock_net(sk), TCP_MIB_CURRESTAB);
- }
-
---
-2.43.0
-
+++ /dev/null
-From 2ad8b03cc0c9d860a128967ac53f5515871ca327 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 8 Apr 2024 18:40:59 -0700
-Subject: usb: gadget: f_fs: Fix race between aio_cancel() and AIO request
- complete
-
-From: Wesley Cheng <quic_wcheng@quicinc.com>
-
-[ Upstream commit 24729b307eefcd7c476065cd7351c1a018082c19 ]
-
-FFS based applications can utilize the aio_cancel() callback to dequeue
-pending USB requests submitted to the UDC. There is a scenario where the
-FFS application issues an AIO cancel call, while the UDC is handling a
-soft disconnect. For a DWC3 based implementation, the callstack looks
-like the following:
-
- DWC3 Gadget FFS Application
-dwc3_gadget_soft_disconnect() ...
- --> dwc3_stop_active_transfers()
- --> dwc3_gadget_giveback(-ESHUTDOWN)
- --> ffs_epfile_async_io_complete() ffs_aio_cancel()
- --> usb_ep_free_request() --> usb_ep_dequeue()
-
-There is currently no locking implemented between the AIO completion
-handler and AIO cancel, so the issue occurs if the completion routine is
-running in parallel to an AIO cancel call coming from the FFS application.
-As the completion call frees the USB request (io_data->req) the FFS
-application is also referencing it for the usb_ep_dequeue() call. This can
-lead to accessing a stale/hanging pointer.
-
-commit b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently")
-relocated the usb_ep_free_request() into ffs_epfile_async_io_complete().
-However, in order to properly implement locking to mitigate this issue, the
-spinlock can't be added to ffs_epfile_async_io_complete(), as
-usb_ep_dequeue() (if successfully dequeuing a USB request) will call the
-function driver's completion handler in the same context. Hence, leading
-into a deadlock.
-
-Fix this issue by moving the usb_ep_free_request() back to
-ffs_user_copy_worker(), and ensuring that it explicitly sets io_data->req
-to NULL after freeing it within the ffs->eps_lock. This resolves the race
-condition above, as the ffs_aio_cancel() routine will not continue
-attempting to dequeue a request that has already been freed, or the
-ffs_user_copy_work() not freeing the USB request until the AIO cancel is
-done referencing it.
-
-This fix depends on
- commit b566d38857fc ("usb: gadget: f_fs: use io_data->status
- consistently")
-
-Fixes: 2e4c7553cd6f ("usb: gadget: f_fs: add aio support")
-Cc: stable <stable@kernel.org> # b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently")
-Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
-Link: https://lore.kernel.org/r/20240409014059.6740-1-quic_wcheng@quicinc.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/usb/gadget/function/f_fs.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
-index 37d18e27ddc64..ad858044e0bfd 100644
---- a/drivers/usb/gadget/function/f_fs.c
-+++ b/drivers/usb/gadget/function/f_fs.c
-@@ -832,6 +832,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
- work);
- int ret = io_data->status;
- bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
-+ unsigned long flags;
-
- if (io_data->read && ret > 0) {
- kthread_use_mm(io_data->mm);
-@@ -844,6 +845,11 @@ static void ffs_user_copy_worker(struct work_struct *work)
- if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
- eventfd_signal(io_data->ffs->ffs_eventfd, 1);
-
-+ spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
-+ usb_ep_free_request(io_data->ep, io_data->req);
-+ io_data->req = NULL;
-+ spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
-+
- if (io_data->read)
- kfree(io_data->to_free);
- ffs_free_buffer(io_data);
-@@ -859,7 +865,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
- ENTER();
-
- io_data->status = req->status ? req->status : req->actual;
-- usb_ep_free_request(_ep, req);
-
- INIT_WORK(&io_data->work, ffs_user_copy_worker);
- queue_work(ffs->io_completion_wq, &io_data->work);
---
-2.43.0
-
+++ /dev/null
-From b9cb2103b4d487c469b2b22b29d80343f0db2928 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 24 Nov 2022 17:04:28 +0000
-Subject: usb: gadget: f_fs: use io_data->status consistently
-
-From: John Keeping <john@metanate.com>
-
-[ Upstream commit b566d38857fcb6777f25b674b90a831eec0817a2 ]
-
-Commit fb1f16d74e26 ("usb: gadget: f_fs: change ep->status safe in
-ffs_epfile_io()") added a new ffs_io_data::status field to fix lifetime
-issues in synchronous requests.
-
-While there are no similar lifetime issues for asynchronous requests
-(the separate ep member in ffs_io_data avoids them) using the status
-field means the USB request can be freed earlier and that there is more
-consistency between the synchronous and asynchronous I/O paths.
-
-Cc: Linyu Yuan <quic_linyyuan@quicinc.com>
-Signed-off-by: John Keeping <john@metanate.com>
-Reviewed-by: Linyu Yuan <quic_linyyuan@quicinc.com>
-Link: https://lore.kernel.org/r/20221124170430.3998755-1-john@metanate.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: 24729b307eef ("usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/usb/gadget/function/f_fs.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
-index a4367a43cdd87..37d18e27ddc64 100644
---- a/drivers/usb/gadget/function/f_fs.c
-+++ b/drivers/usb/gadget/function/f_fs.c
-@@ -830,8 +830,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
- {
- struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
- work);
-- int ret = io_data->req->status ? io_data->req->status :
-- io_data->req->actual;
-+ int ret = io_data->status;
- bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
-
- if (io_data->read && ret > 0) {
-@@ -845,8 +844,6 @@ static void ffs_user_copy_worker(struct work_struct *work)
- if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
- eventfd_signal(io_data->ffs->ffs_eventfd, 1);
-
-- usb_ep_free_request(io_data->ep, io_data->req);
--
- if (io_data->read)
- kfree(io_data->to_free);
- ffs_free_buffer(io_data);
-@@ -861,6 +858,9 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
-
- ENTER();
-
-+ io_data->status = req->status ? req->status : req->actual;
-+ usb_ep_free_request(_ep, req);
-+
- INIT_WORK(&io_data->work, ffs_user_copy_worker);
- queue_work(ffs->io_completion_wq, &io_data->work);
- }
---
-2.43.0
-
+++ /dev/null
-From 347d5f5211f188728422fcaa093770a7d47d5931 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 3 Jun 2024 10:59:26 +0200
-Subject: vxlan: Fix regression when dropping packets due to invalid src
- addresses
-
-From: Daniel Borkmann <daniel@iogearbox.net>
-
-[ Upstream commit 1cd4bc987abb2823836cbb8f887026011ccddc8a ]
-
-Commit f58f45c1e5b9 ("vxlan: drop packets from invalid src-address")
-has recently been added to vxlan mainly in the context of source
-address snooping/learning so that when it is enabled, an entry in the
-FDB is not being created for an invalid address for the corresponding
-tunnel endpoint.
-
-Before commit f58f45c1e5b9 vxlan was similarly behaving as geneve in
-that it passed through whichever macs were set in the L2 header. It
-turns out that this change in behavior breaks setups, for example,
-Cilium with netkit in L3 mode for Pods as well as tunnel mode has been
-passing before the change in f58f45c1e5b9 for both vxlan and geneve.
-After mentioned change it is only passing for geneve as in case of
-vxlan packets are dropped due to vxlan_set_mac() returning false as
-source and destination macs are zero which for E/W traffic via tunnel
-is totally fine.
-
-Fix it by only opting into the is_valid_ether_addr() check in
-vxlan_set_mac() when in fact source address snooping/learning is
-actually enabled in vxlan. This is done by moving the check into
-vxlan_snoop(). With this change, the Cilium connectivity test suite
-passes again for both tunnel flavors.
-
-Fixes: f58f45c1e5b9 ("vxlan: drop packets from invalid src-address")
-Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-Cc: David Bauer <mail@david-bauer.net>
-Cc: Ido Schimmel <idosch@nvidia.com>
-Cc: Nikolay Aleksandrov <razor@blackwall.org>
-Cc: Martin KaFai Lau <martin.lau@kernel.org>
-Reviewed-by: Ido Schimmel <idosch@nvidia.com>
-Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
-Reviewed-by: David Bauer <mail@david-bauer.net>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/vxlan/vxlan_core.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
-index 41b1b23fdd3e9..65a2f4ab89970 100644
---- a/drivers/net/vxlan/vxlan_core.c
-+++ b/drivers/net/vxlan/vxlan_core.c
-@@ -1493,6 +1493,10 @@ static bool vxlan_snoop(struct net_device *dev,
- struct vxlan_fdb *f;
- u32 ifindex = 0;
-
-+ /* Ignore packets from invalid src-address */
-+ if (!is_valid_ether_addr(src_mac))
-+ return true;
-+
- #if IS_ENABLED(CONFIG_IPV6)
- if (src_ip->sa.sa_family == AF_INET6 &&
- (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))
---
-2.43.0
-
+++ /dev/null
-From 007ce78d1573733ad037be53635cf0f2ab6c9ff8 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 17 May 2024 10:00:28 +0300
-Subject: wifi: ath10k: fix QCOM_RPROC_COMMON dependency
-
-From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-
-[ Upstream commit 21ae74e1bf18331ae5e279bd96304b3630828009 ]
-
-If ath10k_snoc is built-in, while Qualcomm remoteprocs are built as
-modules, compilation fails with:
-
-/usr/bin/aarch64-linux-gnu-ld: drivers/net/wireless/ath/ath10k/snoc.o: in function `ath10k_modem_init':
-drivers/net/wireless/ath/ath10k/snoc.c:1534: undefined reference to `qcom_register_ssr_notifier'
-/usr/bin/aarch64-linux-gnu-ld: drivers/net/wireless/ath/ath10k/snoc.o: in function `ath10k_modem_deinit':
-drivers/net/wireless/ath/ath10k/snoc.c:1551: undefined reference to `qcom_unregister_ssr_notifier'
-
-Add corresponding dependency to ATH10K_SNOC Kconfig entry so that it's
-built as module if QCOM_RPROC_COMMON is built as module too.
-
-Fixes: 747ff7d3d742 ("ath10k: Don't always treat modem stop events as crashes")
-Cc: stable@vger.kernel.org
-Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
-Link: https://msgid.link/20240511-ath10k-snoc-dep-v1-1-9666e3af5c27@linaro.org
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/ath/ath10k/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
-index e6ea884cafc19..4f385f4a8cef2 100644
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -45,6 +45,7 @@ config ATH10K_SNOC
- depends on ATH10K
- depends on ARCH_QCOM || COMPILE_TEST
- depends on QCOM_SMEM
-+ depends on QCOM_RPROC_COMMON || QCOM_RPROC_COMMON=n
- select QCOM_SCM
- select QCOM_QMI_HELPERS
- help
---
-2.43.0
-
+++ /dev/null
-From 12b52b078e5bfd61b72af37318d48c6d850cce63 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 2 Dec 2022 12:30:27 +0200
-Subject: wifi: ath10k: fix QCOM_SMEM dependency
-
-From: Kalle Valo <quic_kvalo@quicinc.com>
-
-[ Upstream commit d03407183d97554dfffea70f385b5bdd520f846c ]
-
-Nathan noticed that when HWSPINLOCK is disabled there's a Kconfig warning:
-
- WARNING: unmet direct dependencies detected for QCOM_SMEM
- Depends on [n]: (ARCH_QCOM [=y] || COMPILE_TEST [=n]) && HWSPINLOCK [=n]
- Selected by [m]:
- - ATH10K_SNOC [=m] && NETDEVICES [=y] && WLAN [=y] && WLAN_VENDOR_ATH [=y] && ATH10K [=m] && (ARCH_QCOM [=y] || COMPILE_TEST [=n])
-
-The problem here is that QCOM_SMEM depends on HWSPINLOCK so we cannot select
-QCOM_SMEM and instead we neeed to use 'depends on'.
-
-Reported-by: Nathan Chancellor <nathan@kernel.org>
-Link: https://lore.kernel.org/all/Y4YsyaIW+CPdHWv3@dev-arch.thelio-3990X/
-Fixes: 4d79f6f34bbb ("wifi: ath10k: Store WLAN firmware version in SMEM image table")
-Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
-Signed-off-by: Kalle Valo <kvalo@kernel.org>
-Link: https://lore.kernel.org/r/20221202103027.25974-1-kvalo@kernel.org
-Stable-dep-of: 21ae74e1bf18 ("wifi: ath10k: fix QCOM_RPROC_COMMON dependency")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/ath/ath10k/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
-index e0a51dad8e420..e6ea884cafc19 100644
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -44,7 +44,7 @@ config ATH10K_SNOC
- tristate "Qualcomm ath10k SNOC support"
- depends on ATH10K
- depends on ARCH_QCOM || COMPILE_TEST
-- select QCOM_SMEM
-+ depends on QCOM_SMEM
- select QCOM_SCM
- select QCOM_QMI_HELPERS
- help
---
-2.43.0
-
+++ /dev/null
-From a54a8f74e25cdef2f972684f063bd23c9b4bab95 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 17 Nov 2022 23:35:34 +0530
-Subject: wifi: ath10k: Store WLAN firmware version in SMEM image table
-
-From: Youghandhar Chintala <quic_youghand@quicinc.com>
-
-[ Upstream commit 4d79f6f34bbb01c6715b31ef457d5ab0390501a1 ]
-
-In a SoC based solution, it would be useful to know the versions of the
-various binary firmware blobs the system is running on. On a QCOM based
-SoC, this info can be obtained from socinfo debugfs infrastructure. For
-this to work, respective subsystem drivers have to export the firmware
-version information to an SMEM based version information table.
-
-Having firmware version information at one place will help quickly
-figure out the firmware versions of various subsystems on the device
-instead of going through builds/logs in an event of a system crash.
-
-Fill WLAN firmware version information in SMEM version table to be
-printed as part of socinfo debugfs infrastructure on a Qualcomm based
-SoC.
-
-This change is applicable only for SNOC/QMI based targets.
-
-Example:
-cat /sys/kernel/debug/qcom_socinfo/cnss/name
-QC_IMAGE_VERSION_STRING=WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1
-
-Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1
-
-Signed-off-by: Youghandhar Chintala <quic_youghand@quicinc.com>
-Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
-Link: https://lore.kernel.org/r/20221117180534.2267-1-quic_youghand@quicinc.com
-Stable-dep-of: 21ae74e1bf18 ("wifi: ath10k: fix QCOM_RPROC_COMMON dependency")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/ath/ath10k/Kconfig | 1 +
- drivers/net/wireless/ath/ath10k/qmi.c | 35 +++++++++++++++++++++++++
- 2 files changed, 36 insertions(+)
-
-diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
-index ca007b800f756..e0a51dad8e420 100644
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -44,6 +44,7 @@ config ATH10K_SNOC
- tristate "Qualcomm ath10k SNOC support"
- depends on ATH10K
- depends on ARCH_QCOM || COMPILE_TEST
-+ select QCOM_SMEM
- select QCOM_SCM
- select QCOM_QMI_HELPERS
- help
-diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
-index 80fcb917fe4e1..22bd97d434cc9 100644
---- a/drivers/net/wireless/ath/ath10k/qmi.c
-+++ b/drivers/net/wireless/ath/ath10k/qmi.c
-@@ -14,6 +14,7 @@
- #include <linux/net.h>
- #include <linux/platform_device.h>
- #include <linux/qcom_scm.h>
-+#include <linux/soc/qcom/smem.h>
- #include <linux/string.h>
- #include <net/sock.h>
-
-@@ -22,6 +23,10 @@
-
- #define ATH10K_QMI_CLIENT_ID 0x4b4e454c
- #define ATH10K_QMI_TIMEOUT 30
-+#define SMEM_IMAGE_VERSION_TABLE 469
-+#define SMEM_IMAGE_TABLE_CNSS_INDEX 13
-+#define SMEM_IMAGE_VERSION_ENTRY_SIZE 128
-+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
-
- static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
- struct ath10k_msa_mem_info *mem_info)
-@@ -536,6 +541,33 @@ int ath10k_qmi_wlan_disable(struct ath10k *ar)
- return ath10k_qmi_mode_send_sync_msg(ar, QMI_WLFW_OFF_V01);
- }
-
-+static void ath10k_qmi_add_wlan_ver_smem(struct ath10k *ar, const char *fw_build_id)
-+{
-+ u8 *table_ptr;
-+ size_t smem_item_size;
-+ const u32 smem_img_idx_wlan = SMEM_IMAGE_TABLE_CNSS_INDEX *
-+ SMEM_IMAGE_VERSION_ENTRY_SIZE;
-+
-+ table_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
-+ SMEM_IMAGE_VERSION_TABLE,
-+ &smem_item_size);
-+
-+ if (IS_ERR(table_ptr)) {
-+ ath10k_err(ar, "smem image version table not found\n");
-+ return;
-+ }
-+
-+ if (smem_img_idx_wlan + SMEM_IMAGE_VERSION_ENTRY_SIZE >
-+ smem_item_size) {
-+ ath10k_err(ar, "smem block size too small: %zu\n",
-+ smem_item_size);
-+ return;
-+ }
-+
-+ strscpy(table_ptr + smem_img_idx_wlan, fw_build_id,
-+ SMEM_IMAGE_VERSION_NAME_SIZE);
-+}
-+
- static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
- {
- struct wlfw_cap_resp_msg_v01 *resp;
-@@ -606,6 +638,9 @@ static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
- qmi->fw_version, qmi->fw_build_timestamp, qmi->fw_build_id);
- }
-
-+ if (resp->fw_build_id_valid)
-+ ath10k_qmi_add_wlan_ver_smem(ar, qmi->fw_build_id);
-+
- kfree(resp);
- return 0;
-
---
-2.43.0
-
+++ /dev/null
-From a54a4bdf1179814d1e07117f7184a40be1b736ee Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 21 May 2024 21:47:26 +0200
-Subject: wifi: cfg80211: Lock wiphy in cfg80211_get_station
-
-From: Remi Pommarel <repk@triplefau.lt>
-
-[ Upstream commit 642f89daa34567d02f312d03e41523a894906dae ]
-
-Wiphy should be locked before calling rdev_get_station() (see lockdep
-assert in ieee80211_get_station()).
-
-This fixes the following kernel NULL dereference:
-
- Unable to handle kernel NULL pointer dereference at virtual address 0000000000000050
- Mem abort info:
- ESR = 0x0000000096000006
- EC = 0x25: DABT (current EL), IL = 32 bits
- SET = 0, FnV = 0
- EA = 0, S1PTW = 0
- FSC = 0x06: level 2 translation fault
- Data abort info:
- ISV = 0, ISS = 0x00000006
- CM = 0, WnR = 0
- user pgtable: 4k pages, 48-bit VAs, pgdp=0000000003001000
- [0000000000000050] pgd=0800000002dca003, p4d=0800000002dca003, pud=08000000028e9003, pmd=0000000000000000
- Internal error: Oops: 0000000096000006 [#1] SMP
- Modules linked in: netconsole dwc3_meson_g12a dwc3_of_simple dwc3 ip_gre gre ath10k_pci ath10k_core ath9k ath9k_common ath9k_hw ath
- CPU: 0 PID: 1091 Comm: kworker/u8:0 Not tainted 6.4.0-02144-g565f9a3a7911-dirty #705
- Hardware name: RPT (r1) (DT)
- Workqueue: bat_events batadv_v_elp_throughput_metric_update
- pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
- pc : ath10k_sta_statistics+0x10/0x2dc [ath10k_core]
- lr : sta_set_sinfo+0xcc/0xbd4
- sp : ffff000007b43ad0
- x29: ffff000007b43ad0 x28: ffff0000071fa900 x27: ffff00000294ca98
- x26: ffff000006830880 x25: ffff000006830880 x24: ffff00000294c000
- x23: 0000000000000001 x22: ffff000007b43c90 x21: ffff800008898acc
- x20: ffff00000294c6e8 x19: ffff000007b43c90 x18: 0000000000000000
- x17: 445946354d552d78 x16: 62661f7200000000 x15: 57464f445946354d
- x14: 0000000000000000 x13: 00000000000000e3 x12: d5f0acbcebea978e
- x11: 00000000000000e3 x10: 000000010048fe41 x9 : 0000000000000000
- x8 : ffff000007b43d90 x7 : 000000007a1e2125 x6 : 0000000000000000
- x5 : ffff0000024e0900 x4 : ffff800000a0250c x3 : ffff000007b43c90
- x2 : ffff00000294ca98 x1 : ffff000006831920 x0 : 0000000000000000
- Call trace:
- ath10k_sta_statistics+0x10/0x2dc [ath10k_core]
- sta_set_sinfo+0xcc/0xbd4
- ieee80211_get_station+0x2c/0x44
- cfg80211_get_station+0x80/0x154
- batadv_v_elp_get_throughput+0x138/0x1fc
- batadv_v_elp_throughput_metric_update+0x1c/0xa4
- process_one_work+0x1ec/0x414
- worker_thread+0x70/0x46c
- kthread+0xdc/0xe0
- ret_from_fork+0x10/0x20
- Code: a9bb7bfd 910003fd a90153f3 f9411c40 (f9402814)
-
-This happens because STA has time to disconnect and reconnect before
-batadv_v_elp_throughput_metric_update() delayed work gets scheduled. In
-this situation, ath10k_sta_state() can be in the middle of resetting
-arsta data when the work queue get chance to be scheduled and ends up
-accessing it. Locking wiphy prevents that.
-
-Fixes: 7406353d43c8 ("cfg80211: implement cfg80211_get_station cfg80211 API")
-Signed-off-by: Remi Pommarel <repk@triplefau.lt>
-Reviewed-by: Nicolas Escande <nico.escande@gmail.com>
-Acked-by: Antonio Quartulli <a@unstable.cc>
-Link: https://msgid.link/983b24a6a176e0800c01aedcd74480d9b551cb13.1716046653.git.repk@triplefau.lt
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/wireless/util.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/net/wireless/util.c b/net/wireless/util.c
-index cb15d7f4eb05a..d40c2cf777dc0 100644
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -2033,6 +2033,7 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
- {
- struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
-+ int ret;
-
- wdev = dev->ieee80211_ptr;
- if (!wdev)
-@@ -2044,7 +2045,11 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
-
- memset(sinfo, 0, sizeof(*sinfo));
-
-- return rdev_get_station(rdev, dev, mac_addr, sinfo);
-+ wiphy_lock(&rdev->wiphy);
-+ ret = rdev_get_station(rdev, dev, mac_addr, sinfo);
-+ wiphy_unlock(&rdev->wiphy);
-+
-+ return ret;
- }
- EXPORT_SYMBOL(cfg80211_get_station);
-
---
-2.43.0
-
+++ /dev/null
-From 48052b5da2a3440cd9119e4c0aef05bed91e3e50 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 21 May 2024 15:50:59 +0800
-Subject: wifi: cfg80211: pmsr: use correct nla_get_uX functions
-
-From: Lin Ma <linma@zju.edu.cn>
-
-[ Upstream commit ab904521f4de52fef4f179d2dfc1877645ef5f5c ]
-
-The commit 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM
-initiator API") defines four attributes NL80211_PMSR_FTM_REQ_ATTR_
-{NUM_BURSTS_EXP}/{BURST_PERIOD}/{BURST_DURATION}/{FTMS_PER_BURST} in
-following ways.
-
-static const struct nla_policy
-nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
- ...
- [NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
- NLA_POLICY_MAX(NLA_U8, 15),
- [NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
- [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
- NLA_POLICY_MAX(NLA_U8, 15),
- [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
- NLA_POLICY_MAX(NLA_U8, 31),
- ...
-};
-
-That is, those attributes are expected to be NLA_U8 and NLA_U16 types.
-However, the consumers of these attributes in `pmsr_parse_ftm` blindly
-all use `nla_get_u32`, which is incorrect and causes functionality issues
-on little-endian platforms. Hence, fix them with the correct `nla_get_u8`
-and `nla_get_u16` functions.
-
-Fixes: 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM initiator API")
-Signed-off-by: Lin Ma <linma@zju.edu.cn>
-Link: https://msgid.link/20240521075059.47999-1-linma@zju.edu.cn
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/wireless/pmsr.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
-index 328cf54bda826..65fa39275f73f 100644
---- a/net/wireless/pmsr.c
-+++ b/net/wireless/pmsr.c
-@@ -58,7 +58,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
- out->ftm.burst_period = 0;
- if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD])
- out->ftm.burst_period =
-- nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD]);
-+ nla_get_u16(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD]);
-
- out->ftm.asap = !!tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP];
- if (out->ftm.asap && !capa->ftm.asap) {
-@@ -77,7 +77,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
- out->ftm.num_bursts_exp = 0;
- if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP])
- out->ftm.num_bursts_exp =
-- nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP]);
-+ nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP]);
-
- if (capa->ftm.max_bursts_exponent >= 0 &&
- out->ftm.num_bursts_exp > capa->ftm.max_bursts_exponent) {
-@@ -90,7 +90,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
- out->ftm.burst_duration = 15;
- if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION])
- out->ftm.burst_duration =
-- nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION]);
-+ nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION]);
-
- out->ftm.ftms_per_burst = 0;
- if (tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST])
-@@ -109,7 +109,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
- out->ftm.ftmr_retries = 3;
- if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES])
- out->ftm.ftmr_retries =
-- nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES]);
-+ nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES]);
-
- out->ftm.request_lci = !!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI];
- if (out->ftm.request_lci && !capa->ftm.request_lci) {
---
-2.43.0
-
+++ /dev/null
-From b8239fdc32879358756bf6bd00e43f9866554f0d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 10 May 2024 17:06:39 +0300
-Subject: wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs
- ifdef
-
-From: Shahar S Matityahu <shahar.s.matityahu@intel.com>
-
-[ Upstream commit 87821b67dea87addbc4ab093ba752753b002176a ]
-
-The driver should call iwl_dbg_tlv_free even if debugfs is not defined
-since ini mode does not depend on debugfs ifdef.
-
-Fixes: 68f6f492c4fa ("iwlwifi: trans: support loading ini TLVs from external file")
-Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
-Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
-Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-Link: https://msgid.link/20240510170500.c8e3723f55b0.I5e805732b0be31ee6b83c642ec652a34e974ff10@changeid
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
-index 524b0ad873578..afa89deb7bc3a 100644
---- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
-+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
-@@ -1667,8 +1667,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
- err_fw:
- #ifdef CONFIG_IWLWIFI_DEBUGFS
- debugfs_remove_recursive(drv->dbgfs_drv);
-- iwl_dbg_tlv_free(drv->trans);
- #endif
-+ iwl_dbg_tlv_free(drv->trans);
- kfree(drv);
- err:
- return ERR_PTR(ret);
---
-2.43.0
-
+++ /dev/null
-From 3ecd00c9f7dbcae03177c8a0f79029e10116f6d0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 13 May 2024 13:27:12 +0300
-Subject: wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
-
-From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-
-[ Upstream commit 60d62757df30b74bf397a2847a6db7385c6ee281 ]
-
-In some versions of cfg80211, the ssids poinet might be a valid one even
-though n_ssids is 0. Accessing the pointer in this case will cuase an
-out-of-bound access. Fix this by checking n_ssids first.
-
-Fixes: c1a7515393e4 ("iwlwifi: mvm: add adaptive dwell support")
-Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-Reviewed-by: Ilan Peer <ilan.peer@intel.com>
-Reviewed-by: Johannes Berg <johannes.berg@intel.com>
-Link: https://msgid.link/20240513132416.6e4d1762bf0d.I5a0e6cc8f02050a766db704d15594c61fe583d45@changeid
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
-index c0ffa26bc5aaa..0605363b62720 100644
---- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
-@@ -1312,7 +1312,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
- if (IWL_MVM_ADWELL_MAX_BUDGET)
- cmd->v7.adwell_max_budget =
- cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);
-- else if (params->ssids && params->ssids[0].ssid_len)
-+ else if (params->n_ssids && params->ssids[0].ssid_len)
- cmd->v7.adwell_max_budget =
- cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
- else
-@@ -1414,7 +1414,7 @@ iwl_mvm_scan_umac_dwell_v10(struct iwl_mvm *mvm,
- if (IWL_MVM_ADWELL_MAX_BUDGET)
- general_params->adwell_max_budget =
- cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);
-- else if (params->ssids && params->ssids[0].ssid_len)
-+ else if (params->n_ssids && params->ssids[0].ssid_len)
- general_params->adwell_max_budget =
- cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
- else
---
-2.43.0
-
+++ /dev/null
-From d3db3ca66ecb01738b7ffce54eb38ceaa4894e24 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 13 May 2024 13:27:14 +0300
-Subject: wifi: iwlwifi: mvm: don't read past the mfuart notifcation
-
-From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-
-[ Upstream commit 4bb95f4535489ed830cf9b34b0a891e384d1aee4 ]
-
-In case the firmware sends a notification that claims it has more data
-than it has, we will read past that was allocated for the notification.
-Remove the print of the buffer, we won't see it by default. If needed,
-we can see the content with tracing.
-
-This was reported by KFENCE.
-
-Fixes: bdccdb854f2f ("iwlwifi: mvm: support MFUART dump in case of MFUART assert")
-Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Reviewed-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-Link: https://msgid.link/20240513132416.ba82a01a559e.Ia91dd20f5e1ca1ad380b95e68aebf2794f553d9b@changeid
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ----------
- 1 file changed, 10 deletions(-)
-
-diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
-index d22a5628f9e0d..578956032e08b 100644
---- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
-@@ -95,20 +95,10 @@ void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
- {
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data;
-- __le32 *dump_data = mfu_dump_notif->data;
-- int n_words = le32_to_cpu(mfu_dump_notif->data_size) / sizeof(__le32);
-- int i;
-
- if (mfu_dump_notif->index_num == 0)
- IWL_INFO(mvm, "MFUART assert id 0x%x occurred\n",
- le32_to_cpu(mfu_dump_notif->assert_id));
--
-- for (i = 0; i < n_words; i++)
-- IWL_DEBUG_INFO(mvm,
-- "MFUART assert dump, dword %u: 0x%08x\n",
-- le16_to_cpu(mfu_dump_notif->index_num) *
-- n_words + i,
-- le32_to_cpu(dump_data[i]));
- }
-
- static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
---
-2.43.0
-
+++ /dev/null
-From f43dd9b31cbdfd1b9a58a2ad68715fa957b39518 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 10 May 2024 17:06:33 +0300
-Subject: wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
-
-From: Johannes Berg <johannes.berg@intel.com>
-
-[ Upstream commit 4a7aace2899711592327463c1a29ffee44fcc66e ]
-
-We don't actually support >64 even for HE devices, so revert
-back to 64. This fixes an issue where the session is refused
-because the queue is configured differently from the actual
-session later.
-
-Fixes: 514c30696fbc ("iwlwifi: add support for IEEE802.11ax")
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Liad Kaufman <liad.kaufman@intel.com>
-Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
-Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
-Link: https://msgid.link/20240510170500.52f7b4cf83aa.If47e43adddf7fe250ed7f5571fbb35d8221c7c47@changeid
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 9 ++-------
- 1 file changed, 2 insertions(+), 7 deletions(-)
-
-diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
-index 32104c9f8f5ee..d59a47637d120 100644
---- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
-@@ -133,13 +133,8 @@ enum {
-
- #define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)
- #define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
--/*
-- * FIXME - various places in firmware API still use u8,
-- * e.g. LQ command and SCD config command.
-- * This should be 256 instead.
-- */
--#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (255)
--#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (255)
-+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (64)
-+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (64)
- #define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
-
- #define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
---
-2.43.0
-
+++ /dev/null
-From 2a41bcec40274c2e17b22cc71054b443bc89ed46 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 16 May 2024 10:18:54 +0800
-Subject: wifi: mac80211: correctly parse Spatial Reuse Parameter Set element
-
-From: Lingbo Kong <quic_lingbok@quicinc.com>
-
-[ Upstream commit a26d8dc5227f449a54518a8b40733a54c6600a8b ]
-
-Currently, the way of parsing Spatial Reuse Parameter Set element is
-incorrect and some members of struct ieee80211_he_obss_pd are not assigned.
-
-To address this issue, it must be parsed in the order of the elements of
-Spatial Reuse Parameter Set defined in the IEEE Std 802.11ax specification.
-
-The diagram of the Spatial Reuse Parameter Set element (IEEE Std 802.11ax
--2021-9.4.2.252).
-
--------------------------------------------------------------------------
-| | | | |Non-SRG| SRG | SRG | SRG | SRG |
-|Element|Length| Element | SR |OBSS PD|OBSS PD|OBSS PD| BSS |Partial|
-| ID | | ID |Control| Max | Min | Max |Color | BSSID |
-| | |Extension| | Offset| Offset|Offset |Bitmap|Bitmap |
--------------------------------------------------------------------------
-
-Fixes: 1ced169cc1c2 ("mac80211: allow setting spatial reuse parameters from bss_conf")
-Signed-off-by: Lingbo Kong <quic_lingbok@quicinc.com>
-Link: https://msgid.link/20240516021854.5682-3-quic_lingbok@quicinc.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/mac80211/he.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/net/mac80211/he.c b/net/mac80211/he.c
-index c05af7018f79f..c730ce5132cbc 100644
---- a/net/mac80211/he.c
-+++ b/net/mac80211/he.c
-@@ -223,15 +223,21 @@ ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
-
- if (!he_spr_ie_elem)
- return;
-+
-+ he_obss_pd->sr_ctrl = he_spr_ie_elem->he_sr_control;
- data = he_spr_ie_elem->optional;
-
- if (he_spr_ie_elem->he_sr_control &
- IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
-- data++;
-+ he_obss_pd->non_srg_max_offset = *data++;
-+
- if (he_spr_ie_elem->he_sr_control &
- IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
-- he_obss_pd->max_offset = *data++;
- he_obss_pd->min_offset = *data++;
-+ he_obss_pd->max_offset = *data++;
-+ memcpy(he_obss_pd->bss_color_bitmap, data, 8);
-+ data += 8;
-+ memcpy(he_obss_pd->partial_bssid_bitmap, data, 8);
- he_obss_pd->enable = true;
- }
- }
---
-2.43.0
-
+++ /dev/null
-From 6e8dfd5b602d19e685cb7fa1d5ac3c57d4c339c2 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 29 May 2024 08:57:53 +0200
-Subject: wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
-
-From: Remi Pommarel <repk@triplefau.lt>
-
-[ Upstream commit 44c06bbde6443de206b30f513100b5670b23fc5e ]
-
-The ieee80211_sta_ps_deliver_wakeup() function takes sta->ps_lock to
-synchronizes with ieee80211_tx_h_unicast_ps_buf() which is called from
-softirq context. However using only spin_lock() to get sta->ps_lock in
-ieee80211_sta_ps_deliver_wakeup() does not prevent softirq to execute
-on this same CPU, to run ieee80211_tx_h_unicast_ps_buf() and try to
-take this same lock ending in deadlock. Below is an example of rcu stall
-that arises in such situation.
-
- rcu: INFO: rcu_sched self-detected stall on CPU
- rcu: 2-....: (42413413 ticks this GP) idle=b154/1/0x4000000000000000 softirq=1763/1765 fqs=21206996
- rcu: (t=42586894 jiffies g=2057 q=362405 ncpus=4)
- CPU: 2 PID: 719 Comm: wpa_supplicant Tainted: G W 6.4.0-02158-g1b062f552873 #742
- Hardware name: RPT (r1) (DT)
- pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
- pc : queued_spin_lock_slowpath+0x58/0x2d0
- lr : invoke_tx_handlers_early+0x5b4/0x5c0
- sp : ffff00001ef64660
- x29: ffff00001ef64660 x28: ffff000009bc1070 x27: ffff000009bc0ad8
- x26: ffff000009bc0900 x25: ffff00001ef647a8 x24: 0000000000000000
- x23: ffff000009bc0900 x22: ffff000009bc0900 x21: ffff00000ac0e000
- x20: ffff00000a279e00 x19: ffff00001ef646e8 x18: 0000000000000000
- x17: ffff800016468000 x16: ffff00001ef608c0 x15: 0010533c93f64f80
- x14: 0010395c9faa3946 x13: 0000000000000000 x12: 00000000fa83b2da
- x11: 000000012edeceea x10: ffff0000010fbe00 x9 : 0000000000895440
- x8 : 000000000010533c x7 : ffff00000ad8b740 x6 : ffff00000c350880
- x5 : 0000000000000007 x4 : 0000000000000001 x3 : 0000000000000000
- x2 : 0000000000000000 x1 : 0000000000000001 x0 : ffff00000ac0e0e8
- Call trace:
- queued_spin_lock_slowpath+0x58/0x2d0
- ieee80211_tx+0x80/0x12c
- ieee80211_tx_pending+0x110/0x278
- tasklet_action_common.constprop.0+0x10c/0x144
- tasklet_action+0x20/0x28
- _stext+0x11c/0x284
- ____do_softirq+0xc/0x14
- call_on_irq_stack+0x24/0x34
- do_softirq_own_stack+0x18/0x20
- do_softirq+0x74/0x7c
- __local_bh_enable_ip+0xa0/0xa4
- _ieee80211_wake_txqs+0x3b0/0x4b8
- __ieee80211_wake_queue+0x12c/0x168
- ieee80211_add_pending_skbs+0xec/0x138
- ieee80211_sta_ps_deliver_wakeup+0x2a4/0x480
- ieee80211_mps_sta_status_update.part.0+0xd8/0x11c
- ieee80211_mps_sta_status_update+0x18/0x24
- sta_apply_parameters+0x3bc/0x4c0
- ieee80211_change_station+0x1b8/0x2dc
- nl80211_set_station+0x444/0x49c
- genl_family_rcv_msg_doit.isra.0+0xa4/0xfc
- genl_rcv_msg+0x1b0/0x244
- netlink_rcv_skb+0x38/0x10c
- genl_rcv+0x34/0x48
- netlink_unicast+0x254/0x2bc
- netlink_sendmsg+0x190/0x3b4
- ____sys_sendmsg+0x1e8/0x218
- ___sys_sendmsg+0x68/0x8c
- __sys_sendmsg+0x44/0x84
- __arm64_sys_sendmsg+0x20/0x28
- do_el0_svc+0x6c/0xe8
- el0_svc+0x14/0x48
- el0t_64_sync_handler+0xb0/0xb4
- el0t_64_sync+0x14c/0x150
-
-Using spin_lock_bh()/spin_unlock_bh() instead prevents softirq to raise
-on the same CPU that is holding the lock.
-
-Fixes: 1d147bfa6429 ("mac80211: fix AP powersave TX vs. wakeup race")
-Signed-off-by: Remi Pommarel <repk@triplefau.lt>
-Link: https://msgid.link/8e36fe07d0fbc146f89196cd47a53c8a0afe84aa.1716910344.git.repk@triplefau.lt
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/mac80211/sta_info.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
-index f4deee1926e58..6d2b42cb3ad58 100644
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -1339,7 +1339,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
- skb_queue_head_init(&pending);
-
- /* sync with ieee80211_tx_h_unicast_ps_buf */
-- spin_lock(&sta->ps_lock);
-+ spin_lock_bh(&sta->ps_lock);
- /* Send all buffered frames to the station */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- int count = skb_queue_len(&pending), tmp;
-@@ -1368,7 +1368,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
- */
- clear_sta_flag(sta, WLAN_STA_PSPOLL);
- clear_sta_flag(sta, WLAN_STA_UAPSD);
-- spin_unlock(&sta->ps_lock);
-+ spin_unlock_bh(&sta->ps_lock);
-
- atomic_dec(&ps->num_sta_ps);
-
---
-2.43.0
-
+++ /dev/null
-From 36c885782014e1a47d629d5661ec18cc037a39db Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 28 May 2024 16:26:05 +0200
-Subject: wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
-
-From: Nicolas Escande <nico.escande@gmail.com>
-
-[ Upstream commit b7d7f11a291830fdf69d3301075dd0fb347ced84 ]
-
-The hwmp code use objects of type mesh_preq_queue, added to a list in
-ieee80211_if_mesh, to keep track of mpath we need to resolve. If the mpath
-gets deleted, ex mesh interface is removed, the entries in that list will
-never get cleaned. Fix this by flushing all corresponding items of the
-preq_queue in mesh_path_flush_pending().
-
-This should take care of KASAN reports like this:
-
-unreferenced object 0xffff00000668d800 (size 128):
- comm "kworker/u8:4", pid 67, jiffies 4295419552 (age 1836.444s)
- hex dump (first 32 bytes):
- 00 1f 05 09 00 00 ff ff 00 d5 68 06 00 00 ff ff ..........h.....
- 8e 97 ea eb 3e b8 01 00 00 00 00 00 00 00 00 00 ....>...........
- backtrace:
- [<000000007302a0b6>] __kmem_cache_alloc_node+0x1e0/0x35c
- [<00000000049bd418>] kmalloc_trace+0x34/0x80
- [<0000000000d792bb>] mesh_queue_preq+0x44/0x2a8
- [<00000000c99c3696>] mesh_nexthop_resolve+0x198/0x19c
- [<00000000926bf598>] ieee80211_xmit+0x1d0/0x1f4
- [<00000000fc8c2284>] __ieee80211_subif_start_xmit+0x30c/0x764
- [<000000005926ee38>] ieee80211_subif_start_xmit+0x9c/0x7a4
- [<000000004c86e916>] dev_hard_start_xmit+0x174/0x440
- [<0000000023495647>] __dev_queue_xmit+0xe24/0x111c
- [<00000000cfe9ca78>] batadv_send_skb_packet+0x180/0x1e4
- [<000000007bacc5d5>] batadv_v_elp_periodic_work+0x2f4/0x508
- [<00000000adc3cd94>] process_one_work+0x4b8/0xa1c
- [<00000000b36425d1>] worker_thread+0x9c/0x634
- [<0000000005852dd5>] kthread+0x1bc/0x1c4
- [<000000005fccd770>] ret_from_fork+0x10/0x20
-unreferenced object 0xffff000009051f00 (size 128):
- comm "kworker/u8:4", pid 67, jiffies 4295419553 (age 1836.440s)
- hex dump (first 32 bytes):
- 90 d6 92 0d 00 00 ff ff 00 d8 68 06 00 00 ff ff ..........h.....
- 36 27 92 e4 02 e0 01 00 00 58 79 06 00 00 ff ff 6'.......Xy.....
- backtrace:
- [<000000007302a0b6>] __kmem_cache_alloc_node+0x1e0/0x35c
- [<00000000049bd418>] kmalloc_trace+0x34/0x80
- [<0000000000d792bb>] mesh_queue_preq+0x44/0x2a8
- [<00000000c99c3696>] mesh_nexthop_resolve+0x198/0x19c
- [<00000000926bf598>] ieee80211_xmit+0x1d0/0x1f4
- [<00000000fc8c2284>] __ieee80211_subif_start_xmit+0x30c/0x764
- [<000000005926ee38>] ieee80211_subif_start_xmit+0x9c/0x7a4
- [<000000004c86e916>] dev_hard_start_xmit+0x174/0x440
- [<0000000023495647>] __dev_queue_xmit+0xe24/0x111c
- [<00000000cfe9ca78>] batadv_send_skb_packet+0x180/0x1e4
- [<000000007bacc5d5>] batadv_v_elp_periodic_work+0x2f4/0x508
- [<00000000adc3cd94>] process_one_work+0x4b8/0xa1c
- [<00000000b36425d1>] worker_thread+0x9c/0x634
- [<0000000005852dd5>] kthread+0x1bc/0x1c4
- [<000000005fccd770>] ret_from_fork+0x10/0x20
-
-Fixes: 050ac52cbe1f ("mac80211: code for on-demand Hybrid Wireless Mesh Protocol")
-Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
-Link: https://msgid.link/20240528142605.1060566-1-nico.escande@gmail.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/mac80211/mesh_pathtbl.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
-index 69d5e1ec6edef..e7b9dcf30adc9 100644
---- a/net/mac80211/mesh_pathtbl.c
-+++ b/net/mac80211/mesh_pathtbl.c
-@@ -723,10 +723,23 @@ void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
- */
- void mesh_path_flush_pending(struct mesh_path *mpath)
- {
-+ struct ieee80211_sub_if_data *sdata = mpath->sdata;
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct mesh_preq_queue *preq, *tmp;
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL)
- mesh_path_discard_frame(mpath->sdata, skb);
-+
-+ spin_lock_bh(&ifmsh->mesh_preq_queue_lock);
-+ list_for_each_entry_safe(preq, tmp, &ifmsh->preq_queue.list, list) {
-+ if (ether_addr_equal(mpath->dst, preq->dst)) {
-+ list_del(&preq->list);
-+ kfree(preq);
-+ --ifmsh->preq_queue_len;
-+ }
-+ }
-+ spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
- }
-
- /**
---
-2.43.0
-
+++ /dev/null
-From 0fb3ba2981bdfeed49e23a1f6c7b020405952b3b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 8 Mar 2022 16:30:29 +0100
-Subject: x86/ibt,ftrace: Search for __fentry__ location
-
-From: Peter Zijlstra <peterz@infradead.org>
-
-[ Upstream commit aebfd12521d9c7d0b502cf6d06314cfbcdccfe3b ]
-
-Currently a lot of ftrace code assumes __fentry__ is at sym+0. However
-with Intel IBT enabled the first instruction of a function will most
-likely be ENDBR.
-
-Change ftrace_location() to not only return the __fentry__ location
-when called for the __fentry__ location, but also when called for the
-sym+0 location.
-
-Then audit/update all callsites of this function to consistently use
-these new semantics.
-
-Suggested-by: Steven Rostedt <rostedt@goodmis.org>
-Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
-Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
-Link: https://lore.kernel.org/r/20220308154318.227581603@infradead.org
-Stable-dep-of: e60b613df8b6 ("ftrace: Fix possible use-after-free issue in ftrace_location()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/x86/kernel/kprobes/core.c | 11 ++------
- kernel/bpf/trampoline.c | 20 +++-----------
- kernel/kprobes.c | 8 ++----
- kernel/trace/ftrace.c | 48 ++++++++++++++++++++++++++++------
- 4 files changed, 48 insertions(+), 39 deletions(-)
-
-diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
-index 893f040b97b7d..99dd504307fdc 100644
---- a/arch/x86/kernel/kprobes/core.c
-+++ b/arch/x86/kernel/kprobes/core.c
-@@ -194,17 +194,10 @@ static unsigned long
- __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
- {
- struct kprobe *kp;
-- unsigned long faddr;
-+ bool faddr;
-
- kp = get_kprobe((void *)addr);
-- faddr = ftrace_location(addr);
-- /*
-- * Addresses inside the ftrace location are refused by
-- * arch_check_ftrace_location(). Something went terribly wrong
-- * if such an address is checked here.
-- */
-- if (WARN_ON(faddr && faddr != addr))
-- return 0UL;
-+ faddr = ftrace_location(addr) == addr;
- /*
- * Use the current code if it is not modified by Kprobe
- * and it cannot be modified by ftrace.
-diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
-index 4fa75791b45e2..1bffee0458863 100644
---- a/kernel/bpf/trampoline.c
-+++ b/kernel/bpf/trampoline.c
-@@ -108,18 +108,6 @@ static void bpf_trampoline_module_put(struct bpf_trampoline *tr)
- tr->mod = NULL;
- }
-
--static int is_ftrace_location(void *ip)
--{
-- long addr;
--
-- addr = ftrace_location((long)ip);
-- if (!addr)
-- return 0;
-- if (WARN_ON_ONCE(addr != (long)ip))
-- return -EFAULT;
-- return 1;
--}
--
- static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
- {
- void *ip = tr->func.addr;
-@@ -151,12 +139,12 @@ static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_ad
- static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
- {
- void *ip = tr->func.addr;
-+ unsigned long faddr;
- int ret;
-
-- ret = is_ftrace_location(ip);
-- if (ret < 0)
-- return ret;
-- tr->func.ftrace_managed = ret;
-+ faddr = ftrace_location((unsigned long)ip);
-+ if (faddr)
-+ tr->func.ftrace_managed = true;
-
- if (bpf_trampoline_module_get(tr))
- return -ENOENT;
-diff --git a/kernel/kprobes.c b/kernel/kprobes.c
-index af57705e1fef3..258d425b2c4a5 100644
---- a/kernel/kprobes.c
-+++ b/kernel/kprobes.c
-@@ -1526,14 +1526,10 @@ static inline int warn_kprobe_rereg(struct kprobe *p)
-
- int __weak arch_check_ftrace_location(struct kprobe *p)
- {
-- unsigned long ftrace_addr;
-+ unsigned long addr = (unsigned long)p->addr;
-
-- ftrace_addr = ftrace_location((unsigned long)p->addr);
-- if (ftrace_addr) {
-+ if (ftrace_location(addr) == addr) {
- #ifdef CONFIG_KPROBES_ON_FTRACE
-- /* Given address is not on the instruction boundary */
-- if ((unsigned long)p->addr != ftrace_addr)
-- return -EILSEQ;
- p->flags |= KPROBE_FLAG_FTRACE;
- #else /* !CONFIG_KPROBES_ON_FTRACE */
- return -EINVAL;
-diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
-index 157a1d2d9802f..3dce1a107a7c7 100644
---- a/kernel/trace/ftrace.c
-+++ b/kernel/trace/ftrace.c
-@@ -1575,17 +1575,34 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
- }
-
- /**
-- * ftrace_location - return true if the ip giving is a traced location
-+ * ftrace_location - return the ftrace location
- * @ip: the instruction pointer to check
- *
-- * Returns rec->ip if @ip given is a pointer to a ftrace location.
-- * That is, the instruction that is either a NOP or call to
-- * the function tracer. It checks the ftrace internal tables to
-- * determine if the address belongs or not.
-+ * If @ip matches the ftrace location, return @ip.
-+ * If @ip matches sym+0, return sym's ftrace location.
-+ * Otherwise, return 0.
- */
- unsigned long ftrace_location(unsigned long ip)
- {
-- return ftrace_location_range(ip, ip);
-+ struct dyn_ftrace *rec;
-+ unsigned long offset;
-+ unsigned long size;
-+
-+ rec = lookup_rec(ip, ip);
-+ if (!rec) {
-+ if (!kallsyms_lookup_size_offset(ip, &size, &offset))
-+ goto out;
-+
-+ /* map sym+0 to __fentry__ */
-+ if (!offset)
-+ rec = lookup_rec(ip, ip + size - 1);
-+ }
-+
-+ if (rec)
-+ return rec->ip;
-+
-+out:
-+ return 0;
- }
-
- /**
-@@ -4942,7 +4959,8 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
- {
- struct ftrace_func_entry *entry;
-
-- if (!ftrace_location(ip))
-+ ip = ftrace_location(ip);
-+ if (!ip)
- return -EINVAL;
-
- if (remove) {
-@@ -5090,11 +5108,16 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
- struct ftrace_func_entry *entry;
- struct ftrace_hash *free_hash = NULL;
- struct dyn_ftrace *rec;
-- int ret = -EBUSY;
-+ int ret = -ENODEV;
-
- mutex_lock(&direct_mutex);
-
-+ ip = ftrace_location(ip);
-+ if (!ip)
-+ goto out_unlock;
-+
- /* See if there's a direct function at @ip already */
-+ ret = -EBUSY;
- if (ftrace_find_rec_direct(ip))
- goto out_unlock;
-
-@@ -5223,6 +5246,10 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
-
- mutex_lock(&direct_mutex);
-
-+ ip = ftrace_location(ip);
-+ if (!ip)
-+ goto out_unlock;
-+
- entry = find_direct_entry(&ip, NULL);
- if (!entry)
- goto out_unlock;
-@@ -5354,6 +5381,11 @@ int modify_ftrace_direct(unsigned long ip,
- mutex_lock(&direct_mutex);
-
- mutex_lock(&ftrace_lock);
-+
-+ ip = ftrace_location(ip);
-+ if (!ip)
-+ goto out_unlock;
-+
- entry = find_direct_entry(&ip, &rec);
- if (!entry)
- goto out_unlock;
---
-2.43.0
-