aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1a4ca02729c2..1cd56417cbec 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -113,12 +113,12 @@ int xhci_halt(struct xhci_hcd *xhci)
ret = xhci_handshake(&xhci->op_regs->status,
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
- if (!ret) {
- xhci->xhc_state |= XHCI_STATE_HALTED;
- xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
- } else
- xhci_warn(xhci, "Host not halted after %u microseconds.\n",
- XHCI_MAX_HALT_USEC);
+ if (ret) {
+ xhci_warn(xhci, "Host halt failed, %d\n", ret);
+ return ret;
+ }
+ xhci->xhc_state |= XHCI_STATE_HALTED;
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
return ret;
}
@@ -167,6 +167,12 @@ int xhci_reset(struct xhci_hcd *xhci)
int ret, i;
state = readl(&xhci->op_regs->status);
+
+ if (state == ~(u32)0) {
+ xhci_warn(xhci, "Host not accessible, reset failed.\n");
+ return -ENODEV;
+ }
+
if ((state & STS_HALT) == 0) {
xhci_warn(xhci, "Host controller not halted, aborting reset.\n");
return 0;
@@ -690,7 +696,6 @@ void xhci_stop(struct usb_hcd *hcd)
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
xhci_halt(xhci);
xhci_reset(xhci);
-
spin_unlock_irq(&xhci->lock);
}
@@ -1645,8 +1650,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
/* If the HC already knows the endpoint is disabled,
* or the HCD has noted it is disabled, ignore this request
*/
- if (((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) ==
- cpu_to_le32(EP_STATE_DISABLED)) ||
+ if ((GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) ||
le32_to_cpu(ctrl_ctx->drop_flags) &
xhci_get_endpoint_flag(&ep->desc)) {
/* Do not warn when called after a usb_device_reset */
@@ -3209,7 +3213,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
for (i = 0; i < num_eps; i++) {
ep_index = xhci_get_endpoint_index(&eps[i]->desc);
- max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&eps[i]->desc));
+ max_packet = usb_endpoint_maxp(&eps[i]->desc);
vdev->eps[ep_index].stream_info = xhci_alloc_stream_info(xhci,
num_stream_ctxs,
num_streams,
@@ -3683,27 +3687,26 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
int ret, slot_id;
struct xhci_command *command;
- command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+ command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
if (!command)
return 0;
/* xhci->slot_id and xhci->addr_dev are not thread-safe */
mutex_lock(&xhci->mutex);
spin_lock_irqsave(&xhci->lock, flags);
- command->completion = &xhci->addr_dev;
ret = xhci_queue_slot_control(xhci, command, TRB_ENABLE_SLOT, 0);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
mutex_unlock(&xhci->mutex);
xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
- kfree(command);
+ xhci_free_command(xhci, command);
return 0;
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
wait_for_completion(command->completion);
- slot_id = xhci->slot_id;
+ slot_id = command->slot_id;
mutex_unlock(&xhci->mutex);
if (!slot_id || command->status != COMP_SUCCESS) {
@@ -3711,7 +3714,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
xhci_err(xhci, "Max number of devices this xHCI host supports is %u.\n",
HCS_MAX_SLOTS(
readl(&xhci->cap_regs->hcs_params1)));
- kfree(command);
+ xhci_free_command(xhci, command);
return 0;
}
@@ -3747,7 +3750,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
#endif
- kfree(command);
+ xhci_free_command(xhci, command);
/* Is this a LS or FS device under a HS hub? */
/* Hub or peripherial? */
return 1;
@@ -3755,6 +3758,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
disable_slot:
/* Disable slot, if we can do it without mem alloc */
spin_lock_irqsave(&xhci->lock, flags);
+ kfree(command->completion);
command->completion = NULL;
command->status = 0;
if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
@@ -3816,14 +3820,13 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
}
}
- command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+ command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
if (!command) {
ret = -ENOMEM;
goto out;
}
command->in_ctx = virt_dev->in_ctx;
- command->completion = &xhci->addr_dev;
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx);
@@ -3941,7 +3944,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
out:
mutex_unlock(&xhci->mutex);
- kfree(command);
+ if (command) {
+ kfree(command->completion);
+ kfree(command);
+ }
return ret;
}