Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 1d218bfc51bd68539b902155cd19a8f42c436768)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 2755a6222927b4514b9f31eecc12a8b336d4a24f)
@@ -329,25 +329,30 @@
 	uhci_transfer_batch_t *batch = NULL;
 
+	// Check for the roothub, as it does not schedule into lists
+	if (ep->device->speed == USB_SPEED_MAX) {
+		// FIXME: We shall check the roothub for active transfer. But
+		// as it is polling, there is no way to make it stop doing so.
+		// Return after rewriting uhci rh.
+		return;
+	}
+
+	transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type];
+	assert(list);
+
+	// To avoid ABBA deadlock, we need to take the list first
+	fibril_mutex_lock(&list->guard);
 	fibril_mutex_lock(&ep->guard);
 	if (ep->active_batch) {
 		batch = uhci_transfer_batch_get(ep->active_batch);
-
-		transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type];
-		assert(list);
-
-		fibril_mutex_lock(&list->guard);
+		endpoint_deactivate_locked(ep);
 		transfer_list_remove_batch(list, batch);
-		fibril_mutex_unlock(&list->guard);
-
+	}
+	fibril_mutex_unlock(&ep->guard);
+	fibril_mutex_unlock(&list->guard);
+
+	if (batch) {
+		// The HW could have been looking at the batch.
+		// Better wait two frames before we release the buffers.
 		endpoint_wait_timeout_locked(ep, 2000);
-
-		batch = uhci_transfer_batch_get(ep->active_batch);
-		if (ep->active_batch) {
-			endpoint_deactivate_locked(ep);
-		}
-	}
-	fibril_mutex_unlock(&ep->guard);
-
-	if (batch) {
 		batch->base.error = EINTR;
 		batch->base.transfered_size = 0;
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision 1d218bfc51bd68539b902155cd19a8f42c436768)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision 2755a6222927b4514b9f31eecc12a8b336d4a24f)
@@ -173,6 +173,11 @@
 
 		if (uhci_transfer_batch_check_completed(batch)) {
-			/* Save for processing */
+			/* Remove from schedule, save for processing */
+			fibril_mutex_lock(&batch->base.ep->guard);
+			assert(batch->base.ep->active_batch == &batch->base);
+			endpoint_deactivate_locked(batch->base.ep);
 			transfer_list_remove_batch(instance, batch);
+			fibril_mutex_unlock(&batch->base.ep->guard);
+
 			list_append(current, done);
 		}
@@ -212,4 +217,5 @@
 	assert(uhci_batch->qh);
 	assert(fibril_mutex_is_locked(&instance->guard));
+	assert(!list_empty(&instance->batch_list));
 
 	usb_log_debug2("Batch %p removing from queue %s.",
Index: uspace/drv/bus/usb/uhci/uhci_batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.c	(revision 1d218bfc51bd68539b902155cd19a8f42c436768)
+++ uspace/drv/bus/usb/uhci/uhci_batch.c	(revision 2755a6222927b4514b9f31eecc12a8b336d4a24f)
@@ -179,7 +179,5 @@
 
 			batch->ep->toggle = td_toggle(&uhci_batch->tds[i]);
-			if (i > 0)
-				goto substract_ret;
-			return true;
+			goto substract_ret;
 		}
 
@@ -190,10 +188,8 @@
 	}
 substract_ret:
-	if (batch->ep->transfer_type == USB_TRANSFER_CONTROL)
+	if (batch->transfered_size > 0 && batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
+		assert(batch->transfered_size >= USB_SETUP_PACKET_SIZE);
 		batch->transfered_size -= USB_SETUP_PACKET_SIZE;
-
-	fibril_mutex_lock(&batch->ep->guard);
-	endpoint_deactivate_locked(batch->ep);
-	fibril_mutex_unlock(&batch->ep->guard);
+	}
 
 	if (batch->dir == USB_DIRECTION_IN) {
