ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
+static struct xhci_virt_ep *xhci_get_virt_ep(struct xhci_hcd *xhci,
+ unsigned int slot_id,
+ unsigned int ep_index)
+{
+ if (slot_id == 0 || slot_id >= MAX_HC_SLOTS) {
+ xhci_warn(xhci, "Invalid slot_id %u\n", slot_id);
+ return NULL;
+ }
+ if (ep_index >= EP_CTX_PER_DEV) {
+ xhci_warn(xhci, "Invalid endpoint index %u\n", ep_index);
+ return NULL;
+ }
+ if (!xhci->devs[slot_id]) {
+ xhci_warn(xhci, "No xhci virt device for slot_id %u\n", slot_id);
+ return NULL;
+ }
+
+ return &xhci->devs[slot_id]->eps[ep_index];
+}
+
/* Get the right ring for the given slot_id, ep_index and stream_id.
* If the endpoint supports streams, boundary check the URB's stream ID.
* If the endpoint doesn't support streams, return the singular endpoint ring.
{
struct xhci_virt_ep *ep;
- ep = &xhci->devs[slot_id]->eps[ep_index];
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep)
+ return NULL;
+
/* Common case: no streams */
if (!(ep->ep_state & EP_HAS_STREAMS))
return ep->ring;
memset(&deq_state, 0, sizeof(deq_state));
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
- vdev = xhci->devs[slot_id];
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep)
+ return;
+
+ vdev = ep->vdev;
ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
trace_xhci_handle_cmd_stop_ep(ep_ctx);
- ep = &xhci->devs[slot_id]->eps[ep_index];
last_unlinked_td = list_last_entry(&ep->cancelled_td_list,
struct xhci_td, cancelled_td_list);
unsigned int ep_index;
unsigned int stream_id;
struct xhci_ring *ep_ring;
- struct xhci_virt_device *dev;
struct xhci_virt_ep *ep;
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
- dev = xhci->devs[slot_id];
- ep = &dev->eps[ep_index];
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep)
+ return;
- ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
+ ep_ring = xhci_stream_id_to_ring(ep->vdev, ep_index, stream_id);
if (!ep_ring) {
xhci_warn(xhci, "WARN Set TR deq ptr command for freed stream ID %u\n",
stream_id);
goto cleanup;
}
- ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
- slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
+ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep_index);
+ slot_ctx = xhci_get_slot_ctx(xhci, ep->vdev->out_ctx);
trace_xhci_handle_cmd_set_deq(slot_ctx);
trace_xhci_handle_cmd_set_deq_ep(ep_ctx);
/* Update the ring's dequeue segment and dequeue pointer
* to reflect the new position.
*/
- update_ring_for_set_deq_completion(xhci, dev,
+ update_ring_for_set_deq_completion(xhci, ep->vdev,
ep_ring, ep_index);
} else {
xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n");
}
cleanup:
- dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
- dev->eps[ep_index].queued_deq_seg = NULL;
- dev->eps[ep_index].queued_deq_ptr = NULL;
+ ep->ep_state &= ~SET_DEQ_PENDING;
+ ep->queued_deq_seg = NULL;
+ ep->queued_deq_ptr = NULL;
/* Restart any rings with pending URBs */
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
union xhci_trb *trb, u32 cmd_comp_code)
{
- struct xhci_virt_device *vdev;
+ struct xhci_virt_ep *ep;
struct xhci_ep_ctx *ep_ctx;
unsigned int ep_index;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
- vdev = xhci->devs[slot_id];
- ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep)
+ return;
+
+ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep_index);
trace_xhci_handle_cmd_reset_ep(ep_ctx);
/* This command will only fail if the endpoint wasn't halted,
xhci_ring_cmd_db(xhci);
} else {
/* Clear our internal halted state */
- xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
+ ep->ep_state &= ~EP_HALTED;
}
/* if this was a soft reset, then restart */
static int handle_tx_event(struct xhci_hcd *xhci,
struct xhci_transfer_event *event)
{
- struct xhci_virt_device *xdev;
struct xhci_virt_ep *ep;
struct xhci_ring *ep_ring;
unsigned int slot_id;
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
ep_trb_dma = le64_to_cpu(event->buffer);
- xdev = xhci->devs[slot_id];
- if (!xdev) {
- xhci_err(xhci, "ERROR Transfer event pointed to bad slot %u\n",
- slot_id);
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep) {
+ xhci_err(xhci, "ERROR Invalid Transfer event\n");
goto err_out;
}
- ep = &xdev->eps[ep_index];
ep_ring = xhci_dma_to_transfer_ring(ep, ep_trb_dma);
- ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+ ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep_index);
if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {
xhci_err(xhci,