diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 0ee052b..4b0ff45 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include <drm/drm_bridge.h>
 
@@ -60,6 +61,39 @@
 static DEFINE_MUTEX(bridge_lock);
 static LIST_HEAD(bridge_list);
 
+static void drm_bridge_release(struct kref *ref)
+{
+	struct drm_bridge *bridge = container_of(ref, struct drm_bridge, kref);
+
+	kfree(bridge);
+}
+
+struct drm_bridge *drm_bridge_alloc(struct module *module)
+{
+	struct drm_bridge *bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+
+	if (!bridge)
+		return NULL;
+
+	bridge->module = module;
+	kref_init(&bridge->kref);
+
+	return bridge;
+}
+EXPORT_SYMBOL(drm_bridge_alloc);
+
+void drm_bridge_get(struct drm_bridge *bridge)
+{
+	kref_get(&bridge->kref);
+}
+EXPORT_SYMBOL(drm_bridge_get);
+
+void drm_bridge_put(struct drm_bridge *bridge)
+{
+	kref_put(&bridge->kref, drm_bridge_release);
+}
+EXPORT_SYMBOL(drm_bridge_put);
+
 /**
  * drm_bridge_add - add the given bridge to the global bridge list
  *
@@ -70,6 +104,8 @@
  */
 int drm_bridge_add(struct drm_bridge *bridge)
 {
+	drm_bridge_get(bridge);
+
 	mutex_lock(&bridge_lock);
 	list_add_tail(&bridge->list, &bridge_list);
 	mutex_unlock(&bridge_lock);
@@ -88,6 +124,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 	mutex_lock(&bridge_lock);
 	list_del_init(&bridge->list);
 	mutex_unlock(&bridge_lock);
+
+	drm_bridge_put(bridge);
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
@@ -108,18 +146,35 @@ void drm_bridge_remove(struct drm_bridge *bridge)
  */
 int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
 {
+	int ret = 0;
+
 	if (!dev || !bridge)
 		return -EINVAL;
 
+	mutex_lock(&bridge_lock);
+
 	if (bridge->dev)
-		return -EBUSY;
+		ret = -EBUSY;
+	/* Check that the bridge is still part of the list */
+	else if (list_empty(&bridge->list))
+		ret = -ENOENT;
+	else if (!try_module_get(bridge->module))
+		ret = -ENOENT;
+	else
+		bridge->dev = dev;
 
-	bridge->dev = dev;
+	mutex_unlock(&bridge_lock);
 
-	if (bridge->funcs->attach)
-		return bridge->funcs->attach(bridge);
+	if (ret)
+		return ret;
 
-	return 0;
+	if (bridge->funcs->attach) {
+		ret = bridge->funcs->attach(bridge);
+		if (ret)
+			module_put(bridge->module);
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL(drm_bridge_attach);
 
@@ -144,6 +199,8 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 	if (bridge->funcs->detach)
 		bridge->funcs->detach(bridge);
 
+	module_put(bridge->module);
+
 	bridge->dev = NULL;
 }
 EXPORT_SYMBOL(drm_bridge_detach);
@@ -312,15 +369,17 @@ void drm_bridge_enable(struct drm_bridge *bridge)
 
 #ifdef CONFIG_OF
 /**
- * of_drm_find_bridge - find the bridge corresponding to the device node in
- *			the global bridge list
+ * of_drm_get_bridge - find the bridge corresponding to the device node in
+ *		       the global bridge list and increase its refcount.
+ *                     It is caller responsibility to call drm_bridge_put()
+ *                     when it no longer needs the object.
  *
  * @np: device node
  *
  * RETURNS:
  * drm_bridge control struct on success, NULL on failure
  */
-struct drm_bridge *of_drm_find_bridge(struct device_node *np)
+struct drm_bridge *of_drm_get_bridge(struct device_node *np)
 {
 	struct drm_bridge *bridge;
 
@@ -328,6 +387,7 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np)
 
 	list_for_each_entry(bridge, &bridge_list, list) {
 		if (bridge->of_node == np) {
+			drm_bridge_get(bridge);
 			mutex_unlock(&bridge_lock);
 			return bridge;
 		}
@@ -336,7 +396,7 @@ struct drm_bridge *of_drm_find_bridge(struct device_node *np)
 	mutex_unlock(&bridge_lock);
 	return NULL;
 }
-EXPORT_SYMBOL(of_drm_find_bridge);
+EXPORT_SYMBOL(of_drm_get_bridge);
 #endif
 
 MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>");
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6..cd39b7c 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/module.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_modes.h>
 
@@ -192,15 +193,22 @@ struct drm_bridge {
 #ifdef CONFIG_OF
 	struct device_node *of_node;
 #endif
+	struct kref kref;
+	struct module *module;
+
 	struct list_head list;
 
 	const struct drm_bridge_funcs *funcs;
 	void *driver_private;
 };
 
+struct drm_bridge *drm_bridge_alloc(struct module *module);
+void drm_bridge_get(struct drm_bridge *bridge);
+void drm_bridge_put(struct drm_bridge *bridge);
+
 int drm_bridge_add(struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);
-struct drm_bridge *of_drm_find_bridge(struct device_node *np);
+struct drm_bridge *of_drm_get_bridge(struct device_node *np);
 int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
 void drm_bridge_detach(struct drm_bridge *bridge);
 
