Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 4603b35bfff3d939df56b8ba944e6aba6c14b3a6)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision 51a51be943417c8bcd0347b01f2a7a91627a6850)
@@ -243,17 +243,16 @@
 	}
 
-	/* Reserve default address
-	 * TODO: Make the request synchronous.
-	 */
-	while ((err = usbhc_reserve_default_address(exch)) == EAGAIN) {
-		fibril_condvar_wait_timeout(&port->state_cv, &port->guard, 500000);
-		if (port->state != PORT_CONNECTED) {
-			assert(port->state == PORT_ERROR);
-			port_change_state(port, PORT_DISABLED);
-			goto out_exch;
-		}
-	}
+	/* Reserve default address */
+	err = usb_hub_reserve_default_address(port->hub, exch, &port->guard);
 	if (err != EOK) {
 		port_log(error, port, "Failed to reserve default address: %s", str_error(err));
+		port_change_state(port, PORT_DISABLED);
+		goto out_exch;
+	}
+
+	/* Reservation of default address could have blocked */
+	if (port->state != PORT_CONNECTED) {
+		assert(port->state == PORT_ERROR);
+		port_change_state(port, PORT_DISABLED);
 		goto out_exch;
 	}
@@ -282,12 +281,8 @@
 	if (port->state != PORT_ENABLED)
 		usb_hub_clear_port_feature(port->hub, port->port_number, USB_HUB_FEATURE_C_PORT_ENABLE);
-
 out_address:
-	if ((err = usbhc_release_default_address(exch)))
-		port_log(error, port, "Failed to release default address: %s", str_error(err));
-
+	usb_hub_release_default_address(port->hub, exch);
 out_exch:
 	usb_device_bus_exchange_end(exch);
-
 out:
 	assert(port->state == PORT_ENABLED || port->state == PORT_DISABLED);
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 4603b35bfff3d939df56b8ba944e6aba6c14b3a6)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 51a51be943417c8bcd0347b01f2a7a91627a6850)
@@ -116,4 +116,7 @@
 	}
 	hub_dev->usb_device = usb_dev;
+
+	fibril_mutex_initialize(&hub_dev->default_address_guard);
+	fibril_condvar_initialize(&hub_dev->default_address_cv);
 
 	/* Set hub's first configuration. (There should be only one) */
@@ -603,4 +606,59 @@
 
 /**
+ * Reserve a default address for a port across all other devices connected to
+ * the bus. We aggregate requests for ports to minimize delays between
+ * connecting multiple devices from one hub - which happens e.g. when the hub
+ * is connected with already attached devices.
+ */
+int usb_hub_reserve_default_address(usb_hub_dev_t *hub, async_exch_t *exch, fibril_mutex_t *guard)
+{
+	assert(hub);
+	assert(exch);
+	assert(guard);
+	assert(fibril_mutex_is_locked(guard));
+
+	fibril_mutex_lock(&hub->default_address_guard);
+	if (hub->default_address_requests++ == 0) {
+		/* We're the first to request the address, we can just do it */
+		fibril_mutex_unlock(&hub->default_address_guard);
+		int err;
+		while ((err = usbhc_reserve_default_address(exch)) == EAGAIN) {
+			fibril_mutex_unlock(guard);
+			async_usleep(500000);
+			fibril_mutex_lock(guard);
+			err = usbhc_reserve_default_address(exch);
+		}
+		return err;
+	} else {
+		/* Drop the port guard, we're going to wait */
+		fibril_mutex_unlock(guard);
+
+		/* Wait for a signal */
+		fibril_condvar_wait(&hub->default_address_cv, &hub->default_address_guard);
+
+		/* Remember ABBA, first drop the hub guard */
+		fibril_mutex_unlock(&hub->default_address_guard);
+		fibril_mutex_lock(guard);
+		return EOK;
+	}
+}
+
+/**
+ * Release the default address from a port.
+ */
+int usb_hub_release_default_address(usb_hub_dev_t *hub, async_exch_t *exch)
+{
+	fibril_mutex_lock(&hub->default_address_guard);
+	if (--hub->default_address_requests == 0) {
+		fibril_mutex_unlock(&hub->default_address_guard);
+		return usbhc_release_default_address(exch);
+	} else {
+		fibril_condvar_signal(&hub->default_address_cv);
+		fibril_mutex_unlock(&hub->default_address_guard);
+		return EOK;
+	}
+}
+
+/**
  * @}
  */
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision 4603b35bfff3d939df56b8ba944e6aba6c14b3a6)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision 51a51be943417c8bcd0347b01f2a7a91627a6850)
@@ -70,4 +70,9 @@
 	/** Each port is switched individually. */
 	bool per_port_power;
+
+	/** Default address management */
+	unsigned default_address_requests;
+	fibril_mutex_t default_address_guard;
+	fibril_condvar_t default_address_cv;
 };
 
@@ -84,4 +89,7 @@
 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
 
+int usb_hub_reserve_default_address(usb_hub_dev_t *, async_exch_t *, fibril_mutex_t *);
+int usb_hub_release_default_address(usb_hub_dev_t *, async_exch_t *);
+
 #endif
 
