--- /dev/null
+From eed6e41813deb9ee622cd9242341f21430d7789f Mon Sep 17 00:00:00 2001
+From: Saravana Kannan <saravanak@google.com>
+Date: Thu, 1 Apr 2021 21:03:40 -0700
+Subject: driver core: Fix locking bug in deferred_probe_timeout_work_func()
+
+From: Saravana Kannan <saravanak@google.com>
+
+commit eed6e41813deb9ee622cd9242341f21430d7789f upstream.
+
+list_for_each_entry_safe() is only useful if we are deleting nodes in a
+linked list within the loop. It doesn't protect against other threads
+adding/deleting nodes to the list in parallel. We need to grab
+deferred_probe_mutex when traversing the deferred_probe_pending_list.
+
+Cc: stable@vger.kernel.org
+Fixes: 25b4e70dcce9 ("driver core: allow stopping deferred probe after init")
+Signed-off-by: Saravana Kannan <saravanak@google.com>
+Link: https://lore.kernel.org/r/20210402040342.2944858-2-saravanak@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/dd.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -292,14 +292,16 @@ int driver_deferred_probe_check_state(st
+
+ static void deferred_probe_timeout_work_func(struct work_struct *work)
+ {
+- struct device_private *private, *p;
++ struct device_private *p;
+
+ driver_deferred_probe_timeout = 0;
+ driver_deferred_probe_trigger();
+ flush_work(&deferred_probe_work);
+
+- list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
+- dev_info(private->device, "deferred probe pending\n");
++ mutex_lock(&deferred_probe_mutex);
++ list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe)
++ dev_info(p->device, "deferred probe pending\n");
++ mutex_unlock(&deferred_probe_mutex);
+ wake_up_all(&probe_timeout_waitqueue);
+ }
+ static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
--- /dev/null
+From e409a6a3e0690efdef9b8a96197bc61ff117cfaf Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Date: Mon, 15 Mar 2021 12:50:08 +0100
+Subject: i2c: turn recovery error on init to debug
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+commit e409a6a3e0690efdef9b8a96197bc61ff117cfaf upstream.
+
+In some configurations, recovery is optional. So, don't throw an error
+when it is not used because e.g. pinctrl settings for recovery are not
+provided. Reword the message and make it debug output.
+
+Reported-by: Klaus Kudielka <klaus.kudielka@gmail.com>
+Tested-by: Klaus Kudielka <klaus.kudielka@gmail.com>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -378,7 +378,7 @@ static int i2c_gpio_init_recovery(struct
+ static int i2c_init_recovery(struct i2c_adapter *adap)
+ {
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+- char *err_str;
++ char *err_str, *err_level = KERN_ERR;
+
+ if (!bri)
+ return 0;
+@@ -387,7 +387,8 @@ static int i2c_init_recovery(struct i2c_
+ return -EPROBE_DEFER;
+
+ if (!bri->recover_bus) {
+- err_str = "no recover_bus() found";
++ err_str = "no suitable method provided";
++ err_level = KERN_DEBUG;
+ goto err;
+ }
+
+@@ -414,7 +415,7 @@ static int i2c_init_recovery(struct i2c_
+
+ return 0;
+ err:
+- dev_err(&adap->dev, "Not using recovery: %s\n", err_str);
++ dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str);
+ adap->bus_recovery_info = NULL;
+
+ return -EINVAL;
--- /dev/null
+From 0760fa3d8f7fceeea508b98899f1c826e10ffe78 Mon Sep 17 00:00:00 2001
+From: Roman Gushchin <guro@fb.com>
+Date: Wed, 7 Apr 2021 20:57:33 -0700
+Subject: percpu: make pcpu_nr_empty_pop_pages per chunk type
+
+From: Roman Gushchin <guro@fb.com>
+
+commit 0760fa3d8f7fceeea508b98899f1c826e10ffe78 upstream.
+
+nr_empty_pop_pages is used to guarantee that there are some free
+populated pages to satisfy atomic allocations. Accounted and
+non-accounted allocations are using separate sets of chunks,
+so both need to have a surplus of empty pages.
+
+This commit makes pcpu_nr_empty_pop_pages and the corresponding logic
+per chunk type.
+
+[Dennis]
+This issue came up as I was reviewing [1] and realized I missed this.
+Simultaneously, it was reported btrfs was seeing failed atomic
+allocations in fsstress tests [2] and [3].
+
+[1] https://lore.kernel.org/linux-mm/20210324190626.564297-1-guro@fb.com/
+[2] https://lore.kernel.org/linux-mm/20210401185158.3275.409509F4@e16-tech.com/
+[3] https://lore.kernel.org/linux-mm/CAL3q7H5RNBjCi708GH7jnczAOe0BLnacT9C+OBgA-Dx9jhB6SQ@mail.gmail.com/
+
+Fixes: 3c7be18ac9a0 ("mm: memcg/percpu: account percpu memory to memory cgroups")
+Cc: stable@vger.kernel.org # 5.9+
+Signed-off-by: Roman Gushchin <guro@fb.com>
+Tested-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Dennis Zhou <dennis@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/percpu-internal.h | 2 +-
+ mm/percpu-stats.c | 9 +++++++--
+ mm/percpu.c | 14 +++++++-------
+ 3 files changed, 15 insertions(+), 10 deletions(-)
+
+--- a/mm/percpu-internal.h
++++ b/mm/percpu-internal.h
+@@ -87,7 +87,7 @@ extern spinlock_t pcpu_lock;
+
+ extern struct list_head *pcpu_chunk_lists;
+ extern int pcpu_nr_slots;
+-extern int pcpu_nr_empty_pop_pages;
++extern int pcpu_nr_empty_pop_pages[];
+
+ extern struct pcpu_chunk *pcpu_first_chunk;
+ extern struct pcpu_chunk *pcpu_reserved_chunk;
+--- a/mm/percpu-stats.c
++++ b/mm/percpu-stats.c
+@@ -145,6 +145,7 @@ static int percpu_stats_show(struct seq_
+ int slot, max_nr_alloc;
+ int *buffer;
+ enum pcpu_chunk_type type;
++ int nr_empty_pop_pages;
+
+ alloc_buffer:
+ spin_lock_irq(&pcpu_lock);
+@@ -165,7 +166,11 @@ alloc_buffer:
+ goto alloc_buffer;
+ }
+
+-#define PL(X) \
++ nr_empty_pop_pages = 0;
++ for (type = 0; type < PCPU_NR_CHUNK_TYPES; type++)
++ nr_empty_pop_pages += pcpu_nr_empty_pop_pages[type];
++
++#define PL(X) \
+ seq_printf(m, " %-20s: %12lld\n", #X, (long long int)pcpu_stats_ai.X)
+
+ seq_printf(m,
+@@ -196,7 +201,7 @@ alloc_buffer:
+ PU(nr_max_chunks);
+ PU(min_alloc_size);
+ PU(max_alloc_size);
+- P("empty_pop_pages", pcpu_nr_empty_pop_pages);
++ P("empty_pop_pages", nr_empty_pop_pages);
+ seq_putc(m, '\n');
+
+ #undef PU
+--- a/mm/percpu.c
++++ b/mm/percpu.c
+@@ -172,10 +172,10 @@ struct list_head *pcpu_chunk_lists __ro_
+ static LIST_HEAD(pcpu_map_extend_chunks);
+
+ /*
+- * The number of empty populated pages, protected by pcpu_lock. The
+- * reserved chunk doesn't contribute to the count.
++ * The number of empty populated pages by chunk type, protected by pcpu_lock.
++ * The reserved chunk doesn't contribute to the count.
+ */
+-int pcpu_nr_empty_pop_pages;
++int pcpu_nr_empty_pop_pages[PCPU_NR_CHUNK_TYPES];
+
+ /*
+ * The number of populated pages in use by the allocator, protected by
+@@ -555,7 +555,7 @@ static inline void pcpu_update_empty_pag
+ {
+ chunk->nr_empty_pop_pages += nr;
+ if (chunk != pcpu_reserved_chunk)
+- pcpu_nr_empty_pop_pages += nr;
++ pcpu_nr_empty_pop_pages[pcpu_chunk_type(chunk)] += nr;
+ }
+
+ /*
+@@ -1831,7 +1831,7 @@ area_found:
+ mutex_unlock(&pcpu_alloc_mutex);
+ }
+
+- if (pcpu_nr_empty_pop_pages < PCPU_EMPTY_POP_PAGES_LOW)
++ if (pcpu_nr_empty_pop_pages[type] < PCPU_EMPTY_POP_PAGES_LOW)
+ pcpu_schedule_balance_work();
+
+ /* clear the areas and return address relative to base address */
+@@ -1999,7 +1999,7 @@ retry_pop:
+ pcpu_atomic_alloc_failed = false;
+ } else {
+ nr_to_pop = clamp(PCPU_EMPTY_POP_PAGES_HIGH -
+- pcpu_nr_empty_pop_pages,
++ pcpu_nr_empty_pop_pages[type],
+ 0, PCPU_EMPTY_POP_PAGES_HIGH);
+ }
+
+@@ -2579,7 +2579,7 @@ void __init pcpu_setup_first_chunk(const
+
+ /* link the first chunk in */
+ pcpu_first_chunk = chunk;
+- pcpu_nr_empty_pop_pages = pcpu_first_chunk->nr_empty_pop_pages;
++ pcpu_nr_empty_pop_pages[PCPU_CHUNK_ROOT] = pcpu_first_chunk->nr_empty_pop_pages;
+ pcpu_chunk_relocate(pcpu_first_chunk, -1);
+
+ /* include all regions of the first chunk */
--- /dev/null
+From 65df7d1986a1909a0869419919e7d9c78d70407e Mon Sep 17 00:00:00 2001
+From: Viswas G <Viswas.G@microchip.com>
+Date: Fri, 2 Apr 2021 11:12:12 +0530
+Subject: scsi: pm80xx: Fix chip initialization failure
+
+From: Viswas G <Viswas.G@microchip.com>
+
+commit 65df7d1986a1909a0869419919e7d9c78d70407e upstream.
+
+Inbound and outbound queues were not properly configured and that lead to
+MPI configuration failure.
+
+Fixes: 05c6c029a44d ("scsi: pm80xx: Increase number of supported queues")
+Cc: stable@vger.kernel.org # 5.10+
+Link: https://lore.kernel.org/r/20210402054212.17834-1-Viswas.G@microchip.com.com
+Reported-and-tested-by: Ash Izat <ash@ai0.uk>
+Signed-off-by: Viswas G <Viswas.G@microchip.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/pm8001/pm8001_hwi.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/pm8001/pm8001_hwi.c
++++ b/drivers/scsi/pm8001/pm8001_hwi.c
+@@ -223,7 +223,7 @@ static void init_default_table_values(st
+ PM8001_EVENT_LOG_SIZE;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option = 0x01;
+ pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt = 0x01;
+- for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
++ for (i = 0; i < pm8001_ha->max_q_num; i++) {
+ pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
+ PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
+ pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
+@@ -249,7 +249,7 @@ static void init_default_table_values(st
+ pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
+ pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
+ }
+- for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
++ for (i = 0; i < pm8001_ha->max_q_num; i++) {
+ pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
+ PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
+ pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
+@@ -671,9 +671,9 @@ static int pm8001_chip_init(struct pm800
+ read_outbnd_queue_table(pm8001_ha);
+ /* update main config table ,inbound table and outbound table */
+ update_main_config_table(pm8001_ha);
+- for (i = 0; i < PM8001_MAX_INB_NUM; i++)
++ for (i = 0; i < pm8001_ha->max_q_num; i++)
+ update_inbnd_queue_table(pm8001_ha, i);
+- for (i = 0; i < PM8001_MAX_OUTB_NUM; i++)
++ for (i = 0; i < pm8001_ha->max_q_num; i++)
+ update_outbnd_queue_table(pm8001_ha, i);
+ /* 8081 controller donot require these operations */
+ if (deviceid != 0x8081 && deviceid != 0x0042) {
--- /dev/null
+From 0352c3d3959a6cf543075b88c7e662fd3546f12e Mon Sep 17 00:00:00 2001
+From: Roman Bolshakov <r.bolshakov@yadro.com>
+Date: Sun, 4 Apr 2021 00:54:15 +0300
+Subject: scsi: target: iscsi: Fix zero tag inside a trace event
+
+From: Roman Bolshakov <r.bolshakov@yadro.com>
+
+commit 0352c3d3959a6cf543075b88c7e662fd3546f12e upstream.
+
+target_sequencer_start event is triggered inside target_cmd_init_cdb().
+se_cmd.tag is not initialized with ITT at the moment so the event always
+prints zero tag.
+
+Link: https://lore.kernel.org/r/20210403215415.95077-1-r.bolshakov@yadro.com
+Cc: stable@vger.kernel.org # 5.10+
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/target/iscsi/iscsi_target.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -1166,6 +1166,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_c
+
+ target_get_sess_cmd(&cmd->se_cmd, true);
+
++ cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
+ cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb);
+ if (cmd->sense_reason) {
+ if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
+@@ -1180,8 +1181,6 @@ int iscsit_setup_scsi_cmd(struct iscsi_c
+ if (cmd->sense_reason)
+ goto attach_cmd;
+
+- /* only used for printks or comparing with ->ref_task_tag */
+- cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
+ cmd->sense_reason = target_cmd_parse_cdb(&cmd->se_cmd);
+ if (cmd->sense_reason)
+ goto attach_cmd;
net-hsr-reset-mac-header-for-tx-path.patch
net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch
net-let-skb_orphan_partial-wake-up-waiters.patch
+thunderbolt-fix-a-leak-in-tb_retimer_add.patch
+thunderbolt-fix-off-by-one-in-tb_port_find_retimer.patch
+usbip-add-sysfs_lock-to-synchronize-sysfs-code-paths.patch
+usbip-stub-dev-synchronize-sysfs-code-paths.patch
+usbip-vudc-synchronize-sysfs-code-paths.patch
+usbip-synchronize-event-handler-with-sysfs-code-paths.patch
+driver-core-fix-locking-bug-in-deferred_probe_timeout_work_func.patch
+scsi-pm80xx-fix-chip-initialization-failure.patch
+scsi-target-iscsi-fix-zero-tag-inside-a-trace-event.patch
+percpu-make-pcpu_nr_empty_pop_pages-per-chunk-type.patch
+i2c-turn-recovery-error-on-init-to-debug.patch
--- /dev/null
+From bec4d7c93afc07dd0454ae41c559513f858cfb83 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 29 Mar 2021 09:07:18 +0300
+Subject: thunderbolt: Fix a leak in tb_retimer_add()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit bec4d7c93afc07dd0454ae41c559513f858cfb83 upstream.
+
+After the device_register() succeeds, then the correct way to clean up
+is to call device_unregister(). The unregister calls both device_del()
+and device_put(). Since this code was only device_del() it results in
+a memory leak.
+
+Fixes: dacb12877d92 ("thunderbolt: Add support for on-board retimers")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/retimer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thunderbolt/retimer.c
++++ b/drivers/thunderbolt/retimer.c
+@@ -347,7 +347,7 @@ static int tb_retimer_add(struct tb_port
+ ret = tb_retimer_nvm_add(rt);
+ if (ret) {
+ dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret);
+- device_del(&rt->dev);
++ device_unregister(&rt->dev);
+ return ret;
+ }
+
--- /dev/null
+From 08fe7ae1857080f5075df5ac7fef2ecd4e289117 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 29 Mar 2021 09:08:01 +0300
+Subject: thunderbolt: Fix off by one in tb_port_find_retimer()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 08fe7ae1857080f5075df5ac7fef2ecd4e289117 upstream.
+
+This array uses 1-based indexing so it corrupts memory one element
+beyond of the array. Fix it by making the array one element larger.
+
+Fixes: dacb12877d92 ("thunderbolt: Add support for on-board retimers")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/retimer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thunderbolt/retimer.c
++++ b/drivers/thunderbolt/retimer.c
+@@ -406,7 +406,7 @@ static struct tb_retimer *tb_port_find_r
+ */
+ int tb_retimer_scan(struct tb_port *port)
+ {
+- u32 status[TB_MAX_RETIMER_INDEX] = {};
++ u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
+ int ret, i, last_idx = 0;
+
+ if (!port->cap_usb4)
--- /dev/null
+From 4e9c93af7279b059faf5bb1897ee90512b258a12 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <skhan@linuxfoundation.org>
+Date: Mon, 29 Mar 2021 19:36:48 -0600
+Subject: usbip: add sysfs_lock to synchronize sysfs code paths
+
+From: Shuah Khan <skhan@linuxfoundation.org>
+
+commit 4e9c93af7279b059faf5bb1897ee90512b258a12 upstream.
+
+Fuzzing uncovered race condition between sysfs code paths in usbip
+drivers. Device connect/disconnect code paths initiated through
+sysfs interface are prone to races if disconnect happens during
+connect and vice versa.
+
+This problem is common to all drivers while it can be reproduced easily
+in vhci_hcd. Add a sysfs_lock to usbip_device struct to protect the paths.
+
+Use this in vhci_hcd to protect sysfs paths. For a complete fix, usip_host
+and usip-vudc drivers and the event handler will have to use this lock to
+protect the paths. These changes will be done in subsequent patches.
+
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/b6568f7beae702bbc236a545d3c020106ca75eac.1616807117.git.skhan@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/usbip/usbip_common.h | 3 +++
+ drivers/usb/usbip/vhci_hcd.c | 1 +
+ drivers/usb/usbip/vhci_sysfs.c | 30 +++++++++++++++++++++++++-----
+ 3 files changed, 29 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/usbip/usbip_common.h
++++ b/drivers/usb/usbip/usbip_common.h
+@@ -263,6 +263,9 @@ struct usbip_device {
+ /* lock for status */
+ spinlock_t lock;
+
++ /* mutex for synchronizing sysfs store paths */
++ struct mutex sysfs_lock;
++
+ int sockfd;
+ struct socket *tcp_socket;
+
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -1101,6 +1101,7 @@ static void vhci_device_init(struct vhci
+ vdev->ud.side = USBIP_VHCI;
+ vdev->ud.status = VDEV_ST_NULL;
+ spin_lock_init(&vdev->ud.lock);
++ mutex_init(&vdev->ud.sysfs_lock);
+
+ INIT_LIST_HEAD(&vdev->priv_rx);
+ INIT_LIST_HEAD(&vdev->priv_tx);
+--- a/drivers/usb/usbip/vhci_sysfs.c
++++ b/drivers/usb/usbip/vhci_sysfs.c
+@@ -185,6 +185,8 @@ static int vhci_port_disconnect(struct v
+
+ usbip_dbg_vhci_sysfs("enter\n");
+
++ mutex_lock(&vdev->ud.sysfs_lock);
++
+ /* lock */
+ spin_lock_irqsave(&vhci->lock, flags);
+ spin_lock(&vdev->ud.lock);
+@@ -195,6 +197,7 @@ static int vhci_port_disconnect(struct v
+ /* unlock */
+ spin_unlock(&vdev->ud.lock);
+ spin_unlock_irqrestore(&vhci->lock, flags);
++ mutex_unlock(&vdev->ud.sysfs_lock);
+
+ return -EINVAL;
+ }
+@@ -205,6 +208,8 @@ static int vhci_port_disconnect(struct v
+
+ usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
+
++ mutex_unlock(&vdev->ud.sysfs_lock);
++
+ return 0;
+ }
+
+@@ -349,30 +354,36 @@ static ssize_t attach_store(struct devic
+ else
+ vdev = &vhci->vhci_hcd_hs->vdev[rhport];
+
++ mutex_lock(&vdev->ud.sysfs_lock);
++
+ /* Extract socket from fd. */
+ socket = sockfd_lookup(sockfd, &err);
+ if (!socket) {
+ dev_err(dev, "failed to lookup sock");
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock_mutex;
+ }
+ if (socket->type != SOCK_STREAM) {
+ dev_err(dev, "Expecting SOCK_STREAM - found %d",
+ socket->type);
+ sockfd_put(socket);
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock_mutex;
+ }
+
+ /* create threads before locking */
+ tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
+ if (IS_ERR(tcp_rx)) {
+ sockfd_put(socket);
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock_mutex;
+ }
+ tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
+ if (IS_ERR(tcp_tx)) {
+ kthread_stop(tcp_rx);
+ sockfd_put(socket);
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock_mutex;
+ }
+
+ /* get task structs now */
+@@ -397,7 +408,8 @@ static ssize_t attach_store(struct devic
+ * Will be retried from userspace
+ * if there's another free port.
+ */
+- return -EBUSY;
++ err = -EBUSY;
++ goto unlock_mutex;
+ }
+
+ dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n",
+@@ -422,7 +434,15 @@ static ssize_t attach_store(struct devic
+
+ rh_port_connect(vdev, speed);
+
++ dev_info(dev, "Device attached\n");
++
++ mutex_unlock(&vdev->ud.sysfs_lock);
++
+ return count;
++
++unlock_mutex:
++ mutex_unlock(&vdev->ud.sysfs_lock);
++ return err;
+ }
+ static DEVICE_ATTR_WO(attach);
+
--- /dev/null
+From 9dbf34a834563dada91366c2ac266f32ff34641a Mon Sep 17 00:00:00 2001
+From: Shuah Khan <skhan@linuxfoundation.org>
+Date: Mon, 29 Mar 2021 19:36:49 -0600
+Subject: usbip: stub-dev synchronize sysfs code paths
+
+From: Shuah Khan <skhan@linuxfoundation.org>
+
+commit 9dbf34a834563dada91366c2ac266f32ff34641a upstream.
+
+Fuzzing uncovered race condition between sysfs code paths in usbip
+drivers. Device connect/disconnect code paths initiated through
+sysfs interface are prone to races if disconnect happens during
+connect and vice versa.
+
+Use sysfs_lock to protect sysfs paths in stub-dev.
+
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/2b182f3561b4a065bf3bf6dce3b0e9944ba17b3f.1616807117.git.skhan@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/usbip/stub_dev.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/usbip/stub_dev.c
++++ b/drivers/usb/usbip/stub_dev.c
+@@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct
+
+ dev_info(dev, "stub up\n");
+
++ mutex_lock(&sdev->ud.sysfs_lock);
+ spin_lock_irq(&sdev->ud.lock);
+
+ if (sdev->ud.status != SDEV_ST_AVAILABLE) {
+@@ -87,13 +88,13 @@ static ssize_t usbip_sockfd_store(struct
+ tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
+ if (IS_ERR(tcp_rx)) {
+ sockfd_put(socket);
+- return -EINVAL;
++ goto unlock_mutex;
+ }
+ tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");
+ if (IS_ERR(tcp_tx)) {
+ kthread_stop(tcp_rx);
+ sockfd_put(socket);
+- return -EINVAL;
++ goto unlock_mutex;
+ }
+
+ /* get task structs now */
+@@ -112,6 +113,8 @@ static ssize_t usbip_sockfd_store(struct
+ wake_up_process(sdev->ud.tcp_rx);
+ wake_up_process(sdev->ud.tcp_tx);
+
++ mutex_unlock(&sdev->ud.sysfs_lock);
++
+ } else {
+ dev_info(dev, "stub down\n");
+
+@@ -122,6 +125,7 @@ static ssize_t usbip_sockfd_store(struct
+ spin_unlock_irq(&sdev->ud.lock);
+
+ usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
++ mutex_unlock(&sdev->ud.sysfs_lock);
+ }
+
+ return count;
+@@ -130,6 +134,8 @@ sock_err:
+ sockfd_put(socket);
+ err:
+ spin_unlock_irq(&sdev->ud.lock);
++unlock_mutex:
++ mutex_unlock(&sdev->ud.sysfs_lock);
+ return -EINVAL;
+ }
+ static DEVICE_ATTR_WO(usbip_sockfd);
+@@ -270,6 +276,7 @@ static struct stub_device *stub_device_a
+ sdev->ud.side = USBIP_STUB;
+ sdev->ud.status = SDEV_ST_AVAILABLE;
+ spin_lock_init(&sdev->ud.lock);
++ mutex_init(&sdev->ud.sysfs_lock);
+ sdev->ud.tcp_socket = NULL;
+ sdev->ud.sockfd = -1;
+
--- /dev/null
+From 363eaa3a450abb4e63bd6e3ad79d1f7a0f717814 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <skhan@linuxfoundation.org>
+Date: Mon, 29 Mar 2021 19:36:51 -0600
+Subject: usbip: synchronize event handler with sysfs code paths
+
+From: Shuah Khan <skhan@linuxfoundation.org>
+
+commit 363eaa3a450abb4e63bd6e3ad79d1f7a0f717814 upstream.
+
+Fuzzing uncovered race condition between sysfs code paths in usbip
+drivers. Device connect/disconnect code paths initiated through
+sysfs interface are prone to races if disconnect happens during
+connect and vice versa.
+
+Use sysfs_lock to synchronize event handler with sysfs paths
+in usbip drivers.
+
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/c5c8723d3f29dfe3d759cfaafa7dd16b0dfe2918.1616807117.git.skhan@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/usbip/usbip_event.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/usbip/usbip_event.c
++++ b/drivers/usb/usbip/usbip_event.c
+@@ -70,6 +70,7 @@ static void event_handler(struct work_st
+ while ((ud = get_event()) != NULL) {
+ usbip_dbg_eh("pending event %lx\n", ud->event);
+
++ mutex_lock(&ud->sysfs_lock);
+ /*
+ * NOTE: shutdown must come first.
+ * Shutdown the device.
+@@ -90,6 +91,7 @@ static void event_handler(struct work_st
+ ud->eh_ops.unusable(ud);
+ unset_event(ud, USBIP_EH_UNUSABLE);
+ }
++ mutex_unlock(&ud->sysfs_lock);
+
+ wake_up(&ud->eh_waitq);
+ }
--- /dev/null
+From bd8b82042269a95db48074b8bb400678dbac1815 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <skhan@linuxfoundation.org>
+Date: Mon, 29 Mar 2021 19:36:50 -0600
+Subject: usbip: vudc synchronize sysfs code paths
+
+From: Shuah Khan <skhan@linuxfoundation.org>
+
+commit bd8b82042269a95db48074b8bb400678dbac1815 upstream.
+
+Fuzzing uncovered race condition between sysfs code paths in usbip
+drivers. Device connect/disconnect code paths initiated through
+sysfs interface are prone to races if disconnect happens during
+connect and vice versa.
+
+Use sysfs_lock to protect sysfs paths in vudc.
+
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/caabcf3fc87bdae970509b5ff32d05bb7ce2fb15.1616807117.git.skhan@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/usbip/vudc_dev.c | 1 +
+ drivers/usb/usbip/vudc_sysfs.c | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/usb/usbip/vudc_dev.c
++++ b/drivers/usb/usbip/vudc_dev.c
+@@ -572,6 +572,7 @@ static int init_vudc_hw(struct vudc *udc
+ init_waitqueue_head(&udc->tx_waitq);
+
+ spin_lock_init(&ud->lock);
++ mutex_init(&ud->sysfs_lock);
+ ud->status = SDEV_ST_AVAILABLE;
+ ud->side = USBIP_VUDC;
+
+--- a/drivers/usb/usbip/vudc_sysfs.c
++++ b/drivers/usb/usbip/vudc_sysfs.c
+@@ -112,6 +112,7 @@ static ssize_t usbip_sockfd_store(struct
+ dev_err(dev, "no device");
+ return -ENODEV;
+ }
++ mutex_lock(&udc->ud.sysfs_lock);
+ spin_lock_irqsave(&udc->lock, flags);
+ /* Don't export what we don't have */
+ if (!udc->driver || !udc->pullup) {
+@@ -187,6 +188,8 @@ static ssize_t usbip_sockfd_store(struct
+
+ wake_up_process(udc->ud.tcp_rx);
+ wake_up_process(udc->ud.tcp_tx);
++
++ mutex_unlock(&udc->ud.sysfs_lock);
+ return count;
+
+ } else {
+@@ -207,6 +210,7 @@ static ssize_t usbip_sockfd_store(struct
+ }
+
+ spin_unlock_irqrestore(&udc->lock, flags);
++ mutex_unlock(&udc->ud.sysfs_lock);
+
+ return count;
+
+@@ -216,6 +220,7 @@ unlock_ud:
+ spin_unlock_irq(&udc->ud.lock);
+ unlock:
+ spin_unlock_irqrestore(&udc->lock, flags);
++ mutex_unlock(&udc->ud.sysfs_lock);
+
+ return ret;
+ }