]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Sun, 16 Jun 2024 02:01:18 +0000 (22:01 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 16 Jun 2024 02:01:18 +0000 (22:01 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
50 files changed:
queue-5.4/af_unix-annotate-data-race-of-net-unx.sysctl_max_dgr.patch [new file with mode: 0644]
queue-5.4/af_unix-annotate-data-race-of-sk-sk_shutdown-in-sk_d.patch [new file with mode: 0644]
queue-5.4/af_unix-annotate-data-race-of-sk-sk_state-in-unix_in.patch [new file with mode: 0644]
queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-se.patch [new file with mode: 0644]
queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch [new file with mode: 0644]
queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch-4923 [new file with mode: 0644]
queue-5.4/af_unix-use-skb_queue_len_lockless-in-sk_diag_show_r.patch [new file with mode: 0644]
queue-5.4/af_unix-use-unix_recvq_full_lockless-in-unix_stream_.patch [new file with mode: 0644]
queue-5.4/arm64-dts-agilex-add-nand-ip-to-base-dts.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-fix-race-condition-during-prob.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-handle-missing-required-dt-pro.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-remove-always-zero-of-davinci_.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-remove-legacy-dma_request-pars.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-remove-redundant-assignment-to.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-simplify-the-configuration-par.patch [new file with mode: 0644]
queue-5.4/asoc-ti-davinci-mcasp-use-platform_get_irq_byname_op.patch [new file with mode: 0644]
queue-5.4/drivers-core-reindent-a-couple-uses-around-sysfs_emi.patch [new file with mode: 0644]
queue-5.4/drm-amd-display-handle-y-carry-over-in-vcp-x.y-calcu.patch [new file with mode: 0644]
queue-5.4/ipv6-fix-possible-race-in-__fib6_drop_pcpu_from.patch [new file with mode: 0644]
queue-5.4/ipv6-sr-block-bh-in-seg6_output_core-and-seg6_input_.patch [new file with mode: 0644]
queue-5.4/mmc-davinci-don-t-strip-remove-function-when-driver-.patch [new file with mode: 0644]
queue-5.4/mmc-davinci_mmc-convert-to-platform-remove-callback-.patch [new file with mode: 0644]
queue-5.4/net-mlx5-stop-waiting-for-pci-if-pci-channel-is-offl.patch [new file with mode: 0644]
queue-5.4/net-sched-sch_multiq-fix-possible-oob-write-in-multi.patch [new file with mode: 0644]
queue-5.4/net-sched-taprio-always-validate-tca_taprio_attr_pri.patch [new file with mode: 0644]
queue-5.4/nilfs2-fix-nilfs_empty_dir-misjudgment-and-long-loop.patch [new file with mode: 0644]
queue-5.4/nilfs2-remove-check-for-pageerror.patch [new file with mode: 0644]
queue-5.4/nilfs2-return-the-mapped-address-from-nilfs_get_page.patch [new file with mode: 0644]
queue-5.4/nl80211-extend-support-to-config-spatial-reuse-param.patch [new file with mode: 0644]
queue-5.4/ptp-fix-error-message-on-failed-pin-verification.patch [new file with mode: 0644]
queue-5.4/s390-cpacf-get-rid-of-register-asm.patch [new file with mode: 0644]
queue-5.4/s390-cpacf-split-and-rework-cpacf-query-functions.patch [new file with mode: 0644]
queue-5.4/selftests-mm-compaction_test-fix-bogus-test-success-.patch [new file with mode: 0644]
queue-5.4/selftests-mm-compaction_test-fix-incorrect-write-of-.patch [new file with mode: 0644]
queue-5.4/selftests-mm-conform-test-to-tap-format-output.patch [new file with mode: 0644]
queue-5.4/selftests-mm-log-a-consistent-test-name-for-check_co.patch [new file with mode: 0644]
queue-5.4/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch [new file with mode: 0644]
queue-5.4/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/tcp-count-close-wait-sockets-for-tcp_mib_currestab.patch [new file with mode: 0644]
queue-5.4/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-.patch [new file with mode: 0644]
queue-5.4/usb-gadget-f_fs-remove-likely-unlikely.patch [new file with mode: 0644]
queue-5.4/vxlan-fix-regression-when-dropping-packets-due-to-in.patch [new file with mode: 0644]
queue-5.4/wifi-cfg80211-pmsr-use-correct-nla_get_ux-functions.patch [new file with mode: 0644]
queue-5.4/wifi-iwlwifi-dbg_ini-move-iwl_dbg_tlv_free-outside-o.patch [new file with mode: 0644]
queue-5.4/wifi-iwlwifi-mvm-don-t-read-past-the-mfuart-notifcat.patch [new file with mode: 0644]
queue-5.4/wifi-iwlwifi-mvm-revert-gen2-tx-a-mpdu-size-to-64.patch [new file with mode: 0644]
queue-5.4/wifi-mac80211-correctly-parse-spatial-reuse-paramete.patch [new file with mode: 0644]
queue-5.4/wifi-mac80211-fix-deadlock-in-ieee80211_sta_ps_deliv.patch [new file with mode: 0644]
queue-5.4/wifi-mac80211-mesh-fix-leak-of-mesh_preq_queue-objec.patch [new file with mode: 0644]

diff --git a/queue-5.4/af_unix-annotate-data-race-of-net-unx.sysctl_max_dgr.patch b/queue-5.4/af_unix-annotate-data-race-of-net-unx.sysctl_max_dgr.patch
new file mode 100644 (file)
index 0000000..ea33adb
--- /dev/null
@@ -0,0 +1,38 @@
+From 0b1e52803389e7ea622fb2622bbb9eec07e6c58b 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 0611ff921421e..ec4c462a87f06 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -807,7 +807,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
+
diff --git a/queue-5.4/af_unix-annotate-data-race-of-sk-sk_shutdown-in-sk_d.patch b/queue-5.4/af_unix-annotate-data-race-of-sk-sk_shutdown-in-sk_d.patch
new file mode 100644 (file)
index 0000000..82d0b98
--- /dev/null
@@ -0,0 +1,37 @@
+From 4cf238fc74357a0f31f757f2a3f0d0091077ce16 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 5bc5cb83cc6e4..7066a36234106 100644
+--- a/net/unix/diag.c
++++ b/net/unix/diag.c
+@@ -164,7 +164,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
+
diff --git a/queue-5.4/af_unix-annotate-data-race-of-sk-sk_state-in-unix_in.patch b/queue-5.4/af_unix-annotate-data-race-of-sk-sk_state-in-unix_in.patch
new file mode 100644 (file)
index 0000000..b2eeb9a
--- /dev/null
@@ -0,0 +1,50 @@
+From 97d20d950dde3a2bac290ece7f04282a7c0d394b 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 e8bad973285e4..8ab1e2a781195 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2579,7 +2579,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
+
diff --git a/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-se.patch b/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-se.patch
new file mode 100644 (file)
index 0000000..0bff948
--- /dev/null
@@ -0,0 +1,72 @@
+From 1fd1ac0fbb8ac7d48072851a5a3954fdbb7fd5a6 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 73cc992bed880..0611ff921421e 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1881,7 +1881,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
+               goto out_err;
+       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;
+@@ -2083,7 +2083,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)
+@@ -2097,7 +2097,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);
+@@ -2293,7 +2293,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
+
diff --git a/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch b/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch
new file mode 100644 (file)
index 0000000..63567fa
--- /dev/null
@@ -0,0 +1,128 @@
+From 59a8191976a47505aa700a995da80fe7b02f7f61 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 8ab1e2a781195..73cc992bed880 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -449,9 +449,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;
+ }
+@@ -460,7 +460,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,
+@@ -2678,12 +2678,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)
+@@ -2699,14 +2701,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;
+@@ -2717,12 +2719,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))
+@@ -2739,19 +2743,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
+
diff --git a/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch-4923 b/queue-5.4/af_unix-annotate-data-races-around-sk-sk_state-in-un.patch-4923
new file mode 100644 (file)
index 0000000..b1fe8ac
--- /dev/null
@@ -0,0 +1,71 @@
+From 90ab78f8ad8f064b8934cd594881f42b1c6aa367 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 2975e7a061d0b..4666fabb04933 100644
+--- a/net/unix/diag.c
++++ b/net/unix/diag.c
+@@ -64,7 +64,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,
+@@ -102,7 +102,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 {
+@@ -135,7 +135,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);
+@@ -218,7 +218,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
+
diff --git a/queue-5.4/af_unix-use-skb_queue_len_lockless-in-sk_diag_show_r.patch b/queue-5.4/af_unix-use-skb_queue_len_lockless-in-sk_diag_show_r.patch
new file mode 100644 (file)
index 0000000..f624849
--- /dev/null
@@ -0,0 +1,41 @@
+From ca35f64e7d0cf3e9203e34f0f528d69abeb770b7 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 4666fabb04933..5bc5cb83cc6e4 100644
+--- a/net/unix/diag.c
++++ b/net/unix/diag.c
+@@ -103,7 +103,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
+
diff --git a/queue-5.4/af_unix-use-unix_recvq_full_lockless-in-unix_stream_.patch b/queue-5.4/af_unix-use-unix_recvq_full_lockless-in-unix_stream_.patch
new file mode 100644 (file)
index 0000000..f1f5a10
--- /dev/null
@@ -0,0 +1,72 @@
+From 605cba8e2051f009e1aa6429c6c1c35ee7651c55 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 ec4c462a87f06..ae6aae983b8cb 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -189,15 +189,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)
+@@ -1301,7 +1295,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
+
diff --git a/queue-5.4/arm64-dts-agilex-add-nand-ip-to-base-dts.patch b/queue-5.4/arm64-dts-agilex-add-nand-ip-to-base-dts.patch
new file mode 100644 (file)
index 0000000..399d3b2
--- /dev/null
@@ -0,0 +1,44 @@
+From 73d6beeafd5dccfbe0e8915b9aebeeb76dd1fa99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Nov 2019 09:39:30 -0600
+Subject: arm64: dts: agilex: add NAND IP to base dts
+
+From: Dinh Nguyen <dinguyen@kernel.org>
+
+[ Upstream commit 68441353538b77dbe7cd94b48d0c3677fb451be0 ]
+
+Add NAND entry to base DTSI.
+
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Stable-dep-of: 5d915e584d84 ("af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/intel/socfpga_agilex.dtsi | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+index 19f17bb29e4bd..414f84aff902f 100644
+--- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
++++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+@@ -229,6 +229,18 @@ mmc: dwmmc0@ff808000 {
+                       status = "disabled";
+               };
++              nand: nand@ffb90000 {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      compatible = "altr,socfpga-denali-nand";
++                      reg = <0xffb90000 0x10000>,
++                            <0xffb80000 0x1000>;
++                      reg-names = "nand_data", "denali_reg";
++                      interrupts = <0 97 4>;
++                      resets = <&rst NAND_RESET>, <&rst NAND_OCP_RESET>;
++                      status = "disabled";
++              };
++
+               ocram: sram@ffe00000 {
+                       compatible = "mmio-sram";
+                       reg = <0xffe00000 0x40000>;
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-fix-race-condition-during-prob.patch b/queue-5.4/asoc-ti-davinci-mcasp-fix-race-condition-during-prob.patch
new file mode 100644 (file)
index 0000000..be50cb6
--- /dev/null
@@ -0,0 +1,81 @@
+From 9d27672e7586556b4817f9d2c95ffff76e45b3f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Apr 2024 15:41:38 -0300
+Subject: ASoC: ti: davinci-mcasp: Fix race condition during probe
+
+From: Joao Paulo Goncalves <joao.goncalves@toradex.com>
+
+[ Upstream commit d18ca8635db2f88c17acbdf6412f26d4f6aff414 ]
+
+When using davinci-mcasp as CPU DAI with simple-card, there are some
+conditions that cause simple-card to finish registering a sound card before
+davinci-mcasp finishes registering all sound components. This creates a
+non-working sound card from userspace with no problem indication apart
+from not being able to play/record audio on a PCM stream. The issue
+arises during simultaneous probe execution of both drivers. Specifically,
+the simple-card driver, awaiting a CPU DAI, proceeds as soon as
+davinci-mcasp registers its DAI. However, this process can lead to the
+client mutex lock (client_mutex in soc-core.c) being held or davinci-mcasp
+being preempted before PCM DMA registration on davinci-mcasp finishes.
+This situation occurs when the probes of both drivers run concurrently.
+Below is the code path for this condition. To solve the issue, defer
+davinci-mcasp CPU DAI registration to the last step in the audio part of
+it. This way, simple-card CPU DAI parsing will be deferred until all
+audio components are registered.
+
+Fail Code Path:
+
+simple-card.c: probe starts
+simple-card.c: simple_dai_link_of: simple_parse_node(..,cpu,..) returns EPROBE_DEFER, no CPU DAI yet
+davinci-mcasp.c: probe starts
+davinci-mcasp.c: devm_snd_soc_register_component() register CPU DAI
+simple-card.c: probes again, finish CPU DAI parsing and call devm_snd_soc_register_card()
+simple-card.c: finish probe
+davinci-mcasp.c: *dma_pcm_platform_register() register PCM  DMA
+davinci-mcasp.c: probe finish
+
+Cc: stable@vger.kernel.org
+Fixes: 9fbd58cf4ab0 ("ASoC: davinci-mcasp: Choose PCM driver based on configured DMA controller")
+Signed-off-by: Joao Paulo Goncalves <joao.goncalves@toradex.com>
+Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Reviewed-by: Jai Luthra <j-luthra@ti.com>
+Link: https://lore.kernel.org/r/20240417184138.1104774-1-jpaulo.silvagoncalves@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index 633cd7fd3dcf3..dc40b5c5d501e 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -2270,12 +2270,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       mcasp_reparent_fck(pdev);
+-      ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+-                                            &davinci_mcasp_dai[mcasp->op_mode], 1);
+-
+-      if (ret != 0)
+-              goto err;
+-
+       ret = davinci_mcasp_get_dma_type(mcasp);
+       switch (ret) {
+       case PCM_EDMA:
+@@ -2296,6 +2290,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+               goto err;
+       }
++      ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
++                                            &davinci_mcasp_dai[mcasp->op_mode], 1);
++
++      if (ret != 0)
++              goto err;
++
+ no_audio:
+       ret = davinci_mcasp_init_gpiochip(mcasp);
+       if (ret) {
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-handle-missing-required-dt-pro.patch b/queue-5.4/asoc-ti-davinci-mcasp-handle-missing-required-dt-pro.patch
new file mode 100644 (file)
index 0000000..04f328c
--- /dev/null
@@ -0,0 +1,196 @@
+From 18526aed30042e4e6f15d6513d4c83b1f22784bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Nov 2020 09:25:51 +0200
+Subject: ASoC: ti: davinci-mcasp: Handle missing required DT properties
+
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+
+[ Upstream commit 1b4fb70e5b28a477478417a7958e0228460ffe68 ]
+
+McASP needs three required properties to be usable for audio:
+op-mode, tdm-slots and the serial-dir array.
+
+Instead of probing the driver even without the needed information we should
+make sure that all the parameters are provided for operation.
+
+The fact that McASP can act as a GPIO controller for it's pins complicates
+this a bit, but as a general rule we can:
+- we fail the probe if McASP is not configured to be used as gpiochip
+- we will not register the DAI (and PCM) if gpiochip is defined
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20201106072551.689-5-peter.ujfalusi@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 77 +++++++++++++++++++++++++++---------
+ 1 file changed, 58 insertions(+), 19 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index 637c26cad2e6e..633cd7fd3dcf3 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -82,6 +82,9 @@ struct davinci_mcasp {
+       struct snd_pcm_substream *substreams[2];
+       unsigned int dai_fmt;
++      /* Audio can not be enabled due to missing parameter(s) */
++      bool    missing_audio_param;
++
+       /* McASP specific data */
+       int     tdm_slots;
+       u32     tdm_mask[2];
+@@ -1723,6 +1726,17 @@ static int mcasp_reparent_fck(struct platform_device *pdev)
+       return ret;
+ }
++static bool davinci_mcasp_have_gpiochip(struct davinci_mcasp *mcasp)
++{
++#ifdef CONFIG_OF_GPIO
++      if (mcasp->dev->of_node &&
++          of_property_read_bool(mcasp->dev->of_node, "gpio-controller"))
++              return true;
++#endif
++
++      return false;
++}
++
+ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
+                                   struct platform_device *pdev)
+ {
+@@ -1747,8 +1761,12 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
+               return -EINVAL;
+       }
+-      if (of_property_read_u32(np, "op-mode", &val) == 0)
++      if (of_property_read_u32(np, "op-mode", &val) == 0) {
+               pdata->op_mode = val;
++      } else {
++              mcasp->missing_audio_param = true;
++              goto out;
++      }
+       if (of_property_read_u32(np, "tdm-slots", &val) == 0) {
+               if (val < 2 || val > 32) {
+@@ -1757,6 +1775,9 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
+               }
+               pdata->tdm_slots = val;
++      } else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) {
++              mcasp->missing_audio_param = true;
++              goto out;
+       }
+       of_serial_dir32 = of_get_property(np, "serial-dir", &val);
+@@ -1773,6 +1794,9 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
+               pdata->num_serializer = val;
+               pdata->serial_dir = of_serial_dir;
++      } else {
++              mcasp->missing_audio_param = true;
++              goto out;
+       }
+       if (of_property_read_u32(np, "tx-num-evt", &val) == 0)
+@@ -1798,6 +1822,16 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
+ out:
+       mcasp->pdata = pdata;
++      if (mcasp->missing_audio_param) {
++              if (davinci_mcasp_have_gpiochip(mcasp)) {
++                      dev_dbg(&pdev->dev, "Missing DT parameter(s) for audio\n");
++                      return 0;
++              }
++
++              dev_err(&pdev->dev, "Insufficient DT parameter(s)\n");
++              return -ENODEV;
++      }
++
+       mcasp->op_mode = pdata->op_mode;
+       /* sanity check for tdm slots parameter */
+       if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
+@@ -2044,7 +2078,7 @@ static const struct gpio_chip davinci_mcasp_template_chip = {
+ static int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
+ {
+-      if (!of_property_read_bool(mcasp->dev->of_node, "gpio-controller"))
++      if (!davinci_mcasp_have_gpiochip(mcasp))
+               return 0;
+       mcasp->gpio_chip = davinci_mcasp_template_chip;
+@@ -2083,11 +2117,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (!mcasp)
+               return  -ENOMEM;
+-      mcasp->dev = &pdev->dev;
+-      ret = davinci_mcasp_get_config(mcasp, pdev);
+-      if (ret)
+-              return ret;
+-
+       mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+       if (!mem) {
+               dev_warn(mcasp->dev,
+@@ -2103,8 +2132,23 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (IS_ERR(mcasp->base))
+               return PTR_ERR(mcasp->base);
++      dev_set_drvdata(&pdev->dev, mcasp);
+       pm_runtime_enable(&pdev->dev);
++      mcasp->dev = &pdev->dev;
++      ret = davinci_mcasp_get_config(mcasp, pdev);
++      if (ret)
++              goto err;
++
++      /* All PINS as McASP */
++      pm_runtime_get_sync(mcasp->dev);
++      mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
++      pm_runtime_put(mcasp->dev);
++
++      /* Skip audio related setup code if the configuration is not adequat */
++      if (mcasp->missing_audio_param)
++              goto no_audio;
++
+       irq = platform_get_irq_byname_optional(pdev, "common");
+       if (irq > 0) {
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common",
+@@ -2224,19 +2268,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (ret)
+               goto err;
+-      dev_set_drvdata(&pdev->dev, mcasp);
+-
+       mcasp_reparent_fck(pdev);
+-      /* All PINS as McASP */
+-      pm_runtime_get_sync(mcasp->dev);
+-      mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
+-      pm_runtime_put(mcasp->dev);
+-
+-      ret = davinci_mcasp_init_gpiochip(mcasp);
+-      if (ret)
+-              goto err;
+-
+       ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+                                             &davinci_mcasp_dai[mcasp->op_mode], 1);
+@@ -2263,8 +2296,14 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+               goto err;
+       }
+-      return 0;
++no_audio:
++      ret = davinci_mcasp_init_gpiochip(mcasp);
++      if (ret) {
++              dev_err(&pdev->dev, "gpiochip registration failed: %d\n", ret);
++              goto err;
++      }
++      return 0;
+ err:
+       pm_runtime_disable(&pdev->dev);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-remove-always-zero-of-davinci_.patch b/queue-5.4/asoc-ti-davinci-mcasp-remove-always-zero-of-davinci_.patch
new file mode 100644 (file)
index 0000000..f15a6be
--- /dev/null
@@ -0,0 +1,66 @@
+From 096848df427c94d5de787f6cc41112b55eb2b85e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Nov 2020 18:34:28 +0800
+Subject: ASoC: ti: davinci-mcasp: remove always zero of
+ davinci_mcasp_get_dt_params
+
+From: Zhang Qilong <zhangqilong3@huawei.com>
+
+[ Upstream commit 19f6e424d6150b5eede2277dbc6dfd3bf42e994f ]
+
+davinci_mcasp_get_dt_params alway return zero, and its return value
+could be ignored by the caller. So make it 'void' type to avoid the
+check its return value.
+
+Fixes: 764958f2b5239 ("ASoC: ti: davinci-mcasp: Support for auxclk-fs-ratio")
+Signed-off-by: Zhang Qilong <zhangqilong3@huawei.com>
+Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20201102103428.32678-1-zhangqilong3@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index 76267fd4a9d88..b08948ffc61d0 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -2082,20 +2082,18 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
+ }
+ #endif /* CONFIG_GPIOLIB */
+-static int davinci_mcasp_get_dt_params(struct davinci_mcasp *mcasp)
++static void davinci_mcasp_get_dt_params(struct davinci_mcasp *mcasp)
+ {
+       struct device_node *np = mcasp->dev->of_node;
+       int ret;
+       u32 val;
+       if (!np)
+-              return 0;
++              return;
+       ret = of_property_read_u32(np, "auxclk-fs-ratio", &val);
+       if (ret >= 0)
+               mcasp->auxclk_fs_ratio = val;
+-
+-      return 0;
+ }
+ static int davinci_mcasp_probe(struct platform_device *pdev)
+@@ -2331,9 +2329,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (ret)
+               goto err;
+-      ret = davinci_mcasp_get_dt_params(mcasp);
+-      if (ret)
+-              return -EINVAL;
++      davinci_mcasp_get_dt_params(mcasp);
+       ret = devm_snd_soc_register_component(&pdev->dev,
+                                       &davinci_mcasp_component,
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-remove-legacy-dma_request-pars.patch b/queue-5.4/asoc-ti-davinci-mcasp-remove-legacy-dma_request-pars.patch
new file mode 100644 (file)
index 0000000..3d4a5e2
--- /dev/null
@@ -0,0 +1,141 @@
+From 37a00976cac0ad26a311f8e0eacae8f2545c7fdd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Nov 2020 09:25:49 +0200
+Subject: ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
+
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+
+[ Upstream commit db8793a39b293d5a8983e1713a70a76cb039c2fe ]
+
+The legacy dma_request (which was holding the DMA request number) is no
+longer in use for a long time.
+All legacy platforms has been converted to dma_slave_map.
+
+Remove it along with the DT parsing to get tx_dma_channel and
+rx_dma_channel.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20201106072551.689-3-peter.ujfalusi@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 57 ++----------------------------------
+ 1 file changed, 3 insertions(+), 54 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index 7860382a17a28..e2e272d653480 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -93,7 +93,6 @@ struct davinci_mcasp {
+       u8      bclk_div;
+       int     streams;
+       u32     irq_request[2];
+-      int     dma_request[2];
+       int     sysclk_freq;
+       bool    bclk_master;
+@@ -1730,7 +1729,6 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+       struct davinci_mcasp_pdata *pdata = NULL;
+       const struct of_device_id *match =
+                       of_match_device(mcasp_dt_ids, &pdev->dev);
+-      struct of_phandle_args dma_spec;
+       const u32 *of_serial_dir32;
+       u32 val;
+@@ -1785,31 +1783,6 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+               pdata->serial_dir = of_serial_dir;
+       }
+-      ret = of_property_match_string(np, "dma-names", "tx");
+-      if (ret < 0)
+-              goto nodata;
+-
+-      ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
+-                                       &dma_spec);
+-      if (ret < 0)
+-              goto nodata;
+-
+-      pdata->tx_dma_channel = dma_spec.args[0];
+-
+-      /* RX is not valid in DIT mode */
+-      if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) {
+-              ret = of_property_match_string(np, "dma-names", "rx");
+-              if (ret < 0)
+-                      goto nodata;
+-
+-              ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
+-                                               &dma_spec);
+-              if (ret < 0)
+-                      goto nodata;
+-
+-              pdata->rx_dma_channel = dma_spec.args[0];
+-      }
+-
+       ret = of_property_read_u32(np, "tx-num-evt", &val);
+       if (ret >= 0)
+               pdata->txnumevt = val;
+@@ -2099,11 +2072,10 @@ static void davinci_mcasp_get_dt_params(struct davinci_mcasp *mcasp)
+ static int davinci_mcasp_probe(struct platform_device *pdev)
+ {
+       struct snd_dmaengine_dai_dma_data *dma_data;
+-      struct resource *mem, *res, *dat;
++      struct resource *mem, *dat;
+       struct davinci_mcasp_pdata *pdata;
+       struct davinci_mcasp *mcasp;
+       char *irq_name;
+-      int *dma;
+       int irq;
+       int ret;
+@@ -2238,45 +2210,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+               mcasp->dat_port = true;
+       dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
++      dma_data->filter_data = "tx";
+       if (dat)
+               dma_data->addr = dat->start;
+       else
+               dma_data->addr = mem->start + davinci_mcasp_txdma_offset(pdata);
+-      dma = &mcasp->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
+-      res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+-      if (res)
+-              *dma = res->start;
+-      else
+-              *dma = pdata->tx_dma_channel;
+-
+-      /* dmaengine filter data for DT and non-DT boot */
+-      if (pdev->dev.of_node)
+-              dma_data->filter_data = "tx";
+-      else
+-              dma_data->filter_data = dma;
+       /* RX is not valid in DIT mode */
+       if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
+               dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE];
++              dma_data->filter_data = "rx";
+               if (dat)
+                       dma_data->addr = dat->start;
+               else
+                       dma_data->addr =
+                               mem->start + davinci_mcasp_rxdma_offset(pdata);
+-
+-              dma = &mcasp->dma_request[SNDRV_PCM_STREAM_CAPTURE];
+-              res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+-              if (res)
+-                      *dma = res->start;
+-              else
+-                      *dma = pdata->rx_dma_channel;
+-
+-              /* dmaengine filter data for DT and non-DT boot */
+-              if (pdev->dev.of_node)
+-                      dma_data->filter_data = "rx";
+-              else
+-                      dma_data->filter_data = dma;
+       }
+       if (mcasp->version < MCASP_VERSION_3) {
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-remove-redundant-assignment-to.patch b/queue-5.4/asoc-ti-davinci-mcasp-remove-redundant-assignment-to.patch
new file mode 100644 (file)
index 0000000..a61d8da
--- /dev/null
@@ -0,0 +1,43 @@
+From ccc50e0518485c18a99979fe2e325ec9bc7cedc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Feb 2020 09:24:22 +0000
+Subject: ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
+
+From: Colin Ian King <colin.king@canonical.com>
+
+[ Upstream commit f4d95de415b286090c1bf739c20a5ea2aefda834 ]
+
+The assignment to ret is redundant as it is not used in the error
+return path and hence can be removed.
+
+Addresses-Coverity: ("Unused value")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20200210092423.327499-1-colin.king@canonical.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index 0541071f454bd..76267fd4a9d88 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -1743,10 +1743,8 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+       } else if (match) {
+               pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
+                                    GFP_KERNEL);
+-              if (!pdata) {
+-                      ret = -ENOMEM;
+-                      return pdata;
+-              }
++              if (!pdata)
++                      return NULL;
+       } else {
+               /* control shouldn't reach here. something is wrong */
+               ret = -EINVAL;
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-simplify-the-configuration-par.patch b/queue-5.4/asoc-ti-davinci-mcasp-simplify-the-configuration-par.patch
new file mode 100644 (file)
index 0000000..cc0f1c2
--- /dev/null
@@ -0,0 +1,305 @@
+From 5c5ff97b746a4abfb13723989dbf56f459551811 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Nov 2020 09:25:50 +0200
+Subject: ASoC: ti: davinci-mcasp: Simplify the configuration parameter
+ handling
+
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+
+[ Upstream commit 1125d925990b8d8166c45396c9281e2a705c97f8 ]
+
+Replace the davinci_mcasp_set_pdata_from_of() function which returned a
+pdata pointer with davinci_mcasp_get_config() to return an actual error
+code and handle all pdata validation and private mcasp struct setup in
+there.
+
+Drop the unused ram-size-playback and sram-size-capture query from DT at
+the same time.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20201106072551.689-4-peter.ujfalusi@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 164 +++++++++++++----------------------
+ 1 file changed, 60 insertions(+), 104 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index e2e272d653480..637c26cad2e6e 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -75,6 +75,7 @@ struct davinci_mcasp_ruledata {
+ struct davinci_mcasp {
+       struct snd_dmaengine_dai_dma_data dma_data[2];
++      struct davinci_mcasp_pdata *pdata;
+       void __iomem *base;
+       u32 fifo_base;
+       struct device *dev;
+@@ -1722,44 +1723,37 @@ static int mcasp_reparent_fck(struct platform_device *pdev)
+       return ret;
+ }
+-static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+-                                              struct platform_device *pdev)
++static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
++                                  struct platform_device *pdev)
+ {
++      const struct of_device_id *match = of_match_device(mcasp_dt_ids, &pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
+       struct davinci_mcasp_pdata *pdata = NULL;
+-      const struct of_device_id *match =
+-                      of_match_device(mcasp_dt_ids, &pdev->dev);
+-
+       const u32 *of_serial_dir32;
+       u32 val;
+-      int i, ret = 0;
++      int i;
+       if (pdev->dev.platform_data) {
+               pdata = pdev->dev.platform_data;
+               pdata->dismod = DISMOD_LOW;
+-              return pdata;
++              goto out;
+       } else if (match) {
+               pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
+                                    GFP_KERNEL);
+               if (!pdata)
+-                      return NULL;
++                      return -ENOMEM;
+       } else {
+-              /* control shouldn't reach here. something is wrong */
+-              ret = -EINVAL;
+-              goto nodata;
++              dev_err(&pdev->dev, "No compatible match found\n");
++              return -EINVAL;
+       }
+-      ret = of_property_read_u32(np, "op-mode", &val);
+-      if (ret >= 0)
++      if (of_property_read_u32(np, "op-mode", &val) == 0)
+               pdata->op_mode = val;
+-      ret = of_property_read_u32(np, "tdm-slots", &val);
+-      if (ret >= 0) {
++      if (of_property_read_u32(np, "tdm-slots", &val) == 0) {
+               if (val < 2 || val > 32) {
+-                      dev_err(&pdev->dev,
+-                              "tdm-slots must be in rage [2-32]\n");
+-                      ret = -EINVAL;
+-                      goto nodata;
++                      dev_err(&pdev->dev, "tdm-slots must be in rage [2-32]\n");
++                      return -EINVAL;
+               }
+               pdata->tdm_slots = val;
+@@ -1771,10 +1765,8 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+               u8 *of_serial_dir = devm_kzalloc(&pdev->dev,
+                                                (sizeof(*of_serial_dir) * val),
+                                                GFP_KERNEL);
+-              if (!of_serial_dir) {
+-                      ret = -ENOMEM;
+-                      goto nodata;
+-              }
++              if (!of_serial_dir)
++                      return -ENOMEM;
+               for (i = 0; i < val; i++)
+                       of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
+@@ -1783,24 +1775,16 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+               pdata->serial_dir = of_serial_dir;
+       }
+-      ret = of_property_read_u32(np, "tx-num-evt", &val);
+-      if (ret >= 0)
++      if (of_property_read_u32(np, "tx-num-evt", &val) == 0)
+               pdata->txnumevt = val;
+-      ret = of_property_read_u32(np, "rx-num-evt", &val);
+-      if (ret >= 0)
++      if (of_property_read_u32(np, "rx-num-evt", &val) == 0)
+               pdata->rxnumevt = val;
+-      ret = of_property_read_u32(np, "sram-size-playback", &val);
+-      if (ret >= 0)
+-              pdata->sram_size_playback = val;
+-
+-      ret = of_property_read_u32(np, "sram-size-capture", &val);
+-      if (ret >= 0)
+-              pdata->sram_size_capture = val;
++      if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0)
++              mcasp->auxclk_fs_ratio = val;
+-      ret = of_property_read_u32(np, "dismod", &val);
+-      if (ret >= 0) {
++      if (of_property_read_u32(np, "dismod", &val) == 0) {
+               if (val == 0 || val == 2 || val == 3) {
+                       pdata->dismod = DISMOD_VAL(val);
+               } else {
+@@ -1811,15 +1795,40 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
+               pdata->dismod = DISMOD_LOW;
+       }
+-      return  pdata;
++out:
++      mcasp->pdata = pdata;
+-nodata:
+-      if (ret < 0) {
+-              dev_err(&pdev->dev, "Error populating platform data, err %d\n",
+-                      ret);
+-              pdata = NULL;
++      mcasp->op_mode = pdata->op_mode;
++      /* sanity check for tdm slots parameter */
++      if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
++              if (pdata->tdm_slots < 2) {
++                      dev_warn(&pdev->dev, "invalid tdm slots: %d\n",
++                               pdata->tdm_slots);
++                      mcasp->tdm_slots = 2;
++              } else if (pdata->tdm_slots > 32) {
++                      dev_warn(&pdev->dev, "invalid tdm slots: %d\n",
++                               pdata->tdm_slots);
++                      mcasp->tdm_slots = 32;
++              } else {
++                      mcasp->tdm_slots = pdata->tdm_slots;
++              }
+       }
+-      return  pdata;
++
++      mcasp->num_serializer = pdata->num_serializer;
++#ifdef CONFIG_PM
++      mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
++                                              mcasp->num_serializer, sizeof(u32),
++                                              GFP_KERNEL);
++      if (!mcasp->context.xrsr_regs)
++              return -ENOMEM;
++#endif
++      mcasp->serial_dir = pdata->serial_dir;
++      mcasp->version = pdata->version;
++      mcasp->txnumevt = pdata->txnumevt;
++      mcasp->rxnumevt = pdata->rxnumevt;
++      mcasp->dismod = pdata->dismod;
++
++      return 0;
+ }
+ enum {
+@@ -2055,25 +2064,10 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
+ }
+ #endif /* CONFIG_GPIOLIB */
+-static void davinci_mcasp_get_dt_params(struct davinci_mcasp *mcasp)
+-{
+-      struct device_node *np = mcasp->dev->of_node;
+-      int ret;
+-      u32 val;
+-
+-      if (!np)
+-              return;
+-
+-      ret = of_property_read_u32(np, "auxclk-fs-ratio", &val);
+-      if (ret >= 0)
+-              mcasp->auxclk_fs_ratio = val;
+-}
+-
+ static int davinci_mcasp_probe(struct platform_device *pdev)
+ {
+       struct snd_dmaengine_dai_dma_data *dma_data;
+       struct resource *mem, *dat;
+-      struct davinci_mcasp_pdata *pdata;
+       struct davinci_mcasp *mcasp;
+       char *irq_name;
+       int irq;
+@@ -2089,11 +2083,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (!mcasp)
+               return  -ENOMEM;
+-      pdata = davinci_mcasp_set_pdata_from_of(pdev);
+-      if (!pdata) {
+-              dev_err(&pdev->dev, "no platform data\n");
+-              return -EINVAL;
+-      }
++      mcasp->dev = &pdev->dev;
++      ret = davinci_mcasp_get_config(mcasp, pdev);
++      if (ret)
++              return ret;
+       mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+       if (!mem) {
+@@ -2112,40 +2105,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       pm_runtime_enable(&pdev->dev);
+-      mcasp->op_mode = pdata->op_mode;
+-      /* sanity check for tdm slots parameter */
+-      if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
+-              if (pdata->tdm_slots < 2) {
+-                      dev_err(&pdev->dev, "invalid tdm slots: %d\n",
+-                              pdata->tdm_slots);
+-                      mcasp->tdm_slots = 2;
+-              } else if (pdata->tdm_slots > 32) {
+-                      dev_err(&pdev->dev, "invalid tdm slots: %d\n",
+-                              pdata->tdm_slots);
+-                      mcasp->tdm_slots = 32;
+-              } else {
+-                      mcasp->tdm_slots = pdata->tdm_slots;
+-              }
+-      }
+-
+-      mcasp->num_serializer = pdata->num_serializer;
+-#ifdef CONFIG_PM
+-      mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
+-                                      mcasp->num_serializer, sizeof(u32),
+-                                      GFP_KERNEL);
+-      if (!mcasp->context.xrsr_regs) {
+-              ret = -ENOMEM;
+-              goto err;
+-      }
+-#endif
+-      mcasp->serial_dir = pdata->serial_dir;
+-      mcasp->version = pdata->version;
+-      mcasp->txnumevt = pdata->txnumevt;
+-      mcasp->rxnumevt = pdata->rxnumevt;
+-      mcasp->dismod = pdata->dismod;
+-
+-      mcasp->dev = &pdev->dev;
+-
+       irq = platform_get_irq_byname_optional(pdev, "common");
+       if (irq > 0) {
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common",
+@@ -2214,7 +2173,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (dat)
+               dma_data->addr = dat->start;
+       else
+-              dma_data->addr = mem->start + davinci_mcasp_txdma_offset(pdata);
++              dma_data->addr = mem->start + davinci_mcasp_txdma_offset(mcasp->pdata);
+       /* RX is not valid in DIT mode */
+@@ -2225,7 +2184,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+                       dma_data->addr = dat->start;
+               else
+                       dma_data->addr =
+-                              mem->start + davinci_mcasp_rxdma_offset(pdata);
++                              mem->start + davinci_mcasp_rxdma_offset(mcasp->pdata);
+       }
+       if (mcasp->version < MCASP_VERSION_3) {
+@@ -2278,11 +2237,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       if (ret)
+               goto err;
+-      davinci_mcasp_get_dt_params(mcasp);
+-
+-      ret = devm_snd_soc_register_component(&pdev->dev,
+-                                      &davinci_mcasp_component,
+-                                      &davinci_mcasp_dai[pdata->op_mode], 1);
++      ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
++                                            &davinci_mcasp_dai[mcasp->op_mode], 1);
+       if (ret != 0)
+               goto err;
+-- 
+2.43.0
+
diff --git a/queue-5.4/asoc-ti-davinci-mcasp-use-platform_get_irq_byname_op.patch b/queue-5.4/asoc-ti-davinci-mcasp-use-platform_get_irq_byname_op.patch
new file mode 100644 (file)
index 0000000..992f9c8
--- /dev/null
@@ -0,0 +1,68 @@
+From a01f73b29da09d59cfb55d2430b0a693437e5da2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Nov 2020 09:25:48 +0200
+Subject: ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
+
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+
+[ Upstream commit 372c4bd11de1793667e11d19c29fffc80495eeca ]
+
+Depending on the integration of McASP either the 'common' or the
+'rx' and 'tx' or only the 'tx' interrupt number is valid, provided.
+
+By switching to platform_get_irq_byname_optional() we can clean up the
+bootlog from messages like:
+
+davinci-mcasp 2ba0000.mcasp: IRQ common not found
+
+The irq number == 0 is not valid, fix the check at the same time.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20201106072551.689-2-peter.ujfalusi@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d18ca8635db2 ("ASoC: ti: davinci-mcasp: Fix race condition during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/davinci-mcasp.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index b08948ffc61d0..7860382a17a28 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -2174,8 +2174,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+       mcasp->dev = &pdev->dev;
+-      irq = platform_get_irq_byname(pdev, "common");
+-      if (irq >= 0) {
++      irq = platform_get_irq_byname_optional(pdev, "common");
++      if (irq > 0) {
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common",
+                                         dev_name(&pdev->dev));
+               if (!irq_name) {
+@@ -2195,8 +2195,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+               mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
+       }
+-      irq = platform_get_irq_byname(pdev, "rx");
+-      if (irq >= 0) {
++      irq = platform_get_irq_byname_optional(pdev, "rx");
++      if (irq > 0) {
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx",
+                                         dev_name(&pdev->dev));
+               if (!irq_name) {
+@@ -2214,8 +2214,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+               mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
+       }
+-      irq = platform_get_irq_byname(pdev, "tx");
+-      if (irq >= 0) {
++      irq = platform_get_irq_byname_optional(pdev, "tx");
++      if (irq > 0) {
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx",
+                                         dev_name(&pdev->dev));
+               if (!irq_name) {
+-- 
+2.43.0
+
diff --git a/queue-5.4/drivers-core-reindent-a-couple-uses-around-sysfs_emi.patch b/queue-5.4/drivers-core-reindent-a-couple-uses-around-sysfs_emi.patch
new file mode 100644 (file)
index 0000000..0f0ea89
--- /dev/null
@@ -0,0 +1,54 @@
+From 8af05fe961081463b9e1511e25a9b2074925f9b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Sep 2020 13:40:41 -0700
+Subject: drivers core: Reindent a couple uses around sysfs_emit
+
+From: Joe Perches <joe@perches.com>
+
+[ Upstream commit 27275d301813d1f3b1b2fe5576d4afd690df6b99 ]
+
+Just a couple of whitespace realignment to open parenthesis for
+multi-line statements.
+
+Signed-off-by: Joe Perches <joe@perches.com>
+Link: https://lore.kernel.org/r/33224191421dbb56015eded428edfddcba997d63.1600285923.git.joe@perches.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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/base/node.c        | 4 ++--
+ drivers/base/power/sysfs.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index 666eb55c0774e..c78d190fef376 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -384,9 +384,9 @@ static ssize_t node_read_meminfo(struct device *dev,
+                      nid, K(i.freeram),
+                      nid, K(i.totalram - i.freeram),
+                      nid, K(node_page_state(pgdat, NR_ACTIVE_ANON) +
+-                              node_page_state(pgdat, NR_ACTIVE_FILE)),
++                            node_page_state(pgdat, NR_ACTIVE_FILE)),
+                      nid, K(node_page_state(pgdat, NR_INACTIVE_ANON) +
+-                              node_page_state(pgdat, NR_INACTIVE_FILE)),
++                            node_page_state(pgdat, NR_INACTIVE_FILE)),
+                      nid, K(node_page_state(pgdat, NR_ACTIVE_ANON)),
+                      nid, K(node_page_state(pgdat, NR_INACTIVE_ANON)),
+                      nid, K(node_page_state(pgdat, NR_ACTIVE_FILE)),
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index 2786962e08107..4ac032a1fa228 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -101,7 +101,7 @@ static ssize_t control_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+ {
+       return sysfs_emit(buf, "%s\n",
+-                              dev->power.runtime_auto ? ctrl_auto : ctrl_on);
++                        dev->power.runtime_auto ? ctrl_auto : ctrl_on);
+ }
+ static ssize_t control_store(struct device * dev, struct device_attribute *attr,
+-- 
+2.43.0
+
diff --git a/queue-5.4/drm-amd-display-handle-y-carry-over-in-vcp-x.y-calcu.patch b/queue-5.4/drm-amd-display-handle-y-carry-over-in-vcp-x.y-calcu.patch
new file mode 100644 (file)
index 0000000..0efa96c
--- /dev/null
@@ -0,0 +1,44 @@
+From dd6f777020d75ebb365d7dfc0f9b3f1454c68d42 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 6718777c826dc..5d2013f1c0729 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
+@@ -635,6 +635,12 @@ void enc1_stream_encoder_set_mst_bandwidth(
+                               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
+
diff --git a/queue-5.4/ipv6-fix-possible-race-in-__fib6_drop_pcpu_from.patch b/queue-5.4/ipv6-fix-possible-race-in-__fib6_drop_pcpu_from.patch
new file mode 100644 (file)
index 0000000..5b99f23
--- /dev/null
@@ -0,0 +1,130 @@
+From 2899f9956816e7d33ab89cb754db3fe4f7c301b5 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 3afc32fe9b07b..ef1df9d662d62 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -907,6 +907,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
+        */
+@@ -915,7 +916,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
+@@ -929,6 +932,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 3917755351ad9..65772800d0d33 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -1416,6 +1416,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
+
diff --git a/queue-5.4/ipv6-sr-block-bh-in-seg6_output_core-and-seg6_input_.patch b/queue-5.4/ipv6-sr-block-bh-in-seg6_output_core-and-seg6_input_.patch
new file mode 100644 (file)
index 0000000..80b8e81
--- /dev/null
@@ -0,0 +1,95 @@
+From ceebbdacff8481b66e4c76c2a31a71a3994285ab 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 b626e0b62a549..185b9db0b575e 100644
+--- a/net/ipv6/seg6_iptunnel.c
++++ b/net/ipv6/seg6_iptunnel.c
+@@ -308,9 +308,8 @@ static int seg6_input(struct sk_buff *skb)
+       slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
+-      preempt_disable();
++      local_bh_disable();
+       dst = dst_cache_get(&slwt->cache);
+-      preempt_enable();
+       skb_dst_drop(skb);
+@@ -318,14 +317,13 @@ static int seg6_input(struct sk_buff *skb)
+               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))
+@@ -347,9 +345,9 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+       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);
+@@ -369,9 +367,9 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+                       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
+
diff --git a/queue-5.4/mmc-davinci-don-t-strip-remove-function-when-driver-.patch b/queue-5.4/mmc-davinci-don-t-strip-remove-function-when-driver-.patch
new file mode 100644 (file)
index 0000000..d12a4d3
--- /dev/null
@@ -0,0 +1,59 @@
+From 1f27f96028207a35cd36882848e003df737a40bc 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 2ae2af3bb7161..118ab9edf0d7c 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -1348,7 +1348,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
+
diff --git a/queue-5.4/mmc-davinci_mmc-convert-to-platform-remove-callback-.patch b/queue-5.4/mmc-davinci_mmc-convert-to-platform-remove-callback-.patch
new file mode 100644 (file)
index 0000000..a5a88ae
--- /dev/null
@@ -0,0 +1,67 @@
+From 8d4fca32af8f3242867a86add35a1a1951d82733 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 ade7c022a33c0..2ae2af3bb7161 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -1348,7 +1348,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);
+@@ -1357,8 +1357,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
+
diff --git a/queue-5.4/net-mlx5-stop-waiting-for-pci-if-pci-channel-is-offl.patch b/queue-5.4/net-mlx5-stop-waiting-for-pci-if-pci-channel-is-offl.patch
new file mode 100644 (file)
index 0000000..d42f763
--- /dev/null
@@ -0,0 +1,86 @@
+From 17137e6f2499fc9622cb0dc503cb2715ed517892 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 00:04:42 +0300
+Subject: net/mlx5: Stop waiting for PCI if pci channel is offline
+
+From: Moshe Shemesh <moshe@nvidia.com>
+
+[ Upstream commit 33afbfcc105a572159750f2ebee834a8a70fdd96 ]
+
+In case pci channel becomes offline the driver should not wait for PCI
+reads during health dump and recovery flow. The driver has timeout for
+each of these loops trying to read PCI, so it would fail anyway.
+However, in case of recovery waiting till timeout may cause the pci
+error_detected() callback fail to meet pci_dpc_recovered() wait timeout.
+
+Fixes: b3bd076f7501 ("net/mlx5: Report devlink health on FW fatal issues")
+Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/fw.c          | 4 ++++
+ drivers/net/ethernet/mellanox/mlx5/core/health.c      | 8 ++++++++
+ drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c | 4 ++++
+ 3 files changed, 16 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+index 13e86f0b42f54..43e4bc222cfa7 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+@@ -337,6 +337,10 @@ int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev)
+       do {
+               if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
+                       break;
++              if (pci_channel_offline(dev->pdev)) {
++                      mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
++                      return -EACCES;
++              }
+               cond_resched();
+       } while (!time_after(jiffies, end));
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
+index f628887d8af8c..d4ad0e4192bbe 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
+@@ -250,6 +250,10 @@ void mlx5_error_sw_reset(struct mlx5_core_dev *dev)
+       do {
+               if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
+                       break;
++              if (pci_channel_offline(dev->pdev)) {
++                      mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
++                      goto unlock;
++              }
+               msleep(20);
+       } while (!time_after(jiffies, end));
+@@ -322,6 +326,10 @@ static int mlx5_health_try_recover(struct mlx5_core_dev *dev)
+                                     "health recovery flow aborted, PCI reads still not working\n");
+                       return -EIO;
+               }
++              if (pci_channel_offline(dev->pdev)) {
++                      mlx5_core_err(dev, "PCI channel offline, stop waiting for PCI\n");
++                      return -EACCES;
++              }
+               msleep(100);
+       }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c
+index 6b774e0c27665..d0b595ba61101 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c
+@@ -74,6 +74,10 @@ int mlx5_vsc_gw_lock(struct mlx5_core_dev *dev)
+                       ret = -EBUSY;
+                       goto pci_unlock;
+               }
++              if (pci_channel_offline(dev->pdev)) {
++                      ret = -EACCES;
++                      goto pci_unlock;
++              }
+               /* Check if semaphore is already locked */
+               ret = vsc_read(dev, VSC_SEMAPHORE_OFFSET, &lock_val);
+-- 
+2.43.0
+
diff --git a/queue-5.4/net-sched-sch_multiq-fix-possible-oob-write-in-multi.patch b/queue-5.4/net-sched-sch_multiq-fix-possible-oob-write-in-multi.patch
new file mode 100644 (file)
index 0000000..a7dd2b7
--- /dev/null
@@ -0,0 +1,38 @@
+From 26a8fc07ac9e17412448d2bbce2edfcc17ac7120 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 1330ad2249317..b822d3e74637d 100644
+--- a/net/sched/sch_multiq.c
++++ b/net/sched/sch_multiq.c
+@@ -186,7 +186,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
+
diff --git a/queue-5.4/net-sched-taprio-always-validate-tca_taprio_attr_pri.patch b/queue-5.4/net-sched-taprio-always-validate-tca_taprio_attr_pri.patch
new file mode 100644 (file)
index 0000000..bf26b21
--- /dev/null
@@ -0,0 +1,63 @@
+From 6c0dbca64e1400cf1049a8a3229fbbf9511de6a4 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 e4c4d23a1b535..7b896be009d55 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -925,16 +925,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
+
diff --git a/queue-5.4/nilfs2-fix-nilfs_empty_dir-misjudgment-and-long-loop.patch b/queue-5.4/nilfs2-fix-nilfs_empty_dir-misjudgment-and-long-loop.patch
new file mode 100644 (file)
index 0000000..ff6bf5a
--- /dev/null
@@ -0,0 +1,51 @@
+From 37df14a8a6442eab9b0f386f67d95d281e51bff0 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
+
diff --git a/queue-5.4/nilfs2-remove-check-for-pageerror.patch b/queue-5.4/nilfs2-remove-check-for-pageerror.patch
new file mode 100644 (file)
index 0000000..7b595df
--- /dev/null
@@ -0,0 +1,35 @@
+From aa27c65e7fa6053d28d4cd611111aad4e4292893 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
+
diff --git a/queue-5.4/nilfs2-return-the-mapped-address-from-nilfs_get_page.patch b/queue-5.4/nilfs2-return-the-mapped-address-from-nilfs_get_page.patch
new file mode 100644 (file)
index 0000000..834f100
--- /dev/null
@@ -0,0 +1,146 @@
+From e0284a4b59413b5b5135bace0d4282308d0195ce 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
+
diff --git a/queue-5.4/nl80211-extend-support-to-config-spatial-reuse-param.patch b/queue-5.4/nl80211-extend-support-to-config-spatial-reuse-param.patch
new file mode 100644 (file)
index 0000000..6af4509
--- /dev/null
@@ -0,0 +1,157 @@
+From 5f13dd13b2a5ed39870c4cc4697ba619dca0fb22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Sep 2020 00:28:11 -0700
+Subject: nl80211: extend support to config spatial reuse parameter set
+
+From: Rajkumar Manoharan <rmanohar@codeaurora.org>
+
+[ Upstream commit f5bec330e3010450daeb5cb6a94a4a7c54afa306 ]
+
+Allow the user to configure below Spatial Reuse Parameter Set element.
+  * Non-SRG OBSS PD Max Offset
+  * SRG BSS Color Bitmap
+  * SRG Partial BSSID Bitmap
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org>
+Link: https://lore.kernel.org/r/1601278091-20313-2-git-send-email-rmanohar@codeaurora.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Stable-dep-of: a26d8dc5227f ("wifi: mac80211: correctly parse Spatial Reuse Parameter Set element")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/ieee80211.h    |  7 +++++--
+ include/net/cfg80211.h       | 10 ++++++++++
+ include/uapi/linux/nl80211.h | 11 +++++++++++
+ net/wireless/nl80211.c       | 25 +++++++++++++++++++++++++
+ 4 files changed, 51 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
+index 624d2643bfbaa..3b0459e88ab73 100644
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -2095,8 +2095,11 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
+ }
+ /* HE Spatial Reuse defines */
+-#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT                       0x4
+-#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT              0x8
++#define IEEE80211_HE_SPR_PSR_DISALLOWED                               BIT(0)
++#define IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED                BIT(1)
++#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT                       BIT(2)
++#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT              BIT(3)
++#define IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED              BIT(4)
+ /*
+  * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 2dfa3331604e4..cba78dfe8a3db 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -250,13 +250,23 @@ struct ieee80211_rate {
+  * struct ieee80211_he_obss_pd - AP settings for spatial reuse
+  *
+  * @enable: is the feature enabled.
++ * @sr_ctrl: The SR Control field of SRP element.
++ * @non_srg_max_offset: non-SRG maximum tx power offset
+  * @min_offset: minimal tx power offset an associated station shall use
+  * @max_offset: maximum tx power offset an associated station shall use
++ * @bss_color_bitmap: bitmap that indicates the BSS color values used by
++ *    members of the SRG
++ * @partial_bssid_bitmap: bitmap that indicates the partial BSSID values
++ *    used by members of the SRG
+  */
+ struct ieee80211_he_obss_pd {
+       bool enable;
++      u8 sr_ctrl;
++      u8 non_srg_max_offset;
+       u8 min_offset;
+       u8 max_offset;
++      u8 bss_color_bitmap[8];
++      u8 partial_bssid_bitmap[8];
+ };
+ /**
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index beee59c831a73..4a95edbfc6e43 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -6533,6 +6533,13 @@ enum nl80211_peer_measurement_ftm_resp {
+  *
+  * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset.
+  * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset.
++ * @NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET: the non-SRG OBSS PD maximum
++ *    tx power offset.
++ * @NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP: bitmap that indicates the BSS color
++ *    values used by members of the SRG.
++ * @NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP: bitmap that indicates the partial
++ *    BSSID values used by members of the SRG.
++ * @NL80211_HE_OBSS_PD_ATTR_SR_CTRL: The SR Control field of SRP element.
+  *
+  * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal
+  * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute.
+@@ -6542,6 +6549,10 @@ enum nl80211_obss_pd_attributes {
+       NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET,
+       NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET,
++      NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET,
++      NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP,
++      NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP,
++      NL80211_HE_OBSS_PD_ATTR_SR_CTRL,
+       /* keep last */
+       __NL80211_HE_OBSS_PD_ATTR_LAST,
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 0d15dd68565cb..7e0079aa4e6c4 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -319,6 +319,13 @@ he_obss_pd_policy[NL80211_HE_OBSS_PD_ATTR_MAX + 1] = {
+               NLA_POLICY_RANGE(NLA_U8, 1, 20),
+       [NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET] =
+               NLA_POLICY_RANGE(NLA_U8, 1, 20),
++      [NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET] =
++              NLA_POLICY_RANGE(NLA_U8, 1, 20),
++      [NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP] =
++              NLA_POLICY_EXACT_LEN(8),
++      [NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP] =
++              NLA_POLICY_EXACT_LEN(8),
++      [NL80211_HE_OBSS_PD_ATTR_SR_CTRL] = { .type = NLA_U8 },
+ };
+ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+@@ -4505,16 +4512,34 @@ static int nl80211_parse_he_obss_pd(struct nlattr *attrs,
+       if (err)
+               return err;
++      if (!tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL])
++              return -EINVAL;
++
++      he_obss_pd->sr_ctrl = nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_SR_CTRL]);
++
+       if (tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET])
+               he_obss_pd->min_offset =
+                       nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET]);
+       if (tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET])
+               he_obss_pd->max_offset =
+                       nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET]);
++      if (tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET])
++              he_obss_pd->non_srg_max_offset =
++                      nla_get_u8(tb[NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET]);
+       if (he_obss_pd->min_offset > he_obss_pd->max_offset)
+               return -EINVAL;
++      if (tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP])
++              memcpy(he_obss_pd->bss_color_bitmap,
++                     nla_data(tb[NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP]),
++                     sizeof(he_obss_pd->bss_color_bitmap));
++
++      if (tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP])
++              memcpy(he_obss_pd->partial_bssid_bitmap,
++                     nla_data(tb[NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP]),
++                     sizeof(he_obss_pd->partial_bssid_bitmap));
++
+       he_obss_pd->enable = true;
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-5.4/ptp-fix-error-message-on-failed-pin-verification.patch b/queue-5.4/ptp-fix-error-message-on-failed-pin-verification.patch
new file mode 100644 (file)
index 0000000..d66e030
--- /dev/null
@@ -0,0 +1,42 @@
+From fcd9926e84611aa431a410b22c3304640d0927d5 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 87bd6c072ac2f..37c4807f15c60 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
+
diff --git a/queue-5.4/s390-cpacf-get-rid-of-register-asm.patch b/queue-5.4/s390-cpacf-get-rid-of-register-asm.patch
new file mode 100644 (file)
index 0000000..9716043
--- /dev/null
@@ -0,0 +1,375 @@
+From 960e9d0e6a0f61cc59077a87dd86dcfef6973383 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Jun 2021 16:42:55 +0200
+Subject: s390/cpacf: get rid of register asm
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit b84d0c417a5ac1eb820c8114c0c7cf1fcbf6f017 ]
+
+Using register asm statements has been proven to be very error prone,
+especially when using code instrumentation where gcc may add function
+calls, which clobbers register contents in an unexpected way.
+
+Therefore get rid of register asm statements in cpacf code, and make
+sure this bug class cannot happen.
+
+Reviewed-by: Patrick Steuer <patrick.steuer@de.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Stable-dep-of: 830999bd7e72 ("s390/cpacf: Split and rework cpacf query functions")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/cpacf.h | 208 ++++++++++++++++++----------------
+ 1 file changed, 111 insertions(+), 97 deletions(-)
+
+diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h
+index c0f3bfeddcbeb..646b12981f208 100644
+--- a/arch/s390/include/asm/cpacf.h
++++ b/arch/s390/include/asm/cpacf.h
+@@ -173,17 +173,16 @@ typedef struct { unsigned char bytes[16]; } cpacf_mask_t;
+  */
+ static __always_inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
+ {
+-      register unsigned long r0 asm("0") = 0; /* query function */
+-      register unsigned long r1 asm("1") = (unsigned long) mask;
+-
+       asm volatile(
+-              "       spm 0\n" /* pckmo doesn't change the cc */
++              "       lghi    0,0\n" /* query function */
++              "       lgr     1,%[mask]\n"
++              "       spm     0\n" /* pckmo doesn't change the cc */
+               /* Parameter regs are ignored, but must be nonzero and unique */
+               "0:     .insn   rrf,%[opc] << 16,2,4,6,0\n"
+               "       brc     1,0b\n" /* handle partial completion */
+               : "=m" (*mask)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (opcode)
+-              : "cc");
++              : [mask] "d" ((unsigned long)mask), [opc] "i" (opcode)
++              : "cc", "0", "1");
+ }
+ static __always_inline int __cpacf_check_opcode(unsigned int opcode)
+@@ -249,20 +248,22 @@ static __always_inline int cpacf_query_func(unsigned int opcode, unsigned int fu
+ static inline int cpacf_km(unsigned long func, void *param,
+                          u8 *dest, const u8 *src, long src_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
+-      register unsigned long r4 asm("4") = (unsigned long) dest;
++      union register_pair d, s;
++      d.even = (unsigned long)dest;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,%[dst],%[src]\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KM)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair), [dst] "+&d" (d.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KM)
++              : "cc", "memory", "0", "1");
+-      return src_len - r3;
++      return src_len - s.odd;
+ }
+ /**
+@@ -279,20 +280,22 @@ static inline int cpacf_km(unsigned long func, void *param,
+ static inline int cpacf_kmc(unsigned long func, void *param,
+                           u8 *dest, const u8 *src, long src_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
+-      register unsigned long r4 asm("4") = (unsigned long) dest;
++      union register_pair d, s;
++      d.even = (unsigned long)dest;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,%[dst],%[src]\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMC)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair), [dst] "+&d" (d.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KMC)
++              : "cc", "memory", "0", "1");
+-      return src_len - r3;
++      return src_len - s.odd;
+ }
+ /**
+@@ -306,17 +309,19 @@ static inline int cpacf_kmc(unsigned long func, void *param,
+ static inline void cpacf_kimd(unsigned long func, void *param,
+                             const u8 *src, long src_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
++      union register_pair s;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,0,%[src]\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KIMD)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)(param)),
++                [opc] "i" (CPACF_KIMD)
++              : "cc", "memory", "0", "1");
+ }
+ /**
+@@ -329,17 +334,19 @@ static inline void cpacf_kimd(unsigned long func, void *param,
+ static inline void cpacf_klmd(unsigned long func, void *param,
+                             const u8 *src, long src_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
++      union register_pair s;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,0,%[src]\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KLMD)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KLMD)
++              : "cc", "memory", "0", "1");
+ }
+ /**
+@@ -355,19 +362,21 @@ static inline void cpacf_klmd(unsigned long func, void *param,
+ static inline int cpacf_kmac(unsigned long func, void *param,
+                            const u8 *src, long src_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
++      union register_pair s;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,0,%[src]\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMAC)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KMAC)
++              : "cc", "memory", "0", "1");
+-      return src_len - r3;
++      return src_len - s.odd;
+ }
+ /**
+@@ -385,22 +394,24 @@ static inline int cpacf_kmac(unsigned long func, void *param,
+ static inline int cpacf_kmctr(unsigned long func, void *param, u8 *dest,
+                             const u8 *src, long src_len, u8 *counter)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
+-      register unsigned long r4 asm("4") = (unsigned long) dest;
+-      register unsigned long r6 asm("6") = (unsigned long) counter;
++      union register_pair d, s, c;
++      d.even = (unsigned long)dest;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
++      c.even = (unsigned long)counter;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rrf,%[opc] << 16,%[dst],%[src],%[ctr],0\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [src] "+a" (r2), [len] "+d" (r3),
+-                [dst] "+a" (r4), [ctr] "+a" (r6)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMCTR)
+-              : "cc", "memory");
++              : [src] "+&d" (s.pair), [dst] "+&d" (d.pair),
++                [ctr] "+&d" (c.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KMCTR)
++              : "cc", "memory", "0", "1");
+-      return src_len - r3;
++      return src_len - s.odd;
+ }
+ /**
+@@ -417,20 +428,21 @@ static inline void cpacf_prno(unsigned long func, void *param,
+                             u8 *dest, unsigned long dest_len,
+                             const u8 *seed, unsigned long seed_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) dest;
+-      register unsigned long r3 asm("3") = (unsigned long) dest_len;
+-      register unsigned long r4 asm("4") = (unsigned long) seed;
+-      register unsigned long r5 asm("5") = (unsigned long) seed_len;
++      union register_pair d, s;
++      d.even = (unsigned long)dest;
++      d.odd  = (unsigned long)dest_len;
++      s.even = (unsigned long)seed;
++      s.odd  = (unsigned long)seed_len;
+       asm volatile (
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,%[dst],%[seed]\n"
+               "       brc     1,0b\n"   /* handle partial completion */
+-              : [dst] "+a" (r2), [dlen] "+d" (r3)
+-              : [fc] "d" (r0), [pba] "a" (r1),
+-                [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PRNO)
+-              : "cc", "memory");
++              : [dst] "+&d" (d.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [seed] "d" (s.pair), [opc] "i" (CPACF_PRNO)
++              : "cc", "memory", "0", "1");
+ }
+ /**
+@@ -443,19 +455,19 @@ static inline void cpacf_prno(unsigned long func, void *param,
+ static inline void cpacf_trng(u8 *ucbuf, unsigned long ucbuf_len,
+                             u8 *cbuf, unsigned long cbuf_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) CPACF_PRNO_TRNG;
+-      register unsigned long r2 asm("2") = (unsigned long) ucbuf;
+-      register unsigned long r3 asm("3") = (unsigned long) ucbuf_len;
+-      register unsigned long r4 asm("4") = (unsigned long) cbuf;
+-      register unsigned long r5 asm("5") = (unsigned long) cbuf_len;
++      union register_pair u, c;
++      u.even = (unsigned long)ucbuf;
++      u.odd  = (unsigned long)ucbuf_len;
++      c.even = (unsigned long)cbuf;
++      c.odd  = (unsigned long)cbuf_len;
+       asm volatile (
++              "       lghi    0,%[fc]\n"
+               "0:     .insn   rre,%[opc] << 16,%[ucbuf],%[cbuf]\n"
+               "       brc     1,0b\n"   /* handle partial completion */
+-              : [ucbuf] "+a" (r2), [ucbuflen] "+d" (r3),
+-                [cbuf] "+a" (r4), [cbuflen] "+d" (r5)
+-              : [fc] "d" (r0), [opc] "i" (CPACF_PRNO)
+-              : "cc", "memory");
++              : [ucbuf] "+&d" (u.pair), [cbuf] "+&d" (c.pair)
++              : [fc] "K" (CPACF_PRNO_TRNG), [opc] "i" (CPACF_PRNO)
++              : "cc", "memory", "0");
+ }
+ /**
+@@ -466,15 +478,15 @@ static inline void cpacf_trng(u8 *ucbuf, unsigned long ucbuf_len,
+  */
+ static inline void cpacf_pcc(unsigned long func, void *param)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rre,%[opc] << 16,0,0\n" /* PCC opcode */
+               "       brc     1,0b\n" /* handle partial completion */
+               :
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCC)
+-              : "cc", "memory");
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_PCC)
++              : "cc", "memory", "0", "1");
+ }
+ /**
+@@ -487,14 +499,14 @@ static inline void cpacf_pcc(unsigned long func, void *param)
+  */
+ static inline void cpacf_pckmo(long func, void *param)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "       .insn   rre,%[opc] << 16,0,0\n" /* PCKMO opcode */
+               :
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCKMO)
+-              : "cc", "memory");
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_PCKMO)
++              : "cc", "memory", "0", "1");
+ }
+ /**
+@@ -512,21 +524,23 @@ static inline void cpacf_kma(unsigned long func, void *param, u8 *dest,
+                            const u8 *src, unsigned long src_len,
+                            const u8 *aad, unsigned long aad_len)
+ {
+-      register unsigned long r0 asm("0") = (unsigned long) func;
+-      register unsigned long r1 asm("1") = (unsigned long) param;
+-      register unsigned long r2 asm("2") = (unsigned long) src;
+-      register unsigned long r3 asm("3") = (unsigned long) src_len;
+-      register unsigned long r4 asm("4") = (unsigned long) aad;
+-      register unsigned long r5 asm("5") = (unsigned long) aad_len;
+-      register unsigned long r6 asm("6") = (unsigned long) dest;
++      union register_pair d, s, a;
++      d.even = (unsigned long)dest;
++      s.even = (unsigned long)src;
++      s.odd  = (unsigned long)src_len;
++      a.even = (unsigned long)aad;
++      a.odd  = (unsigned long)aad_len;
+       asm volatile(
++              "       lgr     0,%[fc]\n"
++              "       lgr     1,%[pba]\n"
+               "0:     .insn   rrf,%[opc] << 16,%[dst],%[src],%[aad],0\n"
+               "       brc     1,0b\n" /* handle partial completion */
+-              : [dst] "+a" (r6), [src] "+a" (r2), [slen] "+d" (r3),
+-                [aad] "+a" (r4), [alen] "+d" (r5)
+-              : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMA)
+-              : "cc", "memory");
++              : [dst] "+&d" (d.pair), [src] "+&d" (s.pair),
++                [aad] "+&d" (a.pair)
++              : [fc] "d" (func), [pba] "d" ((unsigned long)param),
++                [opc] "i" (CPACF_KMA)
++              : "cc", "memory", "0", "1");
+ }
+ #endif        /* _ASM_S390_CPACF_H */
+-- 
+2.43.0
+
diff --git a/queue-5.4/s390-cpacf-split-and-rework-cpacf-query-functions.patch b/queue-5.4/s390-cpacf-split-and-rework-cpacf-query-functions.patch
new file mode 100644 (file)
index 0000000..ddff237
--- /dev/null
@@ -0,0 +1,152 @@
+From 4a9ecd61be4df446ea9b2b865e172d434da8deb5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 May 2024 11:31:42 +0200
+Subject: s390/cpacf: Split and rework cpacf query functions
+
+From: Harald Freudenberger <freude@linux.ibm.com>
+
+[ Upstream commit 830999bd7e72f4128b9dfa37090d9fa8120ce323 ]
+
+Rework the cpacf query functions to use the correct RRE
+or RRF instruction formats and set register fields within
+instructions correctly.
+
+Fixes: 1afd43e0fbba ("s390/crypto: allow to query all known cpacf functions")
+Reported-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
+Suggested-by: Heiko Carstens <hca@linux.ibm.com>
+Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
+Suggested-by: Holger Dengler <dengler@linux.ibm.com>
+Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
+Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
+Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/cpacf.h | 101 +++++++++++++++++++++++++++-------
+ 1 file changed, 81 insertions(+), 20 deletions(-)
+
+diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h
+index 646b12981f208..fa31f71cf5746 100644
+--- a/arch/s390/include/asm/cpacf.h
++++ b/arch/s390/include/asm/cpacf.h
+@@ -161,28 +161,79 @@
+ typedef struct { unsigned char bytes[16]; } cpacf_mask_t;
+-/**
+- * cpacf_query() - check if a specific CPACF function is available
+- * @opcode: the opcode of the crypto instruction
+- * @func: the function code to test for
+- *
+- * Executes the query function for the given crypto instruction @opcode
+- * and checks if @func is available
+- *
+- * Returns 1 if @func is available for @opcode, 0 otherwise
+- */
+-static __always_inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
++static __always_inline void __cpacf_query_rre(u32 opc, u8 r1, u8 r2,
++                                            cpacf_mask_t *mask)
+ {
+       asm volatile(
+-              "       lghi    0,0\n" /* query function */
+-              "       lgr     1,%[mask]\n"
+-              "       spm     0\n" /* pckmo doesn't change the cc */
+-              /* Parameter regs are ignored, but must be nonzero and unique */
+-              "0:     .insn   rrf,%[opc] << 16,2,4,6,0\n"
+-              "       brc     1,0b\n" /* handle partial completion */
+-              : "=m" (*mask)
+-              : [mask] "d" ((unsigned long)mask), [opc] "i" (opcode)
+-              : "cc", "0", "1");
++              "       la      %%r1,%[mask]\n"
++              "       xgr     %%r0,%%r0\n"
++              "       .insn   rre,%[opc] << 16,%[r1],%[r2]\n"
++              : [mask] "=R" (*mask)
++              : [opc] "i" (opc),
++                [r1] "i" (r1), [r2] "i" (r2)
++              : "cc", "r0", "r1");
++}
++
++static __always_inline void __cpacf_query_rrf(u32 opc,
++                                            u8 r1, u8 r2, u8 r3, u8 m4,
++                                            cpacf_mask_t *mask)
++{
++      asm volatile(
++              "       la      %%r1,%[mask]\n"
++              "       xgr     %%r0,%%r0\n"
++              "       .insn   rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]\n"
++              : [mask] "=R" (*mask)
++              : [opc] "i" (opc), [r1] "i" (r1), [r2] "i" (r2),
++                [r3] "i" (r3), [m4] "i" (m4)
++              : "cc", "r0", "r1");
++}
++
++static __always_inline void __cpacf_query(unsigned int opcode,
++                                        cpacf_mask_t *mask)
++{
++      switch (opcode) {
++      case CPACF_KDSA:
++              __cpacf_query_rre(CPACF_KDSA, 0, 2, mask);
++              break;
++      case CPACF_KIMD:
++              __cpacf_query_rre(CPACF_KIMD, 0, 2, mask);
++              break;
++      case CPACF_KLMD:
++              __cpacf_query_rre(CPACF_KLMD, 0, 2, mask);
++              break;
++      case CPACF_KM:
++              __cpacf_query_rre(CPACF_KM, 2, 4, mask);
++              break;
++      case CPACF_KMA:
++              __cpacf_query_rrf(CPACF_KMA, 2, 4, 6, 0, mask);
++              break;
++      case CPACF_KMAC:
++              __cpacf_query_rre(CPACF_KMAC, 0, 2, mask);
++              break;
++      case CPACF_KMC:
++              __cpacf_query_rre(CPACF_KMC, 2, 4, mask);
++              break;
++      case CPACF_KMCTR:
++              __cpacf_query_rrf(CPACF_KMCTR, 2, 4, 6, 0, mask);
++              break;
++      case CPACF_KMF:
++              __cpacf_query_rre(CPACF_KMF, 2, 4, mask);
++              break;
++      case CPACF_KMO:
++              __cpacf_query_rre(CPACF_KMO, 2, 4, mask);
++              break;
++      case CPACF_PCC:
++              __cpacf_query_rre(CPACF_PCC, 0, 0, mask);
++              break;
++      case CPACF_PCKMO:
++              __cpacf_query_rre(CPACF_PCKMO, 0, 0, mask);
++              break;
++      case CPACF_PRNO:
++              __cpacf_query_rre(CPACF_PRNO, 2, 4, mask);
++              break;
++      default:
++              BUG();
++      }
+ }
+ static __always_inline int __cpacf_check_opcode(unsigned int opcode)
+@@ -210,6 +261,16 @@ static __always_inline int __cpacf_check_opcode(unsigned int opcode)
+       }
+ }
++/**
++ * cpacf_query() - check if a specific CPACF function is available
++ * @opcode: the opcode of the crypto instruction
++ * @func: the function code to test for
++ *
++ * Executes the query function for the given crypto instruction @opcode
++ * and checks if @func is available
++ *
++ * Returns 1 if @func is available for @opcode, 0 otherwise
++ */
+ static __always_inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
+ {
+       if (__cpacf_check_opcode(opcode)) {
+-- 
+2.43.0
+
diff --git a/queue-5.4/selftests-mm-compaction_test-fix-bogus-test-success-.patch b/queue-5.4/selftests-mm-compaction_test-fix-bogus-test-success-.patch
new file mode 100644 (file)
index 0000000..097b6f9
--- /dev/null
@@ -0,0 +1,109 @@
+From 7fb9fe70fa9377ba39c88b68f9d22245c005f2cd 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 6be4b70a26592..b5587a751664a 100644
+--- a/tools/testing/selftests/vm/compaction_test.c
++++ b/tools/testing/selftests/vm/compaction_test.c
+@@ -81,12 +81,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 */
+@@ -135,7 +136,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);
+@@ -146,11 +152,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
+
diff --git a/queue-5.4/selftests-mm-compaction_test-fix-incorrect-write-of-.patch b/queue-5.4/selftests-mm-compaction_test-fix-incorrect-write-of-.patch
new file mode 100644 (file)
index 0000000..d3cf12c
--- /dev/null
@@ -0,0 +1,43 @@
+From b27c987ca6e06c83461fe53785a3fa931ddace63 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 bcec712508731..cb2db2102dd26 100644
+--- a/tools/testing/selftests/vm/compaction_test.c
++++ b/tools/testing/selftests/vm/compaction_test.c
+@@ -102,6 +102,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
+
diff --git a/queue-5.4/selftests-mm-conform-test-to-tap-format-output.patch b/queue-5.4/selftests-mm-conform-test-to-tap-format-output.patch
new file mode 100644 (file)
index 0000000..53faf8c
--- /dev/null
@@ -0,0 +1,229 @@
+From 708b734cb2987c3c6283284440be164f463e6e0d 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 cb2db2102dd26..43f5044b23c57 100644
+--- a/tools/testing/selftests/vm/compaction_test.c
++++ b/tools/testing/selftests/vm/compaction_test.c
+@@ -32,7 +32,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;
+       }
+@@ -43,7 +43,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;
+       }
+@@ -61,14 +61,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;
+       }
+@@ -77,12 +77,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};
+@@ -93,12 +94,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;
+       }
+@@ -106,7 +109,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;
+       }
+@@ -115,14 +119,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;
+       }
+@@ -130,67 +136,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;
+       unsigned long mem_fragmentable = 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 = mem_free * 0.8 / 1024;
+@@ -226,7 +223,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
+
diff --git a/queue-5.4/selftests-mm-log-a-consistent-test-name-for-check_co.patch b/queue-5.4/selftests-mm-log-a-consistent-test-name-for-check_co.patch
new file mode 100644 (file)
index 0000000..0169621
--- /dev/null
@@ -0,0 +1,124 @@
+From b97247d12bfda0ea6dc5ebf3ac5f13750ab1f72c 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 43f5044b23c57..6be4b70a26592 100644
+--- a/tools/testing/selftests/vm/compaction_test.c
++++ b/tools/testing/selftests/vm/compaction_test.c
+@@ -94,14 +94,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;
+       }
+@@ -109,8 +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)) {
+-              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;
+       }
+@@ -119,16 +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))) {
+-              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;
+       }
+@@ -140,24 +141,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
+
diff --git a/queue-5.4/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch b/queue-5.4/serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch
new file mode 100644 (file)
index 0000000..31521ae
--- /dev/null
@@ -0,0 +1,96 @@
+From d84e25a757a22eabc2a76ef09058567f109c90e9 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 fad8d1f744466..8fb47f73cc7ad 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -489,16 +489,28 @@ static bool sc16is7xx_regmap_precious(struct device *dev, unsigned int reg)
+       return false;
+ }
++/*
++ * 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
+@@ -533,9 +545,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,
+@@ -550,7 +563,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
+
diff --git a/queue-5.4/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch b/queue-5.4/serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch
new file mode 100644 (file)
index 0000000..92a6e38
--- /dev/null
@@ -0,0 +1,39 @@
+From 9f8594fb85e36299743263764f8cfc02e988f02b 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 892e27cddb0ff..fad8d1f744466 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -496,7 +496,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
+
index c66285555870467e4293ea63d8c7f4d36dd28b74..94e67185f20bb56d4c64c4d392e93cb1a34655e7 100644 (file)
@@ -191,3 +191,52 @@ sparc-move-struct-termio-to-asm-termios.h.patch
 ext4-fix-mb_cache_entry-s-e_refcnt-leak-in-ext4_xattr_block_cache_find.patch
 s390-ap-fix-crash-in-ap-internal-function-modify_bitmap.patch
 nfs-fix-undefined-behavior-in-nfs_block_bits.patch
+wifi-mac80211-mesh-fix-leak-of-mesh_preq_queue-objec.patch
+wifi-mac80211-fix-deadlock-in-ieee80211_sta_ps_deliv.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-don-t-read-past-the-mfuart-notifcat.patch
+nl80211-extend-support-to-config-spatial-reuse-param.patch
+wifi-mac80211-correctly-parse-spatial-reuse-paramete.patch
+ipv6-sr-block-bh-in-seg6_output_core-and-seg6_input_.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-mlx5-stop-waiting-for-pci-if-pci-channel-is-offl.patch
+net-sched-taprio-always-validate-tca_taprio_attr_pri.patch
+ptp-fix-error-message-on-failed-pin-verification.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
+af_unix-annotate-data-races-around-sk-sk_state-in-se.patch
+af_unix-annotate-data-races-around-sk-sk_state-in-un.patch-4923
+af_unix-annotate-data-race-of-net-unx.sysctl_max_dgr.patch
+af_unix-use-unix_recvq_full_lockless-in-unix_stream_.patch
+arm64-dts-agilex-add-nand-ip-to-base-dts.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-remove-likely-unlikely.patch
+usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-.patch
+asoc-ti-davinci-mcasp-remove-redundant-assignment-to.patch
+asoc-ti-davinci-mcasp-remove-always-zero-of-davinci_.patch
+asoc-ti-davinci-mcasp-use-platform_get_irq_byname_op.patch
+asoc-ti-davinci-mcasp-remove-legacy-dma_request-pars.patch
+asoc-ti-davinci-mcasp-simplify-the-configuration-par.patch
+asoc-ti-davinci-mcasp-handle-missing-required-dt-pro.patch
+asoc-ti-davinci-mcasp-fix-race-condition-during-prob.patch
+drm-amd-display-handle-y-carry-over-in-vcp-x.y-calcu.patch
+serial-sc16is7xx-replace-hardcoded-divisor-value-wit.patch
+serial-sc16is7xx-fix-bug-in-sc16is7xx_set_baud-when-.patch
+drivers-core-reindent-a-couple-uses-around-sysfs_emi.patch
+mmc-davinci_mmc-convert-to-platform-remove-callback-.patch
+mmc-davinci-don-t-strip-remove-function-when-driver-.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
+s390-cpacf-get-rid-of-register-asm.patch
+s390-cpacf-split-and-rework-cpacf-query-functions.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
diff --git a/queue-5.4/tcp-count-close-wait-sockets-for-tcp_mib_currestab.patch b/queue-5.4/tcp-count-close-wait-sockets-for-tcp_mib_currestab.patch
new file mode 100644 (file)
index 0000000..8c0b52e
--- /dev/null
@@ -0,0 +1,71 @@
+From 9ae5b8da8f7c066c6fd7e6c1da743fa6fe7f785d 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 9a4a3f6d9cb06..a181eb7d6d438 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2258,6 +2258,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)
+@@ -2269,7 +2273,7 @@ void tcp_set_state(struct sock *sk, int state)
+                       inet_put_port(sk);
+               /* fall through */
+       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
+
diff --git a/queue-5.4/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-.patch b/queue-5.4/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-.patch
new file mode 100644 (file)
index 0000000..00b4bfe
--- /dev/null
@@ -0,0 +1,86 @@
+From e90eccd29725720b3e66055421f94a6c45c9ea89 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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
+index 1a8249bc5f715..123cdac5cee64 100644
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -827,6 +827,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
+       int ret = io_data->req->status ? io_data->req->status :
+                                        io_data->req->actual;
+       bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
++      unsigned long flags;
+       if (io_data->read && ret > 0) {
+               mm_segment_t oldfs = get_fs();
+@@ -843,7 +844,10 @@ 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);
+-- 
+2.43.0
+
diff --git a/queue-5.4/usb-gadget-f_fs-remove-likely-unlikely.patch b/queue-5.4/usb-gadget-f_fs-remove-likely-unlikely.patch
new file mode 100644 (file)
index 0000000..0545fbf
--- /dev/null
@@ -0,0 +1,740 @@
+From eb78f6f3dbb11612afcd8a66e3a36699a6d174b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Nov 2020 15:05:59 +0100
+Subject: USB: gadget: f_fs: remove likely/unlikely
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 8704fd73bf5658bf4b827643f7f526481082d83f ]
+
+They are used way too often in this file, in some ways that are actually
+wrong.  Almost all of these are already known by the compiler and CPU so
+just remove them all as none of these should be on any "hot paths" where
+it actually matters.
+
+Cc: Felipe Balbi <balbi@kernel.org>
+Reported-by: Peter Chen <peter.chen@nxp.com>
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Link: https://lore.kernel.org/r/20201127140559.381351-6-gregkh@linuxfoundation.org
+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 | 177 ++++++++++++++---------------
+ 1 file changed, 88 insertions(+), 89 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
+index 1cf4f4bee019b..1a8249bc5f715 100644
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -301,11 +301,11 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
+       reinit_completion(&ffs->ep0req_completion);
+       ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC);
+-      if (unlikely(ret < 0))
++      if (ret < 0)
+               return ret;
+       ret = wait_for_completion_interruptible(&ffs->ep0req_completion);
+-      if (unlikely(ret)) {
++      if (ret) {
+               usb_ep_dequeue(ffs->gadget->ep0, req);
+               return -EINTR;
+       }
+@@ -342,7 +342,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
+       /* Acquire mutex */
+       ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
+-      if (unlikely(ret < 0))
++      if (ret < 0)
+               return ret;
+       /* Check state */
+@@ -350,7 +350,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
+       case FFS_READ_DESCRIPTORS:
+       case FFS_READ_STRINGS:
+               /* Copy data */
+-              if (unlikely(len < 16)) {
++              if (len < 16) {
+                       ret = -EINVAL;
+                       break;
+               }
+@@ -365,7 +365,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
+               if (ffs->state == FFS_READ_DESCRIPTORS) {
+                       pr_info("read descriptors\n");
+                       ret = __ffs_data_got_descs(ffs, data, len);
+-                      if (unlikely(ret < 0))
++                      if (ret < 0)
+                               break;
+                       ffs->state = FFS_READ_STRINGS;
+@@ -373,11 +373,11 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
+               } else {
+                       pr_info("read strings\n");
+                       ret = __ffs_data_got_strings(ffs, data, len);
+-                      if (unlikely(ret < 0))
++                      if (ret < 0)
+                               break;
+                       ret = ffs_epfiles_create(ffs);
+-                      if (unlikely(ret)) {
++                      if (ret) {
+                               ffs->state = FFS_CLOSING;
+                               break;
+                       }
+@@ -386,7 +386,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
+                       mutex_unlock(&ffs->mutex);
+                       ret = ffs_ready(ffs);
+-                      if (unlikely(ret < 0)) {
++                      if (ret < 0) {
+                               ffs->state = FFS_CLOSING;
+                               return ret;
+                       }
+@@ -500,7 +500,7 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
+       spin_unlock_irq(&ffs->ev.waitq.lock);
+       mutex_unlock(&ffs->mutex);
+-      return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
++      return copy_to_user(buf, events, size) ? -EFAULT : size;
+ }
+ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
+@@ -519,7 +519,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
+       /* Acquire mutex */
+       ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
+-      if (unlikely(ret < 0))
++      if (ret < 0)
+               return ret;
+       /* Check state */
+@@ -541,7 +541,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
+       case FFS_NO_SETUP:
+               n = len / sizeof(struct usb_functionfs_event);
+-              if (unlikely(!n)) {
++              if (!n) {
+                       ret = -EINVAL;
+                       break;
+               }
+@@ -572,9 +572,9 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
+               spin_unlock_irq(&ffs->ev.waitq.lock);
+-              if (likely(len)) {
++              if (len) {
+                       data = kmalloc(len, GFP_KERNEL);
+-                      if (unlikely(!data)) {
++                      if (!data) {
+                               ret = -ENOMEM;
+                               goto done_mutex;
+                       }
+@@ -591,7 +591,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
+               /* unlocks spinlock */
+               ret = __ffs_ep0_queue_wait(ffs, data, len);
+-              if (likely(ret > 0) && unlikely(copy_to_user(buf, data, len)))
++              if ((ret > 0) && (copy_to_user(buf, data, len)))
+                       ret = -EFAULT;
+               goto done_mutex;
+@@ -613,7 +613,7 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
+       ENTER();
+-      if (unlikely(ffs->state == FFS_CLOSING))
++      if (ffs->state == FFS_CLOSING)
+               return -EBUSY;
+       file->private_data = ffs;
+@@ -662,7 +662,7 @@ static __poll_t ffs_ep0_poll(struct file *file, poll_table *wait)
+       poll_wait(file, &ffs->ev.waitq, wait);
+       ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK);
+-      if (unlikely(ret < 0))
++      if (ret < 0)
+               return mask;
+       switch (ffs->state) {
+@@ -711,7 +711,7 @@ static const struct file_operations ffs_ep0_operations = {
+ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
+ {
+       ENTER();
+-      if (likely(req->context)) {
++      if (req->context) {
+               struct ffs_ep *ep = _ep->driver_data;
+               ep->status = req->status ? req->status : req->actual;
+               complete(req->context);
+@@ -721,10 +721,10 @@ static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
+ static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter)
+ {
+       ssize_t ret = copy_to_iter(data, data_len, iter);
+-      if (likely(ret == data_len))
++      if (ret == data_len)
+               return ret;
+-      if (unlikely(iov_iter_count(iter)))
++      if (iov_iter_count(iter))
+               return -EFAULT;
+       /*
+@@ -894,7 +894,7 @@ static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
+               return ret;
+       }
+-      if (unlikely(iov_iter_count(iter))) {
++      if (iov_iter_count(iter)) {
+               ret = -EFAULT;
+       } else {
+               buf->length -= ret;
+@@ -915,10 +915,10 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
+       struct ffs_buffer *buf;
+       ssize_t ret = copy_to_iter(data, data_len, iter);
+-      if (likely(data_len == ret))
++      if (data_len == ret)
+               return ret;
+-      if (unlikely(iov_iter_count(iter)))
++      if (iov_iter_count(iter))
+               return -EFAULT;
+       /* See ffs_copy_to_iter for more context. */
+@@ -939,7 +939,7 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
+        * in struct ffs_epfile for full read_buffer pointer synchronisation
+        * story.
+        */
+-      if (unlikely(cmpxchg(&epfile->read_buffer, NULL, buf)))
++      if (cmpxchg(&epfile->read_buffer, NULL, buf))
+               kfree(buf);
+       return ret;
+@@ -977,7 +977,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+       /* We will be using request and read_buffer */
+       ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
+-      if (unlikely(ret))
++      if (ret)
+               goto error;
+       /* Allocate & copy */
+@@ -1022,7 +1022,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+               spin_unlock_irq(&epfile->ffs->eps_lock);
+               data = ffs_alloc_buffer(io_data, data_len);
+-              if (unlikely(!data)) {
++              if (!data) {
+                       ret = -ENOMEM;
+                       goto error_mutex;
+               }
+@@ -1042,7 +1042,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+               ret = usb_ep_set_halt(ep->ep);
+               if (!ret)
+                       ret = -EBADMSG;
+-      } else if (unlikely(data_len == -EINVAL)) {
++      } else if (data_len == -EINVAL) {
+               /*
+                * Sanity Check: even though data_len can't be used
+                * uninitialized at the time I write this comment, some
+@@ -1077,12 +1077,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+               req->complete = ffs_epfile_io_complete;
+               ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
+-              if (unlikely(ret < 0))
++              if (ret < 0)
+                       goto error_lock;
+               spin_unlock_irq(&epfile->ffs->eps_lock);
+-              if (unlikely(wait_for_completion_interruptible(&done))) {
++              if (wait_for_completion_interruptible(&done)) {
+                       /*
+                        * To avoid race condition with ffs_epfile_io_complete,
+                        * dequeue the request first then check
+@@ -1124,7 +1124,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+               req->complete = ffs_epfile_async_io_complete;
+               ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
+-              if (unlikely(ret)) {
++              if (ret) {
+                       io_data->req = NULL;
+                       usb_ep_free_request(ep->ep, req);
+                       goto error_lock;
+@@ -1175,7 +1175,7 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
+       spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
+-      if (likely(io_data && io_data->ep && io_data->req))
++      if (io_data && io_data->ep && io_data->req)
+               value = usb_ep_dequeue(io_data->ep, io_data->req);
+       else
+               value = -EINVAL;
+@@ -1194,7 +1194,7 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from)
+       if (!is_sync_kiocb(kiocb)) {
+               p = kzalloc(sizeof(io_data), GFP_KERNEL);
+-              if (unlikely(!p))
++              if (!p)
+                       return -ENOMEM;
+               p->aio = true;
+       } else {
+@@ -1231,7 +1231,7 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
+       if (!is_sync_kiocb(kiocb)) {
+               p = kzalloc(sizeof(io_data), GFP_KERNEL);
+-              if (unlikely(!p))
++              if (!p)
+                       return -ENOMEM;
+               p->aio = true;
+       } else {
+@@ -1405,7 +1405,7 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
+       inode = new_inode(sb);
+-      if (likely(inode)) {
++      if (inode) {
+               struct timespec64 ts = current_time(inode);
+               inode->i_ino     = get_next_ino();
+@@ -1437,11 +1437,11 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
+       ENTER();
+       dentry = d_alloc_name(sb->s_root, name);
+-      if (unlikely(!dentry))
++      if (!dentry)
+               return NULL;
+       inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms);
+-      if (unlikely(!inode)) {
++      if (!inode) {
+               dput(dentry);
+               return NULL;
+       }
+@@ -1488,12 +1488,11 @@ static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc)
+                                 &simple_dir_inode_operations,
+                                 &data->perms);
+       sb->s_root = d_make_root(inode);
+-      if (unlikely(!sb->s_root))
++      if (!sb->s_root)
+               return -ENOMEM;
+       /* EP0 file */
+-      if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
+-                                       &ffs_ep0_operations)))
++      if (!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations))
+               return -ENOMEM;
+       return 0;
+@@ -1586,13 +1585,13 @@ static int ffs_fs_get_tree(struct fs_context *fc)
+               return invalf(fc, "No source specified");
+       ffs = ffs_data_new(fc->source);
+-      if (unlikely(!ffs))
++      if (!ffs)
+               return -ENOMEM;
+       ffs->file_perms = ctx->perms;
+       ffs->no_disconnect = ctx->no_disconnect;
+       ffs->dev_name = kstrdup(fc->source, GFP_KERNEL);
+-      if (unlikely(!ffs->dev_name)) {
++      if (!ffs->dev_name) {
+               ffs_data_put(ffs);
+               return -ENOMEM;
+       }
+@@ -1674,7 +1673,7 @@ static int functionfs_init(void)
+       ENTER();
+       ret = register_filesystem(&ffs_fs_type);
+-      if (likely(!ret))
++      if (!ret)
+               pr_info("file system registered\n");
+       else
+               pr_err("failed registering file system (%d)\n", ret);
+@@ -1719,7 +1718,7 @@ static void ffs_data_put(struct ffs_data *ffs)
+ {
+       ENTER();
+-      if (unlikely(refcount_dec_and_test(&ffs->ref))) {
++      if (refcount_dec_and_test(&ffs->ref)) {
+               pr_info("%s(): freeing\n", __func__);
+               ffs_data_clear(ffs);
+               ffs_release_dev(ffs->private_data);
+@@ -1770,7 +1769,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
+ static struct ffs_data *ffs_data_new(const char *dev_name)
+ {
+       struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
+-      if (unlikely(!ffs))
++      if (!ffs)
+               return NULL;
+       ENTER();
+@@ -1876,11 +1875,11 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
+               return -EBADFD;
+       first_id = usb_string_ids_n(cdev, ffs->strings_count);
+-      if (unlikely(first_id < 0))
++      if (first_id < 0)
+               return first_id;
+       ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
+-      if (unlikely(!ffs->ep0req))
++      if (!ffs->ep0req)
+               return -ENOMEM;
+       ffs->ep0req->complete = ffs_ep0_complete;
+       ffs->ep0req->context = ffs;
+@@ -1940,7 +1939,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
+               epfile->dentry = ffs_sb_create_file(ffs->sb, epfile->name,
+                                                epfile,
+                                                &ffs_epfile_operations);
+-              if (unlikely(!epfile->dentry)) {
++              if (!epfile->dentry) {
+                       ffs_epfiles_destroy(epfiles, i - 1);
+                       return -ENOMEM;
+               }
+@@ -1981,7 +1980,7 @@ static void ffs_func_eps_disable(struct ffs_function *func)
+       ep = func->eps;
+       while (count--) {
+               /* pending requests get nuked */
+-              if (likely(ep->ep))
++              if (ep->ep)
+                       usb_ep_disable(ep->ep);
+               ++ep;
+@@ -2019,7 +2018,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
+               }
+               ret = usb_ep_enable(ep->ep);
+-              if (likely(!ret)) {
++              if (!ret) {
+                       epfile->ep = ep;
+                       epfile->in = usb_endpoint_dir_in(ep->ep->desc);
+                       epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc);
+@@ -2092,12 +2091,12 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len,
+ #define __entity_check_ENDPOINT(val)   ((val) & USB_ENDPOINT_NUMBER_MASK)
+ #define __entity(type, val) do {                                      \
+               pr_vdebug("entity " #type "(%02x)\n", (val));           \
+-              if (unlikely(!__entity_check_ ##type(val))) {           \
++              if (!__entity_check_ ##type(val)) {                     \
+                       pr_vdebug("invalid entity's value\n");          \
+                       return -EINVAL;                                 \
+               }                                                       \
+               ret = entity(FFS_ ##type, &val, _ds, priv);             \
+-              if (unlikely(ret < 0)) {                                \
++              if (ret < 0) {                                          \
+                       pr_debug("entity " #type "(%02x); ret = %d\n",  \
+                                (val), ret);                           \
+                       return ret;                                     \
+@@ -2222,7 +2221,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
+               /* Record "descriptor" entity */
+               ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv);
+-              if (unlikely(ret < 0)) {
++              if (ret < 0) {
+                       pr_debug("entity DESCRIPTOR(%02lx); ret = %d\n",
+                                num, ret);
+                       return ret;
+@@ -2233,7 +2232,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
+               ret = ffs_do_single_desc(data, len, entity, priv,
+                       &current_class);
+-              if (unlikely(ret < 0)) {
++              if (ret < 0) {
+                       pr_debug("%s returns %d\n", __func__, ret);
+                       return ret;
+               }
+@@ -2339,7 +2338,7 @@ static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
+       /* loop over all ext compat/ext prop descriptors */
+       while (feature_count--) {
+               ret = entity(type, h, data, len, priv);
+-              if (unlikely(ret < 0)) {
++              if (ret < 0) {
+                       pr_debug("bad OS descriptor, type: %d\n", type);
+                       return ret;
+               }
+@@ -2379,7 +2378,7 @@ static int __must_check ffs_do_os_descs(unsigned count,
+                       return -EINVAL;
+               ret = __ffs_do_os_desc_header(&type, desc);
+-              if (unlikely(ret < 0)) {
++              if (ret < 0) {
+                       pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
+                                num, ret);
+                       return ret;
+@@ -2400,7 +2399,7 @@ static int __must_check ffs_do_os_descs(unsigned count,
+                */
+               ret = ffs_do_single_os_desc(data, len, type,
+                                           feature_count, entity, priv, desc);
+-              if (unlikely(ret < 0)) {
++              if (ret < 0) {
+                       pr_debug("%s returns %d\n", __func__, ret);
+                       return ret;
+               }
+@@ -2632,20 +2631,20 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+       ENTER();
+-      if (unlikely(len < 16 ||
+-                   get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
+-                   get_unaligned_le32(data + 4) != len))
++      if (len < 16 ||
++          get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
++          get_unaligned_le32(data + 4) != len)
+               goto error;
+       str_count  = get_unaligned_le32(data + 8);
+       lang_count = get_unaligned_le32(data + 12);
+       /* if one is zero the other must be zero */
+-      if (unlikely(!str_count != !lang_count))
++      if (!str_count != !lang_count)
+               goto error;
+       /* Do we have at least as many strings as descriptors need? */
+       needed_count = ffs->strings_count;
+-      if (unlikely(str_count < needed_count))
++      if (str_count < needed_count)
+               goto error;
+       /*
+@@ -2669,7 +2668,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+               char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
+-              if (unlikely(!vlabuf)) {
++              if (!vlabuf) {
+                       kfree(_data);
+                       return -ENOMEM;
+               }
+@@ -2697,7 +2696,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+               unsigned needed = needed_count;
+               u32 str_per_lang = str_count;
+-              if (unlikely(len < 3))
++              if (len < 3)
+                       goto error_free;
+               t->language = get_unaligned_le16(data);
+               t->strings  = s;
+@@ -2710,7 +2709,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+               do { /* str_count > 0 so we can use do-while */
+                       size_t length = strnlen(data, len);
+-                      if (unlikely(length == len))
++                      if (length == len)
+                               goto error_free;
+                       /*
+@@ -2718,7 +2717,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+                        * if that's the case we simply ignore the
+                        * rest
+                        */
+-                      if (likely(needed)) {
++                      if (needed) {
+                               /*
+                                * s->id will be set while adding
+                                * function to configuration so for
+@@ -2740,7 +2739,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
+       } while (--lang_count);
+       /* Some garbage left? */
+-      if (unlikely(len))
++      if (len)
+               goto error_free;
+       /* Done! */
+@@ -2887,7 +2886,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
+       ffs_ep = func->eps + idx;
+-      if (unlikely(ffs_ep->descs[ep_desc_id])) {
++      if (ffs_ep->descs[ep_desc_id]) {
+               pr_err("two %sspeed descriptors for EP %d\n",
+                         speed_names[ep_desc_id],
+                         ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+@@ -2918,12 +2917,12 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
+               wMaxPacketSize = ds->wMaxPacketSize;
+               pr_vdebug("autoconfig\n");
+               ep = usb_ep_autoconfig(func->gadget, ds);
+-              if (unlikely(!ep))
++              if (!ep)
+                       return -ENOTSUPP;
+               ep->driver_data = func->eps + idx;
+               req = usb_ep_alloc_request(ep, GFP_KERNEL);
+-              if (unlikely(!req))
++              if (!req)
+                       return -ENOMEM;
+               ffs_ep->ep  = ep;
+@@ -2965,7 +2964,7 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
+               idx = *valuep;
+               if (func->interfaces_nums[idx] < 0) {
+                       int id = usb_interface_id(func->conf, &func->function);
+-                      if (unlikely(id < 0))
++                      if (id < 0)
+                               return id;
+                       func->interfaces_nums[idx] = id;
+               }
+@@ -2986,7 +2985,7 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
+                       return 0;
+               idx = (*valuep & USB_ENDPOINT_NUMBER_MASK) - 1;
+-              if (unlikely(!func->eps[idx].ep))
++              if (!func->eps[idx].ep)
+                       return -EINVAL;
+               {
+@@ -3171,12 +3170,12 @@ static int _ffs_func_bind(struct usb_configuration *c,
+       ENTER();
+       /* Has descriptors only for speeds gadget does not support */
+-      if (unlikely(!(full | high | super)))
++      if (!(full | high | super))
+               return -ENOTSUPP;
+       /* Allocate a single chunk, less management later on */
+       vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
+-      if (unlikely(!vlabuf))
++      if (!vlabuf)
+               return -ENOMEM;
+       ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
+@@ -3205,13 +3204,13 @@ static int _ffs_func_bind(struct usb_configuration *c,
+        * endpoints first, so that later we can rewrite the endpoint
+        * numbers without worrying that it may be described later on.
+        */
+-      if (likely(full)) {
++      if (full) {
+               func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
+               fs_len = ffs_do_descs(ffs->fs_descs_count,
+                                     vla_ptr(vlabuf, d, raw_descs),
+                                     d_raw_descs__sz,
+                                     __ffs_func_bind_do_descs, func);
+-              if (unlikely(fs_len < 0)) {
++              if (fs_len < 0) {
+                       ret = fs_len;
+                       goto error;
+               }
+@@ -3219,13 +3218,13 @@ static int _ffs_func_bind(struct usb_configuration *c,
+               fs_len = 0;
+       }
+-      if (likely(high)) {
++      if (high) {
+               func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs);
+               hs_len = ffs_do_descs(ffs->hs_descs_count,
+                                     vla_ptr(vlabuf, d, raw_descs) + fs_len,
+                                     d_raw_descs__sz - fs_len,
+                                     __ffs_func_bind_do_descs, func);
+-              if (unlikely(hs_len < 0)) {
++              if (hs_len < 0) {
+                       ret = hs_len;
+                       goto error;
+               }
+@@ -3233,14 +3232,14 @@ static int _ffs_func_bind(struct usb_configuration *c,
+               hs_len = 0;
+       }
+-      if (likely(super)) {
++      if (super) {
+               func->function.ss_descriptors = func->function.ssp_descriptors =
+                       vla_ptr(vlabuf, d, ss_descs);
+               ss_len = ffs_do_descs(ffs->ss_descs_count,
+                               vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
+                               d_raw_descs__sz - fs_len - hs_len,
+                               __ffs_func_bind_do_descs, func);
+-              if (unlikely(ss_len < 0)) {
++              if (ss_len < 0) {
+                       ret = ss_len;
+                       goto error;
+               }
+@@ -3258,7 +3257,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
+                          (super ? ffs->ss_descs_count : 0),
+                          vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz,
+                          __ffs_func_bind_do_nums, func);
+-      if (unlikely(ret < 0))
++      if (ret < 0)
+               goto error;
+       func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
+@@ -3279,7 +3278,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
+                                     d_raw_descs__sz - fs_len - hs_len -
+                                     ss_len,
+                                     __ffs_func_bind_do_os_desc, func);
+-              if (unlikely(ret < 0))
++              if (ret < 0)
+                       goto error;
+       }
+       func->function.os_desc_n =
+@@ -3330,7 +3329,7 @@ static int ffs_func_set_alt(struct usb_function *f,
+       if (alt != (unsigned)-1) {
+               intf = ffs_func_revmap_intf(func, interface);
+-              if (unlikely(intf < 0))
++              if (intf < 0)
+                       return intf;
+       }
+@@ -3355,7 +3354,7 @@ static int ffs_func_set_alt(struct usb_function *f,
+       ffs->func = func;
+       ret = ffs_func_eps_enable(func);
+-      if (likely(ret >= 0))
++      if (ret >= 0)
+               ffs_event_add(ffs, FUNCTIONFS_ENABLE);
+       return ret;
+ }
+@@ -3397,13 +3396,13 @@ static int ffs_func_setup(struct usb_function *f,
+       switch (creq->bRequestType & USB_RECIP_MASK) {
+       case USB_RECIP_INTERFACE:
+               ret = ffs_func_revmap_intf(func, le16_to_cpu(creq->wIndex));
+-              if (unlikely(ret < 0))
++              if (ret < 0)
+                       return ret;
+               break;
+       case USB_RECIP_ENDPOINT:
+               ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex));
+-              if (unlikely(ret < 0))
++              if (ret < 0)
+                       return ret;
+               if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
+                       ret = func->ffs->eps_addrmap[ret];
+@@ -3662,7 +3661,7 @@ static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
+       ENTER();
+       func = kzalloc(sizeof(*func), GFP_KERNEL);
+-      if (unlikely(!func))
++      if (!func)
+               return ERR_PTR(-ENOMEM);
+       func->function.name    = "Function FS Gadget";
+@@ -3876,7 +3875,7 @@ static void ffs_closed(struct ffs_data *ffs)
+ static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
+ {
+       return nonblock
+-              ? likely(mutex_trylock(mutex)) ? 0 : -EAGAIN
++              ? mutex_trylock(mutex) ? 0 : -EAGAIN
+               : mutex_lock_interruptible(mutex);
+ }
+@@ -3884,14 +3883,14 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len)
+ {
+       char *data;
+-      if (unlikely(!len))
++      if (!len)
+               return NULL;
+       data = kmalloc(len, GFP_KERNEL);
+-      if (unlikely(!data))
++      if (!data)
+               return ERR_PTR(-ENOMEM);
+-      if (unlikely(copy_from_user(data, buf, len))) {
++      if (copy_from_user(data, buf, len)) {
+               kfree(data);
+               return ERR_PTR(-EFAULT);
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.4/vxlan-fix-regression-when-dropping-packets-due-to-in.patch b/queue-5.4/vxlan-fix-regression-when-dropping-packets-due-to-in.patch
new file mode 100644 (file)
index 0000000..d7a82fe
--- /dev/null
@@ -0,0 +1,65 @@
+From 60c7b1b55c60590b9b53dcf7fe703713dc53e83d 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.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
+index 8808a6540b190..ce11fb2b05561 100644
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -1323,6 +1323,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
+
diff --git a/queue-5.4/wifi-cfg80211-pmsr-use-correct-nla_get_ux-functions.patch b/queue-5.4/wifi-cfg80211-pmsr-use-correct-nla_get_ux-functions.patch
new file mode 100644 (file)
index 0000000..b34778b
--- /dev/null
@@ -0,0 +1,85 @@
+From 6f486a31fe8739e0797ee8c21506b3c82339fe18 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 0c7bd1f2c55c0..0cd1cb269ab58 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
+
diff --git a/queue-5.4/wifi-iwlwifi-dbg_ini-move-iwl_dbg_tlv_free-outside-o.patch b/queue-5.4/wifi-iwlwifi-dbg_ini-move-iwl_dbg_tlv_free-outside-o.patch
new file mode 100644 (file)
index 0000000..5102dbf
--- /dev/null
@@ -0,0 +1,41 @@
+From 0f657e8f7b25eae20029fe4613761ec3e4622356 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 1848b957dc5cd..9e63230da1ec0 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+@@ -1669,8 +1669,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
+
diff --git a/queue-5.4/wifi-iwlwifi-mvm-don-t-read-past-the-mfuart-notifcat.patch b/queue-5.4/wifi-iwlwifi-mvm-don-t-read-past-the-mfuart-notifcat.patch
new file mode 100644 (file)
index 0000000..cacb5a9
--- /dev/null
@@ -0,0 +1,55 @@
+From 4cbdb6b051e8536c8eb87adae2afb9f4b1471962 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 c5b08a68f6fa1..27bd9ed48bec4 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+@@ -197,20 +197,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
+
diff --git a/queue-5.4/wifi-iwlwifi-mvm-revert-gen2-tx-a-mpdu-size-to-64.patch b/queue-5.4/wifi-iwlwifi-mvm-revert-gen2-tx-a-mpdu-size-to-64.patch
new file mode 100644 (file)
index 0000000..a7e812d
--- /dev/null
@@ -0,0 +1,49 @@
+From 71b6984ae5b1a85314fd3bb5d9a989d4dac36352 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 428642e666587..c5b48261fae3f 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
+
diff --git a/queue-5.4/wifi-mac80211-correctly-parse-spatial-reuse-paramete.patch b/queue-5.4/wifi-mac80211-correctly-parse-spatial-reuse-paramete.patch
new file mode 100644 (file)
index 0000000..53eefde
--- /dev/null
@@ -0,0 +1,65 @@
+From d703a332b120f4e5908abfbebee77a405aa7f8c1 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 736da0035135a..398cf8a7ebd91 100644
+--- a/net/mac80211/he.c
++++ b/net/mac80211/he.c
+@@ -78,15 +78,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
+
diff --git a/queue-5.4/wifi-mac80211-fix-deadlock-in-ieee80211_sta_ps_deliv.patch b/queue-5.4/wifi-mac80211-fix-deadlock-in-ieee80211_sta_ps_deliv.patch
new file mode 100644 (file)
index 0000000..3df996a
--- /dev/null
@@ -0,0 +1,109 @@
+From 1e6d2ad590200872d31f27728557b3d3b2575c74 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 e330036e02eac..67cefa2137222 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -1326,7 +1326,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;
+@@ -1355,7 +1355,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
+
diff --git a/queue-5.4/wifi-mac80211-mesh-fix-leak-of-mesh_preq_queue-objec.patch b/queue-5.4/wifi-mac80211-mesh-fix-leak-of-mesh_preq_queue-objec.patch
new file mode 100644 (file)
index 0000000..eafb5d6
--- /dev/null
@@ -0,0 +1,100 @@
+From a8010a4732c187547e6359e08312514694dc2e66 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 7e27e5201c54c..55926927c2975 100644
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -725,10 +725,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
+