]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Fri, 1 Oct 2021 14:16:19 +0000 (10:16 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 1 Oct 2021 14:16:19 +0000 (10:16 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/cpufreq-schedutil-destroy-mutex-before-kobject_put-f.patch [new file with mode: 0644]
queue-5.10/cpufreq-schedutil-use-kobject-release-method-to-free.patch [new file with mode: 0644]
queue-5.10/scsi-qla2xxx-changes-to-support-kdump-kernel-for-nvm.patch [new file with mode: 0644]
queue-5.10/series [new file with mode: 0644]
queue-5.10/tty-fix-out-of-bound-vmalloc-access-in-imageblit.patch [new file with mode: 0644]
queue-5.10/usb-cdns3-fix-race-condition-before-setting-doorbell.patch [new file with mode: 0644]

diff --git a/queue-5.10/cpufreq-schedutil-destroy-mutex-before-kobject_put-f.patch b/queue-5.10/cpufreq-schedutil-destroy-mutex-before-kobject_put-f.patch
new file mode 100644 (file)
index 0000000..4a26adc
--- /dev/null
@@ -0,0 +1,70 @@
+From f35aef728ba6afbb764b292918a104aad7d819ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Sep 2021 16:56:23 +0000
+Subject: cpufreq: schedutil: Destroy mutex before kobject_put() frees the
+ memory
+
+From: James Morse <james.morse@arm.com>
+
+[ Upstream commit cdef1196608892b9a46caa5f2b64095a7f0be60c ]
+
+Since commit e5c6b312ce3c ("cpufreq: schedutil: Use kobject release()
+method to free sugov_tunables") kobject_put() has kfree()d the
+attr_set before gov_attr_set_put() returns.
+
+kobject_put() isn't the last user of attr_set in gov_attr_set_put(),
+the subsequent mutex_destroy() triggers a use-after-free:
+| BUG: KASAN: use-after-free in mutex_is_locked+0x20/0x60
+| Read of size 8 at addr ffff000800ca4250 by task cpuhp/2/20
+|
+| CPU: 2 PID: 20 Comm: cpuhp/2 Not tainted 5.15.0-rc1 #12369
+| Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development
+| Platform, BIOS EDK II Jul 30 2018
+| Call trace:
+|  dump_backtrace+0x0/0x380
+|  show_stack+0x1c/0x30
+|  dump_stack_lvl+0x8c/0xb8
+|  print_address_description.constprop.0+0x74/0x2b8
+|  kasan_report+0x1f4/0x210
+|  kasan_check_range+0xfc/0x1a4
+|  __kasan_check_read+0x38/0x60
+|  mutex_is_locked+0x20/0x60
+|  mutex_destroy+0x80/0x100
+|  gov_attr_set_put+0xfc/0x150
+|  sugov_exit+0x78/0x190
+|  cpufreq_offline.isra.0+0x2c0/0x660
+|  cpuhp_cpufreq_offline+0x14/0x24
+|  cpuhp_invoke_callback+0x430/0x6d0
+|  cpuhp_thread_fun+0x1b0/0x624
+|  smpboot_thread_fn+0x5e0/0xa6c
+|  kthread+0x3a0/0x450
+|  ret_from_fork+0x10/0x20
+
+Swap the order of the calls.
+
+Fixes: e5c6b312ce3c ("cpufreq: schedutil: Use kobject release() method to free sugov_tunables")
+Cc: 4.7+ <stable@vger.kernel.org> # 4.7+
+Signed-off-by: James Morse <james.morse@arm.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/cpufreq_governor_attr_set.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cpufreq/cpufreq_governor_attr_set.c b/drivers/cpufreq/cpufreq_governor_attr_set.c
+index 66b05a326910..a6f365b9cc1a 100644
+--- a/drivers/cpufreq/cpufreq_governor_attr_set.c
++++ b/drivers/cpufreq/cpufreq_governor_attr_set.c
+@@ -74,8 +74,8 @@ unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *l
+       if (count)
+               return count;
+-      kobject_put(&attr_set->kobj);
+       mutex_destroy(&attr_set->update_lock);
++      kobject_put(&attr_set->kobj);
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(gov_attr_set_put);
+-- 
+2.33.0
+
diff --git a/queue-5.10/cpufreq-schedutil-use-kobject-release-method-to-free.patch b/queue-5.10/cpufreq-schedutil-use-kobject-release-method-to-free.patch
new file mode 100644 (file)
index 0000000..89a828c
--- /dev/null
@@ -0,0 +1,131 @@
+From 4824586a139df271c047bee204a02f9d49a135fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Aug 2021 15:29:17 +0800
+Subject: cpufreq: schedutil: Use kobject release() method to free
+ sugov_tunables
+
+From: Kevin Hao <haokexin@gmail.com>
+
+[ Upstream commit e5c6b312ce3cc97e90ea159446e6bfa06645364d ]
+
+The struct sugov_tunables is protected by the kobject, so we can't free
+it directly. Otherwise we would get a call trace like this:
+  ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x30
+  WARNING: CPU: 3 PID: 720 at lib/debugobjects.c:505 debug_print_object+0xb8/0x100
+  Modules linked in:
+  CPU: 3 PID: 720 Comm: a.sh Tainted: G        W         5.14.0-rc1-next-20210715-yocto-standard+ #507
+  Hardware name: Marvell OcteonTX CN96XX board (DT)
+  pstate: 40400009 (nZcv daif +PAN -UAO -TCO BTYPE=--)
+  pc : debug_print_object+0xb8/0x100
+  lr : debug_print_object+0xb8/0x100
+  sp : ffff80001ecaf910
+  x29: ffff80001ecaf910 x28: ffff00011b10b8d0 x27: ffff800011043d80
+  x26: ffff00011a8f0000 x25: ffff800013cb3ff0 x24: 0000000000000000
+  x23: ffff80001142aa68 x22: ffff800011043d80 x21: ffff00010de46f20
+  x20: ffff800013c0c520 x19: ffff800011d8f5b0 x18: 0000000000000010
+  x17: 6e6968207473696c x16: 5f72656d6974203a x15: 6570797420746365
+  x14: 6a626f2029302065 x13: 303378302f307830 x12: 2b6e665f72656d69
+  x11: ffff8000124b1560 x10: ffff800012331520 x9 : ffff8000100ca6b0
+  x8 : 000000000017ffe8 x7 : c0000000fffeffff x6 : 0000000000000001
+  x5 : ffff800011d8c000 x4 : ffff800011d8c740 x3 : 0000000000000000
+  x2 : ffff0001108301c0 x1 : ab3c90eedf9c0f00 x0 : 0000000000000000
+  Call trace:
+   debug_print_object+0xb8/0x100
+   __debug_check_no_obj_freed+0x1c0/0x230
+   debug_check_no_obj_freed+0x20/0x88
+   slab_free_freelist_hook+0x154/0x1c8
+   kfree+0x114/0x5d0
+   sugov_exit+0xbc/0xc0
+   cpufreq_exit_governor+0x44/0x90
+   cpufreq_set_policy+0x268/0x4a8
+   store_scaling_governor+0xe0/0x128
+   store+0xc0/0xf0
+   sysfs_kf_write+0x54/0x80
+   kernfs_fop_write_iter+0x128/0x1c0
+   new_sync_write+0xf0/0x190
+   vfs_write+0x2d4/0x478
+   ksys_write+0x74/0x100
+   __arm64_sys_write+0x24/0x30
+   invoke_syscall.constprop.0+0x54/0xe0
+   do_el0_svc+0x64/0x158
+   el0_svc+0x2c/0xb0
+   el0t_64_sync_handler+0xb0/0xb8
+   el0t_64_sync+0x198/0x19c
+  irq event stamp: 5518
+  hardirqs last  enabled at (5517): [<ffff8000100cbd7c>] console_unlock+0x554/0x6c8
+  hardirqs last disabled at (5518): [<ffff800010fc0638>] el1_dbg+0x28/0xa0
+  softirqs last  enabled at (5504): [<ffff8000100106e0>] __do_softirq+0x4d0/0x6c0
+  softirqs last disabled at (5483): [<ffff800010049548>] irq_exit+0x1b0/0x1b8
+
+So split the original sugov_tunables_free() into two functions,
+sugov_clear_global_tunables() is just used to clear the global_tunables
+and the new sugov_tunables_free() is used as kobj_type::release to
+release the sugov_tunables safely.
+
+Fixes: 9bdcb44e391d ("cpufreq: schedutil: New governor based on scheduler utilization data")
+Cc: 4.7+ <stable@vger.kernel.org> # 4.7+
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/cpufreq_schedutil.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index 97d318b0cd0c..5e39da0ae086 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -610,9 +610,17 @@ static struct attribute *sugov_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(sugov);
++static void sugov_tunables_free(struct kobject *kobj)
++{
++      struct gov_attr_set *attr_set = container_of(kobj, struct gov_attr_set, kobj);
++
++      kfree(to_sugov_tunables(attr_set));
++}
++
+ static struct kobj_type sugov_tunables_ktype = {
+       .default_groups = sugov_groups,
+       .sysfs_ops = &governor_sysfs_ops,
++      .release = &sugov_tunables_free,
+ };
+ /********************** cpufreq governor interface *********************/
+@@ -712,12 +720,10 @@ static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_polic
+       return tunables;
+ }
+-static void sugov_tunables_free(struct sugov_tunables *tunables)
++static void sugov_clear_global_tunables(void)
+ {
+       if (!have_governor_per_policy())
+               global_tunables = NULL;
+-
+-      kfree(tunables);
+ }
+ static int sugov_init(struct cpufreq_policy *policy)
+@@ -780,7 +786,7 @@ out:
+ fail:
+       kobject_put(&tunables->attr_set.kobj);
+       policy->governor_data = NULL;
+-      sugov_tunables_free(tunables);
++      sugov_clear_global_tunables();
+ stop_kthread:
+       sugov_kthread_stop(sg_policy);
+@@ -807,7 +813,7 @@ static void sugov_exit(struct cpufreq_policy *policy)
+       count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
+       policy->governor_data = NULL;
+       if (!count)
+-              sugov_tunables_free(tunables);
++              sugov_clear_global_tunables();
+       mutex_unlock(&global_tunables_lock);
+-- 
+2.33.0
+
diff --git a/queue-5.10/scsi-qla2xxx-changes-to-support-kdump-kernel-for-nvm.patch b/queue-5.10/scsi-qla2xxx-changes-to-support-kdump-kernel-for-nvm.patch
new file mode 100644 (file)
index 0000000..fb6ab10
--- /dev/null
@@ -0,0 +1,132 @@
+From bd44b711e31f35a77031831a6309c1b0c6b10534 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Aug 2021 21:37:18 -0700
+Subject: scsi: qla2xxx: Changes to support kdump kernel for NVMe BFS
+
+From: Saurav Kashyap <skashyap@marvell.com>
+
+[ Upstream commit 4a0a542fe5e4273baf9228459ef3f75c29490cba ]
+
+The MSI-X and MSI calls fails in kdump kernel. Because of this
+qla2xxx_create_qpair() fails leading to .create_queue callback failure.
+The fix is to return existing qpair instead of allocating new one and
+allocate a single hw queue.
+
+[   19.975838] qla2xxx [0000:d8:00.1]-00c7:11: MSI-X: Failed to enable support,
+giving   up -- 16/-28.
+[   19.984885] qla2xxx [0000:d8:00.1]-0037:11: Falling back-to MSI mode --
+ret=-28.
+[   19.992278] qla2xxx [0000:d8:00.1]-0039:11: Falling back-to INTa mode --
+ret=-28.
+..
+..
+..
+[   21.141518] qla2xxx [0000:d8:00.0]-2104:2: qla_nvme_alloc_queue: handle
+00000000e7ee499d, idx =1, qsize 32
+[   21.151166] qla2xxx [0000:d8:00.0]-0181:2: FW/Driver is not multi-queue capable.
+[   21.158558] qla2xxx [0000:d8:00.0]-2122:2: Failed to allocate qpair
+[   21.164824] nvme nvme0: NVME-FC{0}: reset: Reconnect attempt failed (-22)
+[   21.171612] nvme nvme0: NVME-FC{0}: Reconnect attempt in 2 seconds
+
+Link: https://lore.kernel.org/r/20210810043720.1137-13-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h  |  1 -
+ drivers/scsi/qla2xxx/qla_isr.c  |  2 ++
+ drivers/scsi/qla2xxx/qla_nvme.c | 40 +++++++++++++++------------------
+ 3 files changed, 20 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 4f0486fe30dd..e1fd91a58120 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -3913,7 +3913,6 @@ struct qla_hw_data {
+               uint32_t        scm_supported_f:1;
+                               /* Enabled in Driver */
+               uint32_t        scm_enabled:1;
+-              uint32_t        max_req_queue_warned:1;
+               uint32_t        plogi_template_valid:1;
+       } flags;
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index a24b82de4aab..5e040b6debc8 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -4158,6 +4158,8 @@ skip_msi:
+               ql_dbg(ql_dbg_init, vha, 0x0125,
+                   "INTa mode: Enabled.\n");
+               ha->flags.mr_intr_valid = 1;
++              /* Set max_qpair to 0, as MSI-X and MSI in not enabled */
++              ha->max_qpairs = 0;
+       }
+ clear_risc_ints:
+diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
+index f6c76a063294..5acee3c798d4 100644
+--- a/drivers/scsi/qla2xxx/qla_nvme.c
++++ b/drivers/scsi/qla2xxx/qla_nvme.c
+@@ -109,19 +109,24 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport,
+               return -EINVAL;
+       }
+-      if (ha->queue_pair_map[qidx]) {
+-              *handle = ha->queue_pair_map[qidx];
+-              ql_log(ql_log_info, vha, 0x2121,
+-                  "Returning existing qpair of %p for idx=%x\n",
+-                  *handle, qidx);
+-              return 0;
+-      }
++      /* Use base qpair if max_qpairs is 0 */
++      if (!ha->max_qpairs) {
++              qpair = ha->base_qpair;
++      } else {
++              if (ha->queue_pair_map[qidx]) {
++                      *handle = ha->queue_pair_map[qidx];
++                      ql_log(ql_log_info, vha, 0x2121,
++                             "Returning existing qpair of %p for idx=%x\n",
++                             *handle, qidx);
++                      return 0;
++              }
+-      qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
+-      if (qpair == NULL) {
+-              ql_log(ql_log_warn, vha, 0x2122,
+-                  "Failed to allocate qpair\n");
+-              return -EINVAL;
++              qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
++              if (!qpair) {
++                      ql_log(ql_log_warn, vha, 0x2122,
++                             "Failed to allocate qpair\n");
++                      return -EINVAL;
++              }
+       }
+       *handle = qpair;
+@@ -715,18 +720,9 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha)
+       WARN_ON(vha->nvme_local_port);
+-      if (ha->max_req_queues < 3) {
+-              if (!ha->flags.max_req_queue_warned)
+-                      ql_log(ql_log_info, vha, 0x2120,
+-                             "%s: Disabling FC-NVME due to lack of free queue pairs (%d).\n",
+-                             __func__, ha->max_req_queues);
+-              ha->flags.max_req_queue_warned = 1;
+-              return ret;
+-      }
+-
+       qla_nvme_fc_transport.max_hw_queues =
+           min((uint8_t)(qla_nvme_fc_transport.max_hw_queues),
+-              (uint8_t)(ha->max_req_queues - 2));
++              (uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1));
+       pinfo.node_name = wwn_to_u64(vha->node_name);
+       pinfo.port_name = wwn_to_u64(vha->port_name);
+-- 
+2.33.0
+
diff --git a/queue-5.10/series b/queue-5.10/series
new file mode 100644 (file)
index 0000000..cb0af10
--- /dev/null
@@ -0,0 +1,5 @@
+tty-fix-out-of-bound-vmalloc-access-in-imageblit.patch
+cpufreq-schedutil-use-kobject-release-method-to-free.patch
+scsi-qla2xxx-changes-to-support-kdump-kernel-for-nvm.patch
+cpufreq-schedutil-destroy-mutex-before-kobject_put-f.patch
+usb-cdns3-fix-race-condition-before-setting-doorbell.patch
diff --git a/queue-5.10/tty-fix-out-of-bound-vmalloc-access-in-imageblit.patch b/queue-5.10/tty-fix-out-of-bound-vmalloc-access-in-imageblit.patch
new file mode 100644 (file)
index 0000000..c89e230
--- /dev/null
@@ -0,0 +1,71 @@
+From 632ed9823cd0fbe39a95d140eb6e4d877378c960 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Jun 2021 10:45:09 -0300
+Subject: tty: Fix out-of-bound vmalloc access in imageblit
+
+From: Igor Matheus Andrade Torrente <igormtorrente@gmail.com>
+
+[ Upstream commit 3b0c406124719b625b1aba431659f5cdc24a982c ]
+
+This issue happens when a userspace program does an ioctl
+FBIOPUT_VSCREENINFO passing the fb_var_screeninfo struct
+containing only the fields xres, yres, and bits_per_pixel
+with values.
+
+If this struct is the same as the previous ioctl, the
+vc_resize() detects it and doesn't call the resize_screen(),
+leaving the fb_var_screeninfo incomplete. And this leads to
+the updatescrollmode() calculates a wrong value to
+fbcon_display->vrows, which makes the real_y() return a
+wrong value of y, and that value, eventually, causes
+the imageblit to access an out-of-bound address value.
+
+To solve this issue I made the resize_screen() be called
+even if the screen does not need any resizing, so it will
+"fix and fill" the fb_var_screeninfo independently.
+
+Cc: stable <stable@vger.kernel.org> # after 5.15-rc2 is out, give it time to bake
+Reported-and-tested-by: syzbot+858dc7a2f7ef07c2c219@syzkaller.appspotmail.com
+Signed-off-by: Igor Matheus Andrade Torrente <igormtorrente@gmail.com>
+Link: https://lore.kernel.org/r/20210628134509.15895-1-igormtorrente@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/vt/vt.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index cea40ef090b7..a7ee1171eeb3 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -1220,8 +1220,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
+       new_row_size = new_cols << 1;
+       new_screen_size = new_row_size * new_rows;
+-      if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
+-              return 0;
++      if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
++              /*
++               * This function is being called here to cover the case
++               * where the userspace calls the FBIOPUT_VSCREENINFO twice,
++               * passing the same fb_var_screeninfo containing the fields
++               * yres/xres equal to a number non-multiple of vc_font.height
++               * and yres_virtual/xres_virtual equal to number lesser than the
++               * vc_font.height and yres/xres.
++               * In the second call, the struct fb_var_screeninfo isn't
++               * being modified by the underlying driver because of the
++               * if above, and this causes the fbcon_display->vrows to become
++               * negative and it eventually leads to out-of-bound
++               * access by the imageblit function.
++               * To give the correct values to the struct and to not have
++               * to deal with possible errors from the code below, we call
++               * the resize_screen here as well.
++               */
++              return resize_screen(vc, new_cols, new_rows, user);
++      }
+       if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
+               return -EINVAL;
+-- 
+2.33.0
+
diff --git a/queue-5.10/usb-cdns3-fix-race-condition-before-setting-doorbell.patch b/queue-5.10/usb-cdns3-fix-race-condition-before-setting-doorbell.patch
new file mode 100644 (file)
index 0000000..1bfa3b0
--- /dev/null
@@ -0,0 +1,63 @@
+From f5dc4ab56be0b62d6db9a401d67a250bd1a623e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Sep 2021 08:26:19 +0200
+Subject: usb: cdns3: fix race condition before setting doorbell
+
+From: Pawel Laszczak <pawell@cadence.com>
+
+[ Upstream commit b69ec50b3e55c4b2a85c8bc46763eaf330605847 ]
+
+For DEV_VER_V3 version there exist race condition between clearing
+ep_sts.EP_STS_TRBERR and setting ep_cmd.EP_CMD_DRDY bit.
+Setting EP_CMD_DRDY will be ignored by controller when
+EP_STS_TRBERR is set. So, between these two instructions we have
+a small time gap in which the EP_STSS_TRBERR can be set. In such case
+the transfer will not start after setting doorbell.
+
+Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
+cc: <stable@vger.kernel.org> # 5.12.x
+Tested-by: Aswath Govindraju <a-govindraju@ti.com>
+Reviewed-by: Aswath Govindraju <a-govindraju@ti.com>
+Signed-off-by: Pawel Laszczak <pawell@cadence.com>
+Link: https://lore.kernel.org/r/20210907062619.34622-1-pawell@gli-login.cadence.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/cdns3/gadget.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
+index 9d38f864cb68..e11162294413 100644
+--- a/drivers/usb/cdns3/gadget.c
++++ b/drivers/usb/cdns3/gadget.c
+@@ -1101,6 +1101,19 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep,
+       return 0;
+ }
++static void cdns3_rearm_drdy_if_needed(struct cdns3_endpoint *priv_ep)
++{
++      struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
++
++      if (priv_dev->dev_ver < DEV_VER_V3)
++              return;
++
++      if (readl(&priv_dev->regs->ep_sts) & EP_STS_TRBERR) {
++              writel(EP_STS_TRBERR, &priv_dev->regs->ep_sts);
++              writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd);
++      }
++}
++
+ /**
+  * cdns3_ep_run_transfer - start transfer on no-default endpoint hardware
+  * @priv_ep: endpoint object
+@@ -1352,6 +1365,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
+               /*clearing TRBERR and EP_STS_DESCMIS before seting DRDY*/
+               writel(EP_STS_TRBERR | EP_STS_DESCMIS, &priv_dev->regs->ep_sts);
+               writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd);
++              cdns3_rearm_drdy_if_needed(priv_ep);
+               trace_cdns3_doorbell_epx(priv_ep->name,
+                                        readl(&priv_dev->regs->ep_traddr));
+       }
+-- 
+2.33.0
+