diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus
index cf6d3eec793a7be66e4d3463ecfa1c4f72073108..41ffc40b8efb3a336dff21d00888460aa3c5cca2 100644
--- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus
+++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus
@@ -6,22 +6,45 @@ Description:
 		The "root" greybus device for the Greybus device tree, or bus,
 		where N is a dynamically assigned 1-based id.
 
-What:		/sys/bus/greybus/device/N-I
+What:		/sys/bus/greybus/device/N-M
+Date:		March 2016
+KernelVersion:	4.XX
+Contact:	Greg Kroah-Hartman <greg@kroah.com>
+Description:
+		A Module M on the bus N, where M is the 1-byte interface
+		ID of the module's primary interface.
+
+What:		/sys/bus/greybus/device/N-M/module_id
+Date:		March 2016
+KernelVersion:	4.XX
+Contact:	Greg Kroah-Hartman <greg@kroah.com>
+Description:
+		The ID of a Greybus module, corresponding to the ID of its
+		primary interface.
+
+What:		/sys/bus/greybus/device/N-M/num_interfaces
+Date:		March 2016
+KernelVersion:	4.XX
+Contact:	Greg Kroah-Hartman <greg@kroah.com>
+Description:
+		The number of interfaces of a module.
+
+What:		/sys/bus/greybus/device/N-M.I
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
-		An Interface I on the bus N, where I is the 1-byte interface
-		ID.
+		An Interface I on the bus N and module N-M, where I is the
+		1-byte interface ID.
 
-What:		/sys/bus/greybus/device/N-I/current_now
+What:		/sys/bus/greybus/device/N-M.I/current_now
 Date:		March 2016
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Current measurement of the interface in microamps (uA)
 
-What:		/sys/bus/greybus/device/N-I/ddbl1_manufacturer_id
+What:		/sys/bus/greybus/device/N-M.I/ddbl1_manufacturer_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -29,7 +52,7 @@ Description:
 		Unipro Device Descriptor Block Level 1 manufacturer ID for the
 		greybus Interface.
 
-What:		/sys/bus/greybus/device/N-I/ddbl1_product_id
+What:		/sys/bus/greybus/device/N-M.I/ddbl1_product_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -37,28 +60,28 @@ Description:
 		Unipro Device Descriptor Block Level 1 product ID for the
 		greybus Interface.
 
-What:		/sys/bus/greybus/device/N-I/interface_id
+What:		/sys/bus/greybus/device/N-M.I/interface_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		The ID of a Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I/power_now
+What:		/sys/bus/greybus/device/N-M.I/power_now
 Date:		March 2016
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Power measurement of the interface in microwatts (uW)
 
-What:		/sys/bus/greybus/device/N-I/product_id
+What:		/sys/bus/greybus/device/N-M.I/product_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Product ID of a Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I/serial_number
+What:		/sys/bus/greybus/device/N-M.I/serial_number
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -66,14 +89,14 @@ Description:
 		Serial Number of the Greybus interface, represented by a 64 bit
 		hexadecimal number.
 
-What:		/sys/bus/greybus/device/N-I/vendor_id
+What:		/sys/bus/greybus/device/N-M.I/vendor_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Vendor ID of a Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I/version
+What:		/sys/bus/greybus/device/N-M.I/version
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -81,14 +104,14 @@ Description:
 		Interface version represented as <16 bit major number>.<16 bit
 		minor number>.
 
-What:		/sys/bus/greybus/device/N-I/voltage_now
+What:		/sys/bus/greybus/device/N-M.I/voltage_now
 Date:		March 2016
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Voltage measurement of the interface in microvolts (uV)
 
-What:		/sys/bus/greybus/device/N-I.ctrl
+What:		/sys/bus/greybus/device/N-M.I.ctrl
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -96,21 +119,21 @@ Description:
 		Abstract control device for interface I that represents the
 		current mode of an enumerated Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I.ctrl/product_string
+What:		/sys/bus/greybus/device/N-M.I.ctrl/product_string
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Product ID string of a Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I.ctrl/vendor_string
+What:		/sys/bus/greybus/device/N-M.I.ctrl/vendor_string
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		Vendor ID string of a Greybus interface.
 
-What:		/sys/bus/greybus/device/N-I.B
+What:		/sys/bus/greybus/device/N-M.I.B
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
@@ -118,21 +141,21 @@ Description:
 		A bundle B on the Interface I, B is replaced by a 1-byte
 		number representing the bundle.
 
-What:		/sys/bus/greybus/device/N-I.B/bundle_class
+What:		/sys/bus/greybus/device/N-M.I.B/bundle_class
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		The greybus class of the bundle B.
 
-What:		/sys/bus/greybus/device/N-I.B/bundle_id
+What:		/sys/bus/greybus/device/N-M.I.B/bundle_id
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
 Description:
 		The interface-unique id of the bundle B.
 
-What:		/sys/bus/greybus/device/N-I.B/state
+What:		/sys/bus/greybus/device/N-M.I.B/state
 Date:		October 2015
 KernelVersion:	4.XX
 Contact:	Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index 65259ea9d1110f1fdbc56cc4043a90c24a636b83..8ec607460ec0e1d2fb55479b7d6cdb73fac0581e 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -2,6 +2,7 @@ greybus-y :=	core.o		\
 		debugfs.o	\
 		hd.o		\
 		manifest.o	\
+		module.o	\
 		interface.o	\
 		bundle.o	\
 		connection.o	\
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 9f143e5a7c9c8471e4f2042ce79588146bf11bab..70a66e28471db548dfed604ee2834726b29fd28e 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -85,6 +85,7 @@ static int greybus_module_match(struct device *dev, struct device_driver *drv)
 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct gb_host_device *hd;
+	struct gb_module *module = NULL;
 	struct gb_interface *intf = NULL;
 	struct gb_control *control = NULL;
 	struct gb_bundle *bundle = NULL;
@@ -92,8 +93,12 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
 
 	if (is_gb_host_device(dev)) {
 		hd = to_gb_host_device(dev);
+	} else if (is_gb_module(dev)) {
+		module = to_gb_module(dev);
+		hd = module->hd;
 	} else if (is_gb_interface(dev)) {
 		intf = to_gb_interface(dev);
+		module = intf->module;
 		hd = intf->hd;
 	} else if (is_gb_control(dev)) {
 		control = to_gb_control(dev);
@@ -102,6 +107,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
 	} else if (is_gb_bundle(dev)) {
 		bundle = to_gb_bundle(dev);
 		intf = bundle->intf;
+		module = intf->module;
 		hd = intf->hd;
 	} else if (is_gb_svc(dev)) {
 		svc = to_gb_svc(dev);
@@ -114,6 +120,11 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
 	if (add_uevent_var(env, "BUS=%u", hd->bus_id))
 		return -ENOMEM;
 
+	if (module) {
+		if (add_uevent_var(env, "MODULE=%u", module->module_id))
+			return -ENOMEM;
+	}
+
 	if (intf) {
 		if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
 			return -ENOMEM;
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index 4ab5f608b8cd4359720b087572619b90d069a2f6..f5447e7592e9c57f87f078c2c5c3e68ce96cfb0e 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -28,6 +28,7 @@
 #include "hd.h"
 #include "svc.h"
 #include "control.h"
+#include "module.h"
 #include "interface.h"
 #include "bundle.h"
 #include "connection.h"
@@ -112,6 +113,7 @@ struct dentry *gb_debugfs_get(void);
 extern struct bus_type greybus_bus_type;
 
 extern struct device_type greybus_hd_type;
+extern struct device_type greybus_module_type;
 extern struct device_type greybus_interface_type;
 extern struct device_type greybus_control_type;
 extern struct device_type greybus_bundle_type;
@@ -122,6 +124,11 @@ static inline int is_gb_host_device(const struct device *dev)
 	return dev->type == &greybus_hd_type;
 }
 
+static inline int is_gb_module(const struct device *dev)
+{
+	return dev->type == &greybus_module_type;
+}
+
 static inline int is_gb_interface(const struct device *dev)
 {
 	return dev->type == &greybus_interface_type;
diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c
index 2c13860e4a05984a5508d13904832dced3655e40..762cc035b128a284fa20596bd0e708028a7e1caf 100644
--- a/drivers/staging/greybus/hd.c
+++ b/drivers/staging/greybus/hd.c
@@ -89,7 +89,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
 	hd->bus_id = ret;
 
 	hd->driver = driver;
-	INIT_LIST_HEAD(&hd->interfaces);
+	INIT_LIST_HEAD(&hd->modules);
 	INIT_LIST_HEAD(&hd->connections);
 	ida_init(&hd->cport_id_map);
 	hd->buffer_size_max = buffer_size_max;
diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h
index b481dd03bd73378284400ff7d250bf785291d9a3..ff71936a7932537eea914a016957635d6d0d61c7 100644
--- a/drivers/staging/greybus/hd.h
+++ b/drivers/staging/greybus/hd.h
@@ -34,7 +34,7 @@ struct gb_host_device {
 	int bus_id;
 	const struct gb_hd_driver *driver;
 
-	struct list_head interfaces;
+	struct list_head modules;
 	struct list_head connections;
 	struct ida cport_id_map;
 
diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c
index 89fe901cb0a360e45026668c0e4bee8ec9b16274..d51c5635f22bedeace70488ad9e18ba459adca50 100644
--- a/drivers/staging/greybus/interface.c
+++ b/drivers/staging/greybus/interface.c
@@ -333,21 +333,6 @@ static struct attribute *interface_attrs[] = {
 };
 ATTRIBUTE_GROUPS(interface);
 
-
-// FIXME, odds are you don't want to call this function, rework the caller to
-// not need it please.
-struct gb_interface *gb_interface_find(struct gb_host_device *hd,
-				       u8 interface_id)
-{
-	struct gb_interface *intf;
-
-	list_for_each_entry(intf, &hd->interfaces, links)
-		if (intf->interface_id == interface_id)
-			return intf;
-
-	return NULL;
-}
-
 static void gb_interface_release(struct device *dev)
 {
 	struct gb_interface *intf = to_gb_interface(dev);
@@ -371,13 +356,11 @@ struct device_type greybus_interface_type = {
  *
  * Returns a pointer to the new interfce or a null pointer if a
  * failure occurs due to memory exhaustion.
- *
- * Locking: Caller ensures serialisation with gb_interface_remove and
- * gb_interface_find.
  */
-struct gb_interface *gb_interface_create(struct gb_host_device *hd,
+struct gb_interface *gb_interface_create(struct gb_module *module,
 					 u8 interface_id)
 {
+	struct gb_host_device *hd = module->hd;
 	struct gb_interface *intf;
 
 	intf = kzalloc(sizeof(*intf), GFP_KERNEL);
@@ -385,6 +368,7 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
 		return NULL;
 
 	intf->hd = hd;		/* XXX refcount? */
+	intf->module = module;
 	intf->interface_id = interface_id;
 	INIT_LIST_HEAD(&intf->bundles);
 	INIT_LIST_HEAD(&intf->manifest_descs);
@@ -392,15 +376,14 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
 	/* Invalid device id to start with */
 	intf->device_id = GB_INTERFACE_DEVICE_ID_BAD;
 
-	intf->dev.parent = &hd->dev;
+	intf->dev.parent = &module->dev;
 	intf->dev.bus = &greybus_bus_type;
 	intf->dev.type = &greybus_interface_type;
 	intf->dev.groups = interface_groups;
-	intf->dev.dma_mask = hd->dev.dma_mask;
+	intf->dev.dma_mask = module->dev.dma_mask;
 	device_initialize(&intf->dev);
-	dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id);
-
-	list_add(&intf->links, &hd->interfaces);
+	dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev),
+			interface_id);
 
 	return intf;
 }
@@ -579,15 +562,16 @@ int gb_interface_add(struct gb_interface *intf)
 	return 0;
 }
 
-/* Deregister an interface and drop its reference. */
-void gb_interface_remove(struct gb_interface *intf)
+/* Deregister an interface. */
+void gb_interface_del(struct gb_interface *intf)
 {
 	if (device_is_registered(&intf->dev)) {
 		device_del(&intf->dev);
 		dev_info(&intf->dev, "Interface removed\n");
 	}
+}
 
-	list_del(&intf->links);
-
+void gb_interface_put(struct gb_interface *intf)
+{
 	put_device(&intf->dev);
 }
diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h
index 63ba696c14a59e5087ed9caee71b9f8a40778406..9185c7f1bd32b44579e54b732ee9f1cc9c414c1d 100644
--- a/drivers/staging/greybus/interface.h
+++ b/drivers/staging/greybus/interface.h
@@ -20,7 +20,7 @@ struct gb_interface {
 	struct gb_control *control;
 
 	struct list_head bundles;
-	struct list_head links;	/* gb_host_device->interfaces */
+	struct list_head module_node;
 	struct list_head manifest_descs;
 	u8 interface_id;	/* Physical location within the Endo */
 	u8 device_id;
@@ -35,6 +35,7 @@ struct gb_interface {
 	u16 version_minor;
 
 	struct gb_host_device *hd;
+	struct gb_module *module;
 
 	unsigned long quirks;
 
@@ -46,13 +47,14 @@ struct gb_interface {
 struct gb_interface *gb_interface_find(struct gb_host_device *hd,
 				       u8 interface_id);
 
-struct gb_interface *gb_interface_create(struct gb_host_device *hd,
+struct gb_interface *gb_interface_create(struct gb_module *module,
 					 u8 interface_id);
 int gb_interface_activate(struct gb_interface *intf);
 void gb_interface_deactivate(struct gb_interface *intf);
 int gb_interface_enable(struct gb_interface *intf);
 void gb_interface_disable(struct gb_interface *intf);
 int gb_interface_add(struct gb_interface *intf);
-void gb_interface_remove(struct gb_interface *intf);
+void gb_interface_del(struct gb_interface *intf);
+void gb_interface_put(struct gb_interface *intf);
 
 #endif /* __INTERFACE_H */
diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c498e0a4eaf7e6c738b994084b4a6cde099d59e
--- /dev/null
+++ b/drivers/staging/greybus/module.c
@@ -0,0 +1,178 @@
+/*
+ * Greybus Module code
+ *
+ * Copyright 2016 Google Inc.
+ * Copyright 2016 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#include "greybus.h"
+
+
+static ssize_t module_id_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct gb_module *module = to_gb_module(dev);
+
+	return sprintf(buf, "%u\n", module->module_id);
+}
+static DEVICE_ATTR_RO(module_id);
+
+static ssize_t num_interfaces_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct gb_module *module = to_gb_module(dev);
+
+	return sprintf(buf, "%zu\n", module->num_interfaces);
+}
+static DEVICE_ATTR_RO(num_interfaces);
+
+static struct attribute *module_attrs[] = {
+	&dev_attr_module_id.attr,
+	&dev_attr_num_interfaces.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(module);
+
+static void gb_module_release(struct device *dev)
+{
+	struct gb_module *module = to_gb_module(dev);
+
+	kfree(module);
+}
+
+struct device_type greybus_module_type = {
+	.name		= "greybus_module",
+	.release	= gb_module_release,
+};
+
+struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id,
+					size_t num_interfaces)
+{
+	struct gb_interface *intf;
+	struct gb_module *module;
+	int i;
+
+	module = kzalloc(sizeof(*module) + num_interfaces * sizeof(intf),
+				GFP_KERNEL);
+	if (!module)
+		return NULL;
+
+	module->hd = hd;
+	module->module_id = module_id;
+	module->num_interfaces = num_interfaces;
+
+	module->dev.parent = &hd->dev;
+	module->dev.bus = &greybus_bus_type;
+	module->dev.type = &greybus_module_type;
+	module->dev.groups = module_groups;
+	module->dev.dma_mask = hd->dev.dma_mask;
+	device_initialize(&module->dev);
+	dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id);
+
+	for (i = 0; i < num_interfaces; ++i) {
+		intf = gb_interface_create(module, module_id + i);
+		if (!intf) {
+			dev_err(&module->dev, "failed to create interface %u\n",
+					module_id + i);
+			goto err_put_interfaces;
+		}
+		module->interfaces[i] = intf;
+	}
+
+	return module;
+
+err_put_interfaces:
+	for (--i; i > 0; --i)
+		gb_interface_put(module->interfaces[i]);
+
+	put_device(&module->dev);
+
+	return NULL;
+}
+
+/*
+ * Register and enable an interface after first attempting to activate it.
+ */
+static void gb_module_register_interface(struct gb_interface *intf)
+{
+	struct gb_module *module = intf->module;
+	u8 intf_id = intf->interface_id;
+	int ret;
+
+	ret = gb_interface_activate(intf);
+	if (ret) {
+		dev_err(&module->dev, "failed to activate interface %u: %d\n",
+				intf_id, ret);
+		gb_interface_add(intf);
+		return;
+	}
+
+	ret = gb_interface_add(intf);
+	if (ret)
+		goto err_interface_deactivate;
+
+	ret = gb_interface_enable(intf);
+	if (ret) {
+		dev_err(&module->dev, "failed to enable interface %u: %d\n",
+				intf_id, ret);
+		goto err_interface_deactivate;
+	}
+
+	return;
+
+err_interface_deactivate:
+	gb_interface_deactivate(intf);
+}
+
+static void gb_module_deregister_interface(struct gb_interface *intf)
+{
+	/* Mark as disconnected to prevent I/O during disable. */
+	if (intf->module->disconnected)
+		intf->disconnected = true;
+
+	gb_interface_disable(intf);
+	gb_interface_deactivate(intf);
+
+	gb_interface_del(intf);
+}
+
+/* Register a module and its interfaces. */
+int gb_module_add(struct gb_module *module)
+{
+	size_t i;
+	int ret;
+
+	ret = device_add(&module->dev);
+	if (ret) {
+		dev_err(&module->dev, "failed to register module: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < module->num_interfaces; ++i)
+		gb_module_register_interface(module->interfaces[i]);
+
+	return 0;
+}
+
+/* Deregister a module and its interfaces. */
+void gb_module_del(struct gb_module *module)
+{
+	size_t i;
+
+	for (i = 0; i < module->num_interfaces; ++i)
+		gb_module_deregister_interface(module->interfaces[i]);
+
+	device_del(&module->dev);
+}
+
+void gb_module_put(struct gb_module *module)
+{
+	size_t i;
+
+	for (i = 0; i < module->num_interfaces; ++i)
+		gb_interface_put(module->interfaces[i]);
+
+	put_device(&module->dev);
+}
diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h
new file mode 100644
index 0000000000000000000000000000000000000000..88a97ce0424347c431afb2d98d9d59d8526969f6
--- /dev/null
+++ b/drivers/staging/greybus/module.h
@@ -0,0 +1,34 @@
+/*
+ * Greybus Module code
+ *
+ * Copyright 2016 Google Inc.
+ * Copyright 2016 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#ifndef __MODULE_H
+#define __MODULE_H
+
+struct gb_module {
+	struct device dev;
+	struct gb_host_device *hd;
+
+	struct list_head hd_node;
+
+	u8 module_id;
+	size_t num_interfaces;
+
+	bool disconnected;
+
+	struct gb_interface *interfaces[0];
+};
+#define to_gb_module(d) container_of(d, struct gb_module, dev)
+
+struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id,
+				   size_t num_interfaces);
+int gb_module_add(struct gb_module *module);
+void gb_module_del(struct gb_module *module);
+void gb_module_put(struct gb_module *module);
+
+#endif /* __MODULE_H */
diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c
index cde59d02400bc277e94ce0fe972cb75f15e80559..94016954a6aba7a339579f56d81be224e4c2175e 100644
--- a/drivers/staging/greybus/svc.c
+++ b/drivers/staging/greybus/svc.c
@@ -665,6 +665,19 @@ static int gb_svc_hello(struct gb_operation *op)
 	return 0;
 }
 
+static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id)
+{
+	struct gb_host_device *hd = svc->hd;
+	struct gb_module *module;
+
+	list_for_each_entry(module, &hd->modules, hd_node) {
+		if (module->module_id == module_id)
+			return module;
+	}
+
+	return NULL;
+}
+
 static void gb_svc_intf_reenable(struct gb_svc *svc, struct gb_interface *intf)
 {
 	int ret;
@@ -689,7 +702,7 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
 	struct gb_connection *connection = operation->connection;
 	struct gb_svc *svc = gb_connection_get_data(connection);
 	struct gb_host_device *hd = connection->hd;
-	struct gb_interface *intf;
+	struct gb_module *module;
 	u8 intf_id;
 	int ret;
 
@@ -699,52 +712,35 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
 
 	dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id);
 
-	intf = gb_interface_find(hd, intf_id);
-	if (intf) {
+	/* All modules are considered 1x2 for now */
+	module = gb_svc_module_lookup(svc, intf_id);
+	if (module) {
 		dev_info(&svc->dev, "mode switch detected on interface %u\n",
 				intf_id);
 
-		return gb_svc_intf_reenable(svc, intf);
+		return gb_svc_intf_reenable(svc, module->interfaces[0]);
 	}
 
-	intf = gb_interface_create(hd, intf_id);
-	if (!intf) {
-		dev_err(&svc->dev, "failed to create interface %u\n",
-				intf_id);
+	module = gb_module_create(hd, intf_id, 1);
+	if (!module) {
+		dev_err(&svc->dev, "failed to create module\n");
 		return;
 	}
 
-	ret = gb_interface_activate(intf);
+	ret = gb_module_add(module);
 	if (ret) {
-		dev_err(&svc->dev, "failed to activate interface %u: %d\n",
-				intf_id, ret);
-		gb_interface_add(intf);
+		gb_module_put(module);
 		return;
 	}
 
-	ret = gb_interface_add(intf);
-	if (ret)
-		goto err_interface_deactivate;
-
-	ret = gb_interface_enable(intf);
-	if (ret) {
-		dev_err(&svc->dev, "failed to enable interface %u: %d\n",
-				intf_id, ret);
-		goto err_interface_deactivate;
-	}
-
-	return;
-
-err_interface_deactivate:
-	gb_interface_deactivate(intf);
+	list_add(&module->hd_node, &hd->modules);
 }
 
 static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation)
 {
 	struct gb_svc *svc = gb_connection_get_data(operation->connection);
 	struct gb_svc_intf_hot_unplug_request *request;
-	struct gb_host_device *hd = operation->connection->hd;
-	struct gb_interface *intf;
+	struct gb_module *module;
 	u8 intf_id;
 
 	/* The request message size has already been verified. */
@@ -753,19 +749,19 @@ static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation)
 
 	dev_dbg(&svc->dev, "%s - id = %u\n", __func__, intf_id);
 
-	intf = gb_interface_find(hd, intf_id);
-	if (!intf) {
+	/* All modules are considered 1x2 for now */
+	module = gb_svc_module_lookup(svc, intf_id);
+	if (!module) {
 		dev_warn(&svc->dev, "could not find hot-unplug interface %u\n",
 				intf_id);
 		return;
 	}
 
-	/* Mark as disconnected to prevent I/O during disable. */
-	intf->disconnected = true;
+	module->disconnected = true;
 
-	gb_interface_disable(intf);
-	gb_interface_deactivate(intf);
-	gb_interface_remove(intf);
+	gb_module_del(module);
+	list_del(&module->hd_node);
+	gb_module_put(module);
 }
 
 static void gb_svc_process_deferred_request(struct work_struct *work)
@@ -1104,14 +1100,15 @@ int gb_svc_add(struct gb_svc *svc)
 	return 0;
 }
 
-static void gb_svc_remove_interfaces(struct gb_svc *svc)
+static void gb_svc_remove_modules(struct gb_svc *svc)
 {
-	struct gb_interface *intf, *tmp;
+	struct gb_host_device *hd = svc->hd;
+	struct gb_module *module, *tmp;
 
-	list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) {
-		gb_interface_disable(intf);
-		gb_interface_deactivate(intf);
-		gb_interface_remove(intf);
+	list_for_each_entry_safe(module, tmp, &hd->modules, hd_node) {
+		gb_module_del(module);
+		list_del(&module->hd_node);
+		gb_module_put(module);
 	}
 }
 
@@ -1132,7 +1129,7 @@ void gb_svc_del(struct gb_svc *svc)
 
 	flush_workqueue(svc->wq);
 
-	gb_svc_remove_interfaces(svc);
+	gb_svc_remove_modules(svc);
 }
 
 void gb_svc_put(struct gb_svc *svc)