Index: uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
+++ uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision 2f762a7c6e72f686c37eb21ceb35942d89b918e5)
@@ -70,14 +70,15 @@
 	} setup;
 
-	/** DMA buffer with enforced policy */
-	dma_buffer_t dma_buffer;
+	/**
+	 * In case a bounce buffer is allocated, the original buffer must to be
+	 * stored to be filled after the IN transaction is finished.
+	 */
+	char *buffer;
 	/** Size of memory buffer */
 	size_t buffer_size;
 
-	/**
-	 * In case the DMA buffer is allocated, the original buffer must to be
-	 * stored to be filled after the IN transaction is finished.
-	 */
-	char *original_buffer;
+	/** DMA buffer with enforced policy */
+	dma_buffer_t dma_buffer;
+	bool is_bounced;
 
 	/** Indicates success/failure of the communication */
@@ -114,4 +115,5 @@
 void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
 
+errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *);
 /** Buffer preparation */
 errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *, char *);
Index: uspace/lib/usbhost/src/usb_transfer_batch.c
===================================================================
--- uspace/lib/usbhost/src/usb_transfer_batch.c	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
+++ uspace/lib/usbhost/src/usb_transfer_batch.c	(revision 2f762a7c6e72f686c37eb21ceb35942d89b918e5)
@@ -103,4 +103,28 @@
 }
 
+errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *batch)
+{
+	assert(batch);
+	assert(!batch->is_bounced);
+
+	if (dma_buffer_is_set(&batch->dma_buffer))
+		dma_buffer_unlock(&batch->dma_buffer, batch->buffer_size);
+
+	usb_log_debug("Batch(%p): Buffer cannot be used directly, "
+	    "falling back to bounce buffer!", batch);
+
+	const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
+	    batch->buffer_size, batch->ep->transfer_buffer_policy);
+	if (err)
+		return err;
+
+	/* Copy the data out */
+	if (batch->dir == USB_DIRECTION_OUT)
+		memcpy(batch->dma_buffer.virt, batch->buffer, batch->buffer_size);
+
+	batch->is_bounced = true;
+	return err;
+}
+
 /**
  * Prepare a DMA buffer according to endpoint policy.
@@ -109,35 +133,23 @@
  * buffer is created.
  */
-errno_t usb_transfer_batch_prepare_buffer(
-    usb_transfer_batch_t *batch, char *buf)
+errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *batch, char *buf)
 {
-	const dma_policy_t policy = batch->ep->transfer_buffer_policy;
-
 	/* Empty transfers do not need a buffer */
 	if (batch->buffer_size == 0)
 		return EOK;
 
-	if (dma_buffer_check_policy(buf, batch->buffer_size, policy)) {
-		/* Mark this case with invalid address */
-		batch->original_buffer = NULL;
+	batch->buffer = buf;
 
-		/* Fill the buffer with virtual address and lock it for DMA */
-		return dma_buffer_lock(&batch->dma_buffer, buf, batch->buffer_size);
-	}
-	else {
-		usb_log_debug("Batch(%p): Buffer cannot be used directly, "
-		    "falling back to bounce buffer!", batch);
-		const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
-		    batch->buffer_size, policy);
+	const dma_policy_t policy = batch->ep->transfer_buffer_policy;
 
-		/* Copy the data out */
-		if (!err && batch->dir == USB_DIRECTION_OUT)
-			memcpy(batch->dma_buffer.virt, buf, batch->buffer_size);
+	/*
+	 * We don't have enough information (yet, WIP) to know if we can skip
+	 * the bounce, so check the conditions carefully.
+	 */
+	if (!dma_buffer_check_policy(buf, batch->buffer_size, policy))
+		return usb_transfer_batch_bounce(batch);
 
-		/* Store the buffer to store the data back before finishing */
-		batch->original_buffer = buf;
-
-		return err;
-	}
+	/* Fill the buffer with virtual address and lock it for DMA */
+	return dma_buffer_lock(&batch->dma_buffer, buf, batch->buffer_size);
 }
 
@@ -156,5 +168,5 @@
 
 	if (batch->error == EOK && batch->buffer_size > 0) {
-		if (batch->original_buffer == NULL) {
+		if (!batch->is_bounced) {
 			/* Unlock the buffer for DMA */
 			dma_buffer_unlock(&batch->dma_buffer,
@@ -164,5 +176,5 @@
 			/* We we're forced to use bounce buffer, copy it back */
 			if (batch->dir == USB_DIRECTION_IN)
-				memcpy(batch->original_buffer,
+				memcpy(batch->buffer,
 				    batch->dma_buffer.virt,
 				    batch->transferred_size);
