--- /dev/null
+From 8d0caedb759683041d9db82069937525999ada53 Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+Date: Sat, 5 Jun 2021 19:26:35 +0900
+Subject: can: bcm/raw/isotp: use per module netdevice notifier
+
+From: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+
+commit 8d0caedb759683041d9db82069937525999ada53 upstream.
+
+syzbot is reporting hung task at register_netdevice_notifier() [1] and
+unregister_netdevice_notifier() [2], for cleanup_net() might perform
+time consuming operations while CAN driver's raw/bcm/isotp modules are
+calling {register,unregister}_netdevice_notifier() on each socket.
+
+Change raw/bcm/isotp modules to call register_netdevice_notifier() from
+module's __init function and call unregister_netdevice_notifier() from
+module's __exit function, as with gw/j1939 modules are doing.
+
+Link: https://syzkaller.appspot.com/bug?id=391b9498827788b3cc6830226d4ff5be87107c30 [1]
+Link: https://syzkaller.appspot.com/bug?id=1724d278c83ca6e6df100a2e320c10d991cf2bce [2]
+Link: https://lore.kernel.org/r/54a5f451-05ed-f977-8534-79e7aa2bcc8f@i-love.sakura.ne.jp
+Cc: linux-stable <stable@vger.kernel.org>
+Reported-by: syzbot <syzbot+355f8edb2ff45d5f95fa@syzkaller.appspotmail.com>
+Reported-by: syzbot <syzbot+0f1827363a305f74996f@syzkaller.appspotmail.com>
+Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
+Tested-by: syzbot <syzbot+355f8edb2ff45d5f95fa@syzkaller.appspotmail.com>
+Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -125,7 +125,7 @@ struct bcm_sock {
+ struct sock sk;
+ int bound;
+ int ifindex;
+- struct notifier_block notifier;
++ struct list_head notifier;
+ struct list_head rx_ops;
+ struct list_head tx_ops;
+ unsigned long dropped_usr_msgs;
+@@ -133,6 +133,10 @@ struct bcm_sock {
+ char procname [32]; /* inode number in decimal with \0 */
+ };
+
++static LIST_HEAD(bcm_notifier_list);
++static DEFINE_SPINLOCK(bcm_notifier_lock);
++static struct bcm_sock *bcm_busy_notifier;
++
+ static inline struct bcm_sock *bcm_sk(const struct sock *sk)
+ {
+ return (struct bcm_sock *)sk;
+@@ -1432,20 +1436,15 @@ static int bcm_sendmsg(struct socket *so
+ /*
+ * notification handler for netdevice status changes
+ */
+-static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
+- void *ptr)
++static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
++ struct net_device *dev)
+ {
+- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+- struct bcm_sock *bo = container_of(nb, struct bcm_sock, notifier);
+ struct sock *sk = &bo->sk;
+ struct bcm_op *op;
+ int notify_enodev = 0;
+
+ if (!net_eq(dev_net(dev), sock_net(sk)))
+- return NOTIFY_DONE;
+-
+- if (dev->type != ARPHRD_CAN)
+- return NOTIFY_DONE;
++ return;
+
+ switch (msg) {
+
+@@ -1480,7 +1479,28 @@ static int bcm_notifier(struct notifier_
+ sk->sk_error_report(sk);
+ }
+ }
++}
+
++static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
++ void *ptr)
++{
++ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
++
++ if (dev->type != ARPHRD_CAN)
++ return NOTIFY_DONE;
++ if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
++ return NOTIFY_DONE;
++ if (unlikely(bcm_busy_notifier)) /* Check for reentrant bug. */
++ return NOTIFY_DONE;
++
++ spin_lock(&bcm_notifier_lock);
++ list_for_each_entry(bcm_busy_notifier, &bcm_notifier_list, notifier) {
++ spin_unlock(&bcm_notifier_lock);
++ bcm_notify(bcm_busy_notifier, msg, dev);
++ spin_lock(&bcm_notifier_lock);
++ }
++ bcm_busy_notifier = NULL;
++ spin_unlock(&bcm_notifier_lock);
+ return NOTIFY_DONE;
+ }
+
+@@ -1500,9 +1520,9 @@ static int bcm_init(struct sock *sk)
+ INIT_LIST_HEAD(&bo->rx_ops);
+
+ /* set notifier */
+- bo->notifier.notifier_call = bcm_notifier;
+-
+- register_netdevice_notifier(&bo->notifier);
++ spin_lock(&bcm_notifier_lock);
++ list_add_tail(&bo->notifier, &bcm_notifier_list);
++ spin_unlock(&bcm_notifier_lock);
+
+ return 0;
+ }
+@@ -1525,7 +1545,14 @@ static int bcm_release(struct socket *so
+
+ /* remove bcm_ops, timer, rx_unregister(), etc. */
+
+- unregister_netdevice_notifier(&bo->notifier);
++ spin_lock(&bcm_notifier_lock);
++ while (bcm_busy_notifier == bo) {
++ spin_unlock(&bcm_notifier_lock);
++ schedule_timeout_uninterruptible(1);
++ spin_lock(&bcm_notifier_lock);
++ }
++ list_del(&bo->notifier);
++ spin_unlock(&bcm_notifier_lock);
+
+ lock_sock(sk);
+
+@@ -1740,6 +1767,10 @@ static struct pernet_operations canbcm_p
+ .exit = canbcm_pernet_exit,
+ };
+
++static struct notifier_block canbcm_notifier = {
++ .notifier_call = bcm_notifier
++};
++
+ static int __init bcm_module_init(void)
+ {
+ int err;
+@@ -1753,12 +1784,14 @@ static int __init bcm_module_init(void)
+ }
+
+ register_pernet_subsys(&canbcm_pernet_ops);
++ register_netdevice_notifier(&canbcm_notifier);
+ return 0;
+ }
+
+ static void __exit bcm_module_exit(void)
+ {
+ can_proto_unregister(&bcm_can_proto);
++ unregister_netdevice_notifier(&canbcm_notifier);
+ unregister_pernet_subsys(&canbcm_pernet_ops);
+ }
+
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -84,7 +84,7 @@ struct raw_sock {
+ struct sock sk;
+ int bound;
+ int ifindex;
+- struct notifier_block notifier;
++ struct list_head notifier;
+ int loopback;
+ int recv_own_msgs;
+ int fd_frames;
+@@ -96,6 +96,10 @@ struct raw_sock {
+ struct uniqframe __percpu *uniq;
+ };
+
++static LIST_HEAD(raw_notifier_list);
++static DEFINE_SPINLOCK(raw_notifier_lock);
++static struct raw_sock *raw_busy_notifier;
++
+ /*
+ * Return pointer to store the extra msg flags for raw_recvmsg().
+ * We use the space of one unsigned int beyond the 'struct sockaddr_can'
+@@ -266,21 +270,16 @@ static int raw_enable_allfilters(struct
+ return err;
+ }
+
+-static int raw_notifier(struct notifier_block *nb,
+- unsigned long msg, void *ptr)
++static void raw_notify(struct raw_sock *ro, unsigned long msg,
++ struct net_device *dev)
+ {
+- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+- struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
+ struct sock *sk = &ro->sk;
+
+ if (!net_eq(dev_net(dev), sock_net(sk)))
+- return NOTIFY_DONE;
+-
+- if (dev->type != ARPHRD_CAN)
+- return NOTIFY_DONE;
++ return;
+
+ if (ro->ifindex != dev->ifindex)
+- return NOTIFY_DONE;
++ return;
+
+ switch (msg) {
+
+@@ -309,7 +308,28 @@ static int raw_notifier(struct notifier_
+ sk->sk_error_report(sk);
+ break;
+ }
++}
++
++static int raw_notifier(struct notifier_block *nb, unsigned long msg,
++ void *ptr)
++{
++ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
++
++ if (dev->type != ARPHRD_CAN)
++ return NOTIFY_DONE;
++ if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
++ return NOTIFY_DONE;
++ if (unlikely(raw_busy_notifier)) /* Check for reentrant bug. */
++ return NOTIFY_DONE;
+
++ spin_lock(&raw_notifier_lock);
++ list_for_each_entry(raw_busy_notifier, &raw_notifier_list, notifier) {
++ spin_unlock(&raw_notifier_lock);
++ raw_notify(raw_busy_notifier, msg, dev);
++ spin_lock(&raw_notifier_lock);
++ }
++ raw_busy_notifier = NULL;
++ spin_unlock(&raw_notifier_lock);
+ return NOTIFY_DONE;
+ }
+
+@@ -338,9 +358,9 @@ static int raw_init(struct sock *sk)
+ return -ENOMEM;
+
+ /* set notifier */
+- ro->notifier.notifier_call = raw_notifier;
+-
+- register_netdevice_notifier(&ro->notifier);
++ spin_lock(&raw_notifier_lock);
++ list_add_tail(&ro->notifier, &raw_notifier_list);
++ spin_unlock(&raw_notifier_lock);
+
+ return 0;
+ }
+@@ -355,7 +375,14 @@ static int raw_release(struct socket *so
+
+ ro = raw_sk(sk);
+
+- unregister_netdevice_notifier(&ro->notifier);
++ spin_lock(&raw_notifier_lock);
++ while (raw_busy_notifier == ro) {
++ spin_unlock(&raw_notifier_lock);
++ schedule_timeout_uninterruptible(1);
++ spin_lock(&raw_notifier_lock);
++ }
++ list_del(&ro->notifier);
++ spin_unlock(&raw_notifier_lock);
+
+ lock_sock(sk);
+
+@@ -870,6 +897,10 @@ static const struct can_proto raw_can_pr
+ .prot = &raw_proto,
+ };
+
++static struct notifier_block canraw_notifier = {
++ .notifier_call = raw_notifier
++};
++
+ static __init int raw_module_init(void)
+ {
+ int err;
+@@ -879,6 +910,8 @@ static __init int raw_module_init(void)
+ err = can_proto_register(&raw_can_proto);
+ if (err < 0)
+ printk(KERN_ERR "can: registration of raw protocol failed\n");
++ else
++ register_netdevice_notifier(&canraw_notifier);
+
+ return err;
+ }
+@@ -886,6 +919,7 @@ static __init int raw_module_init(void)
+ static __exit void raw_module_exit(void)
+ {
+ can_proto_unregister(&raw_can_proto);
++ unregister_netdevice_notifier(&canraw_notifier);
+ }
+
+ module_init(raw_module_init);
--- /dev/null
+From aa6dd211e4b1dde9d5dc25d699d35f789ae7eeba Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 24 Mar 2021 14:53:37 -0700
+Subject: inet: use bigger hash table for IP ID generation
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit aa6dd211e4b1dde9d5dc25d699d35f789ae7eeba upstream.
+
+In commit 73f156a6e8c1 ("inetpeer: get rid of ip_id_count")
+I used a very small hash table that could be abused
+by patient attackers to reveal sensitive information.
+
+Switch to a dynamic sizing, depending on RAM size.
+
+Typical big hosts will now use 128x more storage (2 MB)
+to get a similar increase in security and reduction
+of hash collisions.
+
+As a bonus, use of alloc_large_system_hash() spreads
+allocated memory among all NUMA nodes.
+
+Fixes: 73f156a6e8c1 ("inetpeer: get rid of ip_id_count")
+Reported-by: Amit Klein <aksecurity@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Willy Tarreau <w@1wt.eu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv4/route.c | 46 ++++++++++++++++++++++++++++++----------------
+ 1 file changed, 30 insertions(+), 16 deletions(-)
+
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -70,6 +70,7 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
++#include <linux/bootmem.h>
+ #include <linux/string.h>
+ #include <linux/socket.h>
+ #include <linux/sockios.h>
+@@ -470,8 +471,10 @@ static void ipv4_confirm_neigh(const str
+ __ipv4_confirm_neigh(dev, *(__force u32 *)pkey);
+ }
+
+-#define IP_IDENTS_SZ 2048u
+-
++/* Hash tables of size 2048..262144 depending on RAM size.
++ * Each bucket uses 8 bytes.
++ */
++static u32 ip_idents_mask __read_mostly;
+ static atomic_t *ip_idents __read_mostly;
+ static u32 *ip_tstamps __read_mostly;
+
+@@ -481,12 +484,16 @@ static u32 *ip_tstamps __read_mostly;
+ */
+ u32 ip_idents_reserve(u32 hash, int segs)
+ {
+- u32 *p_tstamp = ip_tstamps + hash % IP_IDENTS_SZ;
+- atomic_t *p_id = ip_idents + hash % IP_IDENTS_SZ;
+- u32 old = READ_ONCE(*p_tstamp);
+- u32 now = (u32)jiffies;
++ u32 bucket, old, now = (u32)jiffies;
++ atomic_t *p_id;
++ u32 *p_tstamp;
+ u32 delta = 0;
+
++ bucket = hash & ip_idents_mask;
++ p_tstamp = ip_tstamps + bucket;
++ p_id = ip_idents + bucket;
++ old = READ_ONCE(*p_tstamp);
++
+ if (old != now && cmpxchg(p_tstamp, old, now) == old)
+ delta = prandom_u32_max(now - old);
+
+@@ -3197,18 +3204,25 @@ struct ip_rt_acct __percpu *ip_rt_acct _
+
+ int __init ip_rt_init(void)
+ {
++ void *idents_hash;
+ int cpu;
+
+- ip_idents = kmalloc_array(IP_IDENTS_SZ, sizeof(*ip_idents),
+- GFP_KERNEL);
+- if (!ip_idents)
+- panic("IP: failed to allocate ip_idents\n");
+-
+- prandom_bytes(ip_idents, IP_IDENTS_SZ * sizeof(*ip_idents));
+-
+- ip_tstamps = kcalloc(IP_IDENTS_SZ, sizeof(*ip_tstamps), GFP_KERNEL);
+- if (!ip_tstamps)
+- panic("IP: failed to allocate ip_tstamps\n");
++ /* For modern hosts, this will use 2 MB of memory */
++ idents_hash = alloc_large_system_hash("IP idents",
++ sizeof(*ip_idents) + sizeof(*ip_tstamps),
++ 0,
++ 16, /* one bucket per 64 KB */
++ HASH_ZERO,
++ NULL,
++ &ip_idents_mask,
++ 2048,
++ 256*1024);
++
++ ip_idents = idents_hash;
++
++ prandom_bytes(ip_idents, (ip_idents_mask + 1) * sizeof(*ip_idents));
++
++ ip_tstamps = idents_hash + (ip_idents_mask + 1) * sizeof(*ip_idents);
+
+ for_each_possible_cpu(cpu) {
+ struct uncached_list *ul = &per_cpu(rt_uncached_list, cpu);
--- /dev/null
+From 94ac0835391efc1a30feda6fc908913ec012951e Mon Sep 17 00:00:00 2001
+From: Eric Auger <eric.auger@redhat.com>
+Date: Mon, 12 Apr 2021 17:00:34 +0200
+Subject: KVM: arm/arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST read
+
+From: Eric Auger <eric.auger@redhat.com>
+
+commit 94ac0835391efc1a30feda6fc908913ec012951e upstream.
+
+When reading the base address of the a REDIST region
+through KVM_VGIC_V3_ADDR_TYPE_REDIST we expect the
+redistributor region list to be populated with a single
+element.
+
+However list_first_entry() expects the list to be non empty.
+Instead we should use list_first_entry_or_null which effectively
+returns NULL if the list is empty.
+
+Fixes: dbd9733ab674 ("KVM: arm/arm64: Replace the single rdist region by a list")
+Cc: <Stable@vger.kernel.org> # v4.18+
+Signed-off-by: Eric Auger <eric.auger@redhat.com>
+Reported-by: Gavin Shan <gshan@redhat.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20210412150034.29185-1-eric.auger@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ virt/kvm/arm/vgic/vgic-kvm-device.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+
+--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
++++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
+@@ -95,8 +95,8 @@ int kvm_vgic_addr(struct kvm *kvm, unsig
+ r = vgic_v3_set_redist_base(kvm, 0, *addr, 0);
+ goto out;
+ }
+- rdreg = list_first_entry(&vgic->rd_regions,
+- struct vgic_redist_region, list);
++ rdreg = list_first_entry_or_null(&vgic->rd_regions,
++ struct vgic_redist_region, list);
+ if (!rdreg)
+ addr_ptr = &undef_value;
+ else
mm-slub.c-include-swab.h.patch
net-fec_ptp-add-clock-rate-zero-check.patch
tools-headers-uapi-sync-linux-in.h-copy-with-the-kernel-sources.patch
+kvm-arm-arm64-fix-kvm_vgic_v3_addr_type_redist-read.patch
+can-bcm-raw-isotp-use-per-module-netdevice-notifier.patch
+inet-use-bigger-hash-table-for-ip-id-generation.patch
+usb-dwc3-debugfs-add-and-remove-endpoint-dirs-dynamically.patch
+usb-dwc3-core-fix-kernel-panic-when-do-reboot.patch
--- /dev/null
+From 4bf584a03eec674975ee9fe36c8583d9d470dab1 Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@kernel.org>
+Date: Tue, 8 Jun 2021 18:56:56 +0800
+Subject: usb: dwc3: core: fix kernel panic when do reboot
+
+From: Peter Chen <peter.chen@kernel.org>
+
+commit 4bf584a03eec674975ee9fe36c8583d9d470dab1 upstream.
+
+When do system reboot, it calls dwc3_shutdown and the whole debugfs
+for dwc3 has removed first, when the gadget tries to do deinit, and
+remove debugfs for its endpoints, it meets NULL pointer dereference
+issue when call debugfs_lookup. Fix it by removing the whole dwc3
+debugfs later than dwc3_drd_exit.
+
+[ 2924.958838] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000002
+....
+[ 2925.030994] pstate: 60000005 (nZCv daif -PAN -UAO -TCO BTYPE=--)
+[ 2925.037005] pc : inode_permission+0x2c/0x198
+[ 2925.041281] lr : lookup_one_len_common+0xb0/0xf8
+[ 2925.045903] sp : ffff80001276ba70
+[ 2925.049218] x29: ffff80001276ba70 x28: ffff0000c01f0000 x27: 0000000000000000
+[ 2925.056364] x26: ffff800011791e70 x25: 0000000000000008 x24: dead000000000100
+[ 2925.063510] x23: dead000000000122 x22: 0000000000000000 x21: 0000000000000001
+[ 2925.070652] x20: ffff8000122c6188 x19: 0000000000000000 x18: 0000000000000000
+[ 2925.077797] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000004
+[ 2925.084943] x14: ffffffffffffffff x13: 0000000000000000 x12: 0000000000000030
+[ 2925.092087] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f x9 : ffff8000102b2420
+[ 2925.099232] x8 : 7f7f7f7f7f7f7f7f x7 : feff73746e2f6f64 x6 : 0000000000008080
+[ 2925.106378] x5 : 61c8864680b583eb x4 : 209e6ec2d263dbb7 x3 : 000074756f307065
+[ 2925.113523] x2 : 0000000000000001 x1 : 0000000000000000 x0 : ffff8000122c6188
+[ 2925.120671] Call trace:
+[ 2925.123119] inode_permission+0x2c/0x198
+[ 2925.127042] lookup_one_len_common+0xb0/0xf8
+[ 2925.131315] lookup_one_len_unlocked+0x34/0xb0
+[ 2925.135764] lookup_positive_unlocked+0x14/0x50
+[ 2925.140296] debugfs_lookup+0x68/0xa0
+[ 2925.143964] dwc3_gadget_free_endpoints+0x84/0xb0
+[ 2925.148675] dwc3_gadget_exit+0x28/0x78
+[ 2925.152518] dwc3_drd_exit+0x100/0x1f8
+[ 2925.156267] dwc3_remove+0x11c/0x120
+[ 2925.159851] dwc3_shutdown+0x14/0x20
+[ 2925.163432] platform_shutdown+0x28/0x38
+[ 2925.167360] device_shutdown+0x15c/0x378
+[ 2925.171291] kernel_restart_prepare+0x3c/0x48
+[ 2925.175650] kernel_restart+0x1c/0x68
+[ 2925.179316] __do_sys_reboot+0x218/0x240
+[ 2925.183247] __arm64_sys_reboot+0x28/0x30
+[ 2925.187262] invoke_syscall+0x48/0x100
+[ 2925.191017] el0_svc_common.constprop.0+0x48/0xc8
+[ 2925.195726] do_el0_svc+0x28/0x88
+[ 2925.199045] el0_svc+0x20/0x30
+[ 2925.202104] el0_sync_handler+0xa8/0xb0
+[ 2925.205942] el0_sync+0x148/0x180
+[ 2925.209270] Code: a9025bf5 2a0203f5 121f0056 370802b5 (79400660)
+[ 2925.215372] ---[ end trace 124254d8e485a58b ]---
+[ 2925.220012] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
+[ 2925.227676] Kernel Offset: disabled
+[ 2925.231164] CPU features: 0x00001001,20000846
+[ 2925.235521] Memory Limit: none
+[ 2925.238580] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
+
+Fixes: 8d396bb0a5b6 ("usb: dwc3: debugfs: Add and remove endpoint dirs dynamically")
+Cc: Jack Pham <jackp@codeaurora.org>
+Tested-by: Jack Pham <jackp@codeaurora.org>
+Signed-off-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20210608105656.10795-1-peter.chen@kernel.org
+(cherry picked from commit 2a042767814bd0edf2619f06fecd374e266ea068)
+Link: https://lore.kernel.org/r/20210615080847.GA10432@jackp-linux.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1550,8 +1550,8 @@ static int dwc3_remove(struct platform_d
+
+ pm_runtime_get_sync(&pdev->dev);
+
+- dwc3_debugfs_exit(dwc);
+ dwc3_core_exit_mode(dwc);
++ dwc3_debugfs_exit(dwc);
+
+ dwc3_core_exit(dwc);
+ dwc3_ulpi_exit(dwc);
--- /dev/null
+From 8d396bb0a5b62b326f6be7594d8bd46b088296bd Mon Sep 17 00:00:00 2001
+From: Jack Pham <jackp@codeaurora.org>
+Date: Sat, 29 May 2021 12:29:32 -0700
+Subject: usb: dwc3: debugfs: Add and remove endpoint dirs dynamically
+
+From: Jack Pham <jackp@codeaurora.org>
+
+commit 8d396bb0a5b62b326f6be7594d8bd46b088296bd upstream.
+
+The DWC3 DebugFS directory and files are currently created once
+during probe. This includes creation of subdirectories for each
+of the gadget's endpoints. This works fine for peripheral-only
+controllers, as dwc3_core_init_mode() calls dwc3_gadget_init()
+just prior to calling dwc3_debugfs_init().
+
+However, for dual-role controllers, dwc3_core_init_mode() will
+instead call dwc3_drd_init() which is problematic in a few ways.
+First, the initial state must be determined, then dwc3_set_mode()
+will have to schedule drd_work and by then dwc3_debugfs_init()
+could have already been invoked. Even if the initial mode is
+peripheral, dwc3_gadget_init() happens after the DebugFS files
+are created, and worse so if the initial state is host and the
+controller switches to peripheral much later. And secondly,
+even if the gadget endpoints' debug entries were successfully
+created, if the controller exits peripheral mode, its dwc3_eps
+are freed so the debug files would now hold stale references.
+
+So it is best if the DebugFS endpoint entries are created and
+removed dynamically at the same time the underlying dwc3_eps are.
+Do this by calling dwc3_debugfs_create_endpoint_dir() as each
+endpoint is created, and conversely remove the DebugFS entry when
+the endpoint is freed.
+
+Fixes: 41ce1456e1db ("usb: dwc3: core: make dwc3_set_mode() work properly")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Peter Chen <peter.chen@kernel.org>
+Signed-off-by: Jack Pham <jackp@codeaurora.org>
+Link: https://lore.kernel.org/r/20210529192932.22912-1-jackp@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/debug.h | 3 +++
+ drivers/usb/dwc3/debugfs.c | 21 ++-------------------
+ drivers/usb/dwc3/gadget.c | 3 +++
+ 3 files changed, 8 insertions(+), 19 deletions(-)
+
+--- a/drivers/usb/dwc3/debug.h
++++ b/drivers/usb/dwc3/debug.h
+@@ -653,9 +653,12 @@ static inline const char *dwc3_gadget_ge
+
+
+ #ifdef CONFIG_DEBUG_FS
++extern void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep);
+ extern void dwc3_debugfs_init(struct dwc3 *);
+ extern void dwc3_debugfs_exit(struct dwc3 *);
+ #else
++static inline void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
++{ }
+ static inline void dwc3_debugfs_init(struct dwc3 *d)
+ { }
+ static inline void dwc3_debugfs_exit(struct dwc3 *d)
+--- a/drivers/usb/dwc3/debugfs.c
++++ b/drivers/usb/dwc3/debugfs.c
+@@ -725,30 +725,14 @@ static void dwc3_debugfs_create_endpoint
+ }
+ }
+
+-static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep,
+- struct dentry *parent)
++void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
+ {
+ struct dentry *dir;
+
+- dir = debugfs_create_dir(dep->name, parent);
++ dir = debugfs_create_dir(dep->name, dep->dwc->root);
+ dwc3_debugfs_create_endpoint_files(dep, dir);
+ }
+
+-static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc,
+- struct dentry *parent)
+-{
+- int i;
+-
+- for (i = 0; i < dwc->num_eps; i++) {
+- struct dwc3_ep *dep = dwc->eps[i];
+-
+- if (!dep)
+- continue;
+-
+- dwc3_debugfs_create_endpoint_dir(dep, parent);
+- }
+-}
+-
+ void dwc3_debugfs_init(struct dwc3 *dwc)
+ {
+ struct dentry *root;
+@@ -777,7 +761,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
+ &dwc3_testmode_fops);
+ debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, dwc,
+ &dwc3_link_state_fops);
+- dwc3_debugfs_create_endpoint_dirs(dwc, root);
+ }
+ }
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2255,6 +2255,8 @@ static int dwc3_gadget_init_endpoint(str
+ INIT_LIST_HEAD(&dep->started_list);
+ INIT_LIST_HEAD(&dep->cancelled_list);
+
++ dwc3_debugfs_create_endpoint_dir(dep);
++
+ return 0;
+ }
+
+@@ -2298,6 +2300,7 @@ static void dwc3_gadget_free_endpoints(s
+ list_del(&dep->endpoint.ep_list);
+ }
+
++ debugfs_remove_recursive(debugfs_lookup(dep->name, dwc->root));
+ kfree(dep);
+ }
+ }