--- /dev/null
+From 197b806ae5db60c6f609d74da04ddb62ea5e1b00 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Tue, 25 Apr 2017 10:55:12 -0700
+Subject: iscsi-target: Set session_fall_back_to_erl0 when forcing reinstatement
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 197b806ae5db60c6f609d74da04ddb62ea5e1b00 upstream.
+
+While testing modification of per se_node_acl queue_depth forcing
+session reinstatement via lio_target_nacl_cmdsn_depth_store() ->
+core_tpg_set_initiator_node_queue_depth(), a hung task bug triggered
+when changing cmdsn_depth invoked session reinstatement while an iscsi
+login was already waiting for session reinstatement to complete.
+
+This can happen when an outstanding se_cmd descriptor is taking a
+long time to complete, and session reinstatement from iscsi login
+or cmdsn_depth change occurs concurrently.
+
+To address this bug, explicitly set session_fall_back_to_erl0 = 1
+when forcing session reinstatement, so session reinstatement is
+not attempted if an active session is already being shutdown.
+
+This patch has been tested with two scenarios. The first when
+iscsi login is blocked waiting for iscsi session reinstatement
+to complete followed by queue_depth change via configfs, and
+second when queue_depth change via configfs us blocked followed
+by a iscsi login driven session reinstatement.
+
+Note this patch depends on commit d36ad77f702 to handle multiple
+sessions per se_node_acl when changing cmdsn_depth, and for
+pre v4.5 kernels will need to be included for stable as well.
+
+Reported-by: Gary Guo <ghg@datera.io>
+Tested-by: Gary Guo <ghg@datera.io>
+Cc: Gary Guo <ghg@datera.io>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target.c | 1 +
+ drivers/target/iscsi/iscsi_target_configfs.c | 1 +
+ drivers/target/iscsi/iscsi_target_login.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -4821,6 +4821,7 @@ int iscsit_release_sessions_for_tpg(stru
+ continue;
+ }
+ atomic_set(&sess->session_reinstatement, 1);
++ atomic_set(&sess->session_fall_back_to_erl0, 1);
+ spin_unlock(&sess->conn_lock);
+
+ list_move_tail(&se_sess->sess_list, &free_list);
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -1608,6 +1608,7 @@ static int lio_tpg_shutdown_session(stru
+ return 0;
+ }
+ atomic_set(&sess->session_reinstatement, 1);
++ atomic_set(&sess->session_fall_back_to_erl0, 1);
+ spin_unlock(&sess->conn_lock);
+
+ iscsit_stop_time2retain_timer(sess);
+--- a/drivers/target/iscsi/iscsi_target_login.c
++++ b/drivers/target/iscsi/iscsi_target_login.c
+@@ -195,6 +195,7 @@ int iscsi_check_for_session_reinstatemen
+ initiatorname_param->value) &&
+ (sess_p->sess_ops->SessionType == sessiontype))) {
+ atomic_set(&sess_p->session_reinstatement, 1);
++ atomic_set(&sess_p->session_fall_back_to_erl0, 1);
+ spin_unlock(&sess_p->conn_lock);
+ iscsit_inc_session_usage_count(sess_p);
+ iscsit_stop_time2retain_timer(sess_p);
xen-adjust-early-dom0-p2m-handling-to-xen-hypervisor-behavior.patch
+target-fix-compare_and_write_callback-handling-for-non-good-status.patch
+target-fileio-fix-zero-length-read-and-write-handling.patch
+target-convert-acl-change-queue_depth-se_session-reference-usage.patch
+iscsi-target-set-session_fall_back_to_erl0-when-forcing-reinstatement.patch
+usb-host-xhci-print-correct-command-ring-address.patch
+usb-serial-ftdi_sio-add-device-id-for-microsemi-arrow-sf2plus-dev-kit.patch
+usb-proper-handling-of-race-condition-when-two-usb-class-drivers-try-to-call-init_usb_class-simultaneously.patch
+staging-vt6656-use-off-stack-for-in-buffer-usb-transfers.patch
+staging-vt6656-use-off-stack-for-out-buffer-usb-transfers.patch
+staging-gdm724x-gdm_mux-fix-use-after-free-on-module-unload.patch
+staging-comedi-jr3_pci-fix-possible-null-pointer-dereference.patch
+staging-comedi-jr3_pci-cope-with-jiffies-wraparound.patch
+usb-misc-add-missing-continue-in-switch.patch
+usb-make-sure-usb-phy-of-gets-built-in.patch
+usb-hub-fix-error-loop-seen-after-hub-communication-errors.patch
+usb-hub-do-not-attempt-to-autosuspend-disconnected-devices.patch
+usb-misc-legousbtower-fix-buffers-on-stack.patch
--- /dev/null
+From 8ec04a491825e08068e92bed0bba7821893b6433 Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Fri, 17 Feb 2017 11:09:09 +0000
+Subject: staging: comedi: jr3_pci: cope with jiffies wraparound
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 8ec04a491825e08068e92bed0bba7821893b6433 upstream.
+
+The timer expiry routine `jr3_pci_poll_dev()` checks for expiry by
+checking whether the absolute value of `jiffies` (stored in local
+variable `now`) is greater than the expected expiry time in jiffy units.
+This will fail when `jiffies` wraps around. Also, it seems to make
+sense to handle the expiry one jiffy earlier than the current test. Use
+`time_after_eq()` to check for expiry.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/jr3_pci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -610,7 +610,7 @@ static void jr3_pci_poll_dev(unsigned lo
+ s = &dev->subdevices[i];
+ spriv = s->private;
+
+- if (now > spriv->next_time_min) {
++ if (time_after_eq(now, spriv->next_time_min)) {
+ struct jr3_pci_poll_delay sub_delay;
+
+ sub_delay = jr3_pci_poll_subdevice(s);
--- /dev/null
+From 45292be0b3db0b7f8286683b376e2d9f949d11f9 Mon Sep 17 00:00:00 2001
+From: Ian Abbott <abbotti@mev.co.uk>
+Date: Fri, 17 Feb 2017 11:09:08 +0000
+Subject: staging: comedi: jr3_pci: fix possible null pointer dereference
+
+From: Ian Abbott <abbotti@mev.co.uk>
+
+commit 45292be0b3db0b7f8286683b376e2d9f949d11f9 upstream.
+
+For some reason, the driver does not consider allocation of the
+subdevice private data to be a fatal error when attaching the COMEDI
+device. It tests the subdevice private data pointer for validity at
+certain points, but omits some crucial tests. In particular,
+`jr3_pci_auto_attach()` calls `jr3_pci_alloc_spriv()` to allocate and
+initialize the subdevice private data, but the same function
+subsequently dereferences the pointer to access the `next_time_min` and
+`next_time_max` members without checking it first. The other missing
+test is in the timer expiry routine `jr3_pci_poll_dev()`, but it will
+crash before it gets that far.
+
+Fix the bug by returning `-ENOMEM` from `jr3_pci_auto_attach()` as soon
+as one of the calls to `jr3_pci_alloc_spriv()` returns `NULL`. The
+COMEDI core will subsequently call `jr3_pci_detach()` to clean up.
+
+Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/comedi/drivers/jr3_pci.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/staging/comedi/drivers/jr3_pci.c
++++ b/drivers/staging/comedi/drivers/jr3_pci.c
+@@ -726,11 +726,12 @@ static int jr3_pci_auto_attach(struct co
+ s->insn_read = jr3_pci_ai_insn_read;
+
+ spriv = jr3_pci_alloc_spriv(dev, s);
+- if (spriv) {
+- /* Channel specific range and maxdata */
+- s->range_table_list = spriv->range_table_list;
+- s->maxdata_list = spriv->maxdata_list;
+- }
++ if (!spriv)
++ return -ENOMEM;
++
++ /* Channel specific range and maxdata */
++ s->range_table_list = spriv->range_table_list;
++ s->maxdata_list = spriv->maxdata_list;
+ }
+
+ /* Reset DSP card */
--- /dev/null
+From b58f45c8fc301fe83ee28cad3e64686c19e78f1c Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Wed, 26 Apr 2017 12:23:04 +0200
+Subject: staging: gdm724x: gdm_mux: fix use-after-free on module unload
+
+From: Johan Hovold <johan@kernel.org>
+
+commit b58f45c8fc301fe83ee28cad3e64686c19e78f1c upstream.
+
+Make sure to deregister the USB driver before releasing the tty driver
+to avoid use-after-free in the USB disconnect callback where the tty
+devices are deregistered.
+
+Fixes: 61e121047645 ("staging: gdm7240: adding LTE USB driver")
+Cc: Won Kang <wkang77@gmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/gdm724x/gdm_mux.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/gdm724x/gdm_mux.c
++++ b/drivers/staging/gdm724x/gdm_mux.c
+@@ -670,14 +670,14 @@ static int __init gdm_usb_mux_init(void)
+
+ static void __exit gdm_usb_mux_exit(void)
+ {
+- unregister_lte_tty_driver();
+-
+ if (mux_rx_wq) {
+ flush_workqueue(mux_rx_wq);
+ destroy_workqueue(mux_rx_wq);
+ }
+
+ usb_deregister(&gdm_mux_driver);
++ unregister_lte_tty_driver();
++
+ }
+
+ module_init(gdm_usb_mux_init);
--- /dev/null
+From 05c0cf88bec588a7cb34de569acd871ceef26760 Mon Sep 17 00:00:00 2001
+From: Malcolm Priestley <tvboxspy@gmail.com>
+Date: Sat, 22 Apr 2017 11:14:58 +0100
+Subject: staging: vt6656: use off stack for in buffer USB transfers.
+
+From: Malcolm Priestley <tvboxspy@gmail.com>
+
+commit 05c0cf88bec588a7cb34de569acd871ceef26760 upstream.
+
+Since 4.9 mandated USB buffers to be heap allocated. This causes
+the driver to fail.
+
+Create buffer for USB transfers.
+
+Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vt6656/usbpipe.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vt6656/usbpipe.c
++++ b/drivers/staging/vt6656/usbpipe.c
+@@ -78,15 +78,28 @@ int vnt_control_in(struct vnt_private *p
+ u16 index, u16 length, u8 *buffer)
+ {
+ int status;
++ u8 *usb_buffer;
+
+ if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
+ return STATUS_FAILURE;
+
+ mutex_lock(&priv->usb_lock);
+
++ usb_buffer = kmalloc(length, GFP_KERNEL);
++ if (!usb_buffer) {
++ mutex_unlock(&priv->usb_lock);
++ return -ENOMEM;
++ }
++
+ status = usb_control_msg(priv->usb,
+- usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
+- index, buffer, length, USB_CTL_WAIT);
++ usb_rcvctrlpipe(priv->usb, 0),
++ request, 0xc0, value,
++ index, usb_buffer, length, USB_CTL_WAIT);
++
++ if (status == length)
++ memcpy(buffer, usb_buffer, length);
++
++ kfree(usb_buffer);
+
+ mutex_unlock(&priv->usb_lock);
+
--- /dev/null
+From 12ecd24ef93277e4e5feaf27b0b18f2d3828bc5e Mon Sep 17 00:00:00 2001
+From: Malcolm Priestley <tvboxspy@gmail.com>
+Date: Sat, 22 Apr 2017 11:14:57 +0100
+Subject: staging: vt6656: use off stack for out buffer USB transfers.
+
+From: Malcolm Priestley <tvboxspy@gmail.com>
+
+commit 12ecd24ef93277e4e5feaf27b0b18f2d3828bc5e upstream.
+
+Since 4.9 mandated USB buffers be heap allocated this causes the driver
+to fail.
+
+Since there is a wide range of buffer sizes use kmemdup to create
+allocated buffer.
+
+Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vt6656/usbpipe.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/vt6656/usbpipe.c
++++ b/drivers/staging/vt6656/usbpipe.c
+@@ -50,15 +50,25 @@ int vnt_control_out(struct vnt_private *
+ u16 index, u16 length, u8 *buffer)
+ {
+ int status = 0;
++ u8 *usb_buffer;
+
+ if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
+ return STATUS_FAILURE;
+
+ mutex_lock(&priv->usb_lock);
+
++ usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
++ if (!usb_buffer) {
++ mutex_unlock(&priv->usb_lock);
++ return -ENOMEM;
++ }
++
+ status = usb_control_msg(priv->usb,
+- usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
+- index, buffer, length, USB_CTL_WAIT);
++ usb_sndctrlpipe(priv->usb, 0),
++ request, 0x40, value,
++ index, usb_buffer, length, USB_CTL_WAIT);
++
++ kfree(usb_buffer);
+
+ mutex_unlock(&priv->usb_lock);
+
--- /dev/null
+From d36ad77f702356afb1009d2987b0ab55da4c7d57 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Thu, 7 Jan 2016 22:15:06 -0800
+Subject: target: Convert ACL change queue_depth se_session reference usage
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit d36ad77f702356afb1009d2987b0ab55da4c7d57 upstream.
+
+This patch converts core_tpg_set_initiator_node_queue_depth()
+to use struct se_node_acl->acl_sess_list when performing
+explicit se_tpg_tfo->shutdown_session() for active sessions,
+in order for new se_node_acl->queue_depth to take effect.
+
+This follows how core_tpg_del_initiator_node_acl() currently
+works when invoking se_tpg_tfo->shutdown-session(), and ahead
+of the next patch to take se_node_acl->acl_kref during lookup,
+the extra get_initiator_node_acl() can go away. In order to
+achieve this, go ahead and change target_get_session() to use
+kref_get_unless_zero() and propigate up the return value
+to know when a session is already being released.
+
+This is because se_node_acl->acl_group is already protecting
+se_node_acl->acl_group reference via configfs, and shutdown
+within core_tpg_del_initiator_node_acl() won't occur until
+sys_write() to core_tpg_set_initiator_node_queue_depth()
+attribute returns back to user-space.
+
+Also, drop the left-over iscsi-target hack, and obtain
+se_portal_group->session_lock in lio_tpg_shutdown_session()
+internally. Remove iscsi-target wrapper and unused se_tpg +
+force parameters and associated code.
+
+Reported-by: Christoph Hellwig <hch@lst.de>
+Cc: Sagi Grimberg <sagig@mellanox.com>
+Cc: Hannes Reinecke <hare@suse.de>
+Cc: Andy Grover <agrover@redhat.com>
+Cc: Mike Christie <michaelc@cs.wisc.edu>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target_configfs.c | 29 +----
+ drivers/target/iscsi/iscsi_target_tpg.c | 10 -
+ drivers/target/iscsi/iscsi_target_tpg.h | 2
+ drivers/target/target_core_tpg.c | 152 +++++++--------------------
+ drivers/target/target_core_transport.c | 4
+ include/target/target_core_fabric.h | 5
+ 6 files changed, 56 insertions(+), 146 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -725,11 +725,8 @@ static ssize_t lio_target_nacl_cmdsn_dep
+
+ if (iscsit_get_tpg(tpg) < 0)
+ return -EINVAL;
+- /*
+- * iscsit_tpg_set_initiator_node_queue_depth() assumes force=1
+- */
+- ret = iscsit_tpg_set_initiator_node_queue_depth(tpg,
+- config_item_name(acl_ci), cmdsn_depth, 1);
++
++ ret = core_tpg_set_initiator_node_queue_depth(se_nacl, cmdsn_depth);
+
+ pr_debug("LIO_Target_ConfigFS: %s/%s Set CmdSN Window: %u for"
+ "InitiatorName: %s\n", config_item_name(wwn_ci),
+@@ -1593,42 +1590,30 @@ static int lio_tpg_check_prot_fabric_onl
+ }
+
+ /*
+- * Called with spin_lock_irq(struct se_portal_group->session_lock) held
+- * or not held.
+- *
+- * Also, this function calls iscsit_inc_session_usage_count() on the
++ * This function calls iscsit_inc_session_usage_count() on the
+ * struct iscsi_session in question.
+ */
+ static int lio_tpg_shutdown_session(struct se_session *se_sess)
+ {
+ struct iscsi_session *sess = se_sess->fabric_sess_ptr;
+- struct se_portal_group *se_tpg = se_sess->se_tpg;
+- bool local_lock = false;
+-
+- if (!spin_is_locked(&se_tpg->session_lock)) {
+- spin_lock_irq(&se_tpg->session_lock);
+- local_lock = true;
+- }
++ struct se_portal_group *se_tpg = &sess->tpg->tpg_se_tpg;
+
++ spin_lock_bh(&se_tpg->session_lock);
+ spin_lock(&sess->conn_lock);
+ if (atomic_read(&sess->session_fall_back_to_erl0) ||
+ atomic_read(&sess->session_logout) ||
+ (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
+ spin_unlock(&sess->conn_lock);
+- if (local_lock)
+- spin_unlock_irq(&sess->conn_lock);
++ spin_unlock_bh(&se_tpg->session_lock);
+ return 0;
+ }
+ atomic_set(&sess->session_reinstatement, 1);
+ spin_unlock(&sess->conn_lock);
+
+ iscsit_stop_time2retain_timer(sess);
+- spin_unlock_irq(&se_tpg->session_lock);
++ spin_unlock_bh(&se_tpg->session_lock);
+
+ iscsit_stop_session(sess, 1, 1);
+- if (!local_lock)
+- spin_lock_irq(&se_tpg->session_lock);
+-
+ return 1;
+ }
+
+--- a/drivers/target/iscsi/iscsi_target_tpg.c
++++ b/drivers/target/iscsi/iscsi_target_tpg.c
+@@ -589,16 +589,6 @@ int iscsit_tpg_del_network_portal(
+ return iscsit_tpg_release_np(tpg_np, tpg, np);
+ }
+
+-int iscsit_tpg_set_initiator_node_queue_depth(
+- struct iscsi_portal_group *tpg,
+- unsigned char *initiatorname,
+- u32 queue_depth,
+- int force)
+-{
+- return core_tpg_set_initiator_node_queue_depth(&tpg->tpg_se_tpg,
+- initiatorname, queue_depth, force);
+-}
+-
+ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
+ {
+ unsigned char buf1[256], buf2[256], *none = NULL;
+--- a/drivers/target/iscsi/iscsi_target_tpg.h
++++ b/drivers/target/iscsi/iscsi_target_tpg.h
+@@ -26,8 +26,6 @@ extern struct iscsi_tpg_np *iscsit_tpg_a
+ int);
+ extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
+ struct iscsi_tpg_np *);
+-extern int iscsit_tpg_set_initiator_node_queue_depth(struct iscsi_portal_group *,
+- unsigned char *, u32, int);
+ extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
+ extern int iscsit_ta_login_timeout(struct iscsi_portal_group *, u32);
+ extern int iscsit_ta_netif_timeout(struct iscsi_portal_group *, u32);
+--- a/drivers/target/target_core_tpg.c
++++ b/drivers/target/target_core_tpg.c
+@@ -169,28 +169,25 @@ void core_tpg_add_node_to_devs(
+ mutex_unlock(&tpg->tpg_lun_mutex);
+ }
+
+-/* core_set_queue_depth_for_node():
+- *
+- *
+- */
+-static int core_set_queue_depth_for_node(
+- struct se_portal_group *tpg,
+- struct se_node_acl *acl)
++static void
++target_set_nacl_queue_depth(struct se_portal_group *tpg,
++ struct se_node_acl *acl, u32 queue_depth)
+ {
++ acl->queue_depth = queue_depth;
++
+ if (!acl->queue_depth) {
+- pr_err("Queue depth for %s Initiator Node: %s is 0,"
++ pr_warn("Queue depth for %s Initiator Node: %s is 0,"
+ "defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
+ acl->initiatorname);
+ acl->queue_depth = 1;
+ }
+-
+- return 0;
+ }
+
+ static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
+ const unsigned char *initiatorname)
+ {
+ struct se_node_acl *acl;
++ u32 queue_depth;
+
+ acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size),
+ GFP_KERNEL);
+@@ -205,24 +202,20 @@ static struct se_node_acl *target_alloc_
+ spin_lock_init(&acl->nacl_sess_lock);
+ mutex_init(&acl->lun_entry_mutex);
+ atomic_set(&acl->acl_pr_ref_count, 0);
++
+ if (tpg->se_tpg_tfo->tpg_get_default_depth)
+- acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
++ queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
+ else
+- acl->queue_depth = 1;
++ queue_depth = 1;
++ target_set_nacl_queue_depth(tpg, acl, queue_depth);
++
+ snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
+ acl->se_tpg = tpg;
+ acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
+
+ tpg->se_tpg_tfo->set_default_node_attributes(acl);
+
+- if (core_set_queue_depth_for_node(tpg, acl) < 0)
+- goto out_free_acl;
+-
+ return acl;
+-
+-out_free_acl:
+- kfree(acl);
+- return NULL;
+ }
+
+ static void target_add_node_acl(struct se_node_acl *acl)
+@@ -369,7 +362,8 @@ void core_tpg_del_initiator_node_acl(str
+ if (sess->sess_tearing_down != 0)
+ continue;
+
+- target_get_session(sess);
++ if (!target_get_session(sess))
++ continue;
+ list_move(&sess->sess_acl_list, &sess_list);
+ }
+ spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
+@@ -406,108 +400,52 @@ void core_tpg_del_initiator_node_acl(str
+ *
+ */
+ int core_tpg_set_initiator_node_queue_depth(
+- struct se_portal_group *tpg,
+- unsigned char *initiatorname,
+- u32 queue_depth,
+- int force)
++ struct se_node_acl *acl,
++ u32 queue_depth)
+ {
+- struct se_session *sess, *init_sess = NULL;
+- struct se_node_acl *acl;
++ LIST_HEAD(sess_list);
++ struct se_portal_group *tpg = acl->se_tpg;
++ struct se_session *sess, *sess_tmp;
+ unsigned long flags;
+- int dynamic_acl = 0;
+-
+- mutex_lock(&tpg->acl_node_mutex);
+- acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
+- if (!acl) {
+- pr_err("Access Control List entry for %s Initiator"
+- " Node %s does not exists for TPG %hu, ignoring"
+- " request.\n", tpg->se_tpg_tfo->get_fabric_name(),
+- initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
+- mutex_unlock(&tpg->acl_node_mutex);
+- return -ENODEV;
+- }
+- if (acl->dynamic_node_acl) {
+- acl->dynamic_node_acl = 0;
+- dynamic_acl = 1;
+- }
+- mutex_unlock(&tpg->acl_node_mutex);
+-
+- spin_lock_irqsave(&tpg->session_lock, flags);
+- list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
+- if (sess->se_node_acl != acl)
+- continue;
+-
+- if (!force) {
+- pr_err("Unable to change queue depth for %s"
+- " Initiator Node: %s while session is"
+- " operational. To forcefully change the queue"
+- " depth and force session reinstatement"
+- " use the \"force=1\" parameter.\n",
+- tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
+- spin_unlock_irqrestore(&tpg->session_lock, flags);
+-
+- mutex_lock(&tpg->acl_node_mutex);
+- if (dynamic_acl)
+- acl->dynamic_node_acl = 1;
+- mutex_unlock(&tpg->acl_node_mutex);
+- return -EEXIST;
+- }
+- /*
+- * Determine if the session needs to be closed by our context.
+- */
+- if (!tpg->se_tpg_tfo->shutdown_session(sess))
+- continue;
+-
+- init_sess = sess;
+- break;
+- }
++ int rc;
+
+ /*
+ * User has requested to change the queue depth for a Initiator Node.
+ * Change the value in the Node's struct se_node_acl, and call
+- * core_set_queue_depth_for_node() to add the requested queue depth.
+- *
+- * Finally call tpg->se_tpg_tfo->close_session() to force session
+- * reinstatement to occur if there is an active session for the
+- * $FABRIC_MOD Initiator Node in question.
++ * target_set_nacl_queue_depth() to set the new queue depth.
+ */
+- acl->queue_depth = queue_depth;
++ target_set_nacl_queue_depth(tpg, acl, queue_depth);
++
++ spin_lock_irqsave(&acl->nacl_sess_lock, flags);
++ list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list,
++ sess_acl_list) {
++ if (sess->sess_tearing_down != 0)
++ continue;
++ if (!target_get_session(sess))
++ continue;
++ spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
+
+- if (core_set_queue_depth_for_node(tpg, acl) < 0) {
+- spin_unlock_irqrestore(&tpg->session_lock, flags);
+ /*
+- * Force session reinstatement if
+- * core_set_queue_depth_for_node() failed, because we assume
+- * the $FABRIC_MOD has already the set session reinstatement
+- * bit from tpg->se_tpg_tfo->shutdown_session() called above.
++ * Finally call tpg->se_tpg_tfo->close_session() to force session
++ * reinstatement to occur if there is an active session for the
++ * $FABRIC_MOD Initiator Node in question.
+ */
+- if (init_sess)
+- tpg->se_tpg_tfo->close_session(init_sess);
+-
+- mutex_lock(&tpg->acl_node_mutex);
+- if (dynamic_acl)
+- acl->dynamic_node_acl = 1;
+- mutex_unlock(&tpg->acl_node_mutex);
+- return -EINVAL;
++ rc = tpg->se_tpg_tfo->shutdown_session(sess);
++ target_put_session(sess);
++ if (!rc) {
++ spin_lock_irqsave(&acl->nacl_sess_lock, flags);
++ continue;
++ }
++ target_put_session(sess);
++ spin_lock_irqsave(&acl->nacl_sess_lock, flags);
+ }
+- spin_unlock_irqrestore(&tpg->session_lock, flags);
+- /*
+- * If the $FABRIC_MOD session for the Initiator Node ACL exists,
+- * forcefully shutdown the $FABRIC_MOD session/nexus.
+- */
+- if (init_sess)
+- tpg->se_tpg_tfo->close_session(init_sess);
++ spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
+
+ pr_debug("Successfully changed queue depth to: %d for Initiator"
+- " Node: %s on %s Target Portal Group: %u\n", queue_depth,
+- initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
++ " Node: %s on %s Target Portal Group: %u\n", acl->queue_depth,
++ acl->initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
+ tpg->se_tpg_tfo->tpg_get_tag(tpg));
+
+- mutex_lock(&tpg->acl_node_mutex);
+- if (dynamic_acl)
+- acl->dynamic_node_acl = 1;
+- mutex_unlock(&tpg->acl_node_mutex);
+-
+ return 0;
+ }
+ EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -383,9 +383,9 @@ static void target_release_session(struc
+ se_tpg->se_tpg_tfo->close_session(se_sess);
+ }
+
+-void target_get_session(struct se_session *se_sess)
++int target_get_session(struct se_session *se_sess)
+ {
+- kref_get(&se_sess->sess_kref);
++ return kref_get_unless_zero(&se_sess->sess_kref);
+ }
+ EXPORT_SYMBOL(target_get_session);
+
+--- a/include/target/target_core_fabric.h
++++ b/include/target/target_core_fabric.h
+@@ -117,7 +117,7 @@ void __transport_register_session(struct
+ struct se_node_acl *, struct se_session *, void *);
+ void transport_register_session(struct se_portal_group *,
+ struct se_node_acl *, struct se_session *, void *);
+-void target_get_session(struct se_session *);
++int target_get_session(struct se_session *);
+ void target_put_session(struct se_session *);
+ ssize_t target_show_dynamic_sessions(struct se_portal_group *, char *);
+ void transport_free_session(struct se_session *);
+@@ -172,8 +172,7 @@ bool target_tpg_has_node_acl(struct se_p
+ const char *);
+ struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
+ unsigned char *);
+-int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
+- unsigned char *, u32, int);
++int core_tpg_set_initiator_node_queue_depth(struct se_node_acl *, u32);
+ int core_tpg_set_initiator_node_tag(struct se_portal_group *,
+ struct se_node_acl *, const char *);
+ int core_tpg_register(struct se_wwn *, struct se_portal_group *, int);
--- /dev/null
+From 59ac9c078141b8fd0186c0b18660a1b2c24e724e Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+Date: Thu, 4 May 2017 15:50:47 -0700
+Subject: target/fileio: Fix zero-length READ and WRITE handling
+
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+
+commit 59ac9c078141b8fd0186c0b18660a1b2c24e724e upstream.
+
+This patch fixes zero-length READ and WRITE handling in target/FILEIO,
+which was broken a long time back by:
+
+Since:
+
+ commit d81cb44726f050d7cf1be4afd9cb45d153b52066
+ Author: Paolo Bonzini <pbonzini@redhat.com>
+ Date: Mon Sep 17 16:36:11 2012 -0700
+
+ target: go through normal processing for all zero-length commands
+
+which moved zero-length READ and WRITE completion out of target-core,
+to doing submission into backend driver code.
+
+To address this, go ahead and invoke target_complete_cmd() for any
+non negative return value in fd_do_rw().
+
+Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Cc: Andy Grover <agrover@redhat.com>
+Cc: David Disseldorp <ddiss@suse.de>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_file.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/target/target_core_file.c
++++ b/drivers/target/target_core_file.c
+@@ -594,8 +594,7 @@ fd_execute_rw(struct se_cmd *cmd, struct
+ if (ret < 0)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+- if (ret)
+- target_complete_cmd(cmd, SAM_STAT_GOOD);
++ target_complete_cmd(cmd, SAM_STAT_GOOD);
+ return 0;
+ }
+
--- /dev/null
+From a71a5dc7f833943998e97ca8fa6a4c708a0ed1a9 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Tue, 11 Apr 2017 16:24:16 -0700
+Subject: target: Fix compare_and_write_callback handling for non GOOD status
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit a71a5dc7f833943998e97ca8fa6a4c708a0ed1a9 upstream.
+
+Following the bugfix for handling non SAM_STAT_GOOD COMPARE_AND_WRITE
+status during COMMIT phase in commit 9b2792c3da1, the same bug exists
+for the READ phase as well.
+
+This would manifest first as a lost SCSI response, and eventual
+hung task during fabric driver logout or re-login, as existing
+shutdown logic waited for the COMPARE_AND_WRITE se_cmd->cmd_kref
+to reach zero.
+
+To address this bug, compare_and_write_callback() has been changed
+to set post_ret = 1 and return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE
+as necessary to signal failure status.
+
+Reported-by: Bill Borsari <wgb@datera.io>
+Cc: Bill Borsari <wgb@datera.io>
+Tested-by: Gary Guo <ghg@datera.io>
+Cc: Gary Guo <ghg@datera.io>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/target_core_sbc.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/target/target_core_sbc.c
++++ b/drivers/target/target_core_sbc.c
+@@ -498,8 +498,11 @@ static sense_reason_t compare_and_write_
+ * been failed with a non-zero SCSI status.
+ */
+ if (cmd->scsi_status) {
+- pr_err("compare_and_write_callback: non zero scsi_status:"
++ pr_debug("compare_and_write_callback: non zero scsi_status:"
+ " 0x%02x\n", cmd->scsi_status);
++ *post_ret = 1;
++ if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
++ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ goto out;
+ }
+
--- /dev/null
+From 6fc091fb0459ade939a795bfdcaf645385b951d4 Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@nxp.com>
+Date: Wed, 19 Apr 2017 16:55:52 +0300
+Subject: usb: host: xhci: print correct command ring address
+
+From: Peter Chen <peter.chen@nxp.com>
+
+commit 6fc091fb0459ade939a795bfdcaf645385b951d4 upstream.
+
+Print correct command ring address using 'val_64'.
+
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-mem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2493,7 +2493,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
+ xhci->cmd_ring->cycle_state;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+- "// Setting command ring address to 0x%x", val);
++ "// Setting command ring address to 0x%016llx", val_64);
+ xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+ xhci_dbg_cmd_ptrs(xhci);
+
--- /dev/null
+From f5cccf49428447dfbc9edb7a04bb8fc316269781 Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Mon, 20 Mar 2017 14:30:50 -0700
+Subject: usb: hub: Do not attempt to autosuspend disconnected devices
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+commit f5cccf49428447dfbc9edb7a04bb8fc316269781 upstream.
+
+While running a bind/unbind stress test with the dwc3 usb driver on rk3399,
+the following crash was observed.
+
+Unable to handle kernel NULL pointer dereference at virtual address 00000218
+pgd = ffffffc00165f000
+[00000218] *pgd=000000000174f003, *pud=000000000174f003,
+ *pmd=0000000001750003, *pte=00e8000001751713
+Internal error: Oops: 96000005 [#1] PREEMPT SMP
+Modules linked in: uinput uvcvideo videobuf2_vmalloc cmac
+ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat rfcomm
+xt_mark fuse bridge stp llc zram btusb btrtl btbcm btintel bluetooth
+ip6table_filter mwifiex_pcie mwifiex cfg80211 cdc_ether usbnet r8152 mii joydev
+snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device ppp_async
+ppp_generic slhc tun
+CPU: 1 PID: 29814 Comm: kworker/1:1 Not tainted 4.4.52 #507
+Hardware name: Google Kevin (DT)
+Workqueue: pm pm_runtime_work
+task: ffffffc0ac540000 ti: ffffffc0af4d4000 task.ti: ffffffc0af4d4000
+PC is at autosuspend_check+0x74/0x174
+LR is at autosuspend_check+0x70/0x174
+...
+Call trace:
+[<ffffffc00080dcc0>] autosuspend_check+0x74/0x174
+[<ffffffc000810500>] usb_runtime_idle+0x20/0x40
+[<ffffffc000785ae0>] __rpm_callback+0x48/0x7c
+[<ffffffc000786af0>] rpm_idle+0x1e8/0x498
+[<ffffffc000787cdc>] pm_runtime_work+0x88/0xcc
+[<ffffffc000249bb8>] process_one_work+0x390/0x6b8
+[<ffffffc00024abcc>] worker_thread+0x480/0x610
+[<ffffffc000251a80>] kthread+0x164/0x178
+[<ffffffc0002045d0>] ret_from_fork+0x10/0x40
+
+Source:
+
+(gdb) l *0xffffffc00080dcc0
+0xffffffc00080dcc0 is in autosuspend_check
+(drivers/usb/core/driver.c:1778).
+1773 /* We don't need to check interfaces that are
+1774 * disabled for runtime PM. Either they are unbound
+1775 * or else their drivers don't support autosuspend
+1776 * and so they are permanently active.
+1777 */
+1778 if (intf->dev.power.disable_depth)
+1779 continue;
+1780 if (atomic_read(&intf->dev.power.usage_count) > 0)
+1781 return -EBUSY;
+1782 w |= intf->needs_remote_wakeup;
+
+Code analysis shows that intf is set to NULL in usb_disable_device() prior
+to setting actconfig to NULL. At the same time, usb_runtime_idle() does not
+lock the usb device, and neither does any of the functions in the
+traceback. This means that there is no protection against a race condition
+where usb_disable_device() is removing dev->actconfig->interface[] pointers
+while those are being accessed from autosuspend_check().
+
+To solve the problem, synchronize and validate device state between
+autosuspend_check() and usb_disconnect().
+
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/driver.c | 3 +++
+ drivers/usb/core/hub.c | 6 ++++++
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1778,6 +1778,9 @@ static int autosuspend_check(struct usb_
+ int w, i;
+ struct usb_interface *intf;
+
++ if (udev->state == USB_STATE_NOTATTACHED)
++ return -ENODEV;
++
+ /* Fail if autosuspend is disabled, or any interfaces are in use, or
+ * any interface drivers require remote wakeup but it isn't available.
+ */
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2071,6 +2071,12 @@ void usb_disconnect(struct usb_device **
+ dev_info(&udev->dev, "USB disconnect, device number %d\n",
+ udev->devnum);
+
++ /*
++ * Ensure that the pm runtime code knows that the USB device
++ * is in the process of being disconnected.
++ */
++ pm_runtime_barrier(&udev->dev);
++
+ usb_lock_device(udev);
+
+ hub_disconnect_children(udev);
--- /dev/null
+From 245b2eecee2aac6fdc77dcafaa73c33f9644c3c7 Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Mon, 20 Mar 2017 11:16:11 -0700
+Subject: usb: hub: Fix error loop seen after hub communication errors
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+commit 245b2eecee2aac6fdc77dcafaa73c33f9644c3c7 upstream.
+
+While stress testing a usb controller using a bind/unbind looop, the
+following error loop was observed.
+
+usb 7-1.2: new low-speed USB device number 3 using xhci-hcd
+usb 7-1.2: hub failed to enable device, error -108
+usb 7-1-port2: cannot disable (err = -22)
+usb 7-1-port2: couldn't allocate usb_device
+usb 7-1-port2: cannot disable (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: activate --> -22
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+** 57 printk messages dropped ** hub 7-1:1.0: activate --> -22
+** 82 printk messages dropped ** hub 7-1:1.0: hub_ext_port_status failed (err = -22)
+
+This continues forever. After adding tracebacks into the code,
+the call sequence leading to this is found to be as follows.
+
+[<ffffffc0007fc8e0>] hub_activate+0x368/0x7b8
+[<ffffffc0007fceb4>] hub_resume+0x2c/0x3c
+[<ffffffc00080b3b8>] usb_resume_interface.isra.6+0x128/0x158
+[<ffffffc00080b5d0>] usb_suspend_both+0x1e8/0x288
+[<ffffffc00080c9c4>] usb_runtime_suspend+0x3c/0x98
+[<ffffffc0007820a0>] __rpm_callback+0x48/0x7c
+[<ffffffc00078217c>] rpm_callback+0xa8/0xd4
+[<ffffffc000786234>] rpm_suspend+0x84/0x758
+[<ffffffc000786ca4>] rpm_idle+0x2c8/0x498
+[<ffffffc000786ed4>] __pm_runtime_idle+0x60/0xac
+[<ffffffc00080eba8>] usb_autopm_put_interface+0x6c/0x7c
+[<ffffffc000803798>] hub_event+0x10ac/0x12ac
+[<ffffffc000249bb8>] process_one_work+0x390/0x6b8
+[<ffffffc00024abcc>] worker_thread+0x480/0x610
+[<ffffffc000251a80>] kthread+0x164/0x178
+[<ffffffc0002045d0>] ret_from_fork+0x10/0x40
+
+kick_hub_wq() is called from hub_activate() even after failures to
+communicate with the hub. This results in an endless sequence of
+hub event -> hub activate -> wq trigger -> hub event -> ...
+
+Provide two solutions for the problem.
+
+- Only trigger the hub event queue if communication with the hub
+ is successful.
+- After a suspend failure, only resume already suspended interfaces
+ if the communication with the device is still possible.
+
+Each of the changes fixes the observed problem. Use both to improve
+robustness.
+
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/driver.c | 18 ++++++++++++++++++
+ drivers/usb/core/hub.c | 5 ++++-
+ 2 files changed, 22 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1328,6 +1328,24 @@ static int usb_suspend_both(struct usb_d
+ */
+ if (udev->parent && !PMSG_IS_AUTO(msg))
+ status = 0;
++
++ /*
++ * If the device is inaccessible, don't try to resume
++ * suspended interfaces and just return the error.
++ */
++ if (status && status != -EBUSY) {
++ int err;
++ u16 devstat;
++
++ err = usb_get_status(udev, USB_RECIP_DEVICE, 0,
++ &devstat);
++ if (err) {
++ dev_err(&udev->dev,
++ "Failed to suspend device, error %d\n",
++ status);
++ goto done;
++ }
++ }
+ }
+
+ /* If the suspend failed, resume interfaces that did get suspended */
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1048,6 +1048,9 @@ static void hub_activate(struct usb_hub
+
+ portstatus = portchange = 0;
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
++ if (status)
++ goto abort;
++
+ if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+ dev_dbg(&port_dev->dev, "status %04x change %04x\n",
+ portstatus, portchange);
+@@ -1180,7 +1183,7 @@ static void hub_activate(struct usb_hub
+
+ /* Scan all ports that need attention */
+ kick_hub_wq(hub);
+-
++ abort:
+ if (type == HUB_INIT2 || type == HUB_INIT3) {
+ /* Allow autosuspend if it was suppressed */
+ disconnected:
--- /dev/null
+From 3d6159640da9c9175d1ca42f151fc1a14caded59 Mon Sep 17 00:00:00 2001
+From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
+Date: Thu, 13 Apr 2017 15:33:34 +0300
+Subject: usb: Make sure usb/phy/of gets built-in
+
+From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
+
+commit 3d6159640da9c9175d1ca42f151fc1a14caded59 upstream.
+
+DWC3 driver uses of_usb_get_phy_mode() which is
+implemented in drivers/usb/phy/of.c and in bare minimal
+configuration it might not be pulled in kernel binary.
+
+In case of ARC or ARM this could be easily reproduced with
+"allnodefconfig" +CONFIG_USB=m +CONFIG_USB_DWC3=m.
+
+On building all ends-up with:
+---------------------->8------------------
+ Kernel: arch/arm/boot/Image is ready
+ Kernel: arch/arm/boot/zImage is ready
+ Building modules, stage 2.
+ MODPOST 5 modules
+ERROR: "of_usb_get_phy_mode" [drivers/usb/dwc3/dwc3.ko] undefined!
+make[1]: *** [__modpost] Error 1
+make: *** [modules] Error 2
+---------------------->8------------------
+
+Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
+Cc: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Felipe Balbi <balbi@kernel.org>
+Cc: Felix Fietkau <nbd@nbd.name>
+Cc: Jeremy Kerr <jk@ozlabs.org>
+Cc: linux-snps-arc@lists.infradead.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -98,6 +98,7 @@ obj-$(CONFIG_USB_PHY) += usb/
+ obj-$(CONFIG_USB) += usb/
+ obj-$(CONFIG_PCI) += usb/
+ obj-$(CONFIG_USB_GADGET) += usb/
++obj-$(CONFIG_OF) += usb/
+ obj-$(CONFIG_SERIO) += input/serio/
+ obj-$(CONFIG_GAMEPORT) += input/gameport/
+ obj-$(CONFIG_INPUT) += input/
--- /dev/null
+From 2c930e3d0aed1505e86e0928d323df5027817740 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
+Date: Mon, 3 Apr 2017 22:48:40 -0500
+Subject: usb: misc: add missing continue in switch
+
+From: Gustavo A. R. Silva <garsilva@embeddedor.com>
+
+commit 2c930e3d0aed1505e86e0928d323df5027817740 upstream.
+
+Add missing continue in switch.
+
+Addresses-Coverity-ID: 1248733
+Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/misc/usbtest.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -135,6 +135,7 @@ get_endpoints(struct usbtest_dev *dev, s
+ case USB_ENDPOINT_XFER_INT:
+ if (dev->info->intr)
+ goto try_intr;
++ continue;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (dev->info->iso)
+ goto try_iso;
--- /dev/null
+From 942a48730faf149ccbf3e12ac718aee120bb3529 Mon Sep 17 00:00:00 2001
+From: Maksim Salau <maksim.salau@gmail.com>
+Date: Tue, 25 Apr 2017 22:49:21 +0300
+Subject: usb: misc: legousbtower: Fix buffers on stack
+
+From: Maksim Salau <maksim.salau@gmail.com>
+
+commit 942a48730faf149ccbf3e12ac718aee120bb3529 upstream.
+
+Allocate buffers on HEAP instead of STACK for local structures
+that are to be received using usb_control_msg().
+
+Signed-off-by: Maksim Salau <maksim.salau@gmail.com>
+Tested-by: Alfredo Rafael Vicente Boix <alviboi@gmail.com>;
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/misc/legousbtower.c | 37 +++++++++++++++++++++++++++----------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -317,9 +317,16 @@ static int tower_open (struct inode *ino
+ int subminor;
+ int retval = 0;
+ struct usb_interface *interface;
+- struct tower_reset_reply reset_reply;
++ struct tower_reset_reply *reset_reply;
+ int result;
+
++ reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL);
++
++ if (!reset_reply) {
++ retval = -ENOMEM;
++ goto exit;
++ }
++
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+
+@@ -364,8 +371,8 @@ static int tower_open (struct inode *ino
+ USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+ 0,
+ 0,
+- &reset_reply,
+- sizeof(reset_reply),
++ reset_reply,
++ sizeof(*reset_reply),
+ 1000);
+ if (result < 0) {
+ dev_err(&dev->udev->dev,
+@@ -406,6 +413,7 @@ unlock_exit:
+ mutex_unlock(&dev->lock);
+
+ exit:
++ kfree(reset_reply);
+ return retval;
+ }
+
+@@ -808,7 +816,7 @@ static int tower_probe (struct usb_inter
+ struct lego_usb_tower *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor* endpoint;
+- struct tower_get_version_reply get_version_reply;
++ struct tower_get_version_reply *get_version_reply = NULL;
+ int i;
+ int retval = -ENOMEM;
+ int result;
+@@ -898,6 +906,13 @@ static int tower_probe (struct usb_inter
+ dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+ dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
++ get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL);
++
++ if (!get_version_reply) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
+ /* get the firmware version and log it */
+ result = usb_control_msg (udev,
+ usb_rcvctrlpipe(udev, 0),
+@@ -905,18 +920,19 @@ static int tower_probe (struct usb_inter
+ USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+ 0,
+ 0,
+- &get_version_reply,
+- sizeof(get_version_reply),
++ get_version_reply,
++ sizeof(*get_version_reply),
+ 1000);
+ if (result < 0) {
+ dev_err(idev, "LEGO USB Tower get version control request failed\n");
+ retval = result;
+ goto error;
+ }
+- dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d "
+- "build %d\n", get_version_reply.major,
+- get_version_reply.minor,
+- le16_to_cpu(get_version_reply.build_no));
++ dev_info(&interface->dev,
++ "LEGO USB Tower firmware version is %d.%d build %d\n",
++ get_version_reply->major,
++ get_version_reply->minor,
++ le16_to_cpu(get_version_reply->build_no));
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata (interface, dev);
+@@ -940,6 +956,7 @@ exit:
+ return retval;
+
+ error:
++ kfree(get_version_reply);
+ tower_delete(dev);
+ return retval;
+ }
--- /dev/null
+From 2f86a96be0ccb1302b7eee7855dbee5ce4dc5dfb Mon Sep 17 00:00:00 2001
+From: Ajay Kaher <ajay.kaher@samsung.com>
+Date: Tue, 28 Mar 2017 08:09:32 -0400
+Subject: USB: Proper handling of Race Condition when two USB class drivers try to call init_usb_class simultaneously
+
+From: Ajay Kaher <ajay.kaher@samsung.com>
+
+commit 2f86a96be0ccb1302b7eee7855dbee5ce4dc5dfb upstream.
+
+There is race condition when two USB class drivers try to call
+init_usb_class at the same time and leads to crash.
+code path: probe->usb_register_dev->init_usb_class
+
+To solve this, mutex locking has been added in init_usb_class() and
+destroy_usb_class().
+
+As pointed by Alan, removed "if (usb_class)" test from destroy_usb_class()
+because usb_class can never be NULL there.
+
+Signed-off-by: Ajay Kaher <ajay.kaher@samsung.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/file.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/file.c
++++ b/drivers/usb/core/file.c
+@@ -26,6 +26,7 @@
+ #define MAX_USB_MINORS 256
+ static const struct file_operations *usb_minors[MAX_USB_MINORS];
+ static DECLARE_RWSEM(minor_rwsem);
++static DEFINE_MUTEX(init_usb_class_mutex);
+
+ static int usb_open(struct inode *inode, struct file *file)
+ {
+@@ -108,8 +109,9 @@ static void release_usb_class(struct kre
+
+ static void destroy_usb_class(void)
+ {
+- if (usb_class)
+- kref_put(&usb_class->kref, release_usb_class);
++ mutex_lock(&init_usb_class_mutex);
++ kref_put(&usb_class->kref, release_usb_class);
++ mutex_unlock(&init_usb_class_mutex);
+ }
+
+ int usb_major_init(void)
+@@ -171,7 +173,10 @@ int usb_register_dev(struct usb_interfac
+ if (intf->minor >= 0)
+ return -EADDRINUSE;
+
++ mutex_lock(&init_usb_class_mutex);
+ retval = init_usb_class();
++ mutex_unlock(&init_usb_class_mutex);
++
+ if (retval)
+ return retval;
+
--- /dev/null
+From 31c5d1922b90ddc1da6a6ddecef7cd31f17aa32b Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Tue, 18 Apr 2017 20:07:56 +0200
+Subject: USB: serial: ftdi_sio: add device ID for Microsemi/Arrow SF2PLUS Dev Kit
+
+From: Marek Vasut <marex@denx.de>
+
+commit 31c5d1922b90ddc1da6a6ddecef7cd31f17aa32b upstream.
+
+This development kit has an FT4232 on it with a custom USB VID/PID.
+The FT4232 provides four UARTs, but only two are used. The UART 0
+is used by the FlashPro5 programmer and UART 2 is connected to the
+SmartFusion2 CortexM3 SoC UART port.
+
+Note that the USB VID is registered to Actel according to Linux USB
+VID database, but that was acquired by Microsemi.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++
+ 2 files changed, 7 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -873,6 +873,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
+ USB_CLASS_VENDOR_SPEC,
+ USB_SUBCLASS_VENDOR_SPEC, 0x00) },
++ { USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
+ { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
+ { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -873,6 +873,12 @@
+ #define FIC_VID 0x1457
+ #define FIC_NEO1973_DEBUG_PID 0x5118
+
++/*
++ * Actel / Microsemi
++ */
++#define ACTEL_VID 0x1514
++#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID 0x2008
++
+ /* Olimex */
+ #define OLIMEX_VID 0x15BA
+ #define OLIMEX_ARM_USB_OCD_PID 0x0003