[PATCH] drm: refcnt drm_display_mode

Rob Clark robdclark at gmail.com
Fri Jul 25 15:51:10 PDT 2014


We're going to need this for atomic.

Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 drivers/gpu/drm/drm_crtc.c                    |  4 +--
 drivers/gpu/drm/drm_crtc_helper.c             |  2 +-
 drivers/gpu/drm/drm_edid.c                    |  6 ++--
 drivers/gpu/drm/drm_fb_helper.c               |  6 ++--
 drivers/gpu/drm/drm_modes.c                   | 41 ++++++++++++++++++++-------
 drivers/gpu/drm/exynos/exynos_drm_connector.c |  2 +-
 drivers/gpu/drm/gma500/psb_intel_sdvo.c       |  3 +-
 drivers/gpu/drm/i915/intel_panel.c            |  8 ++----
 drivers/gpu/drm/i915/intel_sdvo.c             |  3 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c   |  2 +-
 drivers/gpu/drm/omapdrm/omap_connector.c      |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c           |  4 +--
 include/drm/drm_modes.h                       |  5 +++-
 13 files changed, 52 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 1ccf5cb..7a7fced 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -822,7 +822,7 @@ static void drm_mode_remove(struct drm_connector *connector,
 			    struct drm_display_mode *mode)
 {
 	list_del(&mode->head);
-	drm_mode_destroy(connector->dev, mode);
+	drm_mode_unreference(mode);
 }
 
 /**
@@ -2602,7 +2602,7 @@ out:
 		drm_framebuffer_unreference(fb);
 
 	kfree(connector_set);
-	drm_mode_destroy(dev, mode);
+	drm_mode_unreference(mode);
 	drm_modeset_unlock_all(dev);
 	return ret;
 }
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 6c65a0a..757de8b 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -384,7 +384,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 
 	/* FIXME: add subpixel order */
 done:
-	drm_mode_destroy(dev, adjusted_mode);
+	drm_mode_unreference(adjusted_mode);
 	if (!ret) {
 		crtc->enabled = saved_enabled;
 		crtc->mode = saved_mode;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 087d608..cbc021d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1705,7 +1705,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
 		if (!mode)
 			return NULL;
 		if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
-			drm_mode_destroy(dev, mode);
+			drm_mode_unreference(mode);
 			mode = drm_gtf_mode_complex(dev, hsize, vsize,
 						    vrefresh_rate, 0, 0,
 						    drm_gtf2_m(edid),
@@ -2021,7 +2021,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
 		fixup_mode_1366x768(newmode);
 		if (!mode_in_range(newmode, edid, timing) ||
 		    !valid_inferred_mode(connector, newmode)) {
-			drm_mode_destroy(dev, newmode);
+			drm_mode_unreference(newmode);
 			continue;
 		}
 
@@ -2050,7 +2050,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
 		fixup_mode_1366x768(newmode);
 		if (!mode_in_range(newmode, edid, timing) ||
 		    !valid_inferred_mode(connector, newmode)) {
-			drm_mode_destroy(dev, newmode);
+			drm_mode_unreference(newmode);
 			continue;
 		}
 
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3144db9..5c96a6a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -588,7 +588,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
 	for (i = 0; i < helper->crtc_count; i++) {
 		kfree(helper->crtc_info[i].mode_set.connectors);
 		if (helper->crtc_info[i].mode_set.mode)
-			drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode);
+			drm_mode_unreference(helper->crtc_info[i].mode_set.mode);
 	}
 	kfree(helper->crtc_info);
 }
@@ -1606,7 +1606,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 				      mode->name, fb_crtc->mode_set.crtc->base.id);
 			fb_crtc->desired_mode = mode;
 			if (modeset->mode)
-				drm_mode_destroy(dev, modeset->mode);
+				drm_mode_unreference(modeset->mode);
 			modeset->mode = drm_mode_duplicate(dev,
 							   fb_crtc->desired_mode);
 			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
@@ -1621,7 +1621,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 			BUG_ON(modeset->fb);
 			BUG_ON(modeset->num_connectors);
 			if (modeset->mode)
-				drm_mode_destroy(dev, modeset->mode);
+				drm_mode_unreference(modeset->mode);
 			modeset->mode = NULL;
 		}
 	}
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index bedf189..55d51ed 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -82,27 +82,46 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
 		return NULL;
 	}
 
+	kref_init(&nmode->refcount);
+	nmode->dev = dev;
+
 	return nmode;
 }
 EXPORT_SYMBOL(drm_mode_create);
 
 /**
- * drm_mode_destroy - remove a mode
- * @dev: DRM device
+ * drm_mode_reference - incr the mode's refcnt
+ * @mode: display mode
+ *
+ * This functions increments the mode's refcount.
+ */
+void drm_mode_reference(struct drm_display_mode *mode)
+{
+	kref_get(&mode->refcount);
+}
+EXPORT_SYMBOL(drm_mode_reference);
+
+static void drm_mode_free(struct kref *kref)
+{
+	struct drm_display_mode *mode =
+			container_of(kref, struct drm_display_mode, refcount);
+	drm_mode_object_put(mode->dev, &mode->base);
+	kfree(mode);
+}
+
+/**
+ * drm_mode_unreference - decrement the mode's refcnt
  * @mode: mode to remove
  *
- * Release @mode's unique ID, then free it @mode structure itself using kfree.
+ * Decrement the mode's refcount, freeing it after last ref is dropped.
  */
-void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
+void drm_mode_unreference(struct drm_display_mode *mode)
 {
 	if (!mode)
 		return;
-
-	drm_mode_object_put(dev, &mode->base);
-
-	kfree(mode);
+	kref_put(&mode->refcount, drm_mode_free);
 }
-EXPORT_SYMBOL(drm_mode_destroy);
+EXPORT_SYMBOL(drm_mode_unreference);
 
 /**
  * drm_mode_probed_add - add a mode to a connector's probed_mode list
@@ -957,7 +976,7 @@ void drm_mode_prune_invalid(struct drm_device *dev,
 				DRM_DEBUG_KMS("Not using %s mode %d\n",
 					mode->name, mode->status);
 			}
-			drm_mode_destroy(dev, mode);
+			drm_mode_unreference(mode);
 		}
 	}
 }
@@ -1046,7 +1065,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector,
 				else
 					mode->type = pmode->type;
 				list_del(&pmode->head);
-				drm_mode_destroy(connector->dev, pmode);
+				drm_mode_unreference(pmode);
 				break;
 			}
 		}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index ba9b3d5..3f9d44a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -72,7 +72,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 		if (display->ops->get_panel)
 			panel = display->ops->get_panel(display);
 		else {
-			drm_mode_destroy(connector->dev, mode);
+			drm_mode_unreference(mode);
 			return 0;
 		}
 
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 0be96fd..00eb0f63 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1905,8 +1905,7 @@ static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
 	struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder);
 
 	if (psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL)
-		drm_mode_destroy(encoder->dev,
-				 psb_intel_sdvo->sdvo_lvds_fixed_mode);
+		drm_mode_unreference(psb_intel_sdvo->sdvo_lvds_fixed_mode);
 
 	i2c_del_adapter(&psb_intel_sdvo->ddc);
 	gma_encoder_destroy(encoder);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 38a9857..cbf63e0 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1205,13 +1205,9 @@ int intel_panel_init(struct intel_panel *panel,
 
 void intel_panel_fini(struct intel_panel *panel)
 {
-	struct intel_connector *intel_connector =
-		container_of(panel, struct intel_connector, panel);
-
 	if (panel->fixed_mode)
-		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
+		drm_mode_unreference(panel->fixed_mode);
 
 	if (panel->downclock_mode)
-		drm_mode_destroy(intel_connector->base.dev,
-				panel->downclock_mode);
+		drm_mode_unreference(panel->downclock_mode);
 }
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 9350edd..7049ac7 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2248,8 +2248,7 @@ static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
 	struct intel_sdvo *intel_sdvo = to_sdvo(to_intel_encoder(encoder));
 
 	if (intel_sdvo->sdvo_lvds_fixed_mode != NULL)
-		drm_mode_destroy(encoder->dev,
-				 intel_sdvo->sdvo_lvds_fixed_mode);
+		drm_mode_unreference(intel_sdvo->sdvo_lvds_fixed_mode);
 
 	i2c_del_adapter(&intel_sdvo->ddc);
 	intel_encoder_destroy(encoder);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index dbdc9ad..876ae75 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -739,7 +739,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
 	/* destroy the native mode, the attached monitor could have changed.
 	 */
 	if (nv_connector->native_mode) {
-		drm_mode_destroy(dev, nv_connector->native_mode);
+		drm_mode_unreference(nv_connector->native_mode);
 		nv_connector->native_mode = NULL;
 	}
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 36bc5cc..222d42a 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -224,7 +224,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
 		new_mode->vrefresh = 0;
 		if (mode->vrefresh == drm_mode_vrefresh(new_mode))
 			ret = MODE_OK;
-		drm_mode_destroy(dev, new_mode);
+		drm_mode_unreference(new_mode);
 	}
 
 	DBG("connector: mode %s: "
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index d2bc2b0..d726a81 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1964,13 +1964,13 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
 					       mode->vdisplay)) {
 			drm_mode_probed_add(connector, mode);
 		} else {
-			drm_mode_destroy(dev, mode);
+			drm_mode_unreference(mode);
 			mode = NULL;
 		}
 
 		if (du->pref_mode) {
 			list_del_init(&du->pref_mode->head);
-			drm_mode_destroy(dev, du->pref_mode);
+			drm_mode_unreference(du->pref_mode);
 		}
 
 		/* mode might be null here, this is intended */
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 91d0582..ef552c9 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -97,6 +97,8 @@ struct drm_display_mode {
 	/* Header */
 	struct list_head head;
 	struct drm_mode_object base;
+	struct kref refcount;
+	struct drm_device *dev;
 
 	char name[DRM_DISPLAY_MODE_LEN];
 
@@ -178,7 +180,8 @@ struct drm_connector;
 struct drm_cmdline_mode;
 
 struct drm_display_mode *drm_mode_create(struct drm_device *dev);
-void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
+void drm_mode_reference(struct drm_display_mode *mode);
+void drm_mode_unreference(struct drm_display_mode *mode);
 void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
 void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
 
-- 
1.9.3



More information about the dri-devel mailing list