From dc9bb9e8c0a9458b19e9d2e0810e103287b57fc5 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 26 Jan 2024 09:04:45 -0500 Subject: [PATCH] Fixes for 6.6 Signed-off-by: Sasha Levin --- ...ndle-cases-where-a-channel-is-closed.patch | 221 ++++++++++++ ...ers-that-still-advertise-multichanne.patch | 221 ++++++++++++ ...-server-starts-supporting-multichann.patch | 112 +++++++ ...-server-stops-supporting-multichanne.patch | 307 +++++++++++++++++ ...ork-should-have-reference-on-server-.patch | 146 ++++++++ ...orker-should-take-reference-on-serve.patch | 150 +++++++++ ...e_last_update-on-each-query-and-upda.patch | 62 ++++ ...ll-pointer-in-channel-unregistration.patch | 55 +++ ...ma-fix-edmav4-channel-allocation-iss.patch | 58 ++++ ...ove-dma_free_coherent-out-of-spinloc.patch | 72 ++++ ...t.py-fix-potential-command-injection.patch | 316 ++++++++++++++++++ ...ocs-sparse-add-sparse.rst-to-toctree.patch | 91 +++++ ...e-move-tw-sparse.txt-to-tw-dev-tools.patch | 36 ++ ...allow-users-to-configure-device-even.patch | 295 ++++++++++++++++ ...enable-internal-vref-if-external-vre.patch | 67 ++++ ...91r-set-alert-bit-in-config-register.patch | 53 +++ ...c-prevent-dsa-tags-from-breaking-coe.patch | 106 ++++++ queue-6.6/net-stmmac-tx-coe-sw-fallback.patch | 80 +++++ ...nnect-work-should-have-reference-on-.patch | 141 ++++++++ ...x-an-off-by-one-in-get_early_cmdline.patch | 40 +++ ...he-requeue-list-after-inserting-when.patch | 97 ++++++ ...move-the-ufshcd_hba_exit-call-from-u.patch | 48 +++ ...missing-supported-flag-for-rx-during.patch | 45 +++ ...al-core-simplify-uart_get_rs485_mode.patch | 78 +++++ queue-6.6/series | 28 ++ ...me-missed-backlight-field-from-fbdev.patch | 52 +++ ...arsing-of-smb3.1.1-posix-create-cont.patch | 40 +++ ...oundwire-bus-introduce-controller_id.patch | 162 +++++++++ ...itializing-sysfs-for-same-devices-on.patch | 89 +++++ 29 files changed, 3268 insertions(+) create mode 100644 queue-6.6/cifs-handle-cases-where-a-channel-is-closed.patch create mode 100644 queue-6.6/cifs-handle-servers-that-still-advertise-multichanne.patch create mode 100644 queue-6.6/cifs-handle-when-server-starts-supporting-multichann.patch create mode 100644 queue-6.6/cifs-handle-when-server-stops-supporting-multichanne.patch create mode 100644 queue-6.6/cifs-reconnect-work-should-have-reference-on-server-.patch create mode 100644 queue-6.6/cifs-reconnect-worker-should-take-reference-on-serve.patch create mode 100644 queue-6.6/cifs-update-iface_last_update-on-each-query-and-upda.patch create mode 100644 queue-6.6/dmaengine-fix-null-pointer-in-channel-unregistration.patch create mode 100644 queue-6.6/dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch create mode 100644 queue-6.6/dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch create mode 100644 queue-6.6/docs-kernel_feat.py-fix-potential-command-injection.patch create mode 100644 queue-6.6/docs-sparse-add-sparse.rst-to-toctree.patch create mode 100644 queue-6.6/docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch create mode 100644 queue-6.6/iio-adc-ad7091r-allow-users-to-configure-device-even.patch create mode 100644 queue-6.6/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch create mode 100644 queue-6.6/iio-adc-ad7091r-set-alert-bit-in-config-register.patch create mode 100644 queue-6.6/net-stmmac-prevent-dsa-tags-from-breaking-coe.patch create mode 100644 queue-6.6/net-stmmac-tx-coe-sw-fallback.patch create mode 100644 queue-6.6/revert-cifs-reconnect-work-should-have-reference-on-.patch create mode 100644 queue-6.6/riscv-fix-an-off-by-one-in-get_early_cmdline.patch create mode 100644 queue-6.6/scsi-core-kick-the-requeue-list-after-inserting-when.patch create mode 100644 queue-6.6/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch create mode 100644 queue-6.6/serial-core-set-missing-supported-flag-for-rx-during.patch create mode 100644 queue-6.6/serial-core-simplify-uart_get_rs485_mode.patch create mode 100644 queue-6.6/series create mode 100644 queue-6.6/sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch create mode 100644 queue-6.6/smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch create mode 100644 queue-6.6/soundwire-bus-introduce-controller_id.patch create mode 100644 queue-6.6/soundwire-fix-initializing-sysfs-for-same-devices-on.patch 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 index 00000000000..0434ef57173 --- /dev/null +++ b/queue-6.6/cifs-handle-cases-where-a-channel-is-closed.patch @@ -0,0 +1,221 @@ +From a54a0939f5009c54e9af579b3fdc74170c199bdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 09:25:30 +0000 +Subject: cifs: handle cases where a channel is closed + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..09b7c77e747 --- /dev/null +++ b/queue-6.6/cifs-handle-servers-that-still-advertise-multichanne.patch @@ -0,0 +1,221 @@ +From e3a58a9a8a880e691f0c35025084cc98bab84cde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jan 2024 13:14:46 +0000 +Subject: cifs: handle servers that still advertise multichannel after + disabling + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..8e253509bdb --- /dev/null +++ b/queue-6.6/cifs-handle-when-server-starts-supporting-multichann.patch @@ -0,0 +1,112 @@ +From 72a8eaff0ccf35dedb6641183ad07acd1fda9d5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 11:33:21 +0000 +Subject: cifs: handle when server starts supporting multichannel + +From: Shyam Prasad N + +[ 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 +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..aa1ed663131 --- /dev/null +++ b/queue-6.6/cifs-handle-when-server-stops-supporting-multichanne.patch @@ -0,0 +1,307 @@ +From 5b453a7be6de530810c2403054ba14bc1dfadfac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 11:40:09 +0000 +Subject: cifs: handle when server stops supporting multichannel + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..469f64f7318 --- /dev/null +++ b/queue-6.6/cifs-reconnect-work-should-have-reference-on-server-.patch @@ -0,0 +1,146 @@ +From 980324fe16226cda05649fa31e5ad79e60818e1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 11:43:09 +0000 +Subject: cifs: reconnect work should have reference on server struct + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..84f3a2c0b4f --- /dev/null +++ b/queue-6.6/cifs-reconnect-worker-should-take-reference-on-serve.patch @@ -0,0 +1,150 @@ +From e0401d1f68695cd540b09e01970245c8ab6a8e8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Dec 2023 16:37:38 +0000 +Subject: cifs: reconnect worker should take reference on server struct + unconditionally + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..58bcdc37d9e --- /dev/null +++ b/queue-6.6/cifs-update-iface_last_update-on-each-query-and-upda.patch @@ -0,0 +1,62 @@ +From 25c77fdd03109541f14ba45bbc7b11692da19709 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 12:51:49 +0000 +Subject: cifs: update iface_last_update on each query-and-update + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0c20df10644 --- /dev/null +++ b/queue-6.6/dmaengine-fix-null-pointer-in-channel-unregistration.patch @@ -0,0 +1,55 @@ +From 723056ffcc9eaf4dd2e102cfe0897781b1060f55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Dec 2023 17:04:52 +0100 +Subject: dmaengine: fix NULL pointer in channel unregistration function + +From: Amelie Delaunay + +[ 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 +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20231213160452.2598073-1-amelie.delaunay@foss.st.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f1eadffdd22 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-fix-edmav4-channel-allocation-iss.patch @@ -0,0 +1,58 @@ +From 70e27894308fae25daf1e05d775cdd2d16cc7b7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Nov 2023 10:48:21 -0500 +Subject: dmaengine: fsl-edma: fix eDMAv4 channel allocation issue + +From: Frank Li + +[ 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 +Link: https://lore.kernel.org/r/20231114154824.3617255-2-Frank.Li@nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5f5069ee554 --- /dev/null +++ b/queue-6.6/dmaengine-idxd-move-dma_free_coherent-out-of-spinloc.patch @@ -0,0 +1,72 @@ +From e62a16ef2b0f028e5d22351c020db283f51df1cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Dec 2023 10:21:58 +0800 +Subject: dmaengine: idxd: Move dma_free_coherent() out of spinlocked context + +From: Rex Zhang + +[ 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: + + 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 +Reviewed-by: Dave Jiang +Reviewed-by: Fenghua Yu +Link: https://lore.kernel.org/r/20231212022158.358619-2-rex.zhang@intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..70f88aa7ac4 --- /dev/null +++ b/queue-6.6/docs-kernel_feat.py-fix-potential-command-injection.patch @@ -0,0 +1,316 @@ +From fc3445d032b02beb25fe4460daae50404dc8c441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jan 2024 18:47:58 +0100 +Subject: docs: kernel_feat.py: fix potential command injection + +From: Vegard Nossum + +[ 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 +Signed-off-by: Vegard Nossum +Cc: stable@vger.kernel.org +Signed-off-by: Jonathan Corbet +Link: https://lore.kernel.org/r/20240110174758.3680506-1-vegard.nossum@oracle.com +Signed-off-by: Sasha Levin +--- + 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 + +-.. 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 index 00000000000..38f5343577b --- /dev/null +++ b/queue-6.6/docs-sparse-add-sparse.rst-to-toctree.patch @@ -0,0 +1,91 @@ +From 0b21551690eba2dfcb2b9ad0a8f52097515ab394 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Sep 2023 13:25:12 +0800 +Subject: docs: sparse: add sparse.rst to toctree + +From: Min-Hua Chen + +[ Upstream commit c9ad95adc096f25004d4192258863806a68a9bc8 ] + +Add sparst.rst to toctree, so it can be part of the docs build. + +Cc: Randy Dunlap +Cc: Jonathan Corbet +Suggested-by: Jonathan Corbet +Signed-off-by: Min-Hua Chen +Signed-off-by: Jonathan Corbet +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 +--- + .../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 ++ ++============ ++內核開發工具 ++============ ++ ++本文檔是有關內核開發工具文檔的合集。 ++目前這些文檔已經整理在一起,不需要再花費額外的精力。 ++歡迎任何補丁。 ++ ++有關測試專用工具的簡要概述,參見 ++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 index 00000000000..7576ddea4c5 --- /dev/null +++ b/queue-6.6/docs-sparse-move-tw-sparse.txt-to-tw-dev-tools.patch @@ -0,0 +1,36 @@ +From 015fb88e61c923ace77301975fbbb1ccb1600574 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Sep 2023 13:25:10 +0800 +Subject: docs: sparse: move TW sparse.txt to TW dev-tools + +From: Min-Hua Chen + +[ 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 +Suggested-by: Randy Dunlap +Reviewed-by: Randy Dunlap +Signed-off-by: Min-Hua Chen +Signed-off-by: Jonathan Corbet +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 +--- + 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 index 00000000000..1f5f6b5e295 --- /dev/null +++ b/queue-6.6/iio-adc-ad7091r-allow-users-to-configure-device-even.patch @@ -0,0 +1,295 @@ +From 31d9518eba1dcf440452f27f9b15fd44ccc47e54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 17:26:01 -0300 +Subject: iio: adc: ad7091r: Allow users to configure device events + +From: Marcelo Schmitt + +[ 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 +Signed-off-by: Marcelo Schmitt +Link: https://lore.kernel.org/r/59552d3548dabd56adc3107b7b4869afee2b0c3c.1703013352.git.marcelo.schmitt1@gmail.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 ++#include + #include + #include + #include +@@ -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 index 00000000000..40d7f83f993 --- /dev/null +++ b/queue-6.6/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch @@ -0,0 +1,67 @@ +From 2d6478fb8be7e9bcb11f74ee89e8a787c1017b2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/b865033fa6a4fc4bf2b4a98ec51a6144e0f64f77.1703013352.git.marcelo.schmitt1@gmail.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..96afcf8f971 --- /dev/null +++ b/queue-6.6/iio-adc-ad7091r-set-alert-bit-in-config-register.patch @@ -0,0 +1,53 @@ +From b10c2fb17af63766edf41f5062096ba00c4ee4e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Dec 2023 14:46:37 -0300 +Subject: iio: adc: ad7091r: Set alert bit in config register + +From: Marcelo Schmitt + +[ 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 +Link: https://lore.kernel.org/r/e8da2ee98d6df88318b14baf3dc9630e20218418.1702746240.git.marcelo.schmitt1@gmail.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 020e71c7ffc2 ("iio: adc: ad7091r: Allow users to configure device events") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ab88344d860 --- /dev/null +++ b/queue-6.6/net-stmmac-prevent-dsa-tags-from-breaking-coe.patch @@ -0,0 +1,106 @@ +From e4910f6cbaeeb5ede337cab4669d21300960d1bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jan 2024 13:19:17 +0100 +Subject: net: stmmac: Prevent DSA tags from breaking COE + +From: Romain Gantois + +[ 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: +Reported-by: Richard Tresidder +Link: https://lore.kernel.org/netdev/e5c6c75f-2dfa-4e50-a1fb-6bf4cdb617c2@electromag.com.au/ +Reported-by: Romain Gantois +Link: https://lore.kernel.org/netdev/c57283ed-6b9b-b0e6-ee12-5655c1c54495@bootlin.com/ +Reviewed-by: Vladimir Oltean +Reviewed-by: Linus Walleij +Signed-off-by: Romain Gantois +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..20228549b69 --- /dev/null +++ b/queue-6.6/net-stmmac-tx-coe-sw-fallback.patch @@ -0,0 +1,80 @@ +From 071be3267bf1cf00cff09a9e6758055b060f2a7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Sep 2023 14:33:12 +0800 +Subject: net: stmmac: Tx coe sw fallback + +From: Rohan G Thomas + +[ 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 +Signed-off-by: David S. Miller +Stable-dep-of: c2945c435c99 ("net: stmmac: Prevent DSA tags from breaking COE") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7632aa60e45 --- /dev/null +++ b/queue-6.6/revert-cifs-reconnect-work-should-have-reference-on-.patch @@ -0,0 +1,141 @@ +From 8ac376c7b23cd48dc254ca7f1710bfb1727c4d53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Dec 2023 16:37:37 +0000 +Subject: Revert "cifs: reconnect work should have reference on server struct" + +From: Shyam Prasad N + +[ 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 +Signed-off-by: Steve French +Stable-dep-of: 78e727e58e54 ("cifs: update iface_last_update on each query-and-update") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2a93fd47132 --- /dev/null +++ b/queue-6.6/riscv-fix-an-off-by-one-in-get_early_cmdline.patch @@ -0,0 +1,40 @@ +From ff07fb1a8fdd65fa498878c0f0163bab7f24c572 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 29 Oct 2023 08:20:40 +0100 +Subject: riscv: Fix an off-by-one in get_early_cmdline() + +From: Christophe JAILLET + +[ 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 +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/9f66d2b58c8052d4055e90b8477ee55d9a0914f9.1698564026.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..37b3aba9f9a --- /dev/null +++ b/queue-6.6/scsi-core-kick-the-requeue-list-after-inserting-when.patch @@ -0,0 +1,97 @@ +From e31ef064e85fc95060c2fc7ffb201d5213ccf52b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jan 2024 13:05:32 +0100 +Subject: scsi: core: Kick the requeue list after inserting when flushing + +From: Niklas Cassel + +[ 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 +Closes: https://lore.kernel.org/linux-scsi/ZZw3Th70wUUvCiCY@kevinlocke.name/ +Signed-off-by: Niklas Cassel +Link: https://lore.kernel.org/r/20240111120533.3612509-1-cassel@kernel.org +Reviewed-by: Bart Van Assche +Reviewed-by: Damien Le Moal +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5d69a340a21 --- /dev/null +++ b/queue-6.6/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch @@ -0,0 +1,48 @@ +From 5ab54fef88b1be59326a4f6cfb46794a0764fcc9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Fixes: 1d337ec2f35e ("ufs: improve init sequence") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20231218225229.2542156-3-bvanassche@acm.org +Reviewed-by: Can Guo +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4c970c6ee0b --- /dev/null +++ b/queue-6.6/serial-core-set-missing-supported-flag-for-rx-during.patch @@ -0,0 +1,45 @@ +From af43430da925196c65717ffb872eef90043da6f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: +Fixes: 163f080eb717 ("serial: core: Add option to output RS485 RX_DURING_TX state via GPIO") +Reviewed-by: Ilpo Järvinen +Signed-off-by: Lino Sanfilippo +Link: https://lore.kernel.org/r/20240103061818.564-3-l.sanfilippo@kunbus.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..954fe9cd364 --- /dev/null +++ b/queue-6.6/serial-core-simplify-uart_get_rs485_mode.patch @@ -0,0 +1,78 @@ +From b4b7905e246ce50f256f0b7a7717702b93070adf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 17:23:46 +0300 +Subject: serial: core: Simplify uart_get_rs485_mode() + +From: Andy Shevchenko + +[ 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 +Link: https://lore.kernel.org/r/20231003142346.3072929-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 1a33e33ca0e8 ("serial: core: set missing supported flag for RX during TX GPIO") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c48d162efca --- /dev/null +++ b/queue-6.6/series @@ -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 index 00000000000..cbeeb910484 --- /dev/null +++ b/queue-6.6/sh-ecovec24-rename-missed-backlight-field-from-fbdev.patch @@ -0,0 +1,52 @@ +From 28688eee7cbf9785fd95a9cebdf786c613fb31e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202309231601.Uu6qcRnU-lkp@intel.com/ +Signed-off-by: Geert Uytterhoeven +Acked-by: Thomas Zimmermann +Reviewed-by: John Paul Adrian Glaubitz +Link: https://lore.kernel.org/r/20230925111022.3626362-1-geert+renesas@glider.be +Signed-off-by: John Paul Adrian Glaubitz +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5110da3b5e5 --- /dev/null +++ b/queue-6.6/smb-client-fix-parsing-of-smb3.1.1-posix-create-cont.patch @@ -0,0 +1,40 @@ +From 42827830391802507a8b2e627b47d403317e2ce9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jan 2024 01:08:26 -0300 +Subject: smb: client: fix parsing of SMB3.1.1 POSIX create context + +From: Paulo Alcantara + +[ 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 +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..445f39130e5 --- /dev/null +++ b/queue-6.6/soundwire-bus-introduce-controller_id.patch @@ -0,0 +1,162 @@ +From edbdfa05d3a3e9c980696b2165afda2a3eb1c05b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 11:09:32 -0500 +Subject: soundwire: bus: introduce controller_id + +From: Pierre-Louis Bossart + +[ 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 +Reviewed-by: Vijendar Mukunda +Signed-off-by: Pierre-Louis Bossart +Reviewed-by: Krzysztof Kozlowski +Tested-by: Krzysztof Kozlowski +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/stable/20231017160933.12624-2-pierre-louis.bossart%40linux.intel.com +Tested-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231017160933.12624-2-pierre-louis.bossart@linux.intel.com +Signed-off-by: Vinod Koul +Stable-dep-of: 8a8a9ac8a497 ("soundwire: fix initializing sysfs for same devices on different buses") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f3eb8c0d136 --- /dev/null +++ b/queue-6.6/soundwire-fix-initializing-sysfs-for-same-devices-on.patch @@ -0,0 +1,89 @@ +From 8f5395f655b54b48def212f6d1bc5424d8a734ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 11:09:33 -0500 +Subject: soundwire: fix initializing sysfs for same devices on different buses + +From: Krzysztof Kozlowski + +[ 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 +Reviewed-by: Vijendar Mukunda +Co-developed-by: Pierre-Louis Bossart +Signed-off-by: Pierre-Louis Bossart +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Krzysztof Kozlowski +Tested-by: Krzysztof Kozlowski +Acked-by: Mark Brown +Tested-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20231017160933.12624-3-pierre-louis.bossart@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3