]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 May 2017 10:37:33 +0000 (12:37 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 May 2017 10:37:33 +0000 (12:37 +0200)
added patches:
iscsi-target-set-session_fall_back_to_erl0-when-forcing-reinstatement.patch
staging-comedi-jr3_pci-cope-with-jiffies-wraparound.patch
staging-comedi-jr3_pci-fix-possible-null-pointer-dereference.patch
staging-gdm724x-gdm_mux-fix-use-after-free-on-module-unload.patch
staging-vt6656-use-off-stack-for-in-buffer-usb-transfers.patch
staging-vt6656-use-off-stack-for-out-buffer-usb-transfers.patch
target-convert-acl-change-queue_depth-se_session-reference-usage.patch
target-fileio-fix-zero-length-read-and-write-handling.patch
target-fix-compare_and_write_callback-handling-for-non-good-status.patch
usb-host-xhci-print-correct-command-ring-address.patch
usb-hub-do-not-attempt-to-autosuspend-disconnected-devices.patch
usb-hub-fix-error-loop-seen-after-hub-communication-errors.patch
usb-make-sure-usb-phy-of-gets-built-in.patch
usb-misc-add-missing-continue-in-switch.patch
usb-misc-legousbtower-fix-buffers-on-stack.patch
usb-proper-handling-of-race-condition-when-two-usb-class-drivers-try-to-call-init_usb_class-simultaneously.patch
usb-serial-ftdi_sio-add-device-id-for-microsemi-arrow-sf2plus-dev-kit.patch

18 files changed:
queue-4.4/iscsi-target-set-session_fall_back_to_erl0-when-forcing-reinstatement.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/staging-comedi-jr3_pci-cope-with-jiffies-wraparound.patch [new file with mode: 0644]
queue-4.4/staging-comedi-jr3_pci-fix-possible-null-pointer-dereference.patch [new file with mode: 0644]
queue-4.4/staging-gdm724x-gdm_mux-fix-use-after-free-on-module-unload.patch [new file with mode: 0644]
queue-4.4/staging-vt6656-use-off-stack-for-in-buffer-usb-transfers.patch [new file with mode: 0644]
queue-4.4/staging-vt6656-use-off-stack-for-out-buffer-usb-transfers.patch [new file with mode: 0644]
queue-4.4/target-convert-acl-change-queue_depth-se_session-reference-usage.patch [new file with mode: 0644]
queue-4.4/target-fileio-fix-zero-length-read-and-write-handling.patch [new file with mode: 0644]
queue-4.4/target-fix-compare_and_write_callback-handling-for-non-good-status.patch [new file with mode: 0644]
queue-4.4/usb-host-xhci-print-correct-command-ring-address.patch [new file with mode: 0644]
queue-4.4/usb-hub-do-not-attempt-to-autosuspend-disconnected-devices.patch [new file with mode: 0644]
queue-4.4/usb-hub-fix-error-loop-seen-after-hub-communication-errors.patch [new file with mode: 0644]
queue-4.4/usb-make-sure-usb-phy-of-gets-built-in.patch [new file with mode: 0644]
queue-4.4/usb-misc-add-missing-continue-in-switch.patch [new file with mode: 0644]
queue-4.4/usb-misc-legousbtower-fix-buffers-on-stack.patch [new file with mode: 0644]
queue-4.4/usb-proper-handling-of-race-condition-when-two-usb-class-drivers-try-to-call-init_usb_class-simultaneously.patch [new file with mode: 0644]
queue-4.4/usb-serial-ftdi_sio-add-device-id-for-microsemi-arrow-sf2plus-dev-kit.patch [new file with mode: 0644]

diff --git a/queue-4.4/iscsi-target-set-session_fall_back_to_erl0-when-forcing-reinstatement.patch b/queue-4.4/iscsi-target-set-session_fall_back_to_erl0-when-forcing-reinstatement.patch
new file mode 100644 (file)
index 0000000..a3f9148
--- /dev/null
@@ -0,0 +1,75 @@
+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);
index ca0ac415f0bd64f7bc3e1e22696f6b5bf0550cce..37b8dadea6c4bbf85a06c4af5010a06ae4e1c07d 100644 (file)
@@ -1 +1,18 @@
 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
diff --git a/queue-4.4/staging-comedi-jr3_pci-cope-with-jiffies-wraparound.patch b/queue-4.4/staging-comedi-jr3_pci-cope-with-jiffies-wraparound.patch
new file mode 100644 (file)
index 0000000..e2a24fb
--- /dev/null
@@ -0,0 +1,34 @@
+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);
diff --git a/queue-4.4/staging-comedi-jr3_pci-fix-possible-null-pointer-dereference.patch b/queue-4.4/staging-comedi-jr3_pci-fix-possible-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..e687943
--- /dev/null
@@ -0,0 +1,51 @@
+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 */
diff --git a/queue-4.4/staging-gdm724x-gdm_mux-fix-use-after-free-on-module-unload.patch b/queue-4.4/staging-gdm724x-gdm_mux-fix-use-after-free-on-module-unload.patch
new file mode 100644 (file)
index 0000000..ce98553
--- /dev/null
@@ -0,0 +1,41 @@
+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);
diff --git a/queue-4.4/staging-vt6656-use-off-stack-for-in-buffer-usb-transfers.patch b/queue-4.4/staging-vt6656-use-off-stack-for-in-buffer-usb-transfers.patch
new file mode 100644 (file)
index 0000000..016e036
--- /dev/null
@@ -0,0 +1,54 @@
+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);
diff --git a/queue-4.4/staging-vt6656-use-off-stack-for-out-buffer-usb-transfers.patch b/queue-4.4/staging-vt6656-use-off-stack-for-out-buffer-usb-transfers.patch
new file mode 100644 (file)
index 0000000..dce2865
--- /dev/null
@@ -0,0 +1,52 @@
+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);
diff --git a/queue-4.4/target-convert-acl-change-queue_depth-se_session-reference-usage.patch b/queue-4.4/target-convert-acl-change-queue_depth-se_session-reference-usage.patch
new file mode 100644 (file)
index 0000000..5ed62e2
--- /dev/null
@@ -0,0 +1,397 @@
+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);
diff --git a/queue-4.4/target-fileio-fix-zero-length-read-and-write-handling.patch b/queue-4.4/target-fileio-fix-zero-length-read-and-write-handling.patch
new file mode 100644 (file)
index 0000000..e5e6eab
--- /dev/null
@@ -0,0 +1,50 @@
+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;
+ }
diff --git a/queue-4.4/target-fix-compare_and_write_callback-handling-for-non-good-status.patch b/queue-4.4/target-fix-compare_and_write_callback-handling-for-non-good-status.patch
new file mode 100644 (file)
index 0000000..35731b7
--- /dev/null
@@ -0,0 +1,48 @@
+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;
+       }
diff --git a/queue-4.4/usb-host-xhci-print-correct-command-ring-address.patch b/queue-4.4/usb-host-xhci-print-correct-command-ring-address.patch
new file mode 100644 (file)
index 0000000..004a1db
--- /dev/null
@@ -0,0 +1,30 @@
+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);
diff --git a/queue-4.4/usb-hub-do-not-attempt-to-autosuspend-disconnected-devices.patch b/queue-4.4/usb-hub-do-not-attempt-to-autosuspend-disconnected-devices.patch
new file mode 100644 (file)
index 0000000..c54236b
--- /dev/null
@@ -0,0 +1,103 @@
+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);
diff --git a/queue-4.4/usb-hub-fix-error-loop-seen-after-hub-communication-errors.patch b/queue-4.4/usb-hub-fix-error-loop-seen-after-hub-communication-errors.patch
new file mode 100644 (file)
index 0000000..e8e3cab
--- /dev/null
@@ -0,0 +1,137 @@
+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:
diff --git a/queue-4.4/usb-make-sure-usb-phy-of-gets-built-in.patch b/queue-4.4/usb-make-sure-usb-phy-of-gets-built-in.patch
new file mode 100644 (file)
index 0000000..1232d57
--- /dev/null
@@ -0,0 +1,54 @@
+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/
diff --git a/queue-4.4/usb-misc-add-missing-continue-in-switch.patch b/queue-4.4/usb-misc-add-missing-continue-in-switch.patch
new file mode 100644 (file)
index 0000000..73c64e6
--- /dev/null
@@ -0,0 +1,30 @@
+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;
diff --git a/queue-4.4/usb-misc-legousbtower-fix-buffers-on-stack.patch b/queue-4.4/usb-misc-legousbtower-fix-buffers-on-stack.patch
new file mode 100644 (file)
index 0000000..7c2402c
--- /dev/null
@@ -0,0 +1,116 @@
+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;
+ }
diff --git a/queue-4.4/usb-proper-handling-of-race-condition-when-two-usb-class-drivers-try-to-call-init_usb_class-simultaneously.patch b/queue-4.4/usb-proper-handling-of-race-condition-when-two-usb-class-drivers-try-to-call-init_usb_class-simultaneously.patch
new file mode 100644 (file)
index 0000000..f3d5881
--- /dev/null
@@ -0,0 +1,60 @@
+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;
diff --git a/queue-4.4/usb-serial-ftdi_sio-add-device-id-for-microsemi-arrow-sf2plus-dev-kit.patch b/queue-4.4/usb-serial-ftdi_sio-add-device-id-for-microsemi-arrow-sf2plus-dev-kit.patch
new file mode 100644 (file)
index 0000000..3962563
--- /dev/null
@@ -0,0 +1,51 @@
+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