Index: .bzrignore
===================================================================
--- .bzrignore	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ .bzrignore	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -53,4 +53,5 @@
 ./uspace/app/klog/klog
 ./uspace/app/lsusb/lsusb
+./uspace/app/mkbd/mkbd
 ./uspace/app/mkfat/mkfat
 ./uspace/app/netstart/netstart
Index: uspace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/batch.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -44,12 +44,26 @@
 #include "hw_struct/transfer_descriptor.h"
 
+/** OHCI specific data required for USB transfer */
 typedef struct ohci_transfer_batch {
+	/** Endpoint descriptor of the target endpoint. */
 	ed_t *ed;
+	/** List of TDs needed for the transfer */
 	td_t **tds;
+	/** Number of TDs used by the transfer */
 	size_t td_count;
+	/** Dummy TD to be left at the ED and used by the next transfer */
 	size_t leave_td;
-	char *device_buffer;
+	/** Data buffer, must be accessible byb the OHCI hw. */
+	void *device_buffer;
 } ohci_transfer_batch_t;
-
+/*----------------------------------------------------------------------------*/
+static void batch_control(usb_transfer_batch_t *instance,
+    usb_direction_t data_dir, usb_direction_t status_dir);
+static void batch_data(usb_transfer_batch_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Safely destructs ohci_transfer_batch_t structure
+ *
+ * @param[in] ohci_batch Instance to destroy.
+ */
 static void ohci_transfer_batch_dispose(void *ohci_batch)
 {
@@ -69,8 +83,20 @@
 }
 /*----------------------------------------------------------------------------*/
-static void batch_control(usb_transfer_batch_t *instance,
-    usb_direction_t data_dir, usb_direction_t status_dir);
-static void batch_data(usb_transfer_batch_t *instance);
-/*----------------------------------------------------------------------------*/
+/** Allocate memory initialize internal structures
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] ep Communication target
+ * @param[in] buffer Data source/destination.
+ * @param[in] buffer_size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Allocates and initializes structures needed by the OHCI hw for the transfer.
+ */
 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
@@ -107,9 +133,10 @@
 	}
 
-	/* we need one extra place for td that is currently assigned to hcd_ep*/
+	/* We need an extra place for TD that is currently assigned to hcd_ep*/
 	data->tds = calloc(sizeof(td_t*), data->td_count + 1);
 	CHECK_NULL_DISPOSE_RETURN(data->tds,
 	    "Failed to allocate transfer descriptors.\n");
 
+	/* Add TD left over by the previous transfer */
 	data->tds[0] = hcd_ep->td;
 	data->leave_td = 0;
@@ -123,4 +150,8 @@
 	data->ed = hcd_ep->ed;
 
+	/* NOTE: OHCI is capable of handling buffer that crosses page boundaries
+	 * it is, however, not capable of handling buffer that occupies more
+	 * than two pages (the first page is computed using start pointer, the
+	 * other using the end pointer) */
         if (setup_size + buffer_size > 0) {
 		data->device_buffer = malloc32(setup_size + buffer_size);
@@ -135,4 +166,13 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Check batch TDs' status.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ *
+ * Walk all TDs (usually there is just one). Stop with false if there is an
+ * active TD. Stop with true if an error is found. Return true if the walk
+ * completes with the last TD.
+ */
 bool batch_is_complete(usb_transfer_batch_t *instance)
 {
@@ -140,7 +180,6 @@
 	ohci_transfer_batch_t *data = instance->private_data;
 	assert(data);
-	size_t tds = data->td_count;
 	usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
-	    instance, tds);
+	    instance, data->td_count);
 	usb_log_debug("ED: %x:%x:%x:%x.\n",
 	    data->ed->status, data->ed->td_head, data->ed->td_tail,
@@ -148,5 +187,5 @@
 	size_t i = 0;
 	instance->transfered_size = instance->buffer_size;
-	for (; i < tds; ++i) {
+	for (; i < data->td_count; ++i) {
 		assert(data->tds[i] != NULL);
 		usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
@@ -173,10 +212,11 @@
 	assert(hcd_ep);
 	hcd_ep->td = data->tds[i];
-	if (i > 0)
-		instance->transfered_size -= td_remain_size(data->tds[i - 1]);
+	assert(i > 0);
+	for (--i;i < data->td_count; ++i)
+		instance->transfered_size -= td_remain_size(data->tds[i]);
 
 	/* Clear possible ED HALT */
 	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
-	uint32_t pa = addr_to_phys(hcd_ep->td);
+	const uint32_t pa = addr_to_phys(hcd_ep->td);
 	assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
 	assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
@@ -185,4 +225,8 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Starts execution of the TD list
+ *
+ * @param[in] instance Batch structure to use
+ */
 void batch_commit(usb_transfer_batch_t *instance)
 {
@@ -193,4 +237,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction OUT(data stage) and
+ * IN(status stage).
+ */
 void batch_control_write(usb_transfer_batch_t *instance)
 {
@@ -203,4 +254,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepares control read transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction IN(data stage) and
+ * OUT(status stage).
+ */
 void batch_control_read(usb_transfer_batch_t *instance)
 {
@@ -211,4 +269,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
 void batch_interrupt_in(usb_transfer_batch_t *instance)
 {
@@ -219,4 +283,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
 void batch_interrupt_out(usb_transfer_batch_t *instance)
 {
@@ -229,4 +299,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
 void batch_bulk_in(usb_transfer_batch_t *instance)
 {
@@ -237,4 +313,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
 void batch_bulk_out(usb_transfer_batch_t *instance)
 {
@@ -247,12 +329,14 @@
 }
 /*----------------------------------------------------------------------------*/
-ed_t * batch_ed(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	ohci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	return data->ed;
-}
-/*----------------------------------------------------------------------------*/
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_dir Direction to use for data stage.
+ * @param[in] status_dir Direction to use for status stage.
+ *
+ * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
+ * Data stage with alternating toggle and direction supplied by parameter.
+ * Status stage with toggle 1 and direction supplied by parameter.
+ */
 void batch_control(usb_transfer_batch_t *instance,
     usb_direction_t data_dir, usb_direction_t status_dir)
@@ -303,4 +387,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Direction is supplied by the associated ep and toggle is maintained by the
+ * OHCI hw in ED.
+ */
 void batch_data(usb_transfer_batch_t *instance)
 {
Index: uspace/drv/ohci/batch.h
===================================================================
--- uspace/drv/ohci/batch.h	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/batch.h	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -41,6 +41,4 @@
 #include <usb/host/batch.h>
 
-#include "hw_struct/endpoint_descriptor.h"
-
 usb_transfer_batch_t * batch_get(
     ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
@@ -65,6 +63,4 @@
 
 void batch_bulk_out(usb_transfer_batch_t *instance);
-
-ed_t * batch_ed(usb_transfer_batch_t *instance);
 #endif
 /**
Index: uspace/drv/ohci/endpoint_list.c
===================================================================
--- uspace/drv/ohci/endpoint_list.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/endpoint_list.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -34,4 +34,5 @@
 #include <errno.h>
 #include <usb/debug.h>
+#include <arch/barrier.h>
 
 #include "endpoint_list.h"
@@ -43,5 +44,5 @@
  * @return Error code
  *
- * Allocates memory for internal qh_t structure.
+ * Allocates memory for internal ed_t structure.
  */
 int endpoint_list_init(endpoint_list_t *instance, const char *name)
@@ -68,7 +69,6 @@
  * @param[in] instance List to lead.
  * @param[in] next List to append.
- * @return Error code
  *
- * Does not check whether this replaces an existing list .
+ * Does not check whether this replaces an existing list.
  */
 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
@@ -79,9 +79,8 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Submit transfer endpoint to the list and queue.
+/** Add endpoint to the list and queue.
  *
  * @param[in] instance List to use.
- * @param[in] endpoint Transfer endpoint to submit.
- * @return Error code
+ * @param[in] endpoint Endpoint to add.
  *
  * The endpoint is added to the end of the list and queue.
@@ -99,19 +98,24 @@
 	/* Add to the hardware queue. */
 	if (list_empty(&instance->endpoint_list)) {
-		/* There is nothing scheduled */
+		/* There are no active EDs */
 		last_ed = instance->list_head;
 	} else {
-		/* There is something scheduled */
+		/* There are active EDs, get the last one */
 		hcd_endpoint_t *last = list_get_instance(
 		    instance->endpoint_list.prev, hcd_endpoint_t, link);
+		assert(last);
 		last_ed = last->ed;
 	}
-	/* keep link */
+	/* Keep link */
 	hcd_ep->ed->next = last_ed->next;
+	/* Make sure ED is written to the memory */
+	write_barrier();
+
+	/* Add ed to the hw queue */
 	ed_append_ed(last_ed, hcd_ep->ed);
+	/* Make sure ED is updated */
+	write_barrier();
 
-	asm volatile ("": : :"memory");
-
-	/* Add to the driver list */
+	/* Add to the sw list */
 	list_append(&hcd_ep->link, &instance->endpoint_list);
 
@@ -129,59 +133,8 @@
 }
 /*----------------------------------------------------------------------------*/
-#if 0
-/** Create list for finished endpoints.
+/** Remove endpoint from the list and queue.
  *
  * @param[in] instance List to use.
- * @param[in] done list to fill
- */
-void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done)
-{
-	assert(instance);
-	assert(done);
-
-	fibril_mutex_lock(&instance->guard);
-	usb_log_debug2("Checking list %s for completed endpointes(%d).\n",
-	    instance->name, list_count(&instance->endpoint_list));
-	link_t *current = instance->endpoint_list.next;
-	while (current != &instance->endpoint_list) {
-		link_t *next = current->next;
-		hcd_endpoint_t *endpoint =
-		    list_get_instance(current, hcd_endpoint_t, link);
-
-		if (endpoint_is_complete(endpoint)) {
-			/* Save for post-processing */
-			endpoint_list_remove_endpoint(instance, endpoint);
-			list_append(current, done);
-		}
-		current = next;
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Walk the list and abort all endpointes.
- *
- * @param[in] instance List to use.
- */
-void endpoint_list_abort_all(endpoint_list_t *instance)
-{
-	fibril_mutex_lock(&instance->guard);
-	while (!list_empty(&instance->endpoint_list)) {
-		link_t *current = instance->endpoint_list.next;
-		hcd_endpoint_t *endpoint =
-		    list_get_instance(current, hcd_endpoint_t, link);
-		endpoint_list_remove_endpoint(instance, endpoint);
-		hcd_endpoint_finish_error(endpoint, EIO);
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-#endif
-/*----------------------------------------------------------------------------*/
-/** Remove a transfer endpoint from the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] endpoint Transfer endpoint to remove.
- * @return Error code
- *
- * Does not lock the transfer list, caller is responsible for that.
+ * @param[in] endpoint Endpoint to remove.
  */
 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
@@ -212,6 +165,7 @@
 	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
 	prev_ed->next = hcd_ep->ed->next;
+	/* Make sure ED is updated */
+	write_barrier();
 
-	asm volatile ("": : :"memory");
 	usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
 	    hcd_ep, qpos, instance->name, hcd_ep->ed->next);
Index: uspace/drv/ohci/endpoint_list.h
===================================================================
--- uspace/drv/ohci/endpoint_list.h	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/endpoint_list.h	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -41,9 +41,16 @@
 #include "utils/malloc32.h"
 
-typedef struct endpoint_list {
+/** Structure maintains both OHCI queue and software list of active endpoints.*/
+typedef struct endpoint_list
+{
+	/** Guard against add/remove races */
 	fibril_mutex_t guard;
+	/** OHCI hw structure at the beginning of the queue */
 	ed_t *list_head;
+	/** Physical address of the first(dummy) ED */
 	uint32_t list_head_pa;
+	/** Assigned name, provides nicer debug output */
 	const char *name;
+	/** Sw list of all active EDs */
 	link_t endpoint_list;
 } endpoint_list_t;
@@ -53,5 +60,5 @@
  * @param[in] instance Memory place to use.
  *
- * Frees memory for internal qh_t structure.
+ * Frees memory of the internal ed_t structure.
  */
 static inline void endpoint_list_fini(endpoint_list_t *instance)
@@ -68,9 +75,4 @@
 
 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
-#if 0
-void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done);
-
-void endpoint_list_abort_all(endpoint_list_t *instance);
-#endif
 #endif
 /**
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/hc.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -293,5 +293,4 @@
 		rh_interrupt(&instance->rh);
 
-
 	if (status & I_WDH) {
 		fibril_mutex_lock(&instance->guard);
@@ -316,4 +315,9 @@
 		fibril_mutex_unlock(&instance->guard);
 	}
+
+	if (status & I_UE) {
+		hc_start_hw(instance);
+	}
+
 }
 /*----------------------------------------------------------------------------*/
@@ -450,5 +454,4 @@
 {
 	assert(instance);
-
 #define SETUP_ENDPOINT_LIST(type) \
 do { \
@@ -458,5 +461,5 @@
 		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
 		    ret, name); \
-		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
 		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
 		endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
Index: uspace/drv/ohci/hcd_endpoint.h
===================================================================
--- uspace/drv/ohci/hcd_endpoint.h	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/hcd_endpoint.h	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -37,5 +37,4 @@
 #include <assert.h>
 #include <adt/list.h>
-
 #include <usb/host/endpoint.h>
 
@@ -43,5 +42,6 @@
 #include "hw_struct/transfer_descriptor.h"
 
-typedef struct hcd_endpoint {
+typedef struct hcd_endpoint
+{
 	ed_t *ed;
 	td_t *td;
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -44,5 +44,5 @@
 	assert(instance);
 	bzero(instance, sizeof(td_t));
-	instance-> status = 0
+	instance->status = 0
 	    | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
 	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -41,6 +41,8 @@
 #include "completion_codes.h"
 
-/* OHCI TDs can handle up to 8KB buffers */
-#define OHCI_TD_MAX_TRANSFER (8 * 1024)
+/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
+ * Using 4KB buffers guarantees the page count condition.
+ * (OHCI assumes 4KB pages) */
+#define OHCI_TD_MAX_TRANSFER (4 * 1024)
 
 typedef struct td {
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/uhci-hcd/batch.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -45,24 +45,35 @@
 #define DEFAULT_ERROR_COUNT 3
 
+/** UHCI specific data required for USB transfer */
 typedef struct uhci_transfer_batch {
+	/** Queue head
+	 * This QH is used to maintain UHCI schedule structure and the element
+	 * pointer points to the first TD of this batch.
+	 */
 	qh_t *qh;
+	/** List of TDs needed for the transfer */
 	td_t *tds;
+	/** Number of TDs used by the transfer */
+	size_t td_count;
+	/** Data buffer, must be accessible by the UHCI hw */
 	void *device_buffer;
-	size_t td_count;
 } uhci_transfer_batch_t;
 /*----------------------------------------------------------------------------*/
-static void uhci_transfer_batch_dispose(void *uhci_batch)
-{
-	uhci_transfer_batch_t *instance = uhci_batch;
-	assert(instance);
-	free32(instance->device_buffer);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
-
 static void batch_control(usb_transfer_batch_t *instance,
     usb_packet_id data_stage, usb_packet_id status_stage);
 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
-
+/*----------------------------------------------------------------------------*/
+/** Safely destructs uhci_transfer_batch_t structure
+ *
+ * @param[in] uhci_batch Instance to destroy.
+ */
+static void uhci_transfer_batch_dispose(void *uhci_batch)
+{
+	uhci_transfer_batch_t *instance = uhci_batch;
+	assert(instance);
+	free32(instance->device_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
 /** Allocate memory and initialize internal data structure.
  *
@@ -173,6 +184,6 @@
 		instance->error = td_status(&data->tds[i]);
 		if (instance->error != EOK) {
-			usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n",
-			    instance, i, data->tds[i].status);
+			usb_log_debug("Batch(%p) found error TD(%zu):%"
+			    PRIx32 ".\n", instance, i, data->tds[i].status);
 			td_print_status(&data->tds[i]);
 
@@ -397,4 +408,5 @@
 /*----------------------------------------------------------------------------*/
 /** Provides access to QH data structure.
+ *
  * @param[in] instance Batch pointer to use.
  * @return Pointer to the QH used by the batch.
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -34,4 +34,5 @@
 #include <errno.h>
 #include <usb/debug.h>
+#include <arch/barrier.h>
 
 #include "transfer_list.h"
@@ -71,5 +72,5 @@
  * @param[in] instance Memory place to use.
  *
- * Frees memory for internal qh_t structure.
+ * Frees memory of the internal qh_t structure.
  */
 void transfer_list_fini(transfer_list_t *instance)
@@ -126,9 +127,13 @@
 	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
 
+	/* Make sure all data in the batch are written */
+	write_barrier();
+
 	/* keep link */
 	batch_qh(batch)->next = last_qh->next;
 	qh_set_next_qh(last_qh, batch_qh(batch));
 
-	asm volatile ("": : :"memory");
+	/* Make sure the pointer is updated */
+	write_barrier();
 
 	/* Add to the driver list */
@@ -222,5 +227,8 @@
 	    == addr_to_phys(batch_qh(batch)));
 	prev_qh->next = batch_qh(batch)->next;
-	asm volatile ("": : :"memory");
+
+	/* Make sure the pointer is updated */
+	write_barrier();
+
 	/* Remove from the batch list */
 	list_remove(&batch->link);
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -74,5 +74,6 @@
 	if (size <= SLAB_ELEMENT_SIZE)
 		return slab_malloc_g();
-	assert(false);
+	usb_log_warning("Requested %zu bytes, current allocator can't handle "
+	    "that amount, pray that the standard malloc will suffice.", size);
 	return memalign(UHCI_STRCUTURES_ALIGNMENT, size);
 }
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/drv/uhci-rhd/port.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -227,12 +227,9 @@
 		while (uhci_port_read_status(port) & STATUS_IN_RESET);
 	}
+	/* PIO delay, should not be longer than 3ms as the device might
+	 * enter suspend state. */
 	udelay(10);
 	/* Enable the port. */
 	uhci_port_set_enabled(port, true);
-
-	/* Reset recovery period,
-	 * devices do not have to respond during this period
-	 */
-	async_usleep(10000);
 	return EOK;
 }
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision b2995c36bde63fff456febd935929123ef169c49)
+++ uspace/lib/usbdev/src/hub.c	(revision f58154c58b1a88c507d74c1843e1e6a5884650b9)
@@ -41,4 +41,5 @@
 #include <assert.h>
 #include <usb/debug.h>
+#include <time.h>
 
 /** How much time to wait between attempts to register endpoint 0:0.
@@ -218,4 +219,10 @@
 
 	int rc;
+	struct timeval start_time;
+
+	rc = gettimeofday(&start_time, NULL);
+	if (rc != EOK) {
+		return rc;
+	}
 
 	rc = usb_hc_connection_open(&hc_conn);
@@ -264,4 +271,20 @@
 		}
 	} while (rc != EOK);
+	struct timeval end_time;
+
+	rc = gettimeofday(&end_time, NULL);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+
+	/* According to the USB spec part 9.1.2 host allows 100ms time for
+	 * the insertion process to complete. According to 7.1.7.1 this is the
+	 * time between attach detected and port reset. However, the setup done
+	 * above might use much of this time so we should only wait to fill
+	 * up the 100ms quota*/
+	suseconds_t elapsed = tv_sub(&end_time, &start_time);
+	if (elapsed < 100000) {
+		async_usleep(100000 - elapsed);
+	}
 
 	/*
@@ -273,4 +296,10 @@
 		goto leave_release_default_address;
 	}
+	/* USB spec 7.1.7.1: The USB System Software guarantees a minimum of
+	 * 10ms for reset recovery. Device response to any bus transactions
+	 * addressed to the default device address during the reset recovery
+	 * time is undefined.
+	 */
+	async_usleep(10000);
 
 	rc = usb_pipe_probe_default_control(&ctrl_pipe);
