]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 17 Oct 2015 20:50:01 +0000 (13:50 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 17 Oct 2015 20:50:01 +0000 (13:50 -0700)
added patches:
drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch
drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch
drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch
usb-whiteheat-fix-potential-null-deref-at-probe.patch
usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch
usb-xhci-clear-xhci_state_dying-on-start.patch
usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch
usb-xhci-lock-mutex-on-xhci_stop.patch
usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch
xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch
xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch
xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch
xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch

14 files changed:
queue-4.2/drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch [new file with mode: 0644]
queue-4.2/drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch [new file with mode: 0644]
queue-4.2/drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch [new file with mode: 0644]
queue-4.2/series
queue-4.2/usb-whiteheat-fix-potential-null-deref-at-probe.patch [new file with mode: 0644]
queue-4.2/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch [new file with mode: 0644]
queue-4.2/usb-xhci-clear-xhci_state_dying-on-start.patch [new file with mode: 0644]
queue-4.2/usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch [new file with mode: 0644]
queue-4.2/usb-xhci-lock-mutex-on-xhci_stop.patch [new file with mode: 0644]
queue-4.2/usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch [new file with mode: 0644]
queue-4.2/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch [new file with mode: 0644]
queue-4.2/xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch [new file with mode: 0644]
queue-4.2/xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch [new file with mode: 0644]
queue-4.2/xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch [new file with mode: 0644]

diff --git a/queue-4.2/drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch b/queue-4.2/drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch
new file mode 100644 (file)
index 0000000..4f5bad9
--- /dev/null
@@ -0,0 +1,115 @@
+From 274d83524895fe41ca8debae4eec60ede7252bb5 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@redhat.com>
+Date: Wed, 30 Sep 2015 10:39:42 +1000
+Subject: drm/dp/mst: drop cancel work sync in the mstb destroy path (v2)
+
+From: Dave Airlie <airlied@redhat.com>
+
+commit 274d83524895fe41ca8debae4eec60ede7252bb5 upstream.
+
+Since 9eb1e57f564d4e6e10991402726cc83fe0b9172f
+drm/dp/mst: make sure mst_primary mstb is valid in work function
+
+we validate the mstb structs in the work function, and doing
+that takes a reference. So we should never get here with the
+work function running using the mstb device, only if the work
+function hasn't run yet or is running for another mstb.
+
+So we don't need to sync the work here, this was causing
+lockdep spew as below.
+
+[  +0.000160] =============================================
+[  +0.000001] [ INFO: possible recursive locking detected ]
+[  +0.000002] 3.10.0-320.el7.rhel72.stable.backport.3.x86_64.debug #1 Tainted: G        W      ------------
+[  +0.000001] ---------------------------------------------
+[  +0.000001] kworker/4:2/1262 is trying to acquire lock:
+[  +0.000001]  ((&mgr->work)){+.+.+.}, at: [<ffffffff810b29a5>] flush_work+0x5/0x2e0
+[  +0.000007]
+but task is already holding lock:
+[  +0.000001]  ((&mgr->work)){+.+.+.}, at: [<ffffffff810b57e4>] process_one_work+0x1b4/0x710
+[  +0.000004]
+other info that might help us debug this:
+[  +0.000001]  Possible unsafe locking scenario:
+
+[  +0.000002]        CPU0
+[  +0.000000]        ----
+[  +0.000001]   lock((&mgr->work));
+[  +0.000002]   lock((&mgr->work));
+[  +0.000001]
+ *** DEADLOCK ***
+
+[  +0.000001]  May be due to missing lock nesting notation
+
+[  +0.000002] 2 locks held by kworker/4:2/1262:
+[  +0.000001]  #0:  (events_long){.+.+.+}, at: [<ffffffff810b57e4>] process_one_work+0x1b4/0x710
+[  +0.000004]  #1:  ((&mgr->work)){+.+.+.}, at: [<ffffffff810b57e4>] process_one_work+0x1b4/0x710
+[  +0.000003]
+stack backtrace:
+[  +0.000003] CPU: 4 PID: 1262 Comm: kworker/4:2 Tainted: G        W      ------------   3.10.0-320.el7.rhel72.stable.backport.3.x86_64.debug #1
+[  +0.000001] Hardware name: LENOVO 20EGS0R600/20EGS0R600, BIOS GNET71WW (2.19 ) 02/05/2015
+[  +0.000008] Workqueue: events_long drm_dp_mst_link_probe_work [drm_kms_helper]
+[  +0.000001]  ffffffff82c26c90 00000000a527b914 ffff88046399bae8 ffffffff816fe04d
+[  +0.000004]  ffff88046399bb58 ffffffff8110f47f ffff880461438000 0001009b840fc003
+[  +0.000002]  ffff880461438a98 0000000000000000 0000000804dc26e1 ffffffff824a2c00
+[  +0.000003] Call Trace:
+[  +0.000004]  [<ffffffff816fe04d>] dump_stack+0x19/0x1b
+[  +0.000004]  [<ffffffff8110f47f>] __lock_acquire+0x115f/0x1250
+[  +0.000002]  [<ffffffff8110fd49>] lock_acquire+0x99/0x1e0
+[  +0.000002]  [<ffffffff810b29a5>] ? flush_work+0x5/0x2e0
+[  +0.000002]  [<ffffffff810b29ee>] flush_work+0x4e/0x2e0
+[  +0.000002]  [<ffffffff810b29a5>] ? flush_work+0x5/0x2e0
+[  +0.000004]  [<ffffffff81025905>] ? native_sched_clock+0x35/0x80
+[  +0.000002]  [<ffffffff81025959>] ? sched_clock+0x9/0x10
+[  +0.000002]  [<ffffffff810da1f5>] ? local_clock+0x25/0x30
+[  +0.000002]  [<ffffffff8110dca9>] ? mark_held_locks+0xb9/0x140
+[  +0.000003]  [<ffffffff810b4ed5>] ? __cancel_work_timer+0x95/0x160
+[  +0.000002]  [<ffffffff810b4ee8>] __cancel_work_timer+0xa8/0x160
+[  +0.000002]  [<ffffffff810b4fb0>] cancel_work_sync+0x10/0x20
+[  +0.000007]  [<ffffffffa0160d17>] drm_dp_destroy_mst_branch_device+0x27/0x120 [drm_kms_helper]
+[  +0.000006]  [<ffffffffa0163968>] drm_dp_mst_link_probe_work+0x78/0xa0 [drm_kms_helper]
+[  +0.000002]  [<ffffffff810b5850>] process_one_work+0x220/0x710
+[  +0.000002]  [<ffffffff810b57e4>] ? process_one_work+0x1b4/0x710
+[  +0.000005]  [<ffffffff810b5e5b>] worker_thread+0x11b/0x3a0
+[  +0.000003]  [<ffffffff810b5d40>] ? process_one_work+0x710/0x710
+[  +0.000002]  [<ffffffff810beced>] kthread+0xed/0x100
+[  +0.000003]  [<ffffffff810bec00>] ? insert_kthread_work+0x80/0x80
+[  +0.000003]  [<ffffffff817121d8>] ret_from_fork+0x58/0x90
+
+v2: add flush_work.
+
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -804,8 +804,6 @@ static void drm_dp_destroy_mst_branch_de
+       struct drm_dp_mst_port *port, *tmp;
+       bool wake_tx = false;
+-      cancel_work_sync(&mstb->mgr->work);
+-
+       /*
+        * destroy all ports - don't need lock
+        * as there are no more references to the mst branch
+@@ -1991,6 +1989,8 @@ void drm_dp_mst_topology_mgr_suspend(str
+       drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+                          DP_MST_EN | DP_UPSTREAM_IS_SRC);
+       mutex_unlock(&mgr->lock);
++      flush_work(&mgr->work);
++      flush_work(&mgr->destroy_connector_work);
+ }
+ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
+@@ -2753,6 +2753,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_in
+  */
+ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
+ {
++      flush_work(&mgr->work);
+       flush_work(&mgr->destroy_connector_work);
+       mutex_lock(&mgr->payload_lock);
+       kfree(mgr->payloads);
diff --git a/queue-4.2/drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch b/queue-4.2/drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch
new file mode 100644 (file)
index 0000000..2b01d39
--- /dev/null
@@ -0,0 +1,121 @@
+From df4839fdc9b3c922586b945f062f38cbbda022bb Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@redhat.com>
+Date: Wed, 16 Sep 2015 10:37:28 +1000
+Subject: drm/dp/mst: fixup handling hotplug on port removal.
+
+From: Dave Airlie <airlied@redhat.com>
+
+commit df4839fdc9b3c922586b945f062f38cbbda022bb upstream.
+
+output ports should always have a connector, unless
+in the rare case connector allocation fails in the
+driver.
+
+In this case we only need to teardown the pdt,
+and free the struct, and there is no need to
+send a hotplug msg.
+
+In the case were we add the port to the destroy
+list we need to send a hotplug if we destroy
+any connectors, so userspace knows to reprobe
+stuff.
+
+this patch also handles port->connector allocation
+failing which should be a rare event, but makes
+the code consistent.
+
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c |   36 ++++++++++++++++++++++++----------
+ 1 file changed, 26 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -863,29 +863,33 @@ static void drm_dp_destroy_port(struct k
+ {
+       struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
+       struct drm_dp_mst_topology_mgr *mgr = port->mgr;
++
+       if (!port->input) {
+               port->vcpi.num_slots = 0;
+               kfree(port->cached_edid);
+-              /* we can't destroy the connector here, as
+-                 we might be holding the mode_config.mutex
+-                 from an EDID retrieval */
++              /*
++               * The only time we don't have a connector
++               * on an output port is if the connector init
++               * fails.
++               */
+               if (port->connector) {
++                      /* we can't destroy the connector here, as
++                       * we might be holding the mode_config.mutex
++                       * from an EDID retrieval */
++
+                       mutex_lock(&mgr->destroy_connector_lock);
+                       list_add(&port->next, &mgr->destroy_connector_list);
+                       mutex_unlock(&mgr->destroy_connector_lock);
+                       schedule_work(&mgr->destroy_connector_work);
+                       return;
+               }
++              /* no need to clean up vcpi
++               * as if we have no connector we never setup a vcpi */
+               drm_dp_port_teardown_pdt(port, port->pdt);
+-
+-              if (!port->input && port->vcpi.vcpi > 0)
+-                      drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+       }
+       kfree(port);
+-
+-      (*mgr->cbs->hotplug)(mgr);
+ }
+ static void drm_dp_put_port(struct drm_dp_mst_port *port)
+@@ -1115,12 +1119,21 @@ static void drm_dp_add_port(struct drm_d
+               char proppath[255];
+               build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
+               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+-
++              if (!port->connector) {
++                      /* remove it from the port list */
++                      mutex_lock(&mstb->mgr->lock);
++                      list_del(&port->next);
++                      mutex_unlock(&mstb->mgr->lock);
++                      /* drop port list reference */
++                      drm_dp_put_port(port);
++                      goto out;
++              }
+               if (port->port_num >= 8) {
+                       port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+               }
+       }
++out:
+       /* put reference to this port */
+       drm_dp_put_port(port);
+ }
+@@ -2661,7 +2674,7 @@ static void drm_dp_destroy_connector_wor
+ {
+       struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
+       struct drm_dp_mst_port *port;
+-
++      bool send_hotplug = false;
+       /*
+        * Not a regular list traverse as we have to drop the destroy
+        * connector lock before destroying the connector, to avoid AB->BA
+@@ -2684,7 +2697,10 @@ static void drm_dp_destroy_connector_wor
+               if (!port->input && port->vcpi.vcpi > 0)
+                       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+               kfree(port);
++              send_hotplug = true;
+       }
++      if (send_hotplug)
++              (*mgr->cbs->hotplug)(mgr);
+ }
+ /**
diff --git a/queue-4.2/drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch b/queue-4.2/drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch
new file mode 100644 (file)
index 0000000..2d3b2a2
--- /dev/null
@@ -0,0 +1,51 @@
+From 4281f46ef839050d2ef60348f661eb463c21cc2e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel.daenzer@amd.com>
+Date: Mon, 28 Sep 2015 18:16:31 +0900
+Subject: drm/radeon: Restore LCD backlight level on resume (>= R5xx)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel.daenzer@amd.com>
+
+commit 4281f46ef839050d2ef60348f661eb463c21cc2e upstream.
+
+Instead of only enabling the backlight (which seems to set it to max
+brightness), just re-set the current backlight level, which also takes
+care of enabling the backlight if necessary.
+
+Only the radeon_atom_encoder_dpms_dig part tested on a Kaveri laptop,
+the radeon_atom_encoder_dpms_avivo part is only compile tested.
+
+Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/atombios_encoders.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_encoders.c
++++ b/drivers/gpu/drm/radeon/atombios_encoders.c
+@@ -1624,8 +1624,9 @@ radeon_atom_encoder_dpms_avivo(struct dr
+               } else
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+-                      args.ucAction = ATOM_LCD_BLON;
+-                      atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
++                      struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
++
++                      atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+               }
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+@@ -1706,8 +1707,7 @@ radeon_atom_encoder_dpms_dig(struct drm_
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
+               }
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+-                      atombios_dig_transmitter_setup(encoder,
+-                                                     ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
++                      atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
+               break;
index a7f6ffb50f243b094b38848d8c1c45afefd075a9..234e717636ac112510630c1de6a4e72396525a06 100644 (file)
@@ -147,3 +147,16 @@ drm-amdgpu-fix-max_vblank_count-value-for-current-display-engines.patch
 drm-amdgpu-restore-lcd-backlight-level-on-resume.patch
 drm-i915-bios-handle-mipi-sequence-block-v3-gracefully.patch
 drm-reject-dri1-hw-lock-ioctl-functions-for-kms-drivers.patch
+drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch
+drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch
+drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch
+usb-whiteheat-fix-potential-null-deref-at-probe.patch
+xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch
+xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch
+usb-xhci-lock-mutex-on-xhci_stop.patch
+usb-xhci-clear-xhci_state_dying-on-start.patch
+usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch
+usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch
+xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch
+xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch
+usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch
diff --git a/queue-4.2/usb-whiteheat-fix-potential-null-deref-at-probe.patch b/queue-4.2/usb-whiteheat-fix-potential-null-deref-at-probe.patch
new file mode 100644 (file)
index 0000000..b0b1393
--- /dev/null
@@ -0,0 +1,81 @@
+From cbb4be652d374f64661137756b8f357a1827d6a4 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Wed, 23 Sep 2015 11:41:42 -0700
+Subject: USB: whiteheat: fix potential null-deref at probe
+
+From: Johan Hovold <johan@kernel.org>
+
+commit cbb4be652d374f64661137756b8f357a1827d6a4 upstream.
+
+Fix potential null-pointer dereference at probe by making sure that the
+required endpoints are present.
+
+The whiteheat driver assumes there are at least five pairs of bulk
+endpoints, of which the final pair is used for the "command port". An
+attempt to bind to an interface with fewer bulk endpoints would
+currently lead to an oops.
+
+Fixes CVE-2015-5257.
+
+Reported-by: Moein Ghasemzadeh <moein@istuary.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/whiteheat.c |   31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -80,6 +80,8 @@ static int  whiteheat_firmware_download(
+ static int  whiteheat_firmware_attach(struct usb_serial *serial);
+ /* function prototypes for the Connect Tech WhiteHEAT serial converter */
++static int whiteheat_probe(struct usb_serial *serial,
++                              const struct usb_device_id *id);
+ static int  whiteheat_attach(struct usb_serial *serial);
+ static void whiteheat_release(struct usb_serial *serial);
+ static int  whiteheat_port_probe(struct usb_serial_port *port);
+@@ -116,6 +118,7 @@ static struct usb_serial_driver whitehea
+       .description =          "Connect Tech - WhiteHEAT",
+       .id_table =             id_table_std,
+       .num_ports =            4,
++      .probe =                whiteheat_probe,
+       .attach =               whiteheat_attach,
+       .release =              whiteheat_release,
+       .port_probe =           whiteheat_port_probe,
+@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(str
+ /*****************************************************************************
+  * Connect Tech's White Heat serial driver functions
+  *****************************************************************************/
++
++static int whiteheat_probe(struct usb_serial *serial,
++                              const struct usb_device_id *id)
++{
++      struct usb_host_interface *iface_desc;
++      struct usb_endpoint_descriptor *endpoint;
++      size_t num_bulk_in = 0;
++      size_t num_bulk_out = 0;
++      size_t min_num_bulk;
++      unsigned int i;
++
++      iface_desc = serial->interface->cur_altsetting;
++
++      for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
++              endpoint = &iface_desc->endpoint[i].desc;
++              if (usb_endpoint_is_bulk_in(endpoint))
++                      ++num_bulk_in;
++              if (usb_endpoint_is_bulk_out(endpoint))
++                      ++num_bulk_out;
++      }
++
++      min_num_bulk = COMMAND_PORT + 1;
++      if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
++              return -ENODEV;
++
++      return 0;
++}
++
+ static int whiteheat_attach(struct usb_serial *serial)
+ {
+       struct usb_serial_port *command_port;
diff --git a/queue-4.2/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch b/queue-4.2/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch
new file mode 100644 (file)
index 0000000..2875340
--- /dev/null
@@ -0,0 +1,195 @@
+From 4758dcd19a7d9ba9610b38fecb93f65f56f86346 Mon Sep 17 00:00:00 2001
+From: Reyad Attiyat <reyad.attiyat@gmail.com>
+Date: Thu, 6 Aug 2015 19:23:58 +0300
+Subject: usb: xhci: Add support for URB_ZERO_PACKET to bulk/sg transfers
+
+From: Reyad Attiyat <reyad.attiyat@gmail.com>
+
+commit 4758dcd19a7d9ba9610b38fecb93f65f56f86346 upstream.
+
+This commit checks for the URB_ZERO_PACKET flag and creates an extra
+zero-length td if the urb transfer length is a multiple of the endpoint's
+max packet length.
+
+Signed-off-by: Reyad Attiyat <reyad.attiyat@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Cc: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c |   66 +++++++++++++++++++++++++++++++++----------
+ drivers/usb/host/xhci.c      |    5 +++
+ 2 files changed, 57 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -3050,9 +3050,11 @@ static int queue_bulk_sg_tx(struct xhci_
+       struct xhci_td *td;
+       struct scatterlist *sg;
+       int num_sgs;
+-      int trb_buff_len, this_sg_len, running_total;
++      int trb_buff_len, this_sg_len, running_total, ret;
+       unsigned int total_packet_count;
++      bool zero_length_needed;
+       bool first_trb;
++      int last_trb_num;
+       u64 addr;
+       bool more_trbs_coming;
+@@ -3068,13 +3070,27 @@ static int queue_bulk_sg_tx(struct xhci_
+       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
+                       usb_endpoint_maxp(&urb->ep->desc));
+-      trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
++      ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                       ep_index, urb->stream_id,
+                       num_trbs, urb, 0, mem_flags);
+-      if (trb_buff_len < 0)
+-              return trb_buff_len;
++      if (ret < 0)
++              return ret;
+       urb_priv = urb->hcpriv;
++
++      /* Deal with URB_ZERO_PACKET - need one more td/trb */
++      zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
++              urb_priv->length == 2;
++      if (zero_length_needed) {
++              num_trbs++;
++              xhci_dbg(xhci, "Creating zero length td.\n");
++              ret = prepare_transfer(xhci, xhci->devs[slot_id],
++                              ep_index, urb->stream_id,
++                              1, urb, 1, mem_flags);
++              if (ret < 0)
++                      return ret;
++      }
++
+       td = urb_priv->td[0];
+       /*
+@@ -3104,6 +3120,7 @@ static int queue_bulk_sg_tx(struct xhci_
+               trb_buff_len = urb->transfer_buffer_length;
+       first_trb = true;
++      last_trb_num = zero_length_needed ? 2 : 1;
+       /* Queue the first TRB, even if it's zero-length */
+       do {
+               u32 field = 0;
+@@ -3121,12 +3138,15 @@ static int queue_bulk_sg_tx(struct xhci_
+               /* Chain all the TRBs together; clear the chain bit in the last
+                * TRB to indicate it's the last TRB in the chain.
+                */
+-              if (num_trbs > 1) {
++              if (num_trbs > last_trb_num) {
+                       field |= TRB_CHAIN;
+-              } else {
+-                      /* FIXME - add check for ZERO_PACKET flag before this */
++              } else if (num_trbs == last_trb_num) {
+                       td->last_trb = ep_ring->enqueue;
+                       field |= TRB_IOC;
++              } else if (zero_length_needed && num_trbs == 1) {
++                      trb_buff_len = 0;
++                      urb_priv->td[1]->last_trb = ep_ring->enqueue;
++                      field |= TRB_IOC;
+               }
+               /* Only set interrupt on short packet for IN endpoints */
+@@ -3188,7 +3208,7 @@ static int queue_bulk_sg_tx(struct xhci_
+               if (running_total + trb_buff_len > urb->transfer_buffer_length)
+                       trb_buff_len =
+                               urb->transfer_buffer_length - running_total;
+-      } while (running_total < urb->transfer_buffer_length);
++      } while (num_trbs > 0);
+       check_trb_math(urb, num_trbs, running_total);
+       giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
+@@ -3206,7 +3226,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+       int num_trbs;
+       struct xhci_generic_trb *start_trb;
+       bool first_trb;
++      int last_trb_num;
+       bool more_trbs_coming;
++      bool zero_length_needed;
+       int start_cycle;
+       u32 field, length_field;
+@@ -3237,7 +3259,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               num_trbs++;
+               running_total += TRB_MAX_BUFF_SIZE;
+       }
+-      /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */
+       ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                       ep_index, urb->stream_id,
+@@ -3246,6 +3267,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               return ret;
+       urb_priv = urb->hcpriv;
++
++      /* Deal with URB_ZERO_PACKET - need one more td/trb */
++      zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
++              urb_priv->length == 2;
++      if (zero_length_needed) {
++              num_trbs++;
++              xhci_dbg(xhci, "Creating zero length td.\n");
++              ret = prepare_transfer(xhci, xhci->devs[slot_id],
++                              ep_index, urb->stream_id,
++                              1, urb, 1, mem_flags);
++              if (ret < 0)
++                      return ret;
++      }
++
+       td = urb_priv->td[0];
+       /*
+@@ -3267,7 +3302,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               trb_buff_len = urb->transfer_buffer_length;
+       first_trb = true;
+-
++      last_trb_num = zero_length_needed ? 2 : 1;
+       /* Queue the first TRB, even if it's zero-length */
+       do {
+               u32 remainder = 0;
+@@ -3284,12 +3319,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               /* Chain all the TRBs together; clear the chain bit in the last
+                * TRB to indicate it's the last TRB in the chain.
+                */
+-              if (num_trbs > 1) {
++              if (num_trbs > last_trb_num) {
+                       field |= TRB_CHAIN;
+-              } else {
+-                      /* FIXME - add check for ZERO_PACKET flag before this */
++              } else if (num_trbs == last_trb_num) {
+                       td->last_trb = ep_ring->enqueue;
+                       field |= TRB_IOC;
++              } else if (zero_length_needed && num_trbs == 1) {
++                      trb_buff_len = 0;
++                      urb_priv->td[1]->last_trb = ep_ring->enqueue;
++                      field |= TRB_IOC;
+               }
+               /* Only set interrupt on short packet for IN endpoints */
+@@ -3327,7 +3365,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               trb_buff_len = urb->transfer_buffer_length - running_total;
+               if (trb_buff_len > TRB_MAX_BUFF_SIZE)
+                       trb_buff_len = TRB_MAX_BUFF_SIZE;
+-      } while (running_total < urb->transfer_buffer_length);
++      } while (num_trbs > 0);
+       check_trb_math(urb, num_trbs, running_total);
+       giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1335,6 +1335,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+       if (usb_endpoint_xfer_isoc(&urb->ep->desc))
+               size = urb->number_of_packets;
++      else if (usb_endpoint_is_bulk_out(&urb->ep->desc) &&
++          urb->transfer_buffer_length > 0 &&
++          urb->transfer_flags & URB_ZERO_PACKET &&
++          !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc)))
++              size = 2;
+       else
+               size = 1;
diff --git a/queue-4.2/usb-xhci-clear-xhci_state_dying-on-start.patch b/queue-4.2/usb-xhci-clear-xhci_state_dying-on-start.patch
new file mode 100644 (file)
index 0000000..8c163f4
--- /dev/null
@@ -0,0 +1,33 @@
+From e5bfeab0ad515b4f6df39fe716603e9dc6d3dfd0 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 21 Sep 2015 17:46:13 +0300
+Subject: usb: xhci: Clear XHCI_STATE_DYING on start
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit e5bfeab0ad515b4f6df39fe716603e9dc6d3dfd0 upstream.
+
+For whatever reason if XHCI died in the previous instant
+then it will never recover on the next xhci_start unless we
+clear the DYING flag.
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -146,7 +146,8 @@ static int xhci_start(struct xhci_hcd *x
+                               "waited %u microseconds.\n",
+                               XHCI_MAX_HALT_USEC);
+       if (!ret)
+-              xhci->xhc_state &= ~XHCI_STATE_HALTED;
++              xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING);
++
+       return ret;
+ }
diff --git a/queue-4.2/usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch b/queue-4.2/usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch
new file mode 100644 (file)
index 0000000..3eb27fd
--- /dev/null
@@ -0,0 +1,87 @@
+From 448116bfa856d3c076fa7178ed96661a008a5d45 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 21 Sep 2015 17:46:15 +0300
+Subject: usb: xhci: exit early in xhci_setup_device() if we're halted or dying
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 448116bfa856d3c076fa7178ed96661a008a5d45 upstream.
+
+During quick plug/removal of OTG adapter during dual-role testing
+it can happen that xhci_alloc_device() is called for the newly
+detected device after the DRD library has called xhci_stop to
+remove the HCD.
+
+If that is the case, just fail early to prevent the following warning.
+
+[  154.732649] hub 4-0:1.0: USB hub found
+[  154.742204] hub 4-0:1.0: 1 port detected
+[  154.824458] hub 3-0:1.0: state 7 ports 1 chg 0002 evt 0000
+[  154.854609] hub 4-0:1.0: state 7 ports 1 chg 0000 evt 0000
+[  154.944430] usb 3-1: new high-speed USB device number 2 using xhci-hcd
+[  154.951009] xhci-hcd xhci-hcd.0.auto: xhci_setup_device
+[  155.038191] xhci-hcd xhci-hcd.0.auto: remove, state 4
+[  155.043315] usb usb4: USB disconnect, device number 1
+[  155.055270] xhci-hcd xhci-hcd.0.auto: xhci_stop
+[  155.060094] xhci-hcd xhci-hcd.0.auto: USB bus 4 deregistered
+[  155.066576] xhci-hcd xhci-hcd.0.auto: remove, state 1
+[  155.071710] usb usb3: USB disconnect, device number 1
+[  155.077124] xhci-hcd xhci-hcd.0.auto: xhci_setup_device
+[  155.082389] ------------[ cut here ]------------
+[  155.087690] WARNING: CPU: 0 PID: 72 at drivers/usb/host/xhci.c:3800 xhci_setup_device+0x410/0x484 [xhci_hcd]()
+[  155.097861] Modules linked in: sd_mod usb_storage scsi_mod usb_f_ss_lb g_zero libcomposite ipv6 xhci_plat_hcd xhci_hcd usbcore dwc3 udc_core evdev ti_am335x_adc joydev kfifo_buf industrialio snd_soc_simple_cc
+[  155.146734] CPU: 0 PID: 72 Comm: kworker/0:3 Tainted: G        W       4.1.4-00834-gcd9380b-dirty #50
+[  155.156073] Hardware name: Generic AM43 (Flattened Device Tree)
+[  155.162117] Workqueue: usb_hub_wq hub_event [usbcore]
+[  155.167249] Backtrace:
+[  155.169751] [<c0012af0>] (dump_backtrace) from [<c0012c8c>] (show_stack+0x18/0x1c)
+[  155.177390]  r6:c089d4a4 r5:ffffffff r4:00000000 r3:ee46c000
+[  155.183137] [<c0012c74>] (show_stack) from [<c05f7c14>] (dump_stack+0x84/0xd0)
+[  155.190446] [<c05f7b90>] (dump_stack) from [<c00439ac>] (warn_slowpath_common+0x80/0xbc)
+[  155.198605]  r7:00000009 r6:00000ed8 r5:bf27eb70 r4:00000000
+[  155.204348] [<c004392c>] (warn_slowpath_common) from [<c0043a0c>] (warn_slowpath_null+0x24/0x2c)
+[  155.213202]  r8:ee49f000 r7:ee7c0004 r6:00000000 r5:ee7c0158 r4:ee7c0000
+[  155.220051] [<c00439e8>] (warn_slowpath_null) from [<bf27eb70>] (xhci_setup_device+0x410/0x484 [xhci_hcd])
+[  155.229816] [<bf27e760>] (xhci_setup_device [xhci_hcd]) from [<bf27ec10>] (xhci_address_device+0x14/0x18 [xhci_hcd])
+[  155.240415]  r10:ee598200 r9:00000001 r8:00000002 r7:00000001 r6:00000003 r5:00000002
+[  155.248363]  r4:ee49f000
+[  155.250978] [<bf27ebfc>] (xhci_address_device [xhci_hcd]) from [<bf20cb94>] (hub_port_init+0x1b8/0xa9c [usbcore])
+[  155.261403] [<bf20c9dc>] (hub_port_init [usbcore]) from [<bf2101e0>] (hub_event+0x738/0x1020 [usbcore])
+[  155.270874]  r10:ee598200 r9:ee7c0000 r8:ee7c0038 r7:ee518800 r6:ee49f000 r5:00000001
+[  155.278822]  r4:00000000
+[  155.281426] [<bf20faa8>] (hub_event [usbcore]) from [<c005754c>] (process_one_work+0x128/0x340)
+[  155.290196]  r10:00000000 r9:00000003 r8:00000000 r7:fedfa000 r6:eeec5400 r5:ee598314
+[  155.298151]  r4:ee434380
+[  155.300718] [<c0057424>] (process_one_work) from [<c00578f8>] (worker_thread+0x158/0x49c)
+[  155.308963]  r10:ee434380 r9:00000003 r8:eeec5400 r7:00000008 r6:ee434398 r5:eeec5400
+[  155.316913]  r4:eeec5414
+[  155.319482] [<c00577a0>] (worker_thread) from [<c005cc40>] (kthread+0xdc/0xf8)
+[  155.326765]  r10:00000000 r9:00000000 r8:00000000 r7:c00577a0 r6:ee434380 r5:ee4441c0
+[  155.334713]  r4:00000000 r3:00000000
+[  155.338341] [<c005cb64>] (kthread) from [<c000fc08>] (ret_from_fork+0x14/0x2c)
+[  155.345626]  r7:00000000 r6:00000000 r5:c005cb64 r4:ee4441c0
+[  155.356108] ---[ end trace a58d34c223b190e6 ]---
+[  155.360783] xhci-hcd xhci-hcd.0.auto: Virt dev invalid for slot_id 0x1!
+[  155.574404] xhci-hcd xhci-hcd.0.auto: xhci_setup_device
+[  155.579667] ------------[ cut here ]------------
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -3783,6 +3783,9 @@ static int xhci_setup_device(struct usb_
+       mutex_lock(&xhci->mutex);
++      if (xhci->xhc_state)    /* dying or halted */
++              goto out;
++
+       if (!udev->slot_id) {
+               xhci_dbg_trace(xhci, trace_xhci_dbg_address,
+                               "Bad Slot ID %d", udev->slot_id);
diff --git a/queue-4.2/usb-xhci-lock-mutex-on-xhci_stop.patch b/queue-4.2/usb-xhci-lock-mutex-on-xhci_stop.patch
new file mode 100644 (file)
index 0000000..8ef412b
--- /dev/null
@@ -0,0 +1,41 @@
+From 85ac90f8953a58f6a057b727bc9db97721e3fb8e Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 21 Sep 2015 17:46:12 +0300
+Subject: usb: xhci: lock mutex on xhci_stop
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 85ac90f8953a58f6a057b727bc9db97721e3fb8e upstream.
+
+Else it races with xhci_setup_device
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -677,8 +677,11 @@ void xhci_stop(struct usb_hcd *hcd)
+       u32 temp;
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++      mutex_lock(&xhci->mutex);
++
+       if (!usb_hcd_is_primary_hcd(hcd)) {
+               xhci_only_stop_hcd(xhci->shared_hcd);
++              mutex_unlock(&xhci->mutex);
+               return;
+       }
+@@ -717,6 +720,7 @@ void xhci_stop(struct usb_hcd *hcd)
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "xhci_stop completed - status = %x",
+                       readl(&xhci->op_regs->status));
++      mutex_unlock(&xhci->mutex);
+ }
+ /*
diff --git a/queue-4.2/usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch b/queue-4.2/usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch
new file mode 100644 (file)
index 0000000..8a0d449
--- /dev/null
@@ -0,0 +1,63 @@
+From 8c24d6d7b09deee3036ddc4f2b81b53b28c8f877 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 21 Sep 2015 17:46:14 +0300
+Subject: usb: xhci: stop everything on the first call to xhci_stop
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 8c24d6d7b09deee3036ddc4f2b81b53b28c8f877 upstream.
+
+xhci_stop will be called twice, once for the shared hcd
+and again for the primary hcd.
+
+We stop the XHCI controller in any case so clean up
+everything on the first call else we can timeout
+waiting for pending requests to complete.
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |   20 +++++---------------
+ 1 file changed, 5 insertions(+), 15 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -655,15 +655,6 @@ int xhci_run(struct usb_hcd *hcd)
+ }
+ EXPORT_SYMBOL_GPL(xhci_run);
+-static void xhci_only_stop_hcd(struct usb_hcd *hcd)
+-{
+-      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+-
+-      spin_lock_irq(&xhci->lock);
+-      xhci_halt(xhci);
+-      spin_unlock_irq(&xhci->lock);
+-}
+-
+ /*
+  * Stop xHCI driver.
+  *
+@@ -678,15 +669,14 @@ void xhci_stop(struct usb_hcd *hcd)
+       u32 temp;
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+-      mutex_lock(&xhci->mutex);
+-
+-      if (!usb_hcd_is_primary_hcd(hcd)) {
+-              xhci_only_stop_hcd(xhci->shared_hcd);
+-              mutex_unlock(&xhci->mutex);
++      if (xhci->xhc_state & XHCI_STATE_HALTED)
+               return;
+-      }
++      mutex_lock(&xhci->mutex);
+       spin_lock_irq(&xhci->lock);
++      xhci->xhc_state |= XHCI_STATE_HALTED;
++      xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
++
+       /* Make sure the xHC is halted for a USB3 roothub
+        * (xhci_stop() could be called as part of failed init).
+        */
diff --git a/queue-4.2/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch b/queue-4.2/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch
new file mode 100644 (file)
index 0000000..c8283b5
--- /dev/null
@@ -0,0 +1,53 @@
+From dca7794539eff04b786fb6907186989e5eaaa9c2 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 21 Sep 2015 17:46:16 +0300
+Subject: xhci: change xhci 1.0 only restrictions to support xhci 1.1
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit dca7794539eff04b786fb6907186989e5eaaa9c2 upstream.
+
+Some changes between xhci 0.96 and xhci 1.0 specifications forced us to
+check the hci version in code, some of these checks were implemented as
+hci_version == 1.0, which will not work with new xhci 1.1 controllers.
+
+xhci 1.1 behaves similar to xhci 1.0 in these cases, so change these
+checks to hci_version >= 1.0
+
+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  |    6 +++---
+ drivers/usb/host/xhci-ring.c |    4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1498,10 +1498,10 @@ int xhci_endpoint_init(struct xhci_hcd *
+        * use Event Data TRBs, and we don't chain in a link TRB on short
+        * transfers, we're basically dividing by 1.
+        *
+-       * xHCI 1.0 specification indicates that the Average TRB Length should
+-       * be set to 8 for control endpoints.
++       * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
++       * should be set to 8 for control endpoints.
+        */
+-      if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
++      if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
+               ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
+       else
+               ep_ctx->tx_info |=
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -3394,8 +3394,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+       if (start_cycle == 0)
+               field |= 0x1;
+-      /* xHCI 1.0 6.4.1.2.1: Transfer Type field */
+-      if (xhci->hci_version == 0x100) {
++      /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
++      if (xhci->hci_version >= 0x100) {
+               if (urb->transfer_buffer_length > 0) {
+                       if (setup->bRequestType & USB_DIR_IN)
+                               field |= TRB_TX_TYPE(TRB_DATA_IN);
diff --git a/queue-4.2/xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch b/queue-4.2/xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch
new file mode 100644 (file)
index 0000000..c5d2bc8
--- /dev/null
@@ -0,0 +1,38 @@
+From a6809ffd1687b3a8c192960e69add559b9d32649 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 21 Sep 2015 17:46:10 +0300
+Subject: xhci: give command abortion one more chance before killing xhci
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit a6809ffd1687b3a8c192960e69add559b9d32649 upstream.
+
+We want to give the command abortion an additional try to stop
+the command ring before we completely hose xhci.
+
+Tested-by: Vincent Pelletier <plr.vincent@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -302,6 +302,15 @@ static int xhci_abort_cmd_ring(struct xh
+       ret = xhci_handshake(&xhci->op_regs->cmd_ring,
+                       CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
+       if (ret < 0) {
++              /* we are about to kill xhci, give it one more chance */
++              xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
++                            &xhci->op_regs->cmd_ring);
++              udelay(1000);
++              ret = xhci_handshake(&xhci->op_regs->cmd_ring,
++                                   CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
++              if (ret == 0)
++                      return 0;
++
+               xhci_err(xhci, "Stopped the command ring failed, "
+                               "maybe the host is dead\n");
+               xhci->xhc_state |= XHCI_STATE_DYING;
diff --git a/queue-4.2/xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch b/queue-4.2/xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch
new file mode 100644 (file)
index 0000000..4f57ef2
--- /dev/null
@@ -0,0 +1,58 @@
+From cc8e4fc0c3b5e8340bc8358990515d116a3c274c Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 21 Sep 2015 17:46:17 +0300
+Subject: xhci: init command timeout timer earlier to avoid deleting it uninitialized
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit cc8e4fc0c3b5e8340bc8358990515d116a3c274c upstream.
+
+Don't check if timer is running with a timer_pending() before
+deleting it with del_timer_sync(), this defies the whole point of
+the sync part and can cause a possible race.
+
+Instead we just want to make sure the timer is initialized early enough
+before we have a chance to delete it.
+
+Reported-by: Oliver Neukum <oneukum@suse.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 |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1792,8 +1792,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+       int size;
+       int i, j, num_ports;
+-      if (timer_pending(&xhci->cmd_timer))
+-              del_timer_sync(&xhci->cmd_timer);
++      del_timer_sync(&xhci->cmd_timer);
+       /* Free the Event Ring Segment Table and the actual Event Ring */
+       size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
+@@ -2321,6 +2320,10 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+       INIT_LIST_HEAD(&xhci->cmd_list);
++      /* init command timeout timer */
++      setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
++                  (unsigned long)xhci);
++
+       page_size = readl(&xhci->op_regs->page_size);
+       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+                       "Supported page size register = 0x%x", page_size);
+@@ -2505,10 +2508,6 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+                       "Wrote ERST address to ir_set 0.");
+       xhci_print_ir_set(xhci, 0);
+-      /* init command timeout timer */
+-      setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
+-                  (unsigned long)xhci);
+-
+       /*
+        * XXX: Might need to set the Interrupter Moderation Register to
+        * something other than the default (~1ms minimum between interrupts).
diff --git a/queue-4.2/xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch b/queue-4.2/xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch
new file mode 100644 (file)
index 0000000..7fcb85d
--- /dev/null
@@ -0,0 +1,127 @@
+From 2b7627b73e81e5d23d5ae1490fe8e690af86e053 Mon Sep 17 00:00:00 2001
+From: Tomer Barletz <barletz@gmail.com>
+Date: Mon, 21 Sep 2015 17:46:11 +0300
+Subject: xhci: Move xhci_pme_quirk() behind #ifdef CONFIG_PM
+
+From: Tomer Barletz <barletz@gmail.com>
+
+commit 2b7627b73e81e5d23d5ae1490fe8e690af86e053 upstream.
+
+xhci_pme_quirk() is only used when CONFIG_PM is defined.
+Compiling a kernel without PM complains about this function
+
+[reworded commit message -Mathias]
+Signed-off-by: Tomer Barletz <barletz@gmail.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c |   90 ++++++++++++++++++++++----------------------
+ 1 file changed, 45 insertions(+), 45 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -180,51 +180,6 @@ static void xhci_pci_quirks(struct devic
+                               "QUIRK: Resetting on resume");
+ }
+-/*
+- * In some Intel xHCI controllers, in order to get D3 working,
+- * through a vendor specific SSIC CONFIG register at offset 0x883c,
+- * SSIC PORT need to be marked as "unused" before putting xHCI
+- * into D3. After D3 exit, the SSIC port need to be marked as "used".
+- * Without this change, xHCI might not enter D3 state.
+- * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
+- * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
+- */
+-static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
+-{
+-      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+-      struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+-      u32 val;
+-      void __iomem *reg;
+-
+-      if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+-               pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+-
+-              reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
+-
+-              /* Notify SSIC that SSIC profile programming is not done */
+-              val = readl(reg) & ~PROG_DONE;
+-              writel(val, reg);
+-
+-              /* Mark SSIC port as unused(suspend) or used(resume) */
+-              val = readl(reg);
+-              if (suspend)
+-                      val |= SSIC_PORT_UNUSED;
+-              else
+-                      val &= ~SSIC_PORT_UNUSED;
+-              writel(val, reg);
+-
+-              /* Notify SSIC that SSIC profile programming is done */
+-              val = readl(reg) | PROG_DONE;
+-              writel(val, reg);
+-              readl(reg);
+-      }
+-
+-      reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+-      val = readl(reg);
+-      writel(val | BIT(28), reg);
+-      readl(reg);
+-}
+-
+ #ifdef CONFIG_ACPI
+ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
+ {
+@@ -345,6 +300,51 @@ static void xhci_pci_remove(struct pci_d
+ }
+ #ifdef CONFIG_PM
++/*
++ * In some Intel xHCI controllers, in order to get D3 working,
++ * through a vendor specific SSIC CONFIG register at offset 0x883c,
++ * SSIC PORT need to be marked as "unused" before putting xHCI
++ * into D3. After D3 exit, the SSIC port need to be marked as "used".
++ * Without this change, xHCI might not enter D3 state.
++ * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
++ * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
++ */
++static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
++{
++      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++      struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
++      u32 val;
++      void __iomem *reg;
++
++      if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
++               pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
++
++              reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
++
++              /* Notify SSIC that SSIC profile programming is not done */
++              val = readl(reg) & ~PROG_DONE;
++              writel(val, reg);
++
++              /* Mark SSIC port as unused(suspend) or used(resume) */
++              val = readl(reg);
++              if (suspend)
++                      val |= SSIC_PORT_UNUSED;
++              else
++                      val &= ~SSIC_PORT_UNUSED;
++              writel(val, reg);
++
++              /* Notify SSIC that SSIC profile programming is done */
++              val = readl(reg) | PROG_DONE;
++              writel(val, reg);
++              readl(reg);
++      }
++
++      reg = (void __iomem *) xhci->cap_regs + 0x80a4;
++      val = readl(reg);
++      writel(val | BIT(28), reg);
++      readl(reg);
++}
++
+ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);