Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision b4f291d382cff35f121f99b9a2b3e6dc1d8cb2c4)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision dfe4955a28b08501c39f9da03185f4b34b4cc3a4)
@@ -202,5 +202,5 @@
 	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to generate IRQ code: %s.\n", str_error(ret));
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
 
 	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
@@ -217,5 +217,5 @@
 	if (ret != EOK) {
 		usb_log_warning("Failed to enable interrupts: %s."
-		    "Falling back to polling\n", str_error(ret));
+		    " Falling back to polling\n", str_error(ret));
 		/* We don't need that handler */
 		unregister_interrupt_handler(device, irq);
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision b4f291d382cff35f121f99b9a2b3e6dc1d8cb2c4)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision dfe4955a28b08501c39f9da03185f4b34b4cc3a4)
@@ -47,4 +47,13 @@
     (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
 
+static const irq_cmd_t uhci_irq_commands[] =
+{
+	{ .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
+	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
+	  .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
+	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
+	{ .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
+	{ .cmd = CMD_ACCEPT },
+};
 
 static int hc_init_transfer_lists(hc_t *instance);
@@ -54,4 +63,37 @@
 static int hc_interrupt_emulator(void *arg);
 static int hc_debug_checker(void *arg);
+
+/*----------------------------------------------------------------------------*/
+/** Get number of commands used in IRQ code.
+ * @return Number of commands.
+ */
+size_t hc_irq_cmd_count(void)
+{
+	return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
+}
+/*----------------------------------------------------------------------------*/
+/** Generate IRQ code commands.
+ * @param[out] cmds Place to store the commands.
+ * @param[in] cmd_size Size of the place (bytes).
+ * @param[in] regs Physical address of device's registers.
+ * @param[in] reg_size Size of the register area (bytes).
+ *
+ * @return Error code.
+ */
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
+{
+	if (cmd_size < sizeof(uhci_irq_commands)
+	    || reg_size < sizeof(uhci_regs_t))
+		return EOVERFLOW;
+
+	uhci_regs_t *registers = (uhci_regs_t*)regs;
+
+	memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
+
+	cmds[0].addr = (void*)&registers->usbsts;
+	cmds[3].addr = (void*)&registers->usbsts;
+	return EOK;
+}
 /*----------------------------------------------------------------------------*/
 /** Initialize UHCI hc driver structure
@@ -69,5 +111,5 @@
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
 {
-	assert(reg_size >= sizeof(regs_t));
+	assert(reg_size >= sizeof(uhci_regs_t));
 	int ret;
 
@@ -82,5 +124,5 @@
 
 	/* allow access to hc control registers */
-	regs_t *io;
+	uhci_regs_t *io;
 	ret = pio_enable(regs, reg_size, (void **)&io);
 	CHECK_RET_RETURN(ret,
@@ -116,5 +158,5 @@
 {
 	assert(instance);
-	regs_t *registers = instance->registers;
+	uhci_regs_t *registers = instance->registers;
 
 	/* Reset everything, who knows what touched it before us */
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision b4f291d382cff35f121f99b9a2b3e6dc1d8cb2c4)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision dfe4955a28b08501c39f9da03185f4b34b4cc3a4)
@@ -84,5 +84,5 @@
 	/** SOF modification to match external timers */
 	uint8_t sofmod;
-} regs_t;
+} uhci_regs_t;
 
 #define UHCI_FRAME_LIST_COUNT 1024
@@ -100,5 +100,5 @@
 
 	/** Addresses of I/O registers */
-	regs_t *registers;
+	uhci_regs_t *registers;
 
 	/** Frame List contains 1024 link pointers */
@@ -132,9 +132,9 @@
 	unsigned hw_failures;
 } hc_t;
-
+size_t hc_irq_cmd_count(void);
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
-
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
-
 void hc_interrupt(hc_t *instance, uint16_t status);
 
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision b4f291d382cff35f121f99b9a2b3e6dc1d8cb2c4)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision dfe4955a28b08501c39f9da03185f4b34b4cc3a4)
@@ -64,5 +64,4 @@
 {
 	assert(dev);
-	assert(dev->driver_data);
 	return dev->driver_data;
 }
@@ -78,7 +77,10 @@
 	assert(dev);
 	uhci_t *uhci = dev_to_uhci(dev);
+	if (!uhci) {
+		usb_log_error("Interrupt on not yet initialized device.\n");
+		return;
+	}
 	hc_t *hc = &uhci->hc;
 	const uint16_t status = IPC_GET_ARG1(*call);
-	assert(hc);
 	hc_interrupt(hc, status);
 }
@@ -192,4 +194,5 @@
 	} \
 	free(instance); \
+	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -222,27 +225,35 @@
 	ret = pci_disable_legacy(device);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
+	    "Failed to disable legacy USB: %s.\n", str_error(ret));
+
+	const size_t cmd_count = hc_irq_cmd_count();
+	irq_cmd_t irq_cmds[cmd_count];
+	ret =
+	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+
+        /* Register handler to avoid interrupt lockup */
+        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
+        CHECK_RET_DEST_FREE_RETURN(ret,
+            "Failed to register interrupt handler: %s.\n", str_error(ret));
 
 	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling.\n", str_error(ret));
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
 		interrupts = true;
 	}
-#endif
-
 
 	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
+
+	device->driver_data = instance;
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
@@ -253,11 +264,4 @@
 } else (void)0
 
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler: %s.\n",
-	    ret, str_error(ret));
-
 	ret = ddf_fun_bind(instance->hc_fun);
 	CHECK_RET_FINI_RETURN(ret,
@@ -278,5 +282,4 @@
 	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
 
-	device->driver_data = instance;
 	return EOK;
 #undef CHECK_RET_FINI_RETURN
