diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 6dd72bc32897a6099557ad4a6bf683f1c03d9868..5d0694680f590ef2c4dd48b892f77c7b1344e989 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,18 +37,19 @@
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
+#include "nouveau_connector.h"
 
 static struct ida bl_ida;
 #define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
 
-struct backlight_connector {
-	struct list_head head;
+struct nouveau_backlight {
+	struct backlight_device *dev;
 	int id;
 };
 
 static bool
-nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
-		*connector)
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
+			   struct nouveau_backlight *bl)
 {
 	const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
 	if (nb < 0 || nb >= 100)
@@ -57,7 +58,7 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_c
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
 	else
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
-	connector->id = nb;
+	bl->id = nb;
 	return true;
 }
 
@@ -96,36 +97,45 @@ static int
 nv40_backlight_init(struct drm_connector *connector)
 {
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nouveau_backlight *bl;
 	struct nvif_object *device = &drm->client.device.object;
 	struct backlight_properties props;
-	struct backlight_device *bd;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev, drm,
-				       &nv40_bl_ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    drm, &nv40_bl_ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = nv40_get_intensity(bd);
-	backlight_update_status(bd);
+
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = nv40_get_intensity(bl->dev);
+	backlight_update_status(bl->dev);
 
 	return 0;
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 static int
@@ -215,11 +225,11 @@ nv50_backlight_init(struct drm_connector *connector)
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_object *device = &drm->client.device.object;
 	struct nouveau_encoder *nv_encoder;
+	struct nouveau_backlight *bl;
 	struct backlight_properties props;
-	struct backlight_device *bd;
 	const struct backlight_ops *ops;
-	struct backlight_connector bl_connector;
 	char backlight_name[BL_NAME_SIZE];
+	int ret = 0;
 
 	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
 	if (!nv_encoder) {
@@ -231,6 +241,10 @@ nv50_backlight_init(struct drm_connector *connector)
 	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
 		return 0;
 
+	bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+
 	if (drm->client.device.info.chipset <= 0xa0 ||
 	    drm->client.device.info.chipset == 0xaa ||
 	    drm->client.device.info.chipset == 0xac)
@@ -241,79 +255,74 @@ nv50_backlight_init(struct drm_connector *connector)
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 100;
-	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+	if (!nouveau_get_backlight_name(backlight_name, bl)) {
 		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
-		return 0;
+		goto fail_alloc;
 	}
-	bd = backlight_device_register(backlight_name , connector->kdev,
-				       nv_encoder, ops, &props);
 
-	if (IS_ERR(bd)) {
-		if (bl_connector.id >= 0)
-			ida_simple_remove(&bl_ida, bl_connector.id);
-		return PTR_ERR(bd);
+	bl->dev = backlight_device_register(backlight_name, connector->kdev,
+					    nv_encoder, ops, &props);
+	if (IS_ERR(bl->dev)) {
+		if (bl->id >= 0)
+			ida_simple_remove(&bl_ida, bl->id);
+
+		ret = PTR_ERR(bl->dev);
+		goto fail_alloc;
 	}
 
-	list_add(&bl_connector.head, &drm->bl_connectors);
-	drm->backlight = bd;
-	bd->props.brightness = bd->ops->get_brightness(bd);
-	backlight_update_status(bd);
+	nouveau_connector(connector)->backlight = bl;
+	bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+	backlight_update_status(bl->dev);
 	return 0;
+
+fail_alloc:
+	kfree(bl);
+	return ret;
 }
 
 int
-nouveau_backlight_init(struct drm_device *dev)
+nouveau_backlight_init(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvif_device *device = &drm->client.device;
-	struct drm_connector *connector;
-	struct drm_connector_list_iter conn_iter;
-
-	INIT_LIST_HEAD(&drm->bl_connectors);
 
 	if (apple_gmux_present()) {
-		NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+		NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
 		return 0;
 	}
 
-	drm_connector_list_iter_begin(dev, &conn_iter);
-	drm_for_each_connector_iter(connector, &conn_iter) {
-		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
-		    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
-			continue;
-
-		switch (device->info.family) {
-		case NV_DEVICE_INFO_V0_CURIE:
-			return nv40_backlight_init(connector);
-		case NV_DEVICE_INFO_V0_TESLA:
-		case NV_DEVICE_INFO_V0_FERMI:
-		case NV_DEVICE_INFO_V0_KEPLER:
-		case NV_DEVICE_INFO_V0_MAXWELL:
-			return nv50_backlight_init(connector);
-		default:
-			break;
-		}
-	}
-	drm_connector_list_iter_end(&conn_iter);
+	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+	    connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+		return 0;
 
-	return 0;
+	switch (device->info.family) {
+	case NV_DEVICE_INFO_V0_CURIE:
+		return nv40_backlight_init(connector);
+	case NV_DEVICE_INFO_V0_TESLA:
+	case NV_DEVICE_INFO_V0_FERMI:
+	case NV_DEVICE_INFO_V0_KEPLER:
+	case NV_DEVICE_INFO_V0_MAXWELL:
+		return nv50_backlight_init(connector);
+	default:
+		return 0;
+	}
 }
 
 void
-nouveau_backlight_exit(struct drm_device *dev)
+nouveau_backlight_exit(struct drm_connector *connector)
 {
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	struct backlight_connector *connector;
+	struct nouveau_connector *nv_conn = nouveau_connector(connector);
+	struct nouveau_backlight *bl = nv_conn->backlight;
 
-	list_for_each_entry(connector, &drm->bl_connectors, head) {
-		if (connector->id >= 0)
-			ida_simple_remove(&bl_ida, connector->id);
-	}
+	if (!bl)
+		return;
 
-	if (drm->backlight) {
-		backlight_device_unregister(drm->backlight);
-		drm->backlight = NULL;
-	}
+	if (bl->id >= 0)
+		ida_simple_remove(&bl_ida, bl->id);
+
+	backlight_device_unregister(bl->dev);
+	nv_conn->backlight = NULL;
+	kfree(bl);
 }
 
 void
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index dde8724aa8f563621756dc4664670ac27399542b..036c6484c4cddf33c4e54346cc3ab241f1500df6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -885,6 +885,22 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
 		connector->display_info.bpc = 8;
 }
 
+static int
+nouveau_connector_late_register(struct drm_connector *connector)
+{
+	int ret;
+
+	ret = nouveau_backlight_init(connector);
+
+	return ret;
+}
+
+static void
+nouveau_connector_early_unregister(struct drm_connector *connector)
+{
+	nouveau_backlight_exit(connector);
+}
+
 static int
 nouveau_connector_get_modes(struct drm_connector *connector)
 {
@@ -1069,6 +1085,8 @@ nouveau_connector_funcs = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static const struct drm_connector_funcs
@@ -1084,6 +1102,8 @@ nouveau_connector_funcs_lvds = {
 	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
 	.atomic_set_property = nouveau_conn_atomic_set_property,
 	.atomic_get_property = nouveau_conn_atomic_get_property,
+	.late_register = nouveau_connector_late_register,
+	.early_unregister = nouveau_connector_early_unregister,
 };
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 0acc07555bcd53da7a07e4c2b93dc943edda9c0a..6f89d4938059bbfc1cca45682fc3e475f589f027 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -39,6 +39,10 @@
 
 struct nvkm_i2c_port;
 
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+struct nouveau_backlight;
+#endif
+
 struct nouveau_connector {
 	struct drm_connector base;
 	enum dcb_connector_type type;
@@ -55,6 +59,9 @@ struct nouveau_connector {
 	struct nouveau_encoder *detected_encoder;
 	struct edid *edid;
 	struct drm_display_mode *native_mode;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+	struct nouveau_backlight *backlight;
+#endif
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -181,4 +188,30 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
 				     const struct drm_connector_state *,
 				     struct drm_property *, u64 *);
 struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
+
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
+#else
+static inline int
+nouveau_backlight_init(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static inline void
+nouveau_backlight_exit(struct drm_connector *connector) {
+}
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
+#endif
+
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 540c0cbbfcee41bf3fdae2fa339d71373e58a133..f326ffd867664cd98dfc9dea789f91917c21856a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -582,7 +582,6 @@ nouveau_display_create(struct drm_device *dev)
 			goto vblank_err;
 	}
 
-	nouveau_backlight_init(dev);
 	INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
 #ifdef CONFIG_ACPI
 	drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
@@ -607,7 +606,6 @@ nouveau_display_destroy(struct drm_device *dev)
 #ifdef CONFIG_ACPI
 	unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
 #endif
-	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
 
 	drm_kms_helper_poll_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index ff92b54ce448467b290a0c61f59d3e259fed19df..eb77e41c2d4e21823d768d4073529570811d11ee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -85,31 +85,6 @@ int  nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
 
 void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
 
-#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
-extern void nouveau_backlight_ctor(void);
-extern void nouveau_backlight_dtor(void);
-#else
-static inline int
-nouveau_backlight_init(struct drm_device *dev)
-{
-	return 0;
-}
-
-static inline void
-nouveau_backlight_exit(struct drm_device *dev) {
-}
-
-static inline void
-nouveau_backlight_ctor(void) {
-}
-
-static inline void
-nouveau_backlight_dtor(void) {
-}
-#endif
-
 struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
 				const struct drm_mode_fb_cmd2 *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index d9d68791655335a9469a58dff1e478f71cadafe9..0b2191fa96f7bc288e28e2cb6df141422882ef1a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -194,8 +194,6 @@ struct nouveau_drm {
 	/* modesetting */
 	struct nvbios vbios;
 	struct nouveau_display *display;
-	struct backlight_device *backlight;
-	struct list_head bl_connectors;
 	struct work_struct hpd_work;
 	struct work_struct fbcon_work;
 	int fbcon_new_state;