Index: uspace/drv/bus/usb/xhci/transfers.c
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.c	(revision 5fd9c308725be28e98aaeb91d9f3367e470de4f1)
+++ uspace/drv/bus/usb/xhci/transfers.c	(revision 2b6194515b4a1d9d4ac636869626fc887b61cc4f)
@@ -94,26 +94,22 @@
 }
 
-int xhci_init_transfers(xhci_hc_t *hc)
-{
-	assert(hc);
-
-	list_initialize(&hc->transfers);
-	return EOK;
-}
-
-void xhci_fini_transfers(xhci_hc_t *hc)
-{
-	// Note: Untested.
-	assert(hc);
-}
-
-xhci_transfer_t* xhci_transfer_create(endpoint_t* ep) {
-	xhci_transfer_t* transfer = calloc(1, sizeof(xhci_transfer_t));
-	if (!transfer)
-		return NULL;
+/**
+ * There can currently be only one active transfer, because
+ * usb_transfer_batch_init locks the endpoint by endpoint_use.
+ * Therefore, we store the only active transfer per endpoint there.
+ */
+xhci_transfer_t* xhci_transfer_create(endpoint_t* ep)
+{
+	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
+	xhci_transfer_t *transfer = &xhci_ep->active_transfer;
+
+	/* Do not access the transfer yet, it may be still in use. */
 
 	usb_transfer_batch_init(&transfer->batch, ep);
-
-	link_initialize(&transfer->link);
+	assert(ep->active);
+
+	/* Clean just our data. */
+	memset(((void *) transfer) + sizeof(usb_transfer_batch_t), 0,
+	    sizeof(xhci_transfer_t) - sizeof(usb_transfer_batch_t));
 
 	return transfer;
@@ -126,16 +122,9 @@
 	if (transfer->hc_buffer)
 		free32(transfer->hc_buffer);
-
-	free(transfer);
 }
 
 static xhci_trb_ring_t *get_ring(xhci_hc_t *hc, xhci_transfer_t *transfer)
 {
-	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
-	uint8_t slot_id = xhci_ep->device->slot_id;
-
-	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
-	assert(ring);
-	return ring;
+	return &xhci_endpoint_get(transfer->batch.ep)->ring;
 }
 
@@ -202,5 +191,5 @@
 	// Issue a Configure Endpoint command, if needed.
 	if (configure_endpoint_needed(setup)) {
-		const int err = xhci_device_configure(xhci_ep->device, hc);
+		const int err = xhci_device_configure(xhci_ep_to_dev(xhci_ep), hc);
 		if (err)
 			return err;
@@ -226,7 +215,5 @@
 	TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
 
-	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
-	uint8_t slot_id = xhci_ep->device->slot_id;
-	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
+	xhci_trb_ring_t* ring = get_ring(hc, transfer);
 
 	return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
@@ -249,7 +236,5 @@
 	TRB_CTRL_SET_TRB_TYPE(trb, XHCI_TRB_TYPE_NORMAL);
 
-	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(transfer->batch.ep);
-	uint8_t slot_id = xhci_ep->device->slot_id;
-	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[transfer->batch.ep->target.endpoint];
+	xhci_trb_ring_t* ring = get_ring(hc, transfer);
 
 	return xhci_trb_ring_enqueue(ring, &trb, &transfer->interrupt_trb_phys);
@@ -266,22 +251,25 @@
 {
 	uintptr_t addr = trb->parameter;
-	xhci_transfer_t *transfer = NULL;
-
-	link_t *transfer_link = list_first(&hc->transfers);
-	while (transfer_link) {
-		transfer = list_get_instance(transfer_link, xhci_transfer_t, link);
-
-		if (transfer->interrupt_trb_phys == addr)
-			break;
-
-		transfer_link = list_next(transfer_link, &hc->transfers);
-	}
-
-	if (!transfer_link) {
-		usb_log_warning("Transfer not found.");
+	const unsigned slot_id = XHCI_DWORD_EXTRACT(trb->control, 31, 24);
+	const unsigned ep_dci = XHCI_DWORD_EXTRACT(trb->control, 20, 16);
+
+	xhci_device_t *dev = hc->bus.devices_by_slot[slot_id];
+	if (!dev) {
+		usb_log_error("Transfer event on unknown device slot %u!", slot_id);
 		return ENOENT;
 	}
 
-	list_remove(transfer_link);
+	const usb_endpoint_t ep_num = ep_dci / 2;
+	xhci_endpoint_t *ep = xhci_device_get_endpoint(dev, ep_num);
+	if (!ep) {
+		usb_log_error("Transfer event on unknown endpoint num %u, device slot %u!", ep_num, slot_id);
+		return ENOENT;
+	}
+
+	xhci_transfer_t *transfer = &ep->active_transfer;
+
+	/** FIXME: This is racy. Do we care? */
+	ep->ring.dequeue = addr;
+
 	usb_transfer_batch_t *batch = &transfer->batch;
 
@@ -314,8 +302,5 @@
 	xhci_transfer_t *transfer = xhci_transfer_from_batch(batch);
 	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
-	uint8_t slot_id = xhci_ep->device->slot_id;
-
 	assert(xhci_ep);
-	assert(slot_id);
 
 	const usb_transfer_type_t type = batch->ep->transfer_type;
@@ -336,6 +321,5 @@
 		return err;
 
-	list_append(&transfer->link, &hc->transfers);
-
+	const uint8_t slot_id = xhci_ep_to_dev(xhci_ep)->slot_id;
 	const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
 	return hc_ring_doorbell(hc, slot_id, target);
