return 0;
 }
 
-static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
-       struct xhci_transfer_event *event, struct xhci_virt_ep *ep)
+static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+                    struct xhci_ring *ep_ring, struct xhci_td *td,
+                    u32 trb_comp_code)
 {
        struct xhci_ep_ctx *ep_ctx;
-       struct xhci_ring *ep_ring;
-       u32 trb_comp_code;
 
-       ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
        ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
-       trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
 
        switch (trb_comp_code) {
        case COMP_STOPPED_LENGTH_INVALID:
 /*
  * Process control tds, update urb status and actual_length.
  */
-static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
-       union xhci_trb *ep_trb, struct xhci_transfer_event *event,
-       struct xhci_virt_ep *ep)
+static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+               struct xhci_ring *ep_ring,  struct xhci_td *td,
+                          union xhci_trb *ep_trb, struct xhci_transfer_event *event)
 {
        struct xhci_ep_ctx *ep_ctx;
        u32 trb_comp_code;
                td->urb->actual_length = requested;
 
 finish_td:
-       return finish_td(xhci, td, event, ep);
+       return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
 }
 
 /*
  * Process isochronous tds, update urb packet status and actual_length.
  */
-static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
-       union xhci_trb *ep_trb, struct xhci_transfer_event *event,
-       struct xhci_virt_ep *ep)
+static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+               struct xhci_ring *ep_ring, struct xhci_td *td,
+               union xhci_trb *ep_trb, struct xhci_transfer_event *event)
 {
        struct urb_priv *urb_priv;
        int idx;
 
        td->urb->actual_length += frame->actual_length;
 
-       return finish_td(xhci, td, event, ep);
+       return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
 }
 
 static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
 /*
  * Process bulk and interrupt tds, update urb status and actual_length.
  */
-static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
-       union xhci_trb *ep_trb, struct xhci_transfer_event *event,
-       struct xhci_virt_ep *ep)
+static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+               struct xhci_ring *ep_ring, struct xhci_td *td,
+               union xhci_trb *ep_trb, struct xhci_transfer_event *event)
 {
        struct xhci_slot_ctx *slot_ctx;
-       struct xhci_ring *ep_ring;
        u32 trb_comp_code;
        u32 remaining, requested, ep_trb_len;
 
        slot_ctx = xhci_get_slot_ctx(xhci, ep->vdev->out_ctx);
-       ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
        trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
        remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
        ep_trb_len = TRB_LEN(le32_to_cpu(ep_trb->generic.field[2]));
                          remaining);
                td->urb->actual_length = 0;
        }
-       return finish_td(xhci, td, event, ep);
+
+       return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
 }
 
 /*
 
                /* update the urb's actual_length and give back to the core */
                if (usb_endpoint_xfer_control(&td->urb->ep->desc))
-                       process_ctrl_td(xhci, td, ep_trb, event, ep);
+                       process_ctrl_td(xhci, ep, ep_ring, td, ep_trb, event);
                else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc))
-                       process_isoc_td(xhci, td, ep_trb, event, ep);
+                       process_isoc_td(xhci, ep, ep_ring, td, ep_trb, event);
                else
-                       process_bulk_intr_td(xhci, td, ep_trb, event, ep);
+                       process_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event);
 cleanup:
                handling_skipped_tds = ep->skip &&
                        trb_comp_code != COMP_MISSED_SERVICE_ERROR &&