]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Thu, 30 Mar 2023 11:12:56 +0000 (07:12 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 30 Mar 2023 11:12:56 +0000 (07:12 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.15/bus-imx-weim-fix-branch-condition-evaluates-to-a-gar.patch [new file with mode: 0644]
queue-5.15/fsverity-don-t-drop-pagecache-at-end-of-fs_ioc_enabl.patch [new file with mode: 0644]
queue-5.15/kcsan-avoid-passing-g-for-test.patch [new file with mode: 0644]
queue-5.15/kernel-kcsan-kcsan_test-build-without-structleak-plu.patch [new file with mode: 0644]
queue-5.15/ksmbd-don-t-terminate-inactive-sessions-after-a-few-.patch [new file with mode: 0644]
queue-5.15/series [new file with mode: 0644]
queue-5.15/usb-dwc3-gadget-add-1ms-delay-after-end-transfer-com.patch [new file with mode: 0644]
queue-5.15/usb-dwc3-gadget-move-cmd_endtransfer-to-extra-functi.patch [new file with mode: 0644]

diff --git a/queue-5.15/bus-imx-weim-fix-branch-condition-evaluates-to-a-gar.patch b/queue-5.15/bus-imx-weim-fix-branch-condition-evaluates-to-a-gar.patch
new file mode 100644 (file)
index 0000000..feedec6
--- /dev/null
@@ -0,0 +1,44 @@
+From 97b32f0d52a750ff406ecbc485721ca788fbf70f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 16:25:26 +0300
+Subject: bus: imx-weim: fix branch condition evaluates to a garbage value
+
+From: Ivan Bornyakov <i.bornyakov@metrotek.ru>
+
+[ Upstream commit 1adab2922c58e7ff4fa9f0b43695079402cce876 ]
+
+If bus type is other than imx50_weim_devtype and have no child devices,
+variable 'ret' in function weim_parse_dt() will not be initialized, but
+will be used as branch condition and return value. Fix this by
+initializing 'ret' with 0.
+
+This was discovered with help of clang-analyzer, but the situation is
+quite possible in real life.
+
+Fixes: 52c47b63412b ("bus: imx-weim: improve error handling upon child probe-failure")
+Signed-off-by: Ivan Bornyakov <i.bornyakov@metrotek.ru>
+Cc: stable@vger.kernel.org
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/imx-weim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
+index 28bb65a5613fd..201767823edb5 100644
+--- a/drivers/bus/imx-weim.c
++++ b/drivers/bus/imx-weim.c
+@@ -192,8 +192,8 @@ static int weim_parse_dt(struct platform_device *pdev, void __iomem *base)
+       const struct of_device_id *of_id = of_match_device(weim_id_table,
+                                                          &pdev->dev);
+       const struct imx_weim_devtype *devtype = of_id->data;
++      int ret = 0, have_child = 0;
+       struct device_node *child;
+-      int ret, have_child = 0;
+       struct cs_timing_state ts = {};
+       u32 reg;
+-- 
+2.39.2
+
diff --git a/queue-5.15/fsverity-don-t-drop-pagecache-at-end-of-fs_ioc_enabl.patch b/queue-5.15/fsverity-don-t-drop-pagecache-at-end-of-fs_ioc_enabl.patch
new file mode 100644 (file)
index 0000000..0017286
--- /dev/null
@@ -0,0 +1,73 @@
+From c3708cee6516c0fc5cbc69525e42c0b2deea2b22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Mar 2023 16:31:32 -0700
+Subject: fsverity: don't drop pagecache at end of FS_IOC_ENABLE_VERITY
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit a075bacde257f755bea0e53400c9f1cdd1b8e8e6 ]
+
+The full pagecache drop at the end of FS_IOC_ENABLE_VERITY is causing
+performance problems and is hindering adoption of fsverity.  It was
+intended to solve a race condition where unverified pages might be left
+in the pagecache.  But actually it doesn't solve it fully.
+
+Since the incomplete solution for this race condition has too much
+performance impact for it to be worth it, let's remove it for now.
+
+Fixes: 3fda4c617e84 ("fs-verity: implement FS_IOC_ENABLE_VERITY ioctl")
+Cc: stable@vger.kernel.org
+Reviewed-by: Victor Hsieh <victorhsieh@google.com>
+Link: https://lore.kernel.org/r/20230314235332.50270-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/verity/enable.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/fs/verity/enable.c b/fs/verity/enable.c
+index 60a4372aa4d75..dfe8acc32df66 100644
+--- a/fs/verity/enable.c
++++ b/fs/verity/enable.c
+@@ -391,25 +391,27 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
+               goto out_drop_write;
+       err = enable_verity(filp, &arg);
+-      if (err)
+-              goto out_allow_write_access;
+       /*
+-       * Some pages of the file may have been evicted from pagecache after
+-       * being used in the Merkle tree construction, then read into pagecache
+-       * again by another process reading from the file concurrently.  Since
+-       * these pages didn't undergo verification against the file digest which
+-       * fs-verity now claims to be enforcing, we have to wipe the pagecache
+-       * to ensure that all future reads are verified.
++       * We no longer drop the inode's pagecache after enabling verity.  This
++       * used to be done to try to avoid a race condition where pages could be
++       * evicted after being used in the Merkle tree construction, then
++       * re-instantiated by a concurrent read.  Such pages are unverified, and
++       * the backing storage could have filled them with different content, so
++       * they shouldn't be used to fulfill reads once verity is enabled.
++       *
++       * But, dropping the pagecache has a big performance impact, and it
++       * doesn't fully solve the race condition anyway.  So for those reasons,
++       * and also because this race condition isn't very important relatively
++       * speaking (especially for small-ish files, where the chance of a page
++       * being used, evicted, *and* re-instantiated all while enabling verity
++       * is quite small), we no longer drop the inode's pagecache.
+        */
+-      filemap_write_and_wait(inode->i_mapping);
+-      invalidate_inode_pages2(inode->i_mapping);
+       /*
+        * allow_write_access() is needed to pair with deny_write_access().
+        * Regardless, the filesystem won't allow writing to verity files.
+        */
+-out_allow_write_access:
+       allow_write_access(filp);
+ out_drop_write:
+       mnt_drop_write_file(filp);
+-- 
+2.39.2
+
diff --git a/queue-5.15/kcsan-avoid-passing-g-for-test.patch b/queue-5.15/kcsan-avoid-passing-g-for-test.patch
new file mode 100644 (file)
index 0000000..9d8a132
--- /dev/null
@@ -0,0 +1,50 @@
+From d952a98e9995e9a8602b4523c4c1fea7a85d3d74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Mar 2023 23:47:05 +0100
+Subject: kcsan: avoid passing -g for test
+
+From: Marco Elver <elver@google.com>
+
+[ Upstream commit 5eb39cde1e2487ba5ec1802dc5e58a77e700d99e ]
+
+Nathan reported that when building with GNU as and a version of clang that
+defaults to DWARF5, the assembler will complain with:
+
+  Error: non-constant .uleb128 is not supported
+
+This is because `-g` defaults to the compiler debug info default. If the
+assembler does not support some of the directives used, the above errors
+occur. To fix, remove the explicit passing of `-g`.
+
+All the test wants is that stack traces print valid function names, and
+debug info is not required for that. (I currently cannot recall why I
+added the explicit `-g`.)
+
+Link: https://lkml.kernel.org/r/20230316224705.709984-2-elver@google.com
+Fixes: 1fe84fd4a402 ("kcsan: Add test suite")
+Signed-off-by: Marco Elver <elver@google.com>
+Reported-by: Nathan Chancellor <nathan@kernel.org>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/kcsan/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/kcsan/Makefile b/kernel/kcsan/Makefile
+index 5936288ee938b..c4ddd189f3e07 100644
+--- a/kernel/kcsan/Makefile
++++ b/kernel/kcsan/Makefile
+@@ -13,6 +13,6 @@ CFLAGS_core.o := $(call cc-option,-fno-conserve-stack) \
+ obj-y := core.o debugfs.o report.o
+ obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o
+-CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
++CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -fno-omit-frame-pointer
+ CFLAGS_kcsan_test.o += $(DISABLE_STRUCTLEAK_PLUGIN)
+ obj-$(CONFIG_KCSAN_KUNIT_TEST) += kcsan_test.o
+-- 
+2.39.2
+
diff --git a/queue-5.15/kernel-kcsan-kcsan_test-build-without-structleak-plu.patch b/queue-5.15/kernel-kcsan-kcsan_test-build-without-structleak-plu.patch
new file mode 100644 (file)
index 0000000..f9888de
--- /dev/null
@@ -0,0 +1,44 @@
+From 68c64313d57d6fb66818a1cb0aff4a7e2fdb171b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Nov 2022 11:43:58 +0100
+Subject: kernel: kcsan: kcsan_test: build without structleak plugin
+
+From: Anders Roxell <anders.roxell@linaro.org>
+
+[ Upstream commit 6fcd4267a840d0536b8e5334ad5f31e4105fce85 ]
+
+Building kcsan_test with structleak plugin enabled makes the stack frame
+size to grow.
+
+kernel/kcsan/kcsan_test.c:704:1: error: the frame size of 3296 bytes is larger than 2048 bytes [-Werror=frame-larger-than=]
+
+Turn off the structleak plugin checks for kcsan_test.
+
+Link: https://lkml.kernel.org/r/20221128104358.2660634-1-anders.roxell@linaro.org
+Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
+Suggested-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Marco Elver <elver@google.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: David Gow <davidgow@google.com>
+Cc: Jason A. Donenfeld <Jason@zx2c4.com>
+Cc: Kees Cook <keescook@chromium.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 5eb39cde1e24 ("kcsan: avoid passing -g for test")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/kcsan/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/kcsan/Makefile b/kernel/kcsan/Makefile
+index c2bb07f5bcc72..5936288ee938b 100644
+--- a/kernel/kcsan/Makefile
++++ b/kernel/kcsan/Makefile
+@@ -14,4 +14,5 @@ obj-y := core.o debugfs.o report.o
+ obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o
+ CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
++CFLAGS_kcsan_test.o += $(DISABLE_STRUCTLEAK_PLUGIN)
+ obj-$(CONFIG_KCSAN_KUNIT_TEST) += kcsan_test.o
+-- 
+2.39.2
+
diff --git a/queue-5.15/ksmbd-don-t-terminate-inactive-sessions-after-a-few-.patch b/queue-5.15/ksmbd-don-t-terminate-inactive-sessions-after-a-few-.patch
new file mode 100644 (file)
index 0000000..2edf22c
--- /dev/null
@@ -0,0 +1,161 @@
+From 1c83edba3ec947a1b69826ae299db4e36dc3cd4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Mar 2023 15:25:34 +0900
+Subject: ksmbd: don't terminate inactive sessions after a few seconds
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+[ Upstream commit be6f42fad5f5fd1fea9d562df82c38ad6ed3bfe9 ]
+
+Steve reported that inactive sessions are terminated after a few
+seconds. ksmbd terminate when receiving -EAGAIN error from
+kernel_recvmsg(). -EAGAIN means there is no data available in timeout.
+So ksmbd should keep connection with unlimited retries instead of
+terminating inactive sessions.
+
+Cc: stable@vger.kernel.org
+Reported-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ksmbd/connection.c     |  4 ++--
+ fs/ksmbd/connection.h     |  3 ++-
+ fs/ksmbd/transport_rdma.c |  2 +-
+ fs/ksmbd/transport_tcp.c  | 35 +++++++++++++++++++++++------------
+ 4 files changed, 28 insertions(+), 16 deletions(-)
+
+diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c
+index 6105649b4ebb0..610abaadbb677 100644
+--- a/fs/ksmbd/connection.c
++++ b/fs/ksmbd/connection.c
+@@ -292,7 +292,7 @@ int ksmbd_conn_handler_loop(void *p)
+               kvfree(conn->request_buf);
+               conn->request_buf = NULL;
+-              size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
++              size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
+               if (size != sizeof(hdr_buf))
+                       break;
+@@ -335,7 +335,7 @@ int ksmbd_conn_handler_loop(void *p)
+                * We already read 4 bytes to find out PDU size, now
+                * read in PDU
+                */
+-              size = t->ops->read(t, conn->request_buf + 4, pdu_size);
++              size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
+               if (size < 0) {
+                       pr_err("sock_read failed: %d\n", size);
+                       break;
+diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
+index 8694aef482c1a..4b15c5e673d92 100644
+--- a/fs/ksmbd/connection.h
++++ b/fs/ksmbd/connection.h
+@@ -122,7 +122,8 @@ struct ksmbd_conn_ops {
+ struct ksmbd_transport_ops {
+       int (*prepare)(struct ksmbd_transport *t);
+       void (*disconnect)(struct ksmbd_transport *t);
+-      int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
++      int (*read)(struct ksmbd_transport *t, char *buf,
++                  unsigned int size, int max_retries);
+       int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
+                     int size, bool need_invalidate_rkey,
+                     unsigned int remote_key);
+diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
+index 9d67419929d6c..9ca29cdb7898f 100644
+--- a/fs/ksmbd/transport_rdma.c
++++ b/fs/ksmbd/transport_rdma.c
+@@ -663,7 +663,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
+ }
+ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
+-                         unsigned int size)
++                         unsigned int size, int unused)
+ {
+       struct smb_direct_recvmsg *recvmsg;
+       struct smb_direct_data_transfer *data_transfer;
+diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
+index e0ca6cc04b91c..d1d7954368a56 100644
+--- a/fs/ksmbd/transport_tcp.c
++++ b/fs/ksmbd/transport_tcp.c
+@@ -291,16 +291,18 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
+ /**
+  * ksmbd_tcp_readv() - read data from socket in given iovec
+- * @t:                TCP transport instance
+- * @iov_orig: base IO vector
+- * @nr_segs:  number of segments in base iov
+- * @to_read:  number of bytes to read from socket
++ * @t:                        TCP transport instance
++ * @iov_orig:         base IO vector
++ * @nr_segs:          number of segments in base iov
++ * @to_read:          number of bytes to read from socket
++ * @max_retries:      maximum retry count
+  *
+  * Return:    on success return number of bytes read from socket,
+  *            otherwise return error number
+  */
+ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
+-                         unsigned int nr_segs, unsigned int to_read)
++                         unsigned int nr_segs, unsigned int to_read,
++                         int max_retries)
+ {
+       int length = 0;
+       int total_read;
+@@ -308,7 +310,6 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
+       struct msghdr ksmbd_msg;
+       struct kvec *iov;
+       struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
+-      int max_retry = 2;
+       iov = get_conn_iovec(t, nr_segs);
+       if (!iov)
+@@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
+               } else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
+                       total_read = -EAGAIN;
+                       break;
+-              } else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
+-                         max_retry) {
++              } else if (length == -ERESTARTSYS || length == -EAGAIN) {
++                      /*
++                       * If max_retries is negative, Allow unlimited
++                       * retries to keep connection with inactive sessions.
++                       */
++                      if (max_retries == 0) {
++                              total_read = length;
++                              break;
++                      } else if (max_retries > 0) {
++                              max_retries--;
++                      }
++
+                       usleep_range(1000, 2000);
+                       length = 0;
+-                      max_retry--;
+                       continue;
+               } else if (length <= 0) {
+-                      total_read = -EAGAIN;
++                      total_read = length;
+                       break;
+               }
+       }
+@@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
+  * Return:    on success return number of bytes read from socket,
+  *            otherwise return error number
+  */
+-static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
++static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
++                        unsigned int to_read, int max_retries)
+ {
+       struct kvec iov;
+       iov.iov_base = buf;
+       iov.iov_len = to_read;
+-      return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
++      return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
+ }
+ static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
+-- 
+2.39.2
+
diff --git a/queue-5.15/series b/queue-5.15/series
new file mode 100644 (file)
index 0000000..4f31f13
--- /dev/null
@@ -0,0 +1,7 @@
+fsverity-don-t-drop-pagecache-at-end-of-fs_ioc_enabl.patch
+usb-dwc3-gadget-move-cmd_endtransfer-to-extra-functi.patch
+usb-dwc3-gadget-add-1ms-delay-after-end-transfer-com.patch
+kernel-kcsan-kcsan_test-build-without-structleak-plu.patch
+kcsan-avoid-passing-g-for-test.patch
+ksmbd-don-t-terminate-inactive-sessions-after-a-few-.patch
+bus-imx-weim-fix-branch-condition-evaluates-to-a-gar.patch
diff --git a/queue-5.15/usb-dwc3-gadget-add-1ms-delay-after-end-transfer-com.patch b/queue-5.15/usb-dwc3-gadget-add-1ms-delay-after-end-transfer-com.patch
new file mode 100644 (file)
index 0000000..e09573b
--- /dev/null
@@ -0,0 +1,87 @@
+From 8c9c9333b819ac70930f9abe4aa7d37638979308 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 12:05:57 -0800
+Subject: usb: dwc3: gadget: Add 1ms delay after end transfer command without
+ IOC
+
+From: Wesley Cheng <quic_wcheng@quicinc.com>
+
+[ Upstream commit d8a2bb4eb75866275b5cf7de2e593ac3449643e2 ]
+
+Previously, there was a 100uS delay inserted after issuing an end transfer
+command for specific controller revisions.  This was due to the fact that
+there was a GUCTL2 bit field which enabled synchronous completion of the
+end transfer command once the CMDACT bit was cleared in the DEPCMD
+register.  Since this bit does not exist for all controller revisions and
+the current implementation heavily relies on utizling the EndTransfer
+command completion interrupt, add the delay back in for uses where the
+interrupt on completion bit is not set, and increase the duration to 1ms
+for the controller to complete the command.
+
+An issue was seen where the USB request buffer was unmapped while the DWC3
+controller was still accessing the TRB.  However, it was confirmed that the
+end transfer command was successfully submitted. (no end transfer timeout)
+In situations, such as dwc3_gadget_soft_disconnect() and
+__dwc3_gadget_ep_disable(), the dwc3_remove_request() is utilized, which
+will issue the end transfer command, and follow up with
+dwc3_gadget_giveback().  At least for the USB ep disable path, it is
+required for any pending and started requests to be completed and returned
+to the function driver in the same context of the disable call.  Without
+the GUCTL2 bit, it is not ensured that the end transfer is completed before
+the buffers are unmapped.
+
+Fixes: cf2f8b63f7f1 ("usb: dwc3: gadget: Remove END_TRANSFER delay")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/20230306200557.29387-1-quic_wcheng@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/gadget.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 1689c09b937ae..eaf64f33fe077 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1652,6 +1652,7 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
+  */
+ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
+ {
++      struct dwc3 *dwc = dep->dwc;
+       struct dwc3_gadget_ep_cmd_params params;
+       u32 cmd;
+       int ret;
+@@ -1665,10 +1666,13 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
+       WARN_ON_ONCE(ret);
+       dep->resource_index = 0;
+-      if (!interrupt)
++      if (!interrupt) {
++              if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
++                      mdelay(1);
+               dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+-      else if (!ret)
++      } else if (!ret) {
+               dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
++      }
+       return ret;
+ }
+@@ -3654,7 +3658,11 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+        * enabled, the EndTransfer command will have completed upon
+        * returning from this function.
+        *
+-       * This mode is NOT available on the DWC_usb31 IP.
++       * This mode is NOT available on the DWC_usb31 IP.  In this
++       * case, if the IOC bit is not set, then delay by 1ms
++       * after issuing the EndTransfer command.  This allows for the
++       * controller to handle the command completely before DWC3
++       * remove requests attempts to unmap USB request buffers.
+        */
+       __dwc3_stop_active_transfer(dep, force, interrupt);
+-- 
+2.39.2
+
diff --git a/queue-5.15/usb-dwc3-gadget-move-cmd_endtransfer-to-extra-functi.patch b/queue-5.15/usb-dwc3-gadget-move-cmd_endtransfer-to-extra-functi.patch
new file mode 100644 (file)
index 0000000..71006a7
--- /dev/null
@@ -0,0 +1,125 @@
+From e73ad3c25f36dfbbb332e22c332b224f24bc884c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 6 Mar 2022 22:12:51 +0100
+Subject: usb: dwc3: gadget: move cmd_endtransfer to extra function
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+[ Upstream commit e192cc7b52399d1b073f88cd3ba128b74d3a57f1 ]
+
+This patch adds the extra function __dwc3_stop_active_transfer to
+consolidate the same codepath.
+
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Link: https://lore.kernel.org/r/20220306211251.2281335-3-m.grzeschik@pengutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: d8a2bb4eb758 ("usb: dwc3: gadget: Add 1ms delay after end transfer command without IOC")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/gadget.c | 69 +++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index a0100d26de8e1..1689c09b937ae 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1639,6 +1639,40 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
+       return DWC3_DSTS_SOFFN(reg);
+ }
++/**
++ * __dwc3_stop_active_transfer - stop the current active transfer
++ * @dep: isoc endpoint
++ * @force: set forcerm bit in the command
++ * @interrupt: command complete interrupt after End Transfer command
++ *
++ * When setting force, the ForceRM bit will be set. In that case
++ * the controller won't update the TRB progress on command
++ * completion. It also won't clear the HWO bit in the TRB.
++ * The command will also not complete immediately in that case.
++ */
++static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
++{
++      struct dwc3_gadget_ep_cmd_params params;
++      u32 cmd;
++      int ret;
++
++      cmd = DWC3_DEPCMD_ENDTRANSFER;
++      cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
++      cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
++      cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
++      memset(&params, 0, sizeof(params));
++      ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
++      WARN_ON_ONCE(ret);
++      dep->resource_index = 0;
++
++      if (!interrupt)
++              dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
++      else if (!ret)
++              dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
++
++      return ret;
++}
++
+ /**
+  * dwc3_gadget_start_isoc_quirk - workaround invalid frame number
+  * @dep: isoc endpoint
+@@ -1808,21 +1842,8 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
+        * status, issue END_TRANSFER command and retry on the next XferNotReady
+        * event.
+        */
+-      if (ret == -EAGAIN) {
+-              struct dwc3_gadget_ep_cmd_params params;
+-              u32 cmd;
+-
+-              cmd = DWC3_DEPCMD_ENDTRANSFER |
+-                      DWC3_DEPCMD_CMDIOC |
+-                      DWC3_DEPCMD_PARAM(dep->resource_index);
+-
+-              dep->resource_index = 0;
+-              memset(&params, 0, sizeof(params));
+-
+-              ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
+-              if (!ret)
+-                      dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+-      }
++      if (ret == -EAGAIN)
++              ret = __dwc3_stop_active_transfer(dep, false, true);
+       return ret;
+ }
+@@ -3605,10 +3626,6 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
+ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+       bool interrupt)
+ {
+-      struct dwc3_gadget_ep_cmd_params params;
+-      u32 cmd;
+-      int ret;
+-
+       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
+           (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+               return;
+@@ -3640,19 +3657,7 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
+        * This mode is NOT available on the DWC_usb31 IP.
+        */
+-      cmd = DWC3_DEPCMD_ENDTRANSFER;
+-      cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0;
+-      cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0;
+-      cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
+-      memset(&params, 0, sizeof(params));
+-      ret = dwc3_send_gadget_ep_cmd(dep, cmd, &params);
+-      WARN_ON_ONCE(ret);
+-      dep->resource_index = 0;
+-
+-      if (!interrupt)
+-              dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+-      else
+-              dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
++      __dwc3_stop_active_transfer(dep, force, interrupt);
+ }
+ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
+-- 
+2.39.2
+