Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision b2010e2b0367c842795ba5cd97043f8a6ae6912b)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 507c6f349a523ca47c817c9159f5dc1e3c60fb57)
@@ -83,4 +83,14 @@
 };
 
+enum {
+	/** Number of PIO ranges used in IRQ code */
+	hc_irq_pio_range_count = 
+	    sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),
+
+	/** Number of commands used in IRQ code */
+	hc_irq_cmd_count =
+	    sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)
+};
+
 static void hc_gain_control(hc_t *instance);
 static void hc_start(hc_t *instance);
@@ -89,20 +99,4 @@
 static int interrupt_emulator(hc_t *instance);
 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
-
-/** Get number of PIO ranges used in IRQ code.
- * @return Number of ranges.
- */
-size_t hc_irq_pio_range_count(void)
-{
-	return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
-}
-
-/** Get number of commands used in IRQ code.
- * @return Number of commands.
- */
-size_t hc_irq_cmd_count(void)
-{
-	return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
-}
 
 /** Generate IRQ code.
@@ -133,4 +127,48 @@
 	cmds[3].addr = (void *) &registers->interrupt_status;
 	OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
+
+	return EOK;
+}
+
+/** Register interrupt handler.
+ *
+ * @param[in] device Host controller DDF device
+ * @param[in] reg_base Register range base
+ * @param[in] reg_size Register range size
+ * @param[in] irq Interrupt number
+ * @paran[in] handler Interrupt handler
+ *
+ * @return EOK on success or negative error code
+ */
+int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size,
+    int irq, interrupt_handler_t handler)
+{
+	int rc;
+
+	irq_pio_range_t irq_ranges[hc_irq_pio_range_count];
+	irq_cmd_t irq_cmds[hc_irq_cmd_count];
+
+	irq_code_t irq_code = {
+		.rangecount = hc_irq_pio_range_count,
+		.ranges = irq_ranges,
+		.cmdcount = hc_irq_cmd_count,
+		.cmds = irq_cmds
+	};
+
+	rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,
+	    sizeof(irq_cmds), reg_base, reg_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to generate IRQ code: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	/* Register handler to avoid interrupt lockup */
+	rc = register_interrupt_handler(device, irq, handler, &irq_code);
+	if (rc != EOK) {
+		usb_log_error("Failed to register interrupt handler: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
 
 	return EOK;
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision b2010e2b0367c842795ba5cd97043f8a6ae6912b)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision 507c6f349a523ca47c817c9159f5dc1e3c60fb57)
@@ -35,4 +35,5 @@
 #define DRV_OHCI_HC_H
 
+#include <ddf/interrupt.h>
 #include <fibril.h>
 #include <fibril_synch.h>
@@ -74,8 +75,7 @@
 } hc_t;
 
-size_t hc_irq_pio_range_count(void);
-size_t hc_irq_cmd_count(void);
 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t,
     size_t);
+int hc_register_irq_handler(ddf_dev_t *, uintptr_t, size_t, int, interrupt_handler_t);
 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision b2010e2b0367c842795ba5cd97043f8a6ae6912b)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision 507c6f349a523ca47c817c9159f5dc1e3c60fb57)
@@ -143,4 +143,8 @@
 int device_setup_ohci(ddf_dev_t *device)
 {
+	bool ih_registered = false;
+	bool hc_inited = false;
+	int rc;
+
 	if (device == NULL)
 		return EBADMEM;
@@ -152,27 +156,23 @@
 	}
 
-#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
-if (ret != EOK) { \
-	if (instance->hc_fun) { \
-		ddf_fun_destroy(instance->hc_fun); \
-	} \
-	if (instance->rh_fun) { \
-		ddf_fun_destroy(instance->rh_fun); \
-	} \
-	usb_log_error(message); \
-	return ret; \
-} else (void)0
-
 	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
-	int ret = instance->hc_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to create OHCI HC function: %s.\n", str_error(ret));
+	if (instance->hc_fun == NULL) {
+		usb_log_error("Failed to create OHCI HC function: %s.\n",
+		    str_error(ENOMEM));
+		rc = ENOMEM;
+		goto error;
+	}
+
 	ddf_fun_set_ops(instance->hc_fun, &hc_ops);
 	ddf_fun_data_implant(instance->hc_fun, &instance->hc);
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
-	ret = instance->rh_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
+	if (instance->rh_fun == NULL) {
+		usb_log_error("Failed to create OHCI RH function: %s.\n",
+		    str_error(ENOMEM));
+		rc = ENOMEM;
+		goto error;
+	}
+
 	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
 
@@ -181,41 +181,33 @@
 	int irq = 0;
 
-	ret = get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to get register memory addresses for %" PRIun ": %s.\n",
-	    ddf_dev_get_handle(device), str_error(ret));
+	rc = get_my_registers(device, &reg_base, &reg_size, &irq);
+	if (rc != EOK) {
+		usb_log_error("Failed to get register memory addresses "
+		    "for %" PRIun ": %s.\n", ddf_dev_get_handle(device),
+		    str_error(rc));
+		goto error;
+	}
+
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
 	    (void *) reg_base, reg_size, irq);
 
-	const size_t ranges_count = hc_irq_pio_range_count();
-	const size_t cmds_count = hc_irq_cmd_count();
-	irq_pio_range_t irq_ranges[ranges_count];
-	irq_cmd_t irq_cmds[cmds_count];
-	irq_code_t irq_code = {
-		.rangecount = ranges_count,
-		.ranges = irq_ranges,
-		.cmdcount = cmds_count,
-		.cmds = irq_cmds
-	};
-
-	ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), 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));
-
-
-	/* 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));
+	rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler);
+	if (rc != EOK) {
+		usb_log_error("Failed to register interrupt handler: %s.\n",
+		    str_error(rc));
+		goto error;
+	}
+
+	ih_registered = true;
 
 	/* Try to enable interrupts */
 	bool interrupts = false;
-	ret = enable_interrupts(device);
-	if (ret != EOK) {
+	rc = enable_interrupts(device);
+	if (rc != EOK) {
 		usb_log_warning("Failed to enable interrupts: %s."
-		    " Falling back to polling\n", str_error(ret));
+		    " Falling back to polling\n", str_error(rc));
 		/* We don't need that handler */
 		unregister_interrupt_handler(device, irq);
+		ih_registered = false;
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
@@ -223,30 +215,45 @@
 	}
 
-	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to init ohci_hcd: %s.\n", str_error(ret));
-
-#define CHECK_RET_FINI_RETURN(ret, message...) \
-if (ret != EOK) { \
-	hc_fini(&instance->hc); \
-	unregister_interrupt_handler(device, irq); \
-	CHECK_RET_DEST_FREE_RETURN(ret, message); \
-} else (void)0
-
-
-	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to bind OHCI device function: %s.\n", str_error(ret));
-
-	ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
-
-	ret = hc_register_hub(&instance->hc, instance->rh_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to register OHCI root hub: %s.\n", str_error(ret));
-	return ret;
-
-#undef CHECK_RET_FINI_RETURN
+	rc = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	if (rc != EOK) {
+		usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc));
+		goto error;
+	}
+
+	hc_inited = true;
+
+	rc = ddf_fun_bind(instance->hc_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind OHCI device function: %s.\n",
+		    str_error(rc));
+		goto error;
+	}
+
+	rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
+	if (rc != EOK) {
+		usb_log_error("Failed to add OHCI to HC category: %s.\n",
+		    str_error(rc));
+		goto error;
+	}
+
+	rc = hc_register_hub(&instance->hc, instance->rh_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to register OHCI root hub: %s.\n",
+		    str_error(rc));
+		goto error;
+	}
+
+	return EOK;
+
+error:
+	if (hc_inited)
+		hc_fini(&instance->hc);
+	if (ih_registered)
+		unregister_interrupt_handler(device, irq);
+	if (instance->hc_fun != NULL)
+		ddf_fun_destroy(instance->hc_fun);
+	if (instance->rh_fun != NULL)
+		ddf_fun_destroy(instance->rh_fun);
+	return rc;
 }
 /**
