]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Fri, 26 Jan 2024 14:04:45 +0000 (09:04 -0500)
committerSasha Levin <sashal@kernel.org>
Fri, 26 Jan 2024 14:04:45 +0000 (09:04 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
29 files changed:
queue-6.6/cifs-handle-cases-where-a-channel-is-closed.patch [new file with mode: 0644]
queue-6.6/cifs-handle-servers-that-still-advertise-multichanne.patch [new file with mode: 0644]
queue-6.6/cifs-handle-when-server-starts-supporting-multichann.patch [new file with mode: 0644]
queue-6.6/cifs-handle-when-server-stops-supporting-multichanne.patch [new file with mode: 0644]
queue-6.6/cifs-reconnect-work-should-have-reference-on-server-.patch [new file with mode: 0644]
queue-6.6/cifs-reconnect-worker-should-take-reference-on-serve.patch [new file with mode: 0644]
queue-6.6/cifs-update-iface_last_update-on-each-query-and-upda.patch [new file with mode: 0644]
queue-6.6/dmaengine-fix-null-pointer-in-channel-unregistration.patch [new file with mode: 0644]
queue-6.6/dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch [new file with mode: 0644]
queue-6.6/dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch [new file with mode: 0644]
queue-6.6/docs-kernel_feat.py-fix-potential-command-injection.patch [new file with mode: 0644]
queue-6.6/docs-sparse-add-sparse.rst-to-toctree.patch [new file with mode: 0644]
queue-6.6/docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad7091r-allow-users-to-configure-device-even.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad7091r-set-alert-bit-in-config-register.patch [new file with mode: 0644]
queue-6.6/net-stmmac-prevent-dsa-tags-from-breaking-coe.patch [new file with mode: 0644]
queue-6.6/net-stmmac-tx-coe-sw-fallback.patch [new file with mode: 0644]
queue-6.6/revert-cifs-reconnect-work-should-have-reference-on-.patch [new file with mode: 0644]
queue-6.6/riscv-fix-an-off-by-one-in-get_early_cmdline.patch [new file with mode: 0644]
queue-6.6/scsi-core-kick-the-requeue-list-after-inserting-when.patch [new file with mode: 0644]
queue-6.6/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch [new file with mode: 0644]
queue-6.6/serial-core-set-missing-supported-flag-for-rx-during.patch [new file with mode: 0644]
queue-6.6/serial-core-simplify-uart_get_rs485_mode.patch [new file with mode: 0644]
queue-6.6/series [new file with mode: 0644]
queue-6.6/sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch [new file with mode: 0644]
queue-6.6/smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch [new file with mode: 0644]
queue-6.6/soundwire-bus-introduce-controller_id.patch [new file with mode: 0644]
queue-6.6/soundwire-fix-initializing-sysfs-for-same-devices-on.patch [new file with mode: 0644]

diff --git a/queue-6.6/cifs-handle-cases-where-a-channel-is-closed.patch b/queue-6.6/cifs-handle-cases-where-a-channel-is-closed.patch
new file mode 100644 (file)
index 0000000..0434ef5
--- /dev/null
@@ -0,0 +1,221 @@
+From a54a0939f5009c54e9af579b3fdc74170c199bdd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 09:25:30 +0000
+Subject: cifs: handle cases where a channel is closed
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 0c51cc6f2cb0108e7d49805f6e089cd85caab279 ]
+
+So far, SMB multichannel could only scale up, but not
+scale down the number of channels. In this series of
+patch, we now allow the client to deal with the case
+of multichannel disabled on the server when the share
+is mounted. With that change, we now need the ability
+to scale down the channels.
+
+This change allows the client to deal with cases of
+missing channels more gracefully.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifs_debug.c    |  5 +++++
+ fs/smb/client/cifsglob.h      |  1 +
+ fs/smb/client/cifsproto.h     |  2 +-
+ fs/smb/client/connect.c       |  6 +++++-
+ fs/smb/client/sess.c          | 28 ++++++++++++++++++++++++----
+ fs/smb/client/smb2transport.c |  8 +++++++-
+ 6 files changed, 43 insertions(+), 7 deletions(-)
+
+diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
+index a2584ad8808a..3230ed7eadde 100644
+--- a/fs/smb/client/cifs_debug.c
++++ b/fs/smb/client/cifs_debug.c
+@@ -138,6 +138,11 @@ cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
+ {
+       struct TCP_Server_Info *server = chan->server;
++      if (!server) {
++              seq_printf(m, "\n\n\t\tChannel: %d DISABLED", i+1);
++              return;
++      }
++
+       seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx"
+                  "\n\t\tNumber of credits: %d,%d,%d Dialect 0x%x"
+                  "\n\t\tTCP status: %d Instance: %d"
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index ec1e5e20a36b..e3ef8eee68d1 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -1060,6 +1060,7 @@ struct cifs_ses {
+       spinlock_t chan_lock;
+       /* ========= begin: protected by chan_lock ======== */
+ #define CIFS_MAX_CHANNELS 16
++#define CIFS_INVAL_CHAN_INDEX (-1)
+ #define CIFS_ALL_CHANNELS_SET(ses)    \
+       ((1UL << (ses)->chan_count) - 1)
+ #define CIFS_ALL_CHANS_GOOD(ses)              \
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index c858feaf4f92..0eb62ccd476f 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -622,7 +622,7 @@ bool is_server_using_iface(struct TCP_Server_Info *server,
+ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
+ void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
+-unsigned int
++int
+ cifs_ses_get_chan_index(struct cifs_ses *ses,
+                       struct TCP_Server_Info *server);
+ void
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index b82f60d6f47e..a482afa3fa42 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -169,8 +169,12 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
+       list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
+               spin_lock(&ses->chan_lock);
+               for (i = 0; i < ses->chan_count; i++) {
++                      if (!ses->chans[i].server)
++                              continue;
++
+                       spin_lock(&ses->chans[i].server->srv_lock);
+-                      ses->chans[i].server->tcpStatus = CifsNeedReconnect;
++                      if (ses->chans[i].server->tcpStatus != CifsExiting)
++                              ses->chans[i].server->tcpStatus = CifsNeedReconnect;
+                       spin_unlock(&ses->chans[i].server->srv_lock);
+               }
+               spin_unlock(&ses->chan_lock);
+diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
+index 80050e36f045..650a3ec9e6e5 100644
+--- a/fs/smb/client/sess.c
++++ b/fs/smb/client/sess.c
+@@ -69,7 +69,7 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
+ /* channel helper functions. assumed that chan_lock is held by caller. */
+-unsigned int
++int
+ cifs_ses_get_chan_index(struct cifs_ses *ses,
+                       struct TCP_Server_Info *server)
+ {
+@@ -85,14 +85,17 @@ cifs_ses_get_chan_index(struct cifs_ses *ses,
+               cifs_dbg(VFS, "unable to get chan index for server: 0x%llx",
+                        server->conn_id);
+       WARN_ON(1);
+-      return 0;
++      return CIFS_INVAL_CHAN_INDEX;
+ }
+ void
+ cifs_chan_set_in_reconnect(struct cifs_ses *ses,
+                            struct TCP_Server_Info *server)
+ {
+-      unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      int chan_index = cifs_ses_get_chan_index(ses, server);
++
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return;
+       ses->chans[chan_index].in_reconnect = true;
+ }
+@@ -102,6 +105,8 @@ cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
+                            struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return;
+       ses->chans[chan_index].in_reconnect = false;
+ }
+@@ -111,6 +116,8 @@ cifs_chan_in_reconnect(struct cifs_ses *ses,
+                         struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return true;    /* err on the safer side */
+       return CIFS_CHAN_IN_RECONNECT(ses, chan_index);
+ }
+@@ -120,6 +127,8 @@ cifs_chan_set_need_reconnect(struct cifs_ses *ses,
+                            struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return;
+       set_bit(chan_index, &ses->chans_need_reconnect);
+       cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n",
+@@ -131,6 +140,8 @@ cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
+                              struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return;
+       clear_bit(chan_index, &ses->chans_need_reconnect);
+       cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n",
+@@ -142,6 +153,8 @@ cifs_chan_needs_reconnect(struct cifs_ses *ses,
+                         struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return true;    /* err on the safer side */
+       return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index);
+ }
+@@ -151,6 +164,8 @@ cifs_chan_is_iface_active(struct cifs_ses *ses,
+                         struct TCP_Server_Info *server)
+ {
+       unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX)
++              return true;    /* err on the safer side */
+       return ses->chans[chan_index].iface &&
+               ses->chans[chan_index].iface->is_active;
+@@ -293,7 +308,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
+       spin_lock(&ses->chan_lock);
+       chan_index = cifs_ses_get_chan_index(ses, server);
+-      if (!chan_index) {
++      if (chan_index == CIFS_INVAL_CHAN_INDEX) {
+               spin_unlock(&ses->chan_lock);
+               return 0;
+       }
+@@ -403,6 +418,11 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
+       spin_lock(&ses->chan_lock);
+       chan_index = cifs_ses_get_chan_index(ses, server);
++      if (chan_index == CIFS_INVAL_CHAN_INDEX) {
++              spin_unlock(&ses->chan_lock);
++              return 0;
++      }
++
+       ses->chans[chan_index].iface = iface;
+       /* No iface is found. if secondary chan, drop connection */
+diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
+index a136fc4cc2b5..5a3ca62d2f07 100644
+--- a/fs/smb/client/smb2transport.c
++++ b/fs/smb/client/smb2transport.c
+@@ -413,7 +413,13 @@ generate_smb3signingkey(struct cifs_ses *ses,
+                     ses->ses_status == SES_GOOD);
+       chan_index = cifs_ses_get_chan_index(ses, server);
+-      /* TODO: introduce ref counting for channels when the can be freed */
++      if (chan_index == CIFS_INVAL_CHAN_INDEX) {
++              spin_unlock(&ses->chan_lock);
++              spin_unlock(&ses->ses_lock);
++
++              return -EINVAL;
++      }
++
+       spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-handle-servers-that-still-advertise-multichanne.patch b/queue-6.6/cifs-handle-servers-that-still-advertise-multichanne.patch
new file mode 100644 (file)
index 0000000..09b7c77
--- /dev/null
@@ -0,0 +1,221 @@
+From e3a58a9a8a880e691f0c35025084cc98bab84cde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Jan 2024 13:14:46 +0000
+Subject: cifs: handle servers that still advertise multichannel after
+ disabling
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit f591062bdbf4742b7f1622173017f19e927057b0 ]
+
+Some servers like Azure SMB servers always advertise multichannel
+capability in server capabilities list. Such servers return error
+STATUS_NOT_IMPLEMENTED for ioctl calls to query server interfaces,
+and expect clients to consider that as a sign that they do not support
+multichannel.
+
+We already handled this at mount time. Soon after the tree connect,
+we query server interfaces. And when server returned STATUS_NOT_IMPLEMENTED,
+we kept interface list as empty. When cifs_try_adding_channels gets
+called, it would not find any interfaces, so will not add channels.
+
+For the case where an active multichannel mount exists, and multichannel
+is disabled by such a server, this change will now allow the client
+to disable secondary channels on the mount. It will check the return
+status of query server interfaces call soon after a tree reconnect.
+If the return status is EOPNOTSUPP, then instead of the check to add
+more channels, we'll disable the secondary channels instead.
+
+For better code reuse, this change also moves the common code for
+disabling multichannel to a helper function.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/smb2ops.c |   8 +--
+ fs/smb/client/smb2pdu.c | 107 +++++++++++++++++++++++++---------------
+ 2 files changed, 69 insertions(+), 46 deletions(-)
+
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 0604696f59c1..8caf2cefc8a7 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -614,7 +614,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+                                "multichannel not available\n"
+                                "Empty network interface list returned by server %s\n",
+                                ses->server->hostname);
+-              rc = -EINVAL;
++              rc = -EOPNOTSUPP;
+               goto out;
+       }
+@@ -734,12 +734,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+       if ((bytes_left > 8) || p->Next)
+               cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
+-
+-      if (!ses->iface_count) {
+-              rc = -EINVAL;
+-              goto out;
+-      }
+-
+ out:
+       /*
+        * Go through the list again and put the inactive entries
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index a3995c6dc1ad..d846c238b7dd 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -156,6 +156,57 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
+       return;
+ }
++/* helper function for code reuse */
++static int
++cifs_chan_skip_or_disable(struct cifs_ses *ses,
++                        struct TCP_Server_Info *server,
++                        bool from_reconnect)
++{
++      struct TCP_Server_Info *pserver;
++      unsigned int chan_index;
++
++      if (SERVER_IS_CHAN(server)) {
++              cifs_dbg(VFS,
++                      "server %s does not support multichannel anymore. Skip secondary channel\n",
++                       ses->server->hostname);
++
++              spin_lock(&ses->chan_lock);
++              chan_index = cifs_ses_get_chan_index(ses, server);
++              if (chan_index == CIFS_INVAL_CHAN_INDEX) {
++                      spin_unlock(&ses->chan_lock);
++                      goto skip_terminate;
++              }
++
++              ses->chans[chan_index].server = NULL;
++              spin_unlock(&ses->chan_lock);
++
++              /*
++               * the above reference of server by channel
++               * needs to be dropped without holding chan_lock
++               * as cifs_put_tcp_session takes a higher lock
++               * i.e. cifs_tcp_ses_lock
++               */
++              cifs_put_tcp_session(server, from_reconnect);
++
++              server->terminate = true;
++              cifs_signal_cifsd_for_reconnect(server, false);
++
++              /* mark primary server as needing reconnect */
++              pserver = server->primary_server;
++              cifs_signal_cifsd_for_reconnect(pserver, false);
++skip_terminate:
++              mutex_unlock(&ses->session_mutex);
++              return -EHOSTDOWN;
++      }
++
++      cifs_server_dbg(VFS,
++              "server does not support multichannel anymore. Disable all other channels\n");
++      cifs_disable_secondary_channels(ses);
++
++
++      return 0;
++}
++
+ static int
+ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+              struct TCP_Server_Info *server, bool from_reconnect)
+@@ -164,8 +215,6 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+       struct nls_table *nls_codepage = NULL;
+       struct cifs_ses *ses;
+       int xid;
+-      struct TCP_Server_Info *pserver;
+-      unsigned int chan_index;
+       /*
+        * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
+@@ -310,44 +359,11 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+                */
+               if (ses->chan_count > 1 &&
+                   !(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+-                      if (SERVER_IS_CHAN(server)) {
+-                              cifs_dbg(VFS, "server %s does not support " \
+-                                       "multichannel anymore. skipping secondary channel\n",
+-                                       ses->server->hostname);
+-
+-                              spin_lock(&ses->chan_lock);
+-                              chan_index = cifs_ses_get_chan_index(ses, server);
+-                              if (chan_index == CIFS_INVAL_CHAN_INDEX) {
+-                                      spin_unlock(&ses->chan_lock);
+-                                      goto skip_terminate;
+-                              }
+-
+-                              ses->chans[chan_index].server = NULL;
+-                              spin_unlock(&ses->chan_lock);
+-
+-                              /*
+-                               * the above reference of server by channel
+-                               * needs to be dropped without holding chan_lock
+-                               * as cifs_put_tcp_session takes a higher lock
+-                               * i.e. cifs_tcp_ses_lock
+-                               */
+-                              cifs_put_tcp_session(server, from_reconnect);
+-
+-                              server->terminate = true;
+-                              cifs_signal_cifsd_for_reconnect(server, false);
+-
+-                              /* mark primary server as needing reconnect */
+-                              pserver = server->primary_server;
+-                              cifs_signal_cifsd_for_reconnect(pserver, false);
+-
+-skip_terminate:
++                      rc = cifs_chan_skip_or_disable(ses, server,
++                                                     from_reconnect);
++                      if (rc) {
+                               mutex_unlock(&ses->session_mutex);
+-                              rc = -EHOSTDOWN;
+                               goto out;
+-                      } else {
+-                              cifs_server_dbg(VFS, "does not support " \
+-                                       "multichannel anymore. disabling all other channels\n");
+-                              cifs_disable_secondary_channels(ses);
+                       }
+               }
+@@ -395,11 +411,23 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+               rc = SMB3_request_interfaces(xid, tcon, false);
+               free_xid(xid);
+-              if (rc)
++              if (rc == -EOPNOTSUPP) {
++                      /*
++                       * some servers like Azure SMB server do not advertise
++                       * that multichannel has been disabled with server
++                       * capabilities, rather return STATUS_NOT_IMPLEMENTED.
++                       * treat this as server not supporting multichannel
++                       */
++
++                      rc = cifs_chan_skip_or_disable(ses, server,
++                                                     from_reconnect);
++                      goto skip_add_channels;
++              } else if (rc)
+                       cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
+                                __func__, rc);
+               if (ses->chan_max > ses->chan_count &&
++                  ses->iface_count &&
+                   !SERVER_IS_CHAN(server)) {
+                       if (ses->chan_count == 1)
+                               cifs_server_dbg(VFS, "supports multichannel now\n");
+@@ -409,6 +437,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+       } else {
+               mutex_unlock(&ses->session_mutex);
+       }
++skip_add_channels:
+       if (smb2_command != SMB2_INTERNAL_CMD)
+               if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-handle-when-server-starts-supporting-multichann.patch b/queue-6.6/cifs-handle-when-server-starts-supporting-multichann.patch
new file mode 100644 (file)
index 0000000..8e25350
--- /dev/null
@@ -0,0 +1,112 @@
+From 72a8eaff0ccf35dedb6641183ad07acd1fda9d5b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 11:33:21 +0000
+Subject: cifs: handle when server starts supporting multichannel
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 705fc522fe9d58848c253ee0948567060f36e2a7 ]
+
+When the user mounts with multichannel option, but the
+server does not support it, there can be a time in future
+where it can be supported.
+
+With this change, such a case is handled.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsproto.h |  1 +
+ fs/smb/client/connect.c   |  3 +++
+ fs/smb/client/smb2pdu.c   | 32 ++++++++++++++++++++++++++++++--
+ 3 files changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 0eb62ccd476f..4a28cff87038 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -132,6 +132,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
+                       struct smb_hdr *in_buf,
+                       struct smb_hdr *out_buf,
+                       int *bytes_returned);
++
+ void
+ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
+                                     bool all_channels);
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 2f5be7dcd1f9..c0b1f30eecd7 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -128,6 +128,9 @@ static void smb2_query_server_interfaces(struct work_struct *work)
+        */
+       rc = SMB3_request_interfaces(0, tcon, false);
+       if (rc) {
++              if (rc == -EOPNOTSUPP)
++                      return;
++
+               cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
+                               __func__, rc);
+       }
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 0274ef67457b..288f22050c20 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -163,6 +163,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+       int rc = 0;
+       struct nls_table *nls_codepage = NULL;
+       struct cifs_ses *ses;
++      int xid;
+       /*
+        * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
+@@ -307,17 +308,44 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+               tcon->need_reopen_files = true;
+       rc = cifs_tree_connect(0, tcon, nls_codepage);
+-      mutex_unlock(&ses->session_mutex);
+       cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
+       if (rc) {
+               /* If sess reconnected but tcon didn't, something strange ... */
++              mutex_unlock(&ses->session_mutex);
+               cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
+               goto out;
+       }
++      if (!rc &&
++          (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
++              mutex_unlock(&ses->session_mutex);
++
++              /*
++               * query server network interfaces, in case they change
++               */
++              xid = get_xid();
++              rc = SMB3_request_interfaces(xid, tcon, false);
++              free_xid(xid);
++
++              if (rc)
++                      cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
++                               __func__, rc);
++
++              if (ses->chan_max > ses->chan_count &&
++                  !SERVER_IS_CHAN(server)) {
++                      if (ses->chan_count == 1)
++                              cifs_server_dbg(VFS, "supports multichannel now\n");
++
++                      cifs_try_adding_channels(ses);
++              }
++      } else {
++              mutex_unlock(&ses->session_mutex);
++      }
++
+       if (smb2_command != SMB2_INTERNAL_CMD)
+-              mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
++              if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
++                      cifs_put_tcp_session(server, false);
+       atomic_inc(&tconInfoReconnectCount);
+ out:
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-handle-when-server-stops-supporting-multichanne.patch b/queue-6.6/cifs-handle-when-server-stops-supporting-multichanne.patch
new file mode 100644 (file)
index 0000000..aa1ed66
--- /dev/null
@@ -0,0 +1,307 @@
+From 5b453a7be6de530810c2403054ba14bc1dfadfac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 11:40:09 +0000
+Subject: cifs: handle when server stops supporting multichannel
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit ee1d21794e55ab76505745d24101331552182002 ]
+
+When a server stops supporting multichannel, we will
+keep attempting reconnects to the secondary channels today.
+Avoid this by freeing extra channels when negotiate
+returns no multichannel support.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/cifsglob.h  |  1 +
+ fs/smb/client/cifsproto.h |  2 ++
+ fs/smb/client/connect.c   | 10 ++++++
+ fs/smb/client/sess.c      | 64 ++++++++++++++++++++++++++++-----
+ fs/smb/client/smb2pdu.c   | 76 ++++++++++++++++++++++++++++++++++++++-
+ fs/smb/client/transport.c |  2 +-
+ 6 files changed, 145 insertions(+), 10 deletions(-)
+
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index e3ef8eee68d1..5e32c79f03a7 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -659,6 +659,7 @@ struct TCP_Server_Info {
+       bool noautotune;                /* do not autotune send buf sizes */
+       bool nosharesock;
+       bool tcp_nodelay;
++      bool terminate;
+       unsigned int credits;  /* send no more requests at once */
+       unsigned int max_credits; /* can override large 32000 default at mnt */
+       unsigned int in_flight;  /* number of requests on the wire to server */
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 4a28cff87038..c00f84420559 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -647,6 +647,8 @@ cifs_chan_needs_reconnect(struct cifs_ses *ses,
+ bool
+ cifs_chan_is_iface_active(struct cifs_ses *ses,
+                         struct TCP_Server_Info *server);
++void
++cifs_disable_secondary_channels(struct cifs_ses *ses);
+ int
+ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
+ int
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index c0b1f30eecd7..f43f51f2d1c1 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -215,6 +215,14 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+       spin_lock(&cifs_tcp_ses_lock);
+       list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
++              /*
++               * if channel has been marked for termination, nothing to do
++               * for the channel. in fact, we cannot find the channel for the
++               * server. So safe to exit here
++               */
++              if (server->terminate)
++                      break;
++
+               /* check if iface is still active */
+               spin_lock(&ses->chan_lock);
+               if (!cifs_chan_is_iface_active(ses, server)) {
+@@ -252,6 +260,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+                       spin_lock(&tcon->tc_lock);
+                       tcon->status = TID_NEED_RECON;
+                       spin_unlock(&tcon->tc_lock);
++
++                      cancel_delayed_work(&tcon->query_interfaces);
+               }
+               if (ses->tcon_ipc) {
+                       ses->tcon_ipc->need_reconnect = true;
+diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
+index 650a3ec9e6e5..2ce1b7571371 100644
+--- a/fs/smb/client/sess.c
++++ b/fs/smb/client/sess.c
+@@ -290,6 +290,60 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
+       return new_chan_count - old_chan_count;
+ }
++/*
++ * called when multichannel is disabled by the server.
++ * this always gets called from smb2_reconnect
++ * and cannot get called in parallel threads.
++ */
++void
++cifs_disable_secondary_channels(struct cifs_ses *ses)
++{
++      int i, chan_count;
++      struct TCP_Server_Info *server;
++      struct cifs_server_iface *iface;
++
++      spin_lock(&ses->chan_lock);
++      chan_count = ses->chan_count;
++      if (chan_count == 1)
++              goto done;
++
++      ses->chan_count = 1;
++
++      /* for all secondary channels reset the need reconnect bit */
++      ses->chans_need_reconnect &= 1;
++
++      for (i = 1; i < chan_count; i++) {
++              iface = ses->chans[i].iface;
++              server = ses->chans[i].server;
++
++              if (iface) {
++                      spin_lock(&ses->iface_lock);
++                      kref_put(&iface->refcount, release_iface);
++                      ses->chans[i].iface = NULL;
++                      iface->num_channels--;
++                      if (iface->weight_fulfilled)
++                              iface->weight_fulfilled--;
++                      spin_unlock(&ses->iface_lock);
++              }
++
++              spin_unlock(&ses->chan_lock);
++              if (server && !server->terminate) {
++                      server->terminate = true;
++                      cifs_signal_cifsd_for_reconnect(server, false);
++              }
++              spin_lock(&ses->chan_lock);
++
++              if (server) {
++                      ses->chans[i].server = NULL;
++                      cifs_put_tcp_session(server, false);
++              }
++
++      }
++
++done:
++      spin_unlock(&ses->chan_lock);
++}
++
+ /*
+  * update the iface for the channel if necessary.
+  * will return 0 when iface is updated, 1 if removed, 2 otherwise
+@@ -589,14 +643,10 @@ cifs_ses_add_channel(struct cifs_ses *ses,
+ out:
+       if (rc && chan->server) {
+-              /*
+-               * we should avoid race with these delayed works before we
+-               * remove this channel
+-               */
+-              cancel_delayed_work_sync(&chan->server->echo);
+-              cancel_delayed_work_sync(&chan->server->reconnect);
++              cifs_put_tcp_session(chan->server, 0);
+               spin_lock(&ses->chan_lock);
++
+               /* we rely on all bits beyond chan_count to be clear */
+               cifs_chan_clear_need_reconnect(ses, chan->server);
+               ses->chan_count--;
+@@ -606,8 +656,6 @@ cifs_ses_add_channel(struct cifs_ses *ses,
+                */
+               WARN_ON(ses->chan_count < 1);
+               spin_unlock(&ses->chan_lock);
+-
+-              cifs_put_tcp_session(chan->server, 0);
+       }
+       kfree(ctx->UNC);
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 288f22050c20..f1977987ae74 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -164,6 +164,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+       struct nls_table *nls_codepage = NULL;
+       struct cifs_ses *ses;
+       int xid;
++      struct TCP_Server_Info *pserver;
++      unsigned int chan_index;
+       /*
+        * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
+@@ -224,6 +226,12 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+                       return -EAGAIN;
+               }
+       }
++
++      /* if server is marked for termination, cifsd will cleanup */
++      if (server->terminate) {
++              spin_unlock(&server->srv_lock);
++              return -EHOSTDOWN;
++      }
+       spin_unlock(&server->srv_lock);
+ again:
+@@ -242,12 +250,24 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+                tcon->need_reconnect);
+       mutex_lock(&ses->session_mutex);
++      /*
++       * if this is called by delayed work, and the channel has been disabled
++       * in parallel, the delayed work can continue to execute in parallel
++       * there's a chance that this channel may not exist anymore
++       */
++      spin_lock(&server->srv_lock);
++      if (server->tcpStatus == CifsExiting) {
++              spin_unlock(&server->srv_lock);
++              mutex_unlock(&ses->session_mutex);
++              rc = -EHOSTDOWN;
++              goto out;
++      }
++
+       /*
+        * Recheck after acquire mutex. If another thread is negotiating
+        * and the server never sends an answer the socket will be closed
+        * and tcpStatus set to reconnect.
+        */
+-      spin_lock(&server->srv_lock);
+       if (server->tcpStatus == CifsNeedReconnect) {
+               spin_unlock(&server->srv_lock);
+               mutex_unlock(&ses->session_mutex);
+@@ -284,6 +304,53 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+       rc = cifs_negotiate_protocol(0, ses, server);
+       if (!rc) {
++              /*
++               * if server stopped supporting multichannel
++               * and the first channel reconnected, disable all the others.
++               */
++              if (ses->chan_count > 1 &&
++                  !(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
++                      if (SERVER_IS_CHAN(server)) {
++                              cifs_dbg(VFS, "server %s does not support " \
++                                       "multichannel anymore. skipping secondary channel\n",
++                                       ses->server->hostname);
++
++                              spin_lock(&ses->chan_lock);
++                              chan_index = cifs_ses_get_chan_index(ses, server);
++                              if (chan_index == CIFS_INVAL_CHAN_INDEX) {
++                                      spin_unlock(&ses->chan_lock);
++                                      goto skip_terminate;
++                              }
++
++                              ses->chans[chan_index].server = NULL;
++                              spin_unlock(&ses->chan_lock);
++
++                              /*
++                               * the above reference of server by channel
++                               * needs to be dropped without holding chan_lock
++                               * as cifs_put_tcp_session takes a higher lock
++                               * i.e. cifs_tcp_ses_lock
++                               */
++                              cifs_put_tcp_session(server, 1);
++
++                              server->terminate = true;
++                              cifs_signal_cifsd_for_reconnect(server, false);
++
++                              /* mark primary server as needing reconnect */
++                              pserver = server->primary_server;
++                              cifs_signal_cifsd_for_reconnect(pserver, false);
++
++skip_terminate:
++                              mutex_unlock(&ses->session_mutex);
++                              rc = -EHOSTDOWN;
++                              goto out;
++                      } else {
++                              cifs_server_dbg(VFS, "does not support " \
++                                       "multichannel anymore. disabling all other channels\n");
++                              cifs_disable_secondary_channels(ses);
++                      }
++              }
++
+               rc = cifs_setup_session(0, ses, server, nls_codepage);
+               if ((rc == -EACCES) && !tcon->retry) {
+                       mutex_unlock(&ses->session_mutex);
+@@ -3863,6 +3930,13 @@ void smb2_reconnect_server(struct work_struct *work)
+       /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
+       mutex_lock(&pserver->reconnect_mutex);
++      /* if the server is marked for termination, drop the ref count here */
++      if (server->terminate) {
++              cifs_put_tcp_session(server, true);
++              mutex_unlock(&pserver->reconnect_mutex);
++              return;
++      }
++
+       INIT_LIST_HEAD(&tmp_list);
+       INIT_LIST_HEAD(&tmp_ses_list);
+       cifs_dbg(FYI, "Reconnecting tcons and channels\n");
+diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
+index d553b7a54621..4f717ad7c21b 100644
+--- a/fs/smb/client/transport.c
++++ b/fs/smb/client/transport.c
+@@ -1023,7 +1023,7 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
+       spin_lock(&ses->chan_lock);
+       for (i = 0; i < ses->chan_count; i++) {
+               server = ses->chans[i].server;
+-              if (!server)
++              if (!server || server->terminate)
+                       continue;
+               /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-reconnect-work-should-have-reference-on-server-.patch b/queue-6.6/cifs-reconnect-work-should-have-reference-on-server-.patch
new file mode 100644 (file)
index 0000000..469f64f
--- /dev/null
@@ -0,0 +1,146 @@
+From 980324fe16226cda05649fa31e5ad79e60818e1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 11:43:09 +0000
+Subject: cifs: reconnect work should have reference on server struct
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 19a4b9d6c372cab6a3b2c9a061a236136fe95274 ]
+
+The delayed work for reconnect takes server struct
+as a parameter. But it does so without holding a ref
+to it. Normally, this may not show a problem as
+the reconnect work is only cancelled on umount.
+
+However, since we now plan to support scaling down of
+channels, and the scale down can happen from reconnect
+work itself, we need to fix it.
+
+This change takes a reference on the server struct
+before it is passed to the delayed work. And drops
+the reference in the delayed work itself. Or if
+the delayed work is successfully cancelled, by the
+process that cancels it.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/connect.c | 27 +++++++++++++++++++++------
+ fs/smb/client/smb2pdu.c | 23 +++++++++++++----------
+ 2 files changed, 34 insertions(+), 16 deletions(-)
+
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index a482afa3fa42..2f5be7dcd1f9 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -388,7 +388,13 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
+                       spin_unlock(&server->srv_lock);
+                       cifs_swn_reset_server_dstaddr(server);
+                       cifs_server_unlock(server);
+-                      mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
++
++                      /* increase ref count which reconnect work will drop */
++                      spin_lock(&cifs_tcp_ses_lock);
++                      server->srv_count++;
++                      spin_unlock(&cifs_tcp_ses_lock);
++                      if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
++                              cifs_put_tcp_session(server, false);
+               }
+       } while (server->tcpStatus == CifsNeedReconnect);
+@@ -518,7 +524,13 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
+               spin_unlock(&server->srv_lock);
+               cifs_swn_reset_server_dstaddr(server);
+               cifs_server_unlock(server);
+-              mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
++
++              /* increase ref count which reconnect work will drop */
++              spin_lock(&cifs_tcp_ses_lock);
++              server->srv_count++;
++              spin_unlock(&cifs_tcp_ses_lock);
++              if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
++                      cifs_put_tcp_session(server, false);
+       } while (server->tcpStatus == CifsNeedReconnect);
+       mutex_lock(&server->refpath_lock);
+@@ -1605,16 +1617,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
+       cancel_delayed_work_sync(&server->echo);
+-      if (from_reconnect)
++      if (from_reconnect) {
+               /*
+                * Avoid deadlock here: reconnect work calls
+                * cifs_put_tcp_session() at its end. Need to be sure
+                * that reconnect work does nothing with server pointer after
+                * that step.
+                */
+-              cancel_delayed_work(&server->reconnect);
+-      else
+-              cancel_delayed_work_sync(&server->reconnect);
++              if (cancel_delayed_work(&server->reconnect))
++                      cifs_put_tcp_session(server, from_reconnect);
++      } else {
++              if (cancel_delayed_work_sync(&server->reconnect))
++                      cifs_put_tcp_session(server, from_reconnect);
++      }
+       spin_lock(&server->srv_lock);
+       server->tcpStatus = CifsExiting;
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 888eb59ad86f..0274ef67457b 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -3879,12 +3879,6 @@ void smb2_reconnect_server(struct work_struct *work)
+               }
+               spin_unlock(&ses->chan_lock);
+       }
+-      /*
+-       * Get the reference to server struct to be sure that the last call of
+-       * cifs_put_tcon() in the loop below won't release the server pointer.
+-       */
+-      if (tcon_exist || ses_exist)
+-              server->srv_count++;
+       spin_unlock(&cifs_tcp_ses_lock);
+@@ -3932,13 +3926,17 @@ void smb2_reconnect_server(struct work_struct *work)
+ done:
+       cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
+-      if (resched)
++      if (resched) {
+               queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
++              mutex_unlock(&pserver->reconnect_mutex);
++
++              /* no need to put tcp session as we're retrying */
++              return;
++      }
+       mutex_unlock(&pserver->reconnect_mutex);
+       /* now we can safely release srv struct */
+-      if (tcon_exist || ses_exist)
+-              cifs_put_tcp_session(server, 1);
++      cifs_put_tcp_session(server, true);
+ }
+ int
+@@ -3958,7 +3956,12 @@ SMB2_echo(struct TCP_Server_Info *server)
+           server->ops->need_neg(server)) {
+               spin_unlock(&server->srv_lock);
+               /* No need to send echo on newly established connections */
+-              mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
++              spin_lock(&cifs_tcp_ses_lock);
++              server->srv_count++;
++              spin_unlock(&cifs_tcp_ses_lock);
++              if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
++                      cifs_put_tcp_session(server, false);
++
+               return rc;
+       }
+       spin_unlock(&server->srv_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-reconnect-worker-should-take-reference-on-serve.patch b/queue-6.6/cifs-reconnect-worker-should-take-reference-on-serve.patch
new file mode 100644 (file)
index 0000000..84f3a2c
--- /dev/null
@@ -0,0 +1,150 @@
+From e0401d1f68695cd540b09e01970245c8ab6a8e8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Dec 2023 16:37:38 +0000
+Subject: cifs: reconnect worker should take reference on server struct
+ unconditionally
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 04909192ada3285070f8ced0af7f07735478b364 ]
+
+Reconnect worker currently assumes that the server struct
+is alive and only takes reference on the server if it needs
+to call smb2_reconnect.
+
+With the new ability to disable channels based on whether the
+server has multichannel disabled, this becomes a problem when
+we need to disable established channels. While disabling the
+channels and deallocating the server, there could be reconnect
+work that could not be cancelled (because it started).
+
+This change forces the reconnect worker to unconditionally
+take a reference on the server when it runs.
+
+Also, this change now allows smb2_reconnect to know if it was
+called by the reconnect worker. Based on this, the cifs_put_tcp_session
+can decide whether it can cancel the reconnect work synchronously or not.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/connect.c |  8 ++++----
+ fs/smb/client/smb2pdu.c | 29 +++++++++++++++--------------
+ 2 files changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 2a30245287d5..432248e955ed 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -1612,10 +1612,6 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
+       list_del_init(&server->tcp_ses_list);
+       spin_unlock(&cifs_tcp_ses_lock);
+-      /* For secondary channels, we pick up ref-count on the primary server */
+-      if (SERVER_IS_CHAN(server))
+-              cifs_put_tcp_session(server->primary_server, from_reconnect);
+-
+       cancel_delayed_work_sync(&server->echo);
+       if (from_reconnect)
+@@ -1629,6 +1625,10 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
+       else
+               cancel_delayed_work_sync(&server->reconnect);
++      /* For secondary channels, we pick up ref-count on the primary server */
++      if (SERVER_IS_CHAN(server))
++              cifs_put_tcp_session(server->primary_server, from_reconnect);
++
+       spin_lock(&server->srv_lock);
+       server->tcpStatus = CifsExiting;
+       spin_unlock(&server->srv_lock);
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index da752f41a4e6..a3995c6dc1ad 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -158,7 +158,7 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd,
+ static int
+ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+-             struct TCP_Server_Info *server)
++             struct TCP_Server_Info *server, bool from_reconnect)
+ {
+       int rc = 0;
+       struct nls_table *nls_codepage = NULL;
+@@ -331,7 +331,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+                                * as cifs_put_tcp_session takes a higher lock
+                                * i.e. cifs_tcp_ses_lock
+                                */
+-                              cifs_put_tcp_session(server, 1);
++                              cifs_put_tcp_session(server, from_reconnect);
+                               server->terminate = true;
+                               cifs_signal_cifsd_for_reconnect(server, false);
+@@ -504,7 +504,7 @@ static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
+ {
+       int rc;
+-      rc = smb2_reconnect(smb2_command, tcon, server);
++      rc = smb2_reconnect(smb2_command, tcon, server, false);
+       if (rc)
+               return rc;
+@@ -3924,6 +3924,15 @@ void smb2_reconnect_server(struct work_struct *work)
+       int rc;
+       bool resched = false;
++      /* first check if ref count has reached 0, if not inc ref count */
++      spin_lock(&cifs_tcp_ses_lock);
++      if (!server->srv_count) {
++              spin_unlock(&cifs_tcp_ses_lock);
++              return;
++      }
++      server->srv_count++;
++      spin_unlock(&cifs_tcp_ses_lock);
++
+       /* If server is a channel, select the primary channel */
+       pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
+@@ -3981,17 +3990,10 @@ void smb2_reconnect_server(struct work_struct *work)
+               }
+               spin_unlock(&ses->chan_lock);
+       }
+-      /*
+-       * Get the reference to server struct to be sure that the last call of
+-       * cifs_put_tcon() in the loop below won't release the server pointer.
+-       */
+-      if (tcon_exist || ses_exist)
+-              server->srv_count++;
+-
+       spin_unlock(&cifs_tcp_ses_lock);
+       list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
+-              rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
++              rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true);
+               if (!rc)
+                       cifs_reopen_persistent_handles(tcon);
+               else
+@@ -4024,7 +4026,7 @@ void smb2_reconnect_server(struct work_struct *work)
+       /* now reconnect sessions for necessary channels */
+       list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
+               tcon->ses = ses;
+-              rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server);
++              rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true);
+               if (rc)
+                       resched = true;
+               list_del_init(&ses->rlist);
+@@ -4039,8 +4041,7 @@ void smb2_reconnect_server(struct work_struct *work)
+       mutex_unlock(&pserver->reconnect_mutex);
+       /* now we can safely release srv struct */
+-      if (tcon_exist || ses_exist)
+-              cifs_put_tcp_session(server, 1);
++      cifs_put_tcp_session(server, true);
+ }
+ int
+-- 
+2.43.0
+
diff --git a/queue-6.6/cifs-update-iface_last_update-on-each-query-and-upda.patch b/queue-6.6/cifs-update-iface_last_update-on-each-query-and-upda.patch
new file mode 100644 (file)
index 0000000..58bcdc3
--- /dev/null
@@ -0,0 +1,62 @@
+From 25c77fdd03109541f14ba45bbc7b11692da19709 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 12:51:49 +0000
+Subject: cifs: update iface_last_update on each query-and-update
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 78e727e58e54efca4c23863fbd9e16e9d2d83f81 ]
+
+iface_last_update was an unused field when it was introduced.
+Later, when we had periodic update of server interface list,
+this field was used regularly to decide when to update next.
+
+However, with the new logic of updating the interfaces, it
+becomes crucial that this field be updated whenever
+parse_server_interfaces runs successfully.
+
+This change updates this field when either the server does
+not support query of interfaces; so that we do not query
+the interfaces repeatedly. It also updates the field when
+the function reaches the end.
+
+Fixes: aa45dadd34e4 ("cifs: change iface_list from array to sorted linked list")
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/smb2ops.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 8caf2cefc8a7..e33ed0fbc318 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -615,6 +615,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+                                "Empty network interface list returned by server %s\n",
+                                ses->server->hostname);
+               rc = -EOPNOTSUPP;
++              ses->iface_last_update = jiffies;
+               goto out;
+       }
+@@ -712,7 +713,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+               ses->iface_count++;
+               spin_unlock(&ses->iface_lock);
+-              ses->iface_last_update = jiffies;
+ next_iface:
+               nb_iface++;
+               next = le32_to_cpu(p->Next);
+@@ -734,6 +734,8 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+       if ((bytes_left > 8) || p->Next)
+               cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
++      ses->iface_last_update = jiffies;
++
+ out:
+       /*
+        * Go through the list again and put the inactive entries
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fix-null-pointer-in-channel-unregistration.patch b/queue-6.6/dmaengine-fix-null-pointer-in-channel-unregistration.patch
new file mode 100644 (file)
index 0000000..0c20df1
--- /dev/null
@@ -0,0 +1,55 @@
+From 723056ffcc9eaf4dd2e102cfe0897781b1060f55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Dec 2023 17:04:52 +0100
+Subject: dmaengine: fix NULL pointer in channel unregistration function
+
+From: Amelie Delaunay <amelie.delaunay@foss.st.com>
+
+[ Upstream commit f5c24d94512f1b288262beda4d3dcb9629222fc7 ]
+
+__dma_async_device_channel_register() can fail. In case of failure,
+chan->local is freed (with free_percpu()), and chan->local is nullified.
+When dma_async_device_unregister() is called (because of managed API or
+intentionally by DMA controller driver), channels are unconditionally
+unregistered, leading to this NULL pointer:
+[    1.318693] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0
+[...]
+[    1.484499] Call trace:
+[    1.486930]  device_del+0x40/0x394
+[    1.490314]  device_unregister+0x20/0x7c
+[    1.494220]  __dma_async_device_channel_unregister+0x68/0xc0
+
+Look at dma_async_device_register() function error path, channel device
+unregistration is done only if chan->local is not NULL.
+
+Then add the same condition at the beginning of
+__dma_async_device_channel_unregister() function, to avoid NULL pointer
+issue whatever the API used to reach this function.
+
+Fixes: d2fb0a043838 ("dmaengine: break out channel registration")
+Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Link: https://lore.kernel.org/r/20231213160452.2598073-1-amelie.delaunay@foss.st.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/dmaengine.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index b7388ae62d7f..491b22240221 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -1103,6 +1103,9 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_register);
+ static void __dma_async_device_channel_unregister(struct dma_device *device,
+                                                 struct dma_chan *chan)
+ {
++      if (chan->local == NULL)
++              return;
++
+       WARN_ONCE(!device->device_release && chan->client_count,
+                 "%s called while %d clients hold a reference\n",
+                 __func__, chan->client_count);
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch b/queue-6.6/dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch
new file mode 100644 (file)
index 0000000..f1eadff
--- /dev/null
@@ -0,0 +1,58 @@
+From 70e27894308fae25daf1e05d775cdd2d16cc7b7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Nov 2023 10:48:21 -0500
+Subject: dmaengine: fsl-edma: fix eDMAv4 channel allocation issue
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit dc51b4442dd94ab12c146c1897bbdb40e16d5636 ]
+
+The eDMAv4 channel mux has a limitation where certain requests must use
+even channels, while others must use odd numbers.
+
+Add two flags (ARGS_EVEN_CH and ARGS_ODD_CH) to reflect this limitation.
+The device tree source (dts) files need to be updated accordingly.
+
+This issue was identified by the following commit:
+commit a725990557e7 ("arm64: dts: imx93: Fix the dmas entries order")
+
+Reverting channel orders triggered this problem.
+
+Fixes: 72f5801a4e2b ("dmaengine: fsl-edma: integrate v3 support")
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20231114154824.3617255-2-Frank.Li@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-main.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index 00cb70aca34a..30df55da4dbb 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -26,6 +26,8 @@
+ #define ARGS_RX                         BIT(0)
+ #define ARGS_REMOTE                     BIT(1)
+ #define ARGS_MULTI_FIFO                 BIT(2)
++#define ARGS_EVEN_CH                    BIT(3)
++#define ARGS_ODD_CH                     BIT(4)
+ static void fsl_edma_synchronize(struct dma_chan *chan)
+ {
+@@ -159,6 +161,12 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
+               fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE;
+               fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO;
++              if ((dma_spec->args[2] & ARGS_EVEN_CH) && (i & 0x1))
++                      continue;
++
++              if ((dma_spec->args[2] & ARGS_ODD_CH) && !(i & 0x1))
++                      continue;
++
+               if (!b_chmux && i == dma_spec->args[0]) {
+                       chan = dma_get_slave_channel(chan);
+                       chan->device->privatecnt++;
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch b/queue-6.6/dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch
new file mode 100644 (file)
index 0000000..5f5069e
--- /dev/null
@@ -0,0 +1,72 @@
+From e62a16ef2b0f028e5d22351c020db283f51df1cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Dec 2023 10:21:58 +0800
+Subject: dmaengine: idxd: Move dma_free_coherent() out of spinlocked context
+
+From: Rex Zhang <rex.zhang@intel.com>
+
+[ Upstream commit e271c0ba3f919c48e90c64b703538fbb7865cb63 ]
+
+Task may be rescheduled within dma_free_coherent(). So dma_free_coherent()
+can't be called between spin_lock() and spin_unlock() to avoid Call Trace:
+    Call Trace:
+    <TASK>
+    dump_stack_lvl+0x37/0x50
+    __might_resched+0x16a/0x1c0
+    vunmap+0x2c/0x70
+    __iommu_dma_free+0x96/0x100
+    idxd_device_evl_free+0xd5/0x100 [idxd]
+    device_release_driver_internal+0x197/0x200
+    unbind_store+0xa1/0xb0
+    kernfs_fop_write_iter+0x120/0x1c0
+    vfs_write+0x2d3/0x400
+    ksys_write+0x63/0xe0
+    do_syscall_64+0x44/0xa0
+    entry_SYSCALL_64_after_hwframe+0x6e/0xd8
+Move it out of the context.
+
+Fixes: 244da66cda35 ("dmaengine: idxd: setup event log configuration")
+Signed-off-by: Rex Zhang <rex.zhang@intel.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Reviewed-by: Fenghua Yu <fenghua.yu@intel.com>
+Link: https://lore.kernel.org/r/20231212022158.358619-2-rex.zhang@intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/idxd/device.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
+index 8f754f922217..fa0f880beae6 100644
+--- a/drivers/dma/idxd/device.c
++++ b/drivers/dma/idxd/device.c
+@@ -802,6 +802,9 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
+ static void idxd_device_evl_free(struct idxd_device *idxd)
+ {
++      void *evl_log;
++      unsigned int evl_log_size;
++      dma_addr_t evl_dma;
+       union gencfg_reg gencfg;
+       union genctrl_reg genctrl;
+       struct device *dev = &idxd->pdev->dev;
+@@ -822,11 +825,15 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
+       iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET);
+       iowrite64(0, idxd->reg_base + IDXD_EVLCFG_OFFSET + 8);
+-      dma_free_coherent(dev, evl->log_size, evl->log, evl->dma);
+       bitmap_free(evl->bmap);
++      evl_log = evl->log;
++      evl_log_size = evl->log_size;
++      evl_dma = evl->dma;
+       evl->log = NULL;
+       evl->size = IDXD_EVL_SIZE_MIN;
+       spin_unlock(&evl->lock);
++
++      dma_free_coherent(dev, evl_log_size, evl_log, evl_dma);
+ }
+ static void idxd_group_config_write(struct idxd_group *group)
+-- 
+2.43.0
+
diff --git a/queue-6.6/docs-kernel_feat.py-fix-potential-command-injection.patch b/queue-6.6/docs-kernel_feat.py-fix-potential-command-injection.patch
new file mode 100644 (file)
index 0000000..70f88aa
--- /dev/null
@@ -0,0 +1,316 @@
+From fc3445d032b02beb25fe4460daae50404dc8c441 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Jan 2024 18:47:58 +0100
+Subject: docs: kernel_feat.py: fix potential command injection
+
+From: Vegard Nossum <vegard.nossum@oracle.com>
+
+[ Upstream commit c48a7c44a1d02516309015b6134c9bb982e17008 ]
+
+The kernel-feat directive passes its argument straight to the shell.
+This is unfortunate and unnecessary.
+
+Let's always use paths relative to $srctree/Documentation/ and use
+subprocess.check_call() instead of subprocess.Popen(shell=True).
+
+This also makes the code shorter.
+
+This is analogous to commit 3231dd586277 ("docs: kernel_abi.py: fix
+command injection") where we did exactly the same thing for
+kernel_abi.py, somehow I completely missed this one.
+
+Link: https://fosstodon.org/@jani/111676532203641247
+Reported-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jonathan Corbet <corbet@lwn.net>
+Link: https://lore.kernel.org/r/20240110174758.3680506-1-vegard.nossum@oracle.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/admin-guide/features.rst        |  2 +-
+ Documentation/arch/arc/features.rst           |  2 +-
+ Documentation/arch/arm/features.rst           |  2 +-
+ Documentation/arch/arm64/features.rst         |  2 +-
+ Documentation/arch/loongarch/features.rst     |  2 +-
+ Documentation/arch/m68k/features.rst          |  2 +-
+ Documentation/arch/mips/features.rst          |  2 +-
+ Documentation/arch/nios2/features.rst         |  2 +-
+ Documentation/arch/openrisc/features.rst      |  2 +-
+ Documentation/arch/parisc/features.rst        |  2 +-
+ Documentation/arch/s390/features.rst          |  2 +-
+ Documentation/arch/sh/features.rst            |  2 +-
+ Documentation/arch/sparc/features.rst         |  2 +-
+ Documentation/arch/x86/features.rst           |  2 +-
+ Documentation/arch/xtensa/features.rst        |  2 +-
+ Documentation/powerpc/features.rst            |  2 +-
+ Documentation/riscv/features.rst              |  2 +-
+ Documentation/sphinx/kernel_feat.py           | 55 ++++---------------
+ .../zh_CN/arch/loongarch/features.rst         |  2 +-
+ .../translations/zh_CN/arch/mips/features.rst |  2 +-
+ 20 files changed, 30 insertions(+), 63 deletions(-)
+
+diff --git a/Documentation/admin-guide/features.rst b/Documentation/admin-guide/features.rst
+index 8c167082a84f..7651eca38227 100644
+--- a/Documentation/admin-guide/features.rst
++++ b/Documentation/admin-guide/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features
++.. kernel-feat:: features
+diff --git a/Documentation/arch/arc/features.rst b/Documentation/arch/arc/features.rst
+index b793583d688a..49ff446ff744 100644
+--- a/Documentation/arch/arc/features.rst
++++ b/Documentation/arch/arc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features arc
++.. kernel-feat:: features arc
+diff --git a/Documentation/arch/arm/features.rst b/Documentation/arch/arm/features.rst
+index 7414ec03dd15..0e76aaf68eca 100644
+--- a/Documentation/arch/arm/features.rst
++++ b/Documentation/arch/arm/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features arm
++.. kernel-feat:: features arm
+diff --git a/Documentation/arch/arm64/features.rst b/Documentation/arch/arm64/features.rst
+index dfa4cb3cd3ef..03321f4309d0 100644
+--- a/Documentation/arch/arm64/features.rst
++++ b/Documentation/arch/arm64/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features arm64
++.. kernel-feat:: features arm64
+diff --git a/Documentation/arch/loongarch/features.rst b/Documentation/arch/loongarch/features.rst
+index ebacade3ea45..009f44c7951f 100644
+--- a/Documentation/arch/loongarch/features.rst
++++ b/Documentation/arch/loongarch/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features loongarch
++.. kernel-feat:: features loongarch
+diff --git a/Documentation/arch/m68k/features.rst b/Documentation/arch/m68k/features.rst
+index 5107a2119472..de7f0ccf7fc8 100644
+--- a/Documentation/arch/m68k/features.rst
++++ b/Documentation/arch/m68k/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features m68k
++.. kernel-feat:: features m68k
+diff --git a/Documentation/arch/mips/features.rst b/Documentation/arch/mips/features.rst
+index 1973d729b29a..6e0ffe3e7354 100644
+--- a/Documentation/arch/mips/features.rst
++++ b/Documentation/arch/mips/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features mips
++.. kernel-feat:: features mips
+diff --git a/Documentation/arch/nios2/features.rst b/Documentation/arch/nios2/features.rst
+index 8449e63f69b2..89913810ccb5 100644
+--- a/Documentation/arch/nios2/features.rst
++++ b/Documentation/arch/nios2/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features nios2
++.. kernel-feat:: features nios2
+diff --git a/Documentation/arch/openrisc/features.rst b/Documentation/arch/openrisc/features.rst
+index 3f7c40d219f2..bae2e25adfd6 100644
+--- a/Documentation/arch/openrisc/features.rst
++++ b/Documentation/arch/openrisc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features openrisc
++.. kernel-feat:: features openrisc
+diff --git a/Documentation/arch/parisc/features.rst b/Documentation/arch/parisc/features.rst
+index 501d7c450037..b3aa4d243b93 100644
+--- a/Documentation/arch/parisc/features.rst
++++ b/Documentation/arch/parisc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features parisc
++.. kernel-feat:: features parisc
+diff --git a/Documentation/arch/s390/features.rst b/Documentation/arch/s390/features.rst
+index 57c296a9d8f3..2883dc950681 100644
+--- a/Documentation/arch/s390/features.rst
++++ b/Documentation/arch/s390/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features s390
++.. kernel-feat:: features s390
+diff --git a/Documentation/arch/sh/features.rst b/Documentation/arch/sh/features.rst
+index f722af3b6c99..fae48fe81e9b 100644
+--- a/Documentation/arch/sh/features.rst
++++ b/Documentation/arch/sh/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features sh
++.. kernel-feat:: features sh
+diff --git a/Documentation/arch/sparc/features.rst b/Documentation/arch/sparc/features.rst
+index c0c92468b0fe..96835b6d598a 100644
+--- a/Documentation/arch/sparc/features.rst
++++ b/Documentation/arch/sparc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features sparc
++.. kernel-feat:: features sparc
+diff --git a/Documentation/arch/x86/features.rst b/Documentation/arch/x86/features.rst
+index b663f15053ce..a33616346a38 100644
+--- a/Documentation/arch/x86/features.rst
++++ b/Documentation/arch/x86/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features x86
++.. kernel-feat:: features x86
+diff --git a/Documentation/arch/xtensa/features.rst b/Documentation/arch/xtensa/features.rst
+index 6b92c7bfa19d..28dcce1759be 100644
+--- a/Documentation/arch/xtensa/features.rst
++++ b/Documentation/arch/xtensa/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features xtensa
++.. kernel-feat:: features xtensa
+diff --git a/Documentation/powerpc/features.rst b/Documentation/powerpc/features.rst
+index aeae73df86b0..ee4b95e04202 100644
+--- a/Documentation/powerpc/features.rst
++++ b/Documentation/powerpc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features powerpc
++.. kernel-feat:: features powerpc
+diff --git a/Documentation/riscv/features.rst b/Documentation/riscv/features.rst
+index c70ef6ac2368..36e90144adab 100644
+--- a/Documentation/riscv/features.rst
++++ b/Documentation/riscv/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+-.. kernel-feat:: $srctree/Documentation/features riscv
++.. kernel-feat:: features riscv
+diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py
+index 27b701ed3681..bdfaa3e4b202 100644
+--- a/Documentation/sphinx/kernel_feat.py
++++ b/Documentation/sphinx/kernel_feat.py
+@@ -37,8 +37,6 @@ import re
+ import subprocess
+ import sys
+-from os import path
+-
+ from docutils import nodes, statemachine
+ from docutils.statemachine import ViewList
+ from docutils.parsers.rst import directives, Directive
+@@ -76,33 +74,26 @@ class KernelFeat(Directive):
+         self.state.document.settings.env.app.warn(message, prefix="")
+     def run(self):
+-
+         doc = self.state.document
+         if not doc.settings.file_insertion_enabled:
+             raise self.warning("docutils: file insertion disabled")
+         env = doc.settings.env
+-        cwd = path.dirname(doc.current_source)
+-        cmd = "get_feat.pl rest --enable-fname --dir "
+-        cmd += self.arguments[0]
+-
+-        if len(self.arguments) > 1:
+-            cmd += " --arch " + self.arguments[1]
+-        srctree = path.abspath(os.environ["srctree"])
++        srctree = os.path.abspath(os.environ["srctree"])
+-        fname = cmd
++        args = [
++            os.path.join(srctree, 'scripts/get_feat.pl'),
++            'rest',
++            '--enable-fname',
++            '--dir',
++            os.path.join(srctree, 'Documentation', self.arguments[0]),
++        ]
+-        # extend PATH with $(srctree)/scripts
+-        path_env = os.pathsep.join([
+-            srctree + os.sep + "scripts",
+-            os.environ["PATH"]
+-        ])
+-        shell_env = os.environ.copy()
+-        shell_env["PATH"]    = path_env
+-        shell_env["srctree"] = srctree
++        if len(self.arguments) > 1:
++            args.extend(['--arch', self.arguments[1]])
+-        lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
++        lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
+         line_regex = re.compile("^\.\. FILE (\S+)$")
+@@ -121,30 +112,6 @@ class KernelFeat(Directive):
+         nodeList = self.nestedParse(out_lines, fname)
+         return nodeList
+-    def runCmd(self, cmd, **kwargs):
+-        u"""Run command ``cmd`` and return its stdout as unicode."""
+-
+-        try:
+-            proc = subprocess.Popen(
+-                cmd
+-                , stdout = subprocess.PIPE
+-                , stderr = subprocess.PIPE
+-                , **kwargs
+-            )
+-            out, err = proc.communicate()
+-
+-            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
+-
+-            if proc.returncode != 0:
+-                raise self.severe(
+-                    u"command '%s' failed with return code %d"
+-                    % (cmd, proc.returncode)
+-                )
+-        except OSError as exc:
+-            raise self.severe(u"problems with '%s' directive: %s."
+-                              % (self.name, ErrorString(exc)))
+-        return out
+-
+     def nestedParse(self, lines, fname):
+         content = ViewList()
+         node    = nodes.section()
+diff --git a/Documentation/translations/zh_CN/arch/loongarch/features.rst b/Documentation/translations/zh_CN/arch/loongarch/features.rst
+index 82bfac180bdc..cec38dda8298 100644
+--- a/Documentation/translations/zh_CN/arch/loongarch/features.rst
++++ b/Documentation/translations/zh_CN/arch/loongarch/features.rst
+@@ -5,4 +5,4 @@
+ :Original: Documentation/arch/loongarch/features.rst
+ :Translator: Huacai Chen <chenhuacai@loongson.cn>
+-.. kernel-feat:: $srctree/Documentation/features loongarch
++.. kernel-feat:: features loongarch
+diff --git a/Documentation/translations/zh_CN/arch/mips/features.rst b/Documentation/translations/zh_CN/arch/mips/features.rst
+index da1b956e4a40..0d6df97db069 100644
+--- a/Documentation/translations/zh_CN/arch/mips/features.rst
++++ b/Documentation/translations/zh_CN/arch/mips/features.rst
+@@ -10,4 +10,4 @@
+ .. _cn_features:
+-.. kernel-feat:: $srctree/Documentation/features mips
++.. kernel-feat:: features mips
+-- 
+2.43.0
+
diff --git a/queue-6.6/docs-sparse-add-sparse.rst-to-toctree.patch b/queue-6.6/docs-sparse-add-sparse.rst-to-toctree.patch
new file mode 100644 (file)
index 0000000..38f5343
--- /dev/null
@@ -0,0 +1,91 @@
+From 0b21551690eba2dfcb2b9ad0a8f52097515ab394 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 Sep 2023 13:25:12 +0800
+Subject: docs: sparse: add sparse.rst to toctree
+
+From: Min-Hua Chen <minhuadotchen@gmail.com>
+
+[ Upstream commit c9ad95adc096f25004d4192258863806a68a9bc8 ]
+
+Add sparst.rst to toctree, so it can be part of the docs build.
+
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Suggested-by: Jonathan Corbet <corbet@lwn.net>
+Signed-off-by: Min-Hua Chen <minhuadotchen@gmail.com>
+Signed-off-by: Jonathan Corbet <corbet@lwn.net>
+Link: https://lore.kernel.org/r/20230902052512.12184-4-minhuadotchen@gmail.com
+Stable-dep-of: c48a7c44a1d0 ("docs: kernel_feat.py: fix potential command injection")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../translations/zh_TW/dev-tools/index.rst    | 40 +++++++++++++++++++
+ Documentation/translations/zh_TW/index.rst    |  2 +-
+ 2 files changed, 41 insertions(+), 1 deletion(-)
+ create mode 100644 Documentation/translations/zh_TW/dev-tools/index.rst
+
+diff --git a/Documentation/translations/zh_TW/dev-tools/index.rst b/Documentation/translations/zh_TW/dev-tools/index.rst
+new file mode 100644
+index 000000000000..8f101db5a07f
+--- /dev/null
++++ b/Documentation/translations/zh_TW/dev-tools/index.rst
+@@ -0,0 +1,40 @@
++.. include:: ../disclaimer-zh_TW.rst
++
++:Original: Documentation/dev-tools/index.rst
++:Translator: Min-Hua Chen <minhuadotchen@gmail.com>
++
++============
++內核開發工具
++============
++
++本文檔是有關內核開發工具文檔的合集。
++目前這些文檔已經整理在一起,不需要再花費額外的精力。
++歡迎任何補丁。
++
++有關測試專用工具的簡要概述,參見
++Documentation/dev-tools/testing-overview.rst
++
++.. class:: toc-title
++
++         目錄
++
++.. toctree::
++   :maxdepth: 2
++
++   sparse
++
++Todolist:
++
++ - coccinelle
++ - kcov
++ - ubsan
++ - kmemleak
++ - kcsan
++ - kfence
++ - kgdb
++ - kselftest
++ - kunit/index
++ - testing-overview
++ - gcov
++ - kasan
++ - gdb-kernel-debugging
+diff --git a/Documentation/translations/zh_TW/index.rst b/Documentation/translations/zh_TW/index.rst
+index d1cf0b4d8e46..ffcaf3272fe7 100644
+--- a/Documentation/translations/zh_TW/index.rst
++++ b/Documentation/translations/zh_TW/index.rst
+@@ -55,11 +55,11 @@ TODOList:
+    :maxdepth: 1
+    process/license-rules
++   dev-tools/index
+ TODOList:
+ * doc-guide/index
+-* dev-tools/index
+ * dev-tools/testing-overview
+ * kernel-hacking/index
+ * rust/index
+-- 
+2.43.0
+
diff --git a/queue-6.6/docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch b/queue-6.6/docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch
new file mode 100644 (file)
index 0000000..7576dde
--- /dev/null
@@ -0,0 +1,36 @@
+From 015fb88e61c923ace77301975fbbb1ccb1600574 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 Sep 2023 13:25:10 +0800
+Subject: docs: sparse: move TW sparse.txt to TW dev-tools
+
+From: Min-Hua Chen <minhuadotchen@gmail.com>
+
+[ Upstream commit 253f68f413a87a4e2bd93e61b00410e5e1b7b774 ]
+
+Follow Randy's advice [1] to move
+Documentation/translations/zh_TW/sparse.txt
+to
+Documentation/translations/zh_TW/dev-tools/sparse.txt
+
+[1] https://lore.kernel.org/lkml/bfab7c5b-e4d3-d8d9-afab-f43c0cdf26cf@infradead.org/
+
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Suggested-by: Randy Dunlap <rdunlap@infradead.org>
+Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Min-Hua Chen <minhuadotchen@gmail.com>
+Signed-off-by: Jonathan Corbet <corbet@lwn.net>
+Link: https://lore.kernel.org/r/20230902052512.12184-2-minhuadotchen@gmail.com
+Stable-dep-of: c48a7c44a1d0 ("docs: kernel_feat.py: fix potential command injection")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/translations/zh_TW/{ => dev-tools}/sparse.txt | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+ rename Documentation/translations/zh_TW/{ => dev-tools}/sparse.txt (100%)
+
+diff --git a/Documentation/translations/zh_TW/sparse.txt b/Documentation/translations/zh_TW/dev-tools/sparse.txt
+similarity index 100%
+rename from Documentation/translations/zh_TW/sparse.txt
+rename to Documentation/translations/zh_TW/dev-tools/sparse.txt
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad7091r-allow-users-to-configure-device-even.patch b/queue-6.6/iio-adc-ad7091r-allow-users-to-configure-device-even.patch
new file mode 100644 (file)
index 0000000..1f5f6b5
--- /dev/null
@@ -0,0 +1,295 @@
+From 31d9518eba1dcf440452f27f9b15fd44ccc47e54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 17:26:01 -0300
+Subject: iio: adc: ad7091r: Allow users to configure device events
+
+From: Marcelo Schmitt <marcelo.schmitt@analog.com>
+
+[ Upstream commit 020e71c7ffc25dfe29ed9be6c2d39af7bd7f661f ]
+
+AD7091R-5 devices are supported by the ad7091r-5 driver together with
+the ad7091r-base driver. Those drivers declared iio events for notifying
+user space when ADC readings fall bellow the thresholds of low limit
+registers or above the values set in high limit registers.
+However, to configure iio events and their thresholds, a set of callback
+functions must be implemented and those were not present until now.
+The consequence of trying to configure ad7091r-5 events without the
+proper callback functions was a null pointer dereference in the kernel
+because the pointers to the callback functions were not set.
+
+Implement event configuration callbacks allowing users to read/write
+event thresholds and enable/disable event generation.
+
+Since the event spec structs are generic to AD7091R devices, also move
+those from the ad7091r-5 driver the base driver so they can be reused
+when support for ad7091r-2/-4/-8 be added.
+
+Fixes: ca69300173b6 ("iio: adc: Add support for AD7091R5 ADC")
+Suggested-by: David Lechner <dlechner@baylibre.com>
+Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Link: https://lore.kernel.org/r/59552d3548dabd56adc3107b7b4869afee2b0c3c.1703013352.git.marcelo.schmitt1@gmail.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7091r-base.c | 156 +++++++++++++++++++++++++++++++++
+ drivers/iio/adc/ad7091r-base.h |   6 ++
+ drivers/iio/adc/ad7091r5.c     |  28 +-----
+ 3 files changed, 166 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
+index 8aaa854f816f..3d36bcd26b0c 100644
+--- a/drivers/iio/adc/ad7091r-base.c
++++ b/drivers/iio/adc/ad7091r-base.c
+@@ -6,6 +6,7 @@
+  */
+ #include <linux/bitops.h>
++#include <linux/bitfield.h>
+ #include <linux/iio/events.h>
+ #include <linux/iio/iio.h>
+ #include <linux/interrupt.h>
+@@ -50,6 +51,27 @@ struct ad7091r_state {
+       struct mutex lock; /*lock to prevent concurent reads */
+ };
++const struct iio_event_spec ad7091r_events[] = {
++      {
++              .type = IIO_EV_TYPE_THRESH,
++              .dir = IIO_EV_DIR_RISING,
++              .mask_separate = BIT(IIO_EV_INFO_VALUE) |
++                               BIT(IIO_EV_INFO_ENABLE),
++      },
++      {
++              .type = IIO_EV_TYPE_THRESH,
++              .dir = IIO_EV_DIR_FALLING,
++              .mask_separate = BIT(IIO_EV_INFO_VALUE) |
++                               BIT(IIO_EV_INFO_ENABLE),
++      },
++      {
++              .type = IIO_EV_TYPE_THRESH,
++              .dir = IIO_EV_DIR_EITHER,
++              .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
++      },
++};
++EXPORT_SYMBOL_NS_GPL(ad7091r_events, IIO_AD7091R);
++
+ static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
+ {
+       int ret, conf;
+@@ -169,8 +191,142 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
+       return ret;
+ }
++static int ad7091r_read_event_config(struct iio_dev *indio_dev,
++                                   const struct iio_chan_spec *chan,
++                                   enum iio_event_type type,
++                                   enum iio_event_direction dir)
++{
++      struct ad7091r_state *st = iio_priv(indio_dev);
++      int val, ret;
++
++      switch (dir) {
++      case IIO_EV_DIR_RISING:
++              ret = regmap_read(st->map,
++                                AD7091R_REG_CH_HIGH_LIMIT(chan->channel),
++                                &val);
++              if (ret)
++                      return ret;
++              return val != AD7091R_HIGH_LIMIT;
++      case IIO_EV_DIR_FALLING:
++              ret = regmap_read(st->map,
++                                AD7091R_REG_CH_LOW_LIMIT(chan->channel),
++                                &val);
++              if (ret)
++                      return ret;
++              return val != AD7091R_LOW_LIMIT;
++      default:
++              return -EINVAL;
++      }
++}
++
++static int ad7091r_write_event_config(struct iio_dev *indio_dev,
++                                    const struct iio_chan_spec *chan,
++                                    enum iio_event_type type,
++                                    enum iio_event_direction dir, int state)
++{
++      struct ad7091r_state *st = iio_priv(indio_dev);
++
++      if (state) {
++              return regmap_set_bits(st->map, AD7091R_REG_CONF,
++                                     AD7091R_REG_CONF_ALERT_EN);
++      } else {
++              /*
++               * Set thresholds either to 0 or to 2^12 - 1 as appropriate to
++               * prevent alerts and thus disable event generation.
++               */
++              switch (dir) {
++              case IIO_EV_DIR_RISING:
++                      return regmap_write(st->map,
++                                          AD7091R_REG_CH_HIGH_LIMIT(chan->channel),
++                                          AD7091R_HIGH_LIMIT);
++              case IIO_EV_DIR_FALLING:
++                      return regmap_write(st->map,
++                                          AD7091R_REG_CH_LOW_LIMIT(chan->channel),
++                                          AD7091R_LOW_LIMIT);
++              default:
++                      return -EINVAL;
++              }
++      }
++}
++
++static int ad7091r_read_event_value(struct iio_dev *indio_dev,
++                                  const struct iio_chan_spec *chan,
++                                  enum iio_event_type type,
++                                  enum iio_event_direction dir,
++                                  enum iio_event_info info, int *val, int *val2)
++{
++      struct ad7091r_state *st = iio_priv(indio_dev);
++      int ret;
++
++      switch (info) {
++      case IIO_EV_INFO_VALUE:
++              switch (dir) {
++              case IIO_EV_DIR_RISING:
++                      ret = regmap_read(st->map,
++                                        AD7091R_REG_CH_HIGH_LIMIT(chan->channel),
++                                        val);
++                      if (ret)
++                              return ret;
++                      return IIO_VAL_INT;
++              case IIO_EV_DIR_FALLING:
++                      ret = regmap_read(st->map,
++                                        AD7091R_REG_CH_LOW_LIMIT(chan->channel),
++                                        val);
++                      if (ret)
++                              return ret;
++                      return IIO_VAL_INT;
++              default:
++                      return -EINVAL;
++              }
++      case IIO_EV_INFO_HYSTERESIS:
++              ret = regmap_read(st->map,
++                                AD7091R_REG_CH_HYSTERESIS(chan->channel),
++                                val);
++              if (ret)
++                      return ret;
++              return IIO_VAL_INT;
++      default:
++              return -EINVAL;
++      }
++}
++
++static int ad7091r_write_event_value(struct iio_dev *indio_dev,
++                                   const struct iio_chan_spec *chan,
++                                   enum iio_event_type type,
++                                   enum iio_event_direction dir,
++                                   enum iio_event_info info, int val, int val2)
++{
++      struct ad7091r_state *st = iio_priv(indio_dev);
++
++      switch (info) {
++      case IIO_EV_INFO_VALUE:
++              switch (dir) {
++              case IIO_EV_DIR_RISING:
++                      return regmap_write(st->map,
++                                          AD7091R_REG_CH_HIGH_LIMIT(chan->channel),
++                                          val);
++              case IIO_EV_DIR_FALLING:
++                      return regmap_write(st->map,
++                                          AD7091R_REG_CH_LOW_LIMIT(chan->channel),
++                                          val);
++              default:
++                      return -EINVAL;
++              }
++      case IIO_EV_INFO_HYSTERESIS:
++              return regmap_write(st->map,
++                                  AD7091R_REG_CH_HYSTERESIS(chan->channel),
++                                  val);
++      default:
++              return -EINVAL;
++      }
++}
++
+ static const struct iio_info ad7091r_info = {
+       .read_raw = ad7091r_read_raw,
++      .read_event_config = &ad7091r_read_event_config,
++      .write_event_config = &ad7091r_write_event_config,
++      .read_event_value = &ad7091r_read_event_value,
++      .write_event_value = &ad7091r_write_event_value,
+ };
+ static irqreturn_t ad7091r_event_handler(int irq, void *private)
+diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h
+index 509748aef9b1..7a78976a2f80 100644
+--- a/drivers/iio/adc/ad7091r-base.h
++++ b/drivers/iio/adc/ad7091r-base.h
+@@ -8,6 +8,10 @@
+ #ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__
+ #define __DRIVERS_IIO_ADC_AD7091R_BASE_H__
++/* AD7091R_REG_CH_LIMIT */
++#define AD7091R_HIGH_LIMIT            0xFFF
++#define AD7091R_LOW_LIMIT             0x0
++
+ struct device;
+ struct ad7091r_state;
+@@ -17,6 +21,8 @@ struct ad7091r_chip_info {
+       unsigned int vref_mV;
+ };
++extern const struct iio_event_spec ad7091r_events[3];
++
+ extern const struct regmap_config ad7091r_regmap_config;
+ int ad7091r_probe(struct device *dev, const char *name,
+diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c
+index 2f048527b7b7..dae98c95ebb8 100644
+--- a/drivers/iio/adc/ad7091r5.c
++++ b/drivers/iio/adc/ad7091r5.c
+@@ -12,26 +12,6 @@
+ #include "ad7091r-base.h"
+-static const struct iio_event_spec ad7091r5_events[] = {
+-      {
+-              .type = IIO_EV_TYPE_THRESH,
+-              .dir = IIO_EV_DIR_RISING,
+-              .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+-                               BIT(IIO_EV_INFO_ENABLE),
+-      },
+-      {
+-              .type = IIO_EV_TYPE_THRESH,
+-              .dir = IIO_EV_DIR_FALLING,
+-              .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+-                               BIT(IIO_EV_INFO_ENABLE),
+-      },
+-      {
+-              .type = IIO_EV_TYPE_THRESH,
+-              .dir = IIO_EV_DIR_EITHER,
+-              .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+-      },
+-};
+-
+ #define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \
+       .type = IIO_VOLTAGE, \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+@@ -44,10 +24,10 @@ static const struct iio_event_spec ad7091r5_events[] = {
+       .scan_type.realbits = bits, \
+ }
+ static const struct iio_chan_spec ad7091r5_channels_irq[] = {
+-      AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
+-      AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
+-      AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
+-      AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
++      AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
++      AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
++      AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
++      AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
+ };
+ static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch b/queue-6.6/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch
new file mode 100644 (file)
index 0000000..40d7f83
--- /dev/null
@@ -0,0 +1,67 @@
+From 2d6478fb8be7e9bcb11f74ee89e8a787c1017b2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 17:26:27 -0300
+Subject: iio: adc: ad7091r: Enable internal vref if external vref is not
+ supplied
+
+From: Marcelo Schmitt <marcelo.schmitt@analog.com>
+
+[ Upstream commit e71c5c89bcb165a02df35325aa13d1ee40112401 ]
+
+The ADC needs a voltage reference to work correctly.
+Users can provide an external voltage reference or use the chip internal
+reference to operate the ADC.
+The availability of an in chip reference for the ADC saves the user from
+having to supply an external voltage reference, which makes the external
+reference an optional property as described in the device tree
+documentation.
+Though, to use the internal reference, it must be enabled by writing to
+the configuration register.
+Enable AD7091R internal voltage reference if no external vref is supplied.
+
+Fixes: 260442cc5be4 ("iio: adc: ad7091r5: Add scale and external VREF support")
+Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Link: https://lore.kernel.org/r/b865033fa6a4fc4bf2b4a98ec51a6144e0f64f77.1703013352.git.marcelo.schmitt1@gmail.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7091r-base.c | 7 +++++++
+ drivers/iio/adc/ad7091r-base.h | 2 ++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
+index 3d36bcd26b0c..76002b91c86a 100644
+--- a/drivers/iio/adc/ad7091r-base.c
++++ b/drivers/iio/adc/ad7091r-base.c
+@@ -405,7 +405,14 @@ int ad7091r_probe(struct device *dev, const char *name,
+       if (IS_ERR(st->vref)) {
+               if (PTR_ERR(st->vref) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
++
+               st->vref = NULL;
++              /* Enable internal vref */
++              ret = regmap_set_bits(st->map, AD7091R_REG_CONF,
++                                    AD7091R_REG_CONF_INT_VREF);
++              if (ret)
++                      return dev_err_probe(st->dev, ret,
++                                           "Error on enable internal reference\n");
+       } else {
+               ret = regulator_enable(st->vref);
+               if (ret)
+diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h
+index 7a78976a2f80..b9e1c8bf3440 100644
+--- a/drivers/iio/adc/ad7091r-base.h
++++ b/drivers/iio/adc/ad7091r-base.h
+@@ -8,6 +8,8 @@
+ #ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__
+ #define __DRIVERS_IIO_ADC_AD7091R_BASE_H__
++#define AD7091R_REG_CONF_INT_VREF     BIT(0)
++
+ /* AD7091R_REG_CH_LIMIT */
+ #define AD7091R_HIGH_LIMIT            0xFFF
+ #define AD7091R_LOW_LIMIT             0x0
+-- 
+2.43.0
+
diff --git a/queue-6.6/iio-adc-ad7091r-set-alert-bit-in-config-register.patch b/queue-6.6/iio-adc-ad7091r-set-alert-bit-in-config-register.patch
new file mode 100644 (file)
index 0000000..96afcf8
--- /dev/null
@@ -0,0 +1,53 @@
+From b10c2fb17af63766edf41f5062096ba00c4ee4e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Dec 2023 14:46:37 -0300
+Subject: iio: adc: ad7091r: Set alert bit in config register
+
+From: Marcelo Schmitt <marcelo.schmitt@analog.com>
+
+[ Upstream commit 149694f5e79b0c7a36ceb76e7c0d590db8f151c1 ]
+
+The ad7091r-base driver sets up an interrupt handler for firing events
+when inputs are either above or below a certain threshold.
+However, for the interrupt signal to come from the device it must be
+configured to enable the ALERT/BUSY/GPO pin to be used as ALERT, which
+was not being done until now.
+Enable interrupt signals on the ALERT/BUSY/GPO pin by setting the proper
+bit in the configuration register.
+
+Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Link: https://lore.kernel.org/r/e8da2ee98d6df88318b14baf3dc9630e20218418.1702746240.git.marcelo.schmitt1@gmail.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 020e71c7ffc2 ("iio: adc: ad7091r: Allow users to configure device events")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7091r-base.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
+index 0e5d3d2e9c98..8aaa854f816f 100644
+--- a/drivers/iio/adc/ad7091r-base.c
++++ b/drivers/iio/adc/ad7091r-base.c
+@@ -28,6 +28,7 @@
+ #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
+ /* AD7091R_REG_CONF */
++#define AD7091R_REG_CONF_ALERT_EN   BIT(4)
+ #define AD7091R_REG_CONF_AUTO   BIT(8)
+ #define AD7091R_REG_CONF_CMD    BIT(10)
+@@ -232,6 +233,11 @@ int ad7091r_probe(struct device *dev, const char *name,
+       iio_dev->channels = chip_info->channels;
+       if (irq) {
++              ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
++                                       AD7091R_REG_CONF_ALERT_EN, BIT(4));
++              if (ret)
++                      return ret;
++
+               ret = devm_request_threaded_irq(dev, irq, NULL,
+                               ad7091r_event_handler,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, iio_dev);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-stmmac-prevent-dsa-tags-from-breaking-coe.patch b/queue-6.6/net-stmmac-prevent-dsa-tags-from-breaking-coe.patch
new file mode 100644 (file)
index 0000000..ab88344
--- /dev/null
@@ -0,0 +1,106 @@
+From e4910f6cbaeeb5ede337cab4669d21300960d1bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Jan 2024 13:19:17 +0100
+Subject: net: stmmac: Prevent DSA tags from breaking COE
+
+From: Romain Gantois <romain.gantois@bootlin.com>
+
+[ Upstream commit c2945c435c999c63e47f337bc7c13c98c21d0bcc ]
+
+Some DSA tagging protocols change the EtherType field in the MAC header
+e.g.  DSA_TAG_PROTO_(DSA/EDSA/BRCM/MTK/RTL4C_A/SJA1105). On TX these tagged
+frames are ignored by the checksum offload engine and IP header checker of
+some stmmac cores.
+
+On RX, the stmmac driver wrongly assumes that checksums have been computed
+for these tagged packets, and sets CHECKSUM_UNNECESSARY.
+
+Add an additional check in the stmmac TX and RX hotpaths so that COE is
+deactivated for packets with ethertypes that will not trigger the COE and
+IP header checks.
+
+Fixes: 6b2c6e4a938f ("net: stmmac: propagate feature flags to vlan")
+Cc:  <stable@vger.kernel.org>
+Reported-by: Richard Tresidder <rtresidd@electromag.com.au>
+Link: https://lore.kernel.org/netdev/e5c6c75f-2dfa-4e50-a1fb-6bf4cdb617c2@electromag.com.au/
+Reported-by: Romain Gantois <romain.gantois@bootlin.com>
+Link: https://lore.kernel.org/netdev/c57283ed-6b9b-b0e6-ee12-5655c1c54495@bootlin.com/
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 32 +++++++++++++++++--
+ 1 file changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 59e07efe08c9..684ec7058c82 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -4356,6 +4356,28 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
+       return NETDEV_TX_OK;
+ }
++/**
++ * stmmac_has_ip_ethertype() - Check if packet has IP ethertype
++ * @skb: socket buffer to check
++ *
++ * Check if a packet has an ethertype that will trigger the IP header checks
++ * and IP/TCP checksum engine of the stmmac core.
++ *
++ * Return: true if the ethertype can trigger the checksum engine, false
++ * otherwise
++ */
++static bool stmmac_has_ip_ethertype(struct sk_buff *skb)
++{
++      int depth = 0;
++      __be16 proto;
++
++      proto = __vlan_get_protocol(skb, eth_header_parse_protocol(skb),
++                                  &depth);
++
++      return (depth <= ETH_HLEN) &&
++              (proto == htons(ETH_P_IP) || proto == htons(ETH_P_IPV6));
++}
++
+ /**
+  *  stmmac_xmit - Tx entry point of the driver
+  *  @skb : the socket buffer
+@@ -4420,9 +4442,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+       /* DWMAC IPs can be synthesized to support tx coe only for a few tx
+        * queues. In that case, checksum offloading for those queues that don't
+        * support tx coe needs to fallback to software checksum calculation.
++       *
++       * Packets that won't trigger the COE e.g. most DSA-tagged packets will
++       * also have to be checksummed in software.
+        */
+       if (csum_insertion &&
+-          priv->plat->tx_queues_cfg[queue].coe_unsupported) {
++          (priv->plat->tx_queues_cfg[queue].coe_unsupported ||
++           !stmmac_has_ip_ethertype(skb))) {
+               if (unlikely(skb_checksum_help(skb)))
+                       goto dma_map_err;
+               csum_insertion = !csum_insertion;
+@@ -4982,7 +5008,7 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
+       stmmac_rx_vlan(priv->dev, skb);
+       skb->protocol = eth_type_trans(skb, priv->dev);
+-      if (unlikely(!coe))
++      if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb))
+               skb_checksum_none_assert(skb);
+       else
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+@@ -5498,7 +5524,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+               stmmac_rx_vlan(priv->dev, skb);
+               skb->protocol = eth_type_trans(skb, priv->dev);
+-              if (unlikely(!coe))
++              if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb))
+                       skb_checksum_none_assert(skb);
+               else
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-stmmac-tx-coe-sw-fallback.patch b/queue-6.6/net-stmmac-tx-coe-sw-fallback.patch
new file mode 100644 (file)
index 0000000..2022854
--- /dev/null
@@ -0,0 +1,80 @@
+From 071be3267bf1cf00cff09a9e6758055b060f2a7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Sep 2023 14:33:12 +0800
+Subject: net: stmmac: Tx coe sw fallback
+
+From: Rohan G Thomas <rohan.g.thomas@intel.com>
+
+[ Upstream commit 8452a05b2c633b708dbe3e742f71b24bf21fe42d ]
+
+Add sw fallback of tx checksum calculation for those tx queues that
+don't support tx checksum offloading. DW xGMAC IP can be synthesized
+such that it can support tx checksum offloading only for a few
+initial tx queues. Also as Serge pointed out, for the DW QoS IP, tx
+coe can be individually configured for each tx queue.
+
+So when tx coe is enabled, for any tx queue that doesn't support
+tx coe with 'coe-unsupported' flag set will have a sw fallback
+happen in the driver for tx checksum calculation when any packets to
+be transmitted on these tx queues.
+
+Signed-off-by: Rohan G Thomas <rohan.g.thomas@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: c2945c435c99 ("net: stmmac: Prevent DSA tags from breaking COE")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     | 10 ++++++++++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c |  3 +++
+ include/linux/stmmac.h                                |  1 +
+ 3 files changed, 14 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 1bfcf673b3ce..59e07efe08c9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -4417,6 +4417,16 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+       WARN_ON(tx_q->tx_skbuff[first_entry]);
+       csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
++      /* DWMAC IPs can be synthesized to support tx coe only for a few tx
++       * queues. In that case, checksum offloading for those queues that don't
++       * support tx coe needs to fallback to software checksum calculation.
++       */
++      if (csum_insertion &&
++          priv->plat->tx_queues_cfg[queue].coe_unsupported) {
++              if (unlikely(skb_checksum_help(skb)))
++                      goto dma_map_err;
++              csum_insertion = !csum_insertion;
++      }
+       if (likely(priv->extend_desc))
+               desc = (struct dma_desc *)(tx_q->dma_etx + entry);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 2f0678f15fb7..30d5e635190e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -276,6 +276,9 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
+                       plat->tx_queues_cfg[queue].use_prio = true;
+               }
++              plat->tx_queues_cfg[queue].coe_unsupported =
++                      of_property_read_bool(q_node, "snps,coe-unsupported");
++
+               queue++;
+       }
+       if (queue != plat->tx_queues_to_use) {
+diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
+index e3f7ee169c08..5acb77968902 100644
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -139,6 +139,7 @@ struct stmmac_rxq_cfg {
+ struct stmmac_txq_cfg {
+       u32 weight;
++      bool coe_unsupported;
+       u8 mode_to_use;
+       /* Credit Base Shaper parameters */
+       u32 send_slope;
+-- 
+2.43.0
+
diff --git a/queue-6.6/revert-cifs-reconnect-work-should-have-reference-on-.patch b/queue-6.6/revert-cifs-reconnect-work-should-have-reference-on-.patch
new file mode 100644 (file)
index 0000000..7632aa6
--- /dev/null
@@ -0,0 +1,141 @@
+From 8ac376c7b23cd48dc254ca7f1710bfb1727c4d53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Dec 2023 16:37:37 +0000
+Subject: Revert "cifs: reconnect work should have reference on server struct"
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 823342524868168bf681f135d01b4ae10f5863ec ]
+
+This reverts commit 19a4b9d6c372cab6a3b2c9a061a236136fe95274.
+
+This earlier commit was making an assumption that each mod_delayed_work
+called for the reconnect work would result in smb2_reconnect_server
+being called twice. This assumption turns out to be untrue. So reverting
+this change for now.
+
+I will submit a follow-up patch to fix the actual problem in a different
+way.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/connect.c | 27 ++++++---------------------
+ fs/smb/client/smb2pdu.c | 23 ++++++++++-------------
+ 2 files changed, 16 insertions(+), 34 deletions(-)
+
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index f43f51f2d1c1..2a30245287d5 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -401,13 +401,7 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
+                       spin_unlock(&server->srv_lock);
+                       cifs_swn_reset_server_dstaddr(server);
+                       cifs_server_unlock(server);
+-
+-                      /* increase ref count which reconnect work will drop */
+-                      spin_lock(&cifs_tcp_ses_lock);
+-                      server->srv_count++;
+-                      spin_unlock(&cifs_tcp_ses_lock);
+-                      if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
+-                              cifs_put_tcp_session(server, false);
++                      mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+               }
+       } while (server->tcpStatus == CifsNeedReconnect);
+@@ -537,13 +531,7 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server)
+               spin_unlock(&server->srv_lock);
+               cifs_swn_reset_server_dstaddr(server);
+               cifs_server_unlock(server);
+-
+-              /* increase ref count which reconnect work will drop */
+-              spin_lock(&cifs_tcp_ses_lock);
+-              server->srv_count++;
+-              spin_unlock(&cifs_tcp_ses_lock);
+-              if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
+-                      cifs_put_tcp_session(server, false);
++              mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+       } while (server->tcpStatus == CifsNeedReconnect);
+       mutex_lock(&server->refpath_lock);
+@@ -1630,19 +1618,16 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
+       cancel_delayed_work_sync(&server->echo);
+-      if (from_reconnect) {
++      if (from_reconnect)
+               /*
+                * Avoid deadlock here: reconnect work calls
+                * cifs_put_tcp_session() at its end. Need to be sure
+                * that reconnect work does nothing with server pointer after
+                * that step.
+                */
+-              if (cancel_delayed_work(&server->reconnect))
+-                      cifs_put_tcp_session(server, from_reconnect);
+-      } else {
+-              if (cancel_delayed_work_sync(&server->reconnect))
+-                      cifs_put_tcp_session(server, from_reconnect);
+-      }
++              cancel_delayed_work(&server->reconnect);
++      else
++              cancel_delayed_work_sync(&server->reconnect);
+       spin_lock(&server->srv_lock);
+       server->tcpStatus = CifsExiting;
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index f1977987ae74..da752f41a4e6 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -3981,6 +3981,12 @@ void smb2_reconnect_server(struct work_struct *work)
+               }
+               spin_unlock(&ses->chan_lock);
+       }
++      /*
++       * Get the reference to server struct to be sure that the last call of
++       * cifs_put_tcon() in the loop below won't release the server pointer.
++       */
++      if (tcon_exist || ses_exist)
++              server->srv_count++;
+       spin_unlock(&cifs_tcp_ses_lock);
+@@ -4028,17 +4034,13 @@ void smb2_reconnect_server(struct work_struct *work)
+ done:
+       cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
+-      if (resched) {
++      if (resched)
+               queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
+-              mutex_unlock(&pserver->reconnect_mutex);
+-
+-              /* no need to put tcp session as we're retrying */
+-              return;
+-      }
+       mutex_unlock(&pserver->reconnect_mutex);
+       /* now we can safely release srv struct */
+-      cifs_put_tcp_session(server, true);
++      if (tcon_exist || ses_exist)
++              cifs_put_tcp_session(server, 1);
+ }
+ int
+@@ -4058,12 +4060,7 @@ SMB2_echo(struct TCP_Server_Info *server)
+           server->ops->need_neg(server)) {
+               spin_unlock(&server->srv_lock);
+               /* No need to send echo on newly established connections */
+-              spin_lock(&cifs_tcp_ses_lock);
+-              server->srv_count++;
+-              spin_unlock(&cifs_tcp_ses_lock);
+-              if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0))
+-                      cifs_put_tcp_session(server, false);
+-
++              mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+               return rc;
+       }
+       spin_unlock(&server->srv_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.6/riscv-fix-an-off-by-one-in-get_early_cmdline.patch b/queue-6.6/riscv-fix-an-off-by-one-in-get_early_cmdline.patch
new file mode 100644 (file)
index 0000000..2a93fd4
--- /dev/null
@@ -0,0 +1,40 @@
+From ff07fb1a8fdd65fa498878c0f0163bab7f24c572 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 29 Oct 2023 08:20:40 +0100
+Subject: riscv: Fix an off-by-one in get_early_cmdline()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit adb1f95d388a43c4c564ef3e436f18900dde978e ]
+
+The ending NULL is not taken into account by strncat(), so switch to
+strlcat() to correctly compute the size of the available memory when
+appending CONFIG_CMDLINE to 'early_cmdline'.
+
+Fixes: 26e7aacb83df ("riscv: Allow to downgrade paging mode from the command line")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Link: https://lore.kernel.org/r/9f66d2b58c8052d4055e90b8477ee55d9a0914f9.1698564026.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/pi/cmdline_early.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/riscv/kernel/pi/cmdline_early.c b/arch/riscv/kernel/pi/cmdline_early.c
+index 68e786c84c94..f6d4dedffb84 100644
+--- a/arch/riscv/kernel/pi/cmdline_early.c
++++ b/arch/riscv/kernel/pi/cmdline_early.c
+@@ -38,8 +38,7 @@ static char *get_early_cmdline(uintptr_t dtb_pa)
+       if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
+           IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
+           fdt_cmdline_size == 0 /* CONFIG_CMDLINE_FALLBACK */) {
+-              strncat(early_cmdline, CONFIG_CMDLINE,
+-                      COMMAND_LINE_SIZE - fdt_cmdline_size);
++              strlcat(early_cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+       }
+       return early_cmdline;
+-- 
+2.43.0
+
diff --git a/queue-6.6/scsi-core-kick-the-requeue-list-after-inserting-when.patch b/queue-6.6/scsi-core-kick-the-requeue-list-after-inserting-when.patch
new file mode 100644 (file)
index 0000000..37b3aba
--- /dev/null
@@ -0,0 +1,97 @@
+From e31ef064e85fc95060c2fc7ffb201d5213ccf52b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Jan 2024 13:05:32 +0100
+Subject: scsi: core: Kick the requeue list after inserting when flushing
+
+From: Niklas Cassel <cassel@kernel.org>
+
+[ Upstream commit 6df0e077d76bd144c533b61d6182676aae6b0a85 ]
+
+When libata calls ata_link_abort() to abort all ata queued commands, it
+calls blk_abort_request() on the SCSI command representing each QC.
+
+This causes scsi_timeout() to be called, which calls scsi_eh_scmd_add() for
+each SCSI command.
+
+scsi_eh_scmd_add() sets the SCSI host to state recovery, and then adds the
+command to shost->eh_cmd_q.
+
+This will wake up the SCSI EH, and eventually the libata EH strategy
+handler will be called, which calls scsi_eh_flush_done_q() to either flush
+retry or flush finish each failed command.
+
+The commands that are flush retried by scsi_eh_flush_done_q() are done so
+using scsi_queue_insert().
+
+Before commit 8b566edbdbfb ("scsi: core: Only kick the requeue list if
+necessary"), __scsi_queue_insert() called blk_mq_requeue_request() with the
+second argument set to true, indicating that it should always kick/run the
+requeue list after inserting.
+
+After commit 8b566edbdbfb ("scsi: core: Only kick the requeue list if
+necessary"), __scsi_queue_insert() does not kick/run the requeue list after
+inserting, if the current SCSI host state is recovery (which is the case in
+the libata example above).
+
+This optimization is probably fine in most cases, as I can only assume that
+most often someone will eventually kick/run the queues.
+
+However, that is not the case for scsi_eh_flush_done_q(), where we can see
+that the request gets inserted to the requeue list, but the queue is never
+started after the request has been inserted, leading to the block layer
+waiting for the completion of command that never gets to run.
+
+Since scsi_eh_flush_done_q() is called by SCSI EH context, the SCSI host
+state is most likely always in recovery when this function is called.
+
+Thus, let scsi_eh_flush_done_q() explicitly kick the requeue list after
+inserting a flush retry command, so that scsi_eh_flush_done_q() keeps the
+same behavior as before commit 8b566edbdbfb ("scsi: core: Only kick the
+requeue list if necessary").
+
+Simple reproducer for the libata example above:
+$ hdparm -Y /dev/sda
+$ echo 1 > /sys/class/scsi_device/0\:0\:0\:0/device/delete
+
+Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
+Reported-by: Kevin Locke <kevin@kevinlocke.name>
+Closes: https://lore.kernel.org/linux-scsi/ZZw3Th70wUUvCiCY@kevinlocke.name/
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Link: https://lore.kernel.org/r/20240111120533.3612509-1-cassel@kernel.org
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_error.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 1223d34c04da..d983f4a0e9f1 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -2196,15 +2196,18 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
+       struct scsi_cmnd *scmd, *next;
+       list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
++              struct scsi_device *sdev = scmd->device;
++
+               list_del_init(&scmd->eh_entry);
+-              if (scsi_device_online(scmd->device) &&
+-                  !scsi_noretry_cmd(scmd) && scsi_cmd_retry_allowed(scmd) &&
+-                      scsi_eh_should_retry_cmd(scmd)) {
++              if (scsi_device_online(sdev) && !scsi_noretry_cmd(scmd) &&
++                  scsi_cmd_retry_allowed(scmd) &&
++                  scsi_eh_should_retry_cmd(scmd)) {
+                       SCSI_LOG_ERROR_RECOVERY(3,
+                               scmd_printk(KERN_INFO, scmd,
+                                            "%s: flush retry cmd\n",
+                                            current->comm));
+                               scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
++                              blk_mq_kick_requeue_list(sdev->request_queue);
+               } else {
+                       /*
+                        * If just we got sense for the device (called
+-- 
+2.43.0
+
diff --git a/queue-6.6/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch b/queue-6.6/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch
new file mode 100644 (file)
index 0000000..5d69a34
--- /dev/null
@@ -0,0 +1,48 @@
+From 5ab54fef88b1be59326a4f6cfb46794a0764fcc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Dec 2023 14:52:15 -0800
+Subject: scsi: ufs: core: Remove the ufshcd_hba_exit() call from
+ ufshcd_async_scan()
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+[ Upstream commit ee36710912b2075c417100a8acc642c9c6496501 ]
+
+Calling ufshcd_hba_exit() from a function that is called asynchronously
+from ufshcd_init() is wrong because this triggers multiple race
+conditions. Instead of calling ufshcd_hba_exit(), log an error message.
+
+Reported-by: Daniel Mentz <danielmentz@google.com>
+Fixes: 1d337ec2f35e ("ufs: improve init sequence")
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20231218225229.2542156-3-bvanassche@acm.org
+Reviewed-by: Can Guo <quic_cang@quicinc.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/core/ufshcd.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index 0971ae37f2a7..44e0437bd19d 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -8810,12 +8810,9 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
+ out:
+       pm_runtime_put_sync(hba->dev);
+-      /*
+-       * If we failed to initialize the device or the device is not
+-       * present, turn off the power/clocks etc.
+-       */
++
+       if (ret)
+-              ufshcd_hba_exit(hba);
++              dev_err(hba->dev, "%s failed: %d\n", __func__, ret);
+ }
+ static enum scsi_timeout_action ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-core-set-missing-supported-flag-for-rx-during.patch b/queue-6.6/serial-core-set-missing-supported-flag-for-rx-during.patch
new file mode 100644 (file)
index 0000000..4c970c6
--- /dev/null
@@ -0,0 +1,45 @@
+From af43430da925196c65717ffb872eef90043da6f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jan 2024 07:18:13 +0100
+Subject: serial: core: set missing supported flag for RX during TX GPIO
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+
+[ Upstream commit 1a33e33ca0e80d485458410f149265cdc0178cfa ]
+
+If the RS485 feature RX-during-TX is supported by means of a GPIO set the
+according supported flag. Otherwise setting this feature from userspace may
+not be possible, since in uart_sanitize_serial_rs485() the passed RS485
+configuration is matched against the supported features and unsupported
+settings are thereby removed and thus take no effect.
+
+Cc:  <stable@vger.kernel.org>
+Fixes: 163f080eb717 ("serial: core: Add option to output RS485 RX_DURING_TX state via GPIO")
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Link: https://lore.kernel.org/r/20240103061818.564-3-l.sanfilippo@kunbus.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/serial_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
+index 021e096bc4ed..bde5b6015305 100644
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -3630,6 +3630,8 @@ int uart_get_rs485_mode(struct uart_port *port)
+       if (IS_ERR(desc))
+               return dev_err_probe(dev, PTR_ERR(desc), "Cannot get rs485-rx-during-tx-gpios\n");
+       port->rs485_rx_during_tx_gpio = desc;
++      if (port->rs485_rx_during_tx_gpio)
++              port->rs485_supported.flags |= SER_RS485_RX_DURING_TX;
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/serial-core-simplify-uart_get_rs485_mode.patch b/queue-6.6/serial-core-simplify-uart_get_rs485_mode.patch
new file mode 100644 (file)
index 0000000..954fe9c
--- /dev/null
@@ -0,0 +1,78 @@
+From b4b7905e246ce50f256f0b7a7717702b93070adf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 17:23:46 +0300
+Subject: serial: core: Simplify uart_get_rs485_mode()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 7cda0b9eb6eb9e761f452e2ef4e81eca20b19938 ]
+
+Simplify uart_get_rs485_mode() by using temporary variable for
+the GPIO descriptor. With that, use proper type for the flags
+of the GPIO descriptor.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231003142346.3072929-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 1a33e33ca0e8 ("serial: core: set missing supported flag for RX during TX GPIO")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/serial_core.c | 30 ++++++++++++------------------
+ 1 file changed, 12 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
+index 18b49b1439a5..021e096bc4ed 100644
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -3572,9 +3572,10 @@ int uart_get_rs485_mode(struct uart_port *port)
+ {
+       struct serial_rs485 *rs485conf = &port->rs485;
+       struct device *dev = port->dev;
++      enum gpiod_flags dflags;
++      struct gpio_desc *desc;
+       u32 rs485_delay[2];
+       int ret;
+-      int rx_during_tx_gpio_flag;
+       if (!(port->rs485_supported.flags & SER_RS485_ENABLED))
+               return 0;
+@@ -3616,26 +3617,19 @@ int uart_get_rs485_mode(struct uart_port *port)
+        * bus participants enable it, no communication is possible at all.
+        * Works fine for short cables and users may enable for longer cables.
+        */
+-      port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term",
+-                                                      GPIOD_OUT_LOW);
+-      if (IS_ERR(port->rs485_term_gpio)) {
+-              ret = PTR_ERR(port->rs485_term_gpio);
+-              port->rs485_term_gpio = NULL;
+-              return dev_err_probe(dev, ret, "Cannot get rs485-term-gpios\n");
+-      }
++      desc = devm_gpiod_get_optional(dev, "rs485-term", GPIOD_OUT_LOW);
++      if (IS_ERR(desc))
++              return dev_err_probe(dev, PTR_ERR(desc), "Cannot get rs485-term-gpios\n");
++      port->rs485_term_gpio = desc;
+       if (port->rs485_term_gpio)
+               port->rs485_supported.flags |= SER_RS485_TERMINATE_BUS;
+-      rx_during_tx_gpio_flag = (rs485conf->flags & SER_RS485_RX_DURING_TX) ?
+-                               GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
+-      port->rs485_rx_during_tx_gpio = devm_gpiod_get_optional(dev,
+-                                                              "rs485-rx-during-tx",
+-                                                              rx_during_tx_gpio_flag);
+-      if (IS_ERR(port->rs485_rx_during_tx_gpio)) {
+-              ret = PTR_ERR(port->rs485_rx_during_tx_gpio);
+-              port->rs485_rx_during_tx_gpio = NULL;
+-              return dev_err_probe(dev, ret, "Cannot get rs485-rx-during-tx-gpios\n");
+-      }
++      dflags = (rs485conf->flags & SER_RS485_RX_DURING_TX) ?
++               GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
++      desc = devm_gpiod_get_optional(dev, "rs485-rx-during-tx", dflags);
++      if (IS_ERR(desc))
++              return dev_err_probe(dev, PTR_ERR(desc), "Cannot get rs485-rx-during-tx-gpios\n");
++      port->rs485_rx_during_tx_gpio = desc;
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/series b/queue-6.6/series
new file mode 100644 (file)
index 0000000..c48d162
--- /dev/null
@@ -0,0 +1,28 @@
+docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch
+docs-sparse-add-sparse.rst-to-toctree.patch
+docs-kernel_feat.py-fix-potential-command-injection.patch
+serial-core-simplify-uart_get_rs485_mode.patch
+serial-core-set-missing-supported-flag-for-rx-during.patch
+soundwire-bus-introduce-controller_id.patch
+soundwire-fix-initializing-sysfs-for-same-devices-on.patch
+net-stmmac-tx-coe-sw-fallback.patch
+net-stmmac-prevent-dsa-tags-from-breaking-coe.patch
+iio-adc-ad7091r-set-alert-bit-in-config-register.patch
+iio-adc-ad7091r-allow-users-to-configure-device-even.patch
+iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch
+dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch
+dmaengine-fix-null-pointer-in-channel-unregistration.patch
+dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch
+scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch
+riscv-fix-an-off-by-one-in-get_early_cmdline.patch
+scsi-core-kick-the-requeue-list-after-inserting-when.patch
+sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch
+smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch
+cifs-handle-cases-where-a-channel-is-closed.patch
+cifs-reconnect-work-should-have-reference-on-server-.patch
+cifs-handle-when-server-starts-supporting-multichann.patch
+cifs-handle-when-server-stops-supporting-multichanne.patch
+revert-cifs-reconnect-work-should-have-reference-on-.patch
+cifs-reconnect-worker-should-take-reference-on-serve.patch
+cifs-handle-servers-that-still-advertise-multichanne.patch
+cifs-update-iface_last_update-on-each-query-and-upda.patch
diff --git a/queue-6.6/sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch b/queue-6.6/sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch
new file mode 100644 (file)
index 0000000..cbeeb91
--- /dev/null
@@ -0,0 +1,52 @@
+From 28688eee7cbf9785fd95a9cebdf786c613fb31e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 13:10:22 +0200
+Subject: sh: ecovec24: Rename missed backlight field from fbdev to dev
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit d87123aa9a7920e88633ffc5c5a0a22ab08bdc06 ]
+
+One instance of gpio_backlight_platform_data.fbdev was renamed, but the
+second instance was forgotten, causing a build failure:
+
+    arch/sh/boards/mach-ecovec24/setup.c: In function ‘arch_setup’:
+    arch/sh/boards/mach-ecovec24/setup.c:1223:37: error: ‘struct gpio_backlight_platform_data’ has no member named ‘fbdev’; did you mean ‘dev’?
+     1223 |                 gpio_backlight_data.fbdev = NULL;
+         |                                     ^~~~~
+         |                                     dev
+
+Fix this by updating the second instance.
+
+Fixes: ed369def91c1579a ("backlight/gpio_backlight: Rename field 'fbdev' to 'dev'")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202309231601.Uu6qcRnU-lkp@intel.com/
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Link: https://lore.kernel.org/r/20230925111022.3626362-1-geert+renesas@glider.be
+Signed-off-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/sh/boards/mach-ecovec24/setup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
+index 3be293335de5..7a788d44cc73 100644
+--- a/arch/sh/boards/mach-ecovec24/setup.c
++++ b/arch/sh/boards/mach-ecovec24/setup.c
+@@ -1220,7 +1220,7 @@ static int __init arch_setup(void)
+               lcdc_info.ch[0].num_modes               = ARRAY_SIZE(ecovec_dvi_modes);
+               /* No backlight */
+-              gpio_backlight_data.fbdev = NULL;
++              gpio_backlight_data.dev = NULL;
+               gpio_set_value(GPIO_PTA2, 1);
+               gpio_set_value(GPIO_PTU1, 1);
+-- 
+2.43.0
+
diff --git a/queue-6.6/smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch b/queue-6.6/smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch
new file mode 100644 (file)
index 0000000..5110da3
--- /dev/null
@@ -0,0 +1,40 @@
+From 42827830391802507a8b2e627b47d403317e2ce9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jan 2024 01:08:26 -0300
+Subject: smb: client: fix parsing of SMB3.1.1 POSIX create context
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+[ Upstream commit 76025cc2285d9ede3d717fe4305d66f8be2d9346 ]
+
+The data offset for the SMB3.1.1 POSIX create context will always be
+8-byte aligned so having the check 'noff + nlen >= doff' in
+smb2_parse_contexts() is wrong as it will lead to -EINVAL because noff
++ nlen == doff.
+
+Fix the sanity check to correctly handle aligned create context data.
+
+Fixes: af1689a9b770 ("smb: client: fix potential OOBs in smb2_parse_contexts()")
+Signed-off-by: Paulo Alcantara <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/smb2pdu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 5276992e3647..888eb59ad86f 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -2185,7 +2185,7 @@ int smb2_parse_contexts(struct TCP_Server_Info *server,
+               noff = le16_to_cpu(cc->NameOffset);
+               nlen = le16_to_cpu(cc->NameLength);
+-              if (noff + nlen >= doff)
++              if (noff + nlen > doff)
+                       return -EINVAL;
+               name = (char *)cc + noff;
+-- 
+2.43.0
+
diff --git a/queue-6.6/soundwire-bus-introduce-controller_id.patch b/queue-6.6/soundwire-bus-introduce-controller_id.patch
new file mode 100644 (file)
index 0000000..445f391
--- /dev/null
@@ -0,0 +1,162 @@
+From edbdfa05d3a3e9c980696b2165afda2a3eb1c05b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 11:09:32 -0500
+Subject: soundwire: bus: introduce controller_id
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 6543ac13c623f906200dfd3f1c407d8d333b6995 ]
+
+The existing SoundWire support misses a clear Controller/Manager
+hiearchical definition to deal with all variants across SOC vendors.
+
+a) Intel platforms have one controller with 4 or more Managers.
+b) AMD platforms have two controllers with one Manager each, but due
+to BIOS issues use two different link_id values within the scope of a
+single controller.
+c) QCOM platforms have one or more controller with one Manager each.
+
+This patch adds a 'controller_id' which can be set by higher
+levels. If assigned to -1, the controller_id will be set to the
+system-unique IDA-assigned bus->id.
+
+The main change is that the bus->id is no longer used for any device
+name, which makes the definition completely predictable and not
+dependent on any enumeration order. The bus->id is only used to insert
+the Managers in the stream rt context.
+
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Reviewed-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/stable/20231017160933.12624-2-pierre-louis.bossart%40linux.intel.com
+Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20231017160933.12624-2-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 8a8a9ac8a497 ("soundwire: fix initializing sysfs for same devices on different buses")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/amd_manager.c     | 8 ++++++++
+ drivers/soundwire/bus.c             | 4 ++++
+ drivers/soundwire/debugfs.c         | 2 +-
+ drivers/soundwire/intel_auxdevice.c | 3 +++
+ drivers/soundwire/master.c          | 2 +-
+ drivers/soundwire/qcom.c            | 3 +++
+ include/linux/soundwire/sdw.h       | 4 +++-
+ 7 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
+index 3a99f6dcdfaf..a3b1f4e6f0f9 100644
+--- a/drivers/soundwire/amd_manager.c
++++ b/drivers/soundwire/amd_manager.c
+@@ -927,6 +927,14 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
+       amd_manager->bus.clk_stop_timeout = 200;
+       amd_manager->bus.link_id = amd_manager->instance;
++      /*
++       * Due to BIOS compatibility, the two links are exposed within
++       * the scope of a single controller. If this changes, the
++       * controller_id will have to be updated with drv_data
++       * information.
++       */
++      amd_manager->bus.controller_id = 0;
++
+       switch (amd_manager->instance) {
+       case ACP_SDW0:
+               amd_manager->num_dout_ports = AMD_SDW0_MAX_TX_PORTS;
+diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
+index 0e7bc3c40f9d..e7553c38be59 100644
+--- a/drivers/soundwire/bus.c
++++ b/drivers/soundwire/bus.c
+@@ -22,6 +22,10 @@ static int sdw_get_id(struct sdw_bus *bus)
+               return rc;
+       bus->id = rc;
++
++      if (bus->controller_id == -1)
++              bus->controller_id = rc;
++
+       return 0;
+ }
+diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
+index d1553cb77187..67abd7e52f09 100644
+--- a/drivers/soundwire/debugfs.c
++++ b/drivers/soundwire/debugfs.c
+@@ -20,7 +20,7 @@ void sdw_bus_debugfs_init(struct sdw_bus *bus)
+               return;
+       /* create the debugfs master-N */
+-      snprintf(name, sizeof(name), "master-%d-%d", bus->id, bus->link_id);
++      snprintf(name, sizeof(name), "master-%d-%d", bus->controller_id, bus->link_id);
+       bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root);
+ }
+diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
+index 7f15e3549e53..93698532deac 100644
+--- a/drivers/soundwire/intel_auxdevice.c
++++ b/drivers/soundwire/intel_auxdevice.c
+@@ -234,6 +234,9 @@ static int intel_link_probe(struct auxiliary_device *auxdev,
+       cdns->instance = sdw->instance;
+       cdns->msg_count = 0;
++      /* single controller for all SoundWire links */
++      bus->controller_id = 0;
++
+       bus->link_id = auxdev->id;
+       bus->clk_stop_timeout = 1;
+diff --git a/drivers/soundwire/master.c b/drivers/soundwire/master.c
+index 9b05c9e25ebe..51abedbbaa66 100644
+--- a/drivers/soundwire/master.c
++++ b/drivers/soundwire/master.c
+@@ -145,7 +145,7 @@ int sdw_master_device_add(struct sdw_bus *bus, struct device *parent,
+       md->dev.fwnode = fwnode;
+       md->dev.dma_mask = parent->dma_mask;
+-      dev_set_name(&md->dev, "sdw-master-%d", bus->id);
++      dev_set_name(&md->dev, "sdw-master-%d-%d", bus->controller_id, bus->link_id);
+       ret = device_register(&md->dev);
+       if (ret) {
+diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
+index 55be9f4b8d59..e3ae4e4e07ac 100644
+--- a/drivers/soundwire/qcom.c
++++ b/drivers/soundwire/qcom.c
+@@ -1612,6 +1612,9 @@ static int qcom_swrm_probe(struct platform_device *pdev)
+               }
+       }
++      /* FIXME: is there a DT-defined value to use ? */
++      ctrl->bus.controller_id = -1;
++
+       ret = sdw_bus_master_add(&ctrl->bus, dev, dev->fwnode);
+       if (ret) {
+               dev_err(dev, "Failed to register Soundwire controller (%d)\n",
+diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
+index 4f3d14bb1538..c383579a008b 100644
+--- a/include/linux/soundwire/sdw.h
++++ b/include/linux/soundwire/sdw.h
+@@ -886,7 +886,8 @@ struct sdw_master_ops {
+  * struct sdw_bus - SoundWire bus
+  * @dev: Shortcut to &bus->md->dev to avoid changing the entire code.
+  * @md: Master device
+- * @link_id: Link id number, can be 0 to N, unique for each Master
++ * @controller_id: system-unique controller ID. If set to -1, the bus @id will be used.
++ * @link_id: Link id number, can be 0 to N, unique for each Controller
+  * @id: bus system-wide unique id
+  * @slaves: list of Slaves on this bus
+  * @assigned: Bitmap for Slave device numbers.
+@@ -918,6 +919,7 @@ struct sdw_master_ops {
+ struct sdw_bus {
+       struct device *dev;
+       struct sdw_master_device *md;
++      int controller_id;
+       unsigned int link_id;
+       int id;
+       struct list_head slaves;
+-- 
+2.43.0
+
diff --git a/queue-6.6/soundwire-fix-initializing-sysfs-for-same-devices-on.patch b/queue-6.6/soundwire-fix-initializing-sysfs-for-same-devices-on.patch
new file mode 100644 (file)
index 0000000..f3eb8c0
--- /dev/null
@@ -0,0 +1,89 @@
+From 8f5395f655b54b48def212f6d1bc5424d8a734ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 11:09:33 -0500
+Subject: soundwire: fix initializing sysfs for same devices on different buses
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 8a8a9ac8a4972ee69d3dd3d1ae43963ae39cee18 ]
+
+If same devices with same device IDs are present on different soundwire
+buses, the probe fails due to conflicting device names and sysfs
+entries:
+
+  sysfs: cannot create duplicate filename '/bus/soundwire/devices/sdw:0:0217:0204:00:0'
+
+The link ID is 0 for both devices, so they should be differentiated by
+the controller ID. Add the controller ID so, the device names and sysfs entries look
+like:
+
+  sdw:1:0:0217:0204:00:0 -> ../../../devices/platform/soc@0/6ab0000.soundwire-controller/sdw-master-1-0/sdw:1:0:0217:0204:00:0
+  sdw:3:0:0217:0204:00:0 -> ../../../devices/platform/soc@0/6b10000.soundwire-controller/sdw-master-3-0/sdw:3:0:0217:0204:00:0
+
+[PLB changes: use bus->controller_id instead of bus->id]
+
+Fixes: 7c3cd189b86d ("soundwire: Add Master registration")
+Cc: stable@vger.kernel.org
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Reviewed-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Co-developed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Acked-by: Mark Brown <broonie@kernel.org>
+Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Link: https://lore.kernel.org/r/20231017160933.12624-3-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soundwire/slave.c        | 12 ++++++------
+ sound/soc/intel/boards/sof_sdw.c |  4 ++--
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c
+index c1c1a2ac293a..060c2982e26b 100644
+--- a/drivers/soundwire/slave.c
++++ b/drivers/soundwire/slave.c
+@@ -39,14 +39,14 @@ int sdw_slave_add(struct sdw_bus *bus,
+       slave->dev.fwnode = fwnode;
+       if (id->unique_id == SDW_IGNORED_UNIQUE_ID) {
+-              /* name shall be sdw:link:mfg:part:class */
+-              dev_set_name(&slave->dev, "sdw:%01x:%04x:%04x:%02x",
+-                           bus->link_id, id->mfg_id, id->part_id,
++              /* name shall be sdw:ctrl:link:mfg:part:class */
++              dev_set_name(&slave->dev, "sdw:%01x:%01x:%04x:%04x:%02x",
++                           bus->controller_id, bus->link_id, id->mfg_id, id->part_id,
+                            id->class_id);
+       } else {
+-              /* name shall be sdw:link:mfg:part:class:unique */
+-              dev_set_name(&slave->dev, "sdw:%01x:%04x:%04x:%02x:%01x",
+-                           bus->link_id, id->mfg_id, id->part_id,
++              /* name shall be sdw:ctrl:link:mfg:part:class:unique */
++              dev_set_name(&slave->dev, "sdw:%01x:%01x:%04x:%04x:%02x:%01x",
++                           bus->controller_id, bus->link_id, id->mfg_id, id->part_id,
+                            id->class_id, id->unique_id);
+       }
+diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
+index 24e966a2ac2b..9ed572141fe5 100644
+--- a/sound/soc/intel/boards/sof_sdw.c
++++ b/sound/soc/intel/boards/sof_sdw.c
+@@ -1197,11 +1197,11 @@ static int fill_sdw_codec_dlc(struct device *dev,
+       else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id,
+                                 class_id, adr_index))
+               codec->name = devm_kasprintf(dev, GFP_KERNEL,
+-                                           "sdw:%01x:%04x:%04x:%02x", link_id,
++                                           "sdw:0:%01x:%04x:%04x:%02x", link_id,
+                                            mfg_id, part_id, class_id);
+       else
+               codec->name = devm_kasprintf(dev, GFP_KERNEL,
+-                                           "sdw:%01x:%04x:%04x:%02x:%01x", link_id,
++                                           "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id,
+                                            mfg_id, part_id, class_id, unique_id);
+       if (!codec->name)
+-- 
+2.43.0
+