aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-12-03 12:44:31 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:55:27 -0500
commit06df572909080786e128eabdb2e39a12bce239de (patch)
treea00ea73a802b3a7d6f70f4cdc81b264a357913d3 /drivers/usb/host/xhci-ring.c
parent74f9fe21e0440066eb337b9f644238cb3050b91c (diff)
USB: xhci: Fix command completion after a drop endpoint.
The xHCI driver issues a Configure Endpoint command for two reasons: - a new configuration or alternate interface setting is selected - a quirky Fresco Logic prototype requires the command after a Reset Endpoint command. The xHCI driver only waits on the command in the first case. When a configure endpoint command completes, the driver needs to know why the command was generated. When the driver only supported selecting an initial configuration, the check was simple. Unfortunately that check doesn't work now that the driver supports alternate interfaces. If an endpoint must be dropped (because it's not in the new alternate setting) and no new endpoints are added, the math involving xhci_last_valid_endpoint() will assign -1 to an unsigned integer and cause an out-of-bounds array access. Move the check for the quirky hardware sooner and avoid the bad array access. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c36
1 files changed, 20 insertions, 16 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2e346334a363..ee7bc7ecbc59 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -903,28 +903,32 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
903 virt_dev->in_ctx); 903 virt_dev->in_ctx);
904 /* Input ctx add_flags are the endpoint index plus one */ 904 /* Input ctx add_flags are the endpoint index plus one */
905 ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1; 905 ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
906 ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; 906 /* A usb_set_interface() call directly after clearing a halted
907 if (!ep_ring) { 907 * condition may race on this quirky hardware.
908 /* This must have been an initial configure endpoint */ 908 * Not worth worrying about, since this is prototype hardware.
909 xhci->devs[slot_id]->cmd_status = 909 */
910 GET_COMP_CODE(event->status);
911 complete(&xhci->devs[slot_id]->cmd_completion);
912 break;
913 }
914 ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
915 xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
916 "state = %d\n", ep_index, ep_state);
917 if (xhci->quirks & XHCI_RESET_EP_QUIRK && 910 if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
918 ep_state & EP_HALTED) { 911 ep_index != (unsigned int) -1 &&
912 ctrl_ctx->add_flags - SLOT_FLAG ==
913 ctrl_ctx->drop_flags) {
914 ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
915 ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
916 if (!(ep_state & EP_HALTED))
917 goto bandwidth_change;
918 xhci_dbg(xhci, "Completed config ep cmd - "
919 "last ep index = %d, state = %d\n",
920 ep_index, ep_state);
919 /* Clear our internal halted state and restart ring */ 921 /* Clear our internal halted state and restart ring */
920 xhci->devs[slot_id]->eps[ep_index].ep_state &= 922 xhci->devs[slot_id]->eps[ep_index].ep_state &=
921 ~EP_HALTED; 923 ~EP_HALTED;
922 ring_ep_doorbell(xhci, slot_id, ep_index); 924 ring_ep_doorbell(xhci, slot_id, ep_index);
923 } else { 925 break;
924 xhci->devs[slot_id]->cmd_status =
925 GET_COMP_CODE(event->status);
926 complete(&xhci->devs[slot_id]->cmd_completion);
927 } 926 }
927bandwidth_change:
928 xhci_dbg(xhci, "Completed config ep cmd\n");
929 xhci->devs[slot_id]->cmd_status =
930 GET_COMP_CODE(event->status);
931 complete(&xhci->devs[slot_id]->cmd_completion);
928 break; 932 break;
929 case TRB_TYPE(TRB_EVAL_CONTEXT): 933 case TRB_TYPE(TRB_EVAL_CONTEXT):
930 virt_dev = xhci->devs[slot_id]; 934 virt_dev = xhci->devs[slot_id];