From: Greg Kroah-Hartman Date: Sat, 17 Oct 2015 20:50:01 +0000 (-0700) Subject: 4.2-stable patches X-Git-Tag: v3.10.91~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8df200bbb047a926522a9b110e4d10c268f4bc31;p=thirdparty%2Fkernel%2Fstable-queue.git 4.2-stable patches 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 --- 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 index 00000000000..4f5bad9136b --- /dev/null +++ b/queue-4.2/drm-dp-mst-drop-cancel-work-sync-in-the-mstb-destroy-path-v2.patch @@ -0,0 +1,115 @@ +From 274d83524895fe41ca8debae4eec60ede7252bb5 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +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 + +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: [] flush_work+0x5/0x2e0 +[ +0.000007] +but task is already holding lock: +[ +0.000001] ((&mgr->work)){+.+.+.}, at: [] 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: [] process_one_work+0x1b4/0x710 +[ +0.000004] #1: ((&mgr->work)){+.+.+.}, at: [] 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] [] dump_stack+0x19/0x1b +[ +0.000004] [] __lock_acquire+0x115f/0x1250 +[ +0.000002] [] lock_acquire+0x99/0x1e0 +[ +0.000002] [] ? flush_work+0x5/0x2e0 +[ +0.000002] [] flush_work+0x4e/0x2e0 +[ +0.000002] [] ? flush_work+0x5/0x2e0 +[ +0.000004] [] ? native_sched_clock+0x35/0x80 +[ +0.000002] [] ? sched_clock+0x9/0x10 +[ +0.000002] [] ? local_clock+0x25/0x30 +[ +0.000002] [] ? mark_held_locks+0xb9/0x140 +[ +0.000003] [] ? __cancel_work_timer+0x95/0x160 +[ +0.000002] [] __cancel_work_timer+0xa8/0x160 +[ +0.000002] [] cancel_work_sync+0x10/0x20 +[ +0.000007] [] drm_dp_destroy_mst_branch_device+0x27/0x120 [drm_kms_helper] +[ +0.000006] [] drm_dp_mst_link_probe_work+0x78/0xa0 [drm_kms_helper] +[ +0.000002] [] process_one_work+0x220/0x710 +[ +0.000002] [] ? process_one_work+0x1b4/0x710 +[ +0.000005] [] worker_thread+0x11b/0x3a0 +[ +0.000003] [] ? process_one_work+0x710/0x710 +[ +0.000002] [] kthread+0xed/0x100 +[ +0.000003] [] ? insert_kthread_work+0x80/0x80 +[ +0.000003] [] ret_from_fork+0x58/0x90 + +v2: add flush_work. + +Reviewed-by: Daniel Vetter +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2b01d390957 --- /dev/null +++ b/queue-4.2/drm-dp-mst-fixup-handling-hotplug-on-port-removal.patch @@ -0,0 +1,121 @@ +From df4839fdc9b3c922586b945f062f38cbbda022bb Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Wed, 16 Sep 2015 10:37:28 +1000 +Subject: drm/dp/mst: fixup handling hotplug on port removal. + +From: Dave Airlie + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2d3b2a227ee --- /dev/null +++ b/queue-4.2/drm-radeon-restore-lcd-backlight-level-on-resume-r5xx.patch @@ -0,0 +1,51 @@ +From 4281f46ef839050d2ef60348f661eb463c21cc2e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michel=20D=C3=A4nzer?= +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?= + +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 +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.2/series b/queue-4.2/series index a7f6ffb50f2..234e717636a 100644 --- a/queue-4.2/series +++ b/queue-4.2/series @@ -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 index 00000000000..b0b1393f321 --- /dev/null +++ b/queue-4.2/usb-whiteheat-fix-potential-null-deref-at-probe.patch @@ -0,0 +1,81 @@ +From cbb4be652d374f64661137756b8f357a1827d6a4 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 23 Sep 2015 11:41:42 -0700 +Subject: USB: whiteheat: fix potential null-deref at probe + +From: Johan Hovold + +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 +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..287534062a2 --- /dev/null +++ b/queue-4.2/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch @@ -0,0 +1,195 @@ +From 4758dcd19a7d9ba9610b38fecb93f65f56f86346 Mon Sep 17 00:00:00 2001 +From: Reyad Attiyat +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 + +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 +Signed-off-by: Mathias Nyman +Cc: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8c163f4ec6c --- /dev/null +++ b/queue-4.2/usb-xhci-clear-xhci_state_dying-on-start.patch @@ -0,0 +1,33 @@ +From e5bfeab0ad515b4f6df39fe716603e9dc6d3dfd0 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +Date: Mon, 21 Sep 2015 17:46:13 +0300 +Subject: usb: xhci: Clear XHCI_STATE_DYING on start + +From: Roger Quadros + +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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..3eb27fd5b9c --- /dev/null +++ b/queue-4.2/usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch @@ -0,0 +1,87 @@ +From 448116bfa856d3c076fa7178ed96661a008a5d45 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +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 + +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] [] (dump_backtrace) from [] (show_stack+0x18/0x1c) +[ 155.177390] r6:c089d4a4 r5:ffffffff r4:00000000 r3:ee46c000 +[ 155.183137] [] (show_stack) from [] (dump_stack+0x84/0xd0) +[ 155.190446] [] (dump_stack) from [] (warn_slowpath_common+0x80/0xbc) +[ 155.198605] r7:00000009 r6:00000ed8 r5:bf27eb70 r4:00000000 +[ 155.204348] [] (warn_slowpath_common) from [] (warn_slowpath_null+0x24/0x2c) +[ 155.213202] r8:ee49f000 r7:ee7c0004 r6:00000000 r5:ee7c0158 r4:ee7c0000 +[ 155.220051] [] (warn_slowpath_null) from [] (xhci_setup_device+0x410/0x484 [xhci_hcd]) +[ 155.229816] [] (xhci_setup_device [xhci_hcd]) from [] (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] [] (xhci_address_device [xhci_hcd]) from [] (hub_port_init+0x1b8/0xa9c [usbcore]) +[ 155.261403] [] (hub_port_init [usbcore]) from [] (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] [] (hub_event [usbcore]) from [] (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] [] (process_one_work) from [] (worker_thread+0x158/0x49c) +[ 155.308963] r10:ee434380 r9:00000003 r8:eeec5400 r7:00000008 r6:ee434398 r5:eeec5400 +[ 155.316913] r4:eeec5414 +[ 155.319482] [] (worker_thread) from [] (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] [] (kthread) from [] (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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8ef412b061a --- /dev/null +++ b/queue-4.2/usb-xhci-lock-mutex-on-xhci_stop.patch @@ -0,0 +1,41 @@ +From 85ac90f8953a58f6a057b727bc9db97721e3fb8e Mon Sep 17 00:00:00 2001 +From: Roger Quadros +Date: Mon, 21 Sep 2015 17:46:12 +0300 +Subject: usb: xhci: lock mutex on xhci_stop + +From: Roger Quadros + +commit 85ac90f8953a58f6a057b727bc9db97721e3fb8e upstream. + +Else it races with xhci_setup_device + +Signed-off-by: Roger Quadros +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8a0d4492318 --- /dev/null +++ b/queue-4.2/usb-xhci-stop-everything-on-the-first-call-to-xhci_stop.patch @@ -0,0 +1,63 @@ +From 8c24d6d7b09deee3036ddc4f2b81b53b28c8f877 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +Date: Mon, 21 Sep 2015 17:46:14 +0300 +Subject: usb: xhci: stop everything on the first call to xhci_stop + +From: Roger Quadros + +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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c8283b5511f --- /dev/null +++ b/queue-4.2/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch @@ -0,0 +1,53 @@ +From dca7794539eff04b786fb6907186989e5eaaa9c2 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c5d2bc8146b --- /dev/null +++ b/queue-4.2/xhci-give-command-abortion-one-more-chance-before-killing-xhci.patch @@ -0,0 +1,38 @@ +From a6809ffd1687b3a8c192960e69add559b9d32649 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 21 Sep 2015 17:46:10 +0300 +Subject: xhci: give command abortion one more chance before killing xhci + +From: Mathias Nyman + +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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4f57ef210e9 --- /dev/null +++ b/queue-4.2/xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch @@ -0,0 +1,58 @@ +From cc8e4fc0c3b5e8340bc8358990515d116a3c274c Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 21 Sep 2015 17:46:17 +0300 +Subject: xhci: init command timeout timer earlier to avoid deleting it uninitialized + +From: Mathias Nyman + +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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7fcb85d1550 --- /dev/null +++ b/queue-4.2/xhci-move-xhci_pme_quirk-behind-ifdef-config_pm.patch @@ -0,0 +1,127 @@ +From 2b7627b73e81e5d23d5ae1490fe8e690af86e053 Mon Sep 17 00:00:00 2001 +From: Tomer Barletz +Date: Mon, 21 Sep 2015 17:46:11 +0300 +Subject: xhci: Move xhci_pme_quirk() behind #ifdef CONFIG_PM + +From: Tomer Barletz + +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 +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + 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);