Jelajahi Sumber

disp: msm: dp: use base connector properties for mst connectors

When DRM property objects are created, the DRM framework attaches a
dellocator which can eventually free the object when the last reference
is removed from it. The framework can only do this before the driver is
registered. If a property is created after the registration then the
framework is unable to attach a deallocator causing a memory leak during
tear down.

The current DP driver creates a new colorspace property whenever a
new dp connector is initialized. It creates a base connector at probe
time prior to registration. But then it also creates new connectors,
post registration, whenever a new MST dongle is attached to the
topology, causing memory leaks.

This change limits the property creation to the base connector and
attaches the same object to MST connectors to avoid memory leak.

Change-Id: Ib97dc7aac260b4f3f96c1097f58bd276c68501f8
Signed-off-by: Rajkumar Subbiah <[email protected]>
Rajkumar Subbiah 5 tahun lalu
induk
melakukan
9522cd1382
6 mengubah file dengan 59 tambahan dan 4 penghapusan
  1. 31 0
      msm/dp/dp_drm.c
  2. 14 0
      msm/dp/dp_drm.h
  3. 1 0
      msm/dp/dp_mst_drm.c
  4. 2 4
      msm/sde/sde_connector.c
  5. 8 0
      msm/sde/sde_connector.h
  6. 3 0
      msm/sde/sde_kms.c

+ 31 - 0
msm/dp/dp_drm.c

@@ -702,3 +702,34 @@ int dp_connector_update_pps(struct drm_connector *connector,
 	dp_disp = display;
 	return dp_disp->update_pps(dp_disp, connector, pps_cmd);
 }
+
+int dp_connector_install_properties(void *display, struct drm_connector *conn)
+{
+	struct dp_display *dp_display = display;
+	struct drm_connector *base_conn;
+	int rc;
+
+	if (!display || !conn) {
+		DP_ERR("invalid params\n");
+		return -EINVAL;
+	}
+
+	base_conn = dp_display->base_connector;
+
+	/*
+	 * Create the property on the base connector during probe time and then
+	 * attach the same property onto new connector objects created for MST
+	 */
+	if (!base_conn->colorspace_property) {
+		/* This is the base connector. create the drm property */
+		rc = drm_mode_create_dp_colorspace_property(base_conn);
+		if (rc)
+			return rc;
+	} else {
+		conn->colorspace_property = base_conn->colorspace_property;
+	}
+
+	drm_object_attach_property(&conn->base, conn->colorspace_property, 0);
+
+	return 0;
+}

+ 14 - 0
msm/dp/dp_drm.h

@@ -158,6 +158,14 @@ void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
 int dp_connector_update_pps(struct drm_connector *connector,
 		char *pps_cmd, void *display);
 
+/**
+ * dp_connector_install_properties - install drm properties
+ * @display: Pointer to private display structure
+ * @conn: Pointer to connector
+ */
+int dp_connector_install_properties(void *display,
+		struct drm_connector *conn);
+
 #else
 static inline int dp_connector_config_hdr(struct drm_connector *connector,
 		void *display, struct sde_connector_state *c_state)
@@ -239,6 +247,12 @@ static inline void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
 				struct drm_display_mode *drm_mode)
 {
 }
+
+static int dp_connector_install_properties(void *display,
+		struct drm_connector *conn)
+{
+	return 0;
+}
 #endif /* CONFIG_DRM_MSM_DP */
 
 #endif /* _DP_DRM_H_ */

+ 1 - 0
msm/dp/dp_mst_drm.c

@@ -1747,6 +1747,7 @@ dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr,
 		.config_hdr = dp_mst_connector_config_hdr,
 		.pre_destroy = dp_mst_connector_pre_destroy,
 		.update_pps = dp_connector_update_pps,
+		.install_properties = dp_connector_install_properties,
 	};
 	struct dp_mst_private *dp_mst;
 	struct drm_device *dev;

+ 2 - 4
msm/sde/sde_connector.c

@@ -2729,10 +2729,8 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 			      sizeof(hdr),
 			      CONNECTOR_PROP_EXT_HDR_INFO);
 
-		/* create and attach colorspace property for DP */
-		if (!drm_mode_create_dp_colorspace_property(connector))
-			drm_object_attach_property(&connector->base,
-				connector->colorspace_property, 0);
+		if (c_conn->ops.install_properties)
+			c_conn->ops.install_properties(display, connector);
 	}
 
 	msm_property_install_volatile_range(&c_conn->property_info,

+ 8 - 0
msm/sde/sde_connector.h

@@ -351,6 +351,14 @@ struct sde_connector_ops {
 	 */
 	int (*prepare_commit)(void *display,
 		struct msm_display_conn_params *params);
+
+	/**
+	 * install_properties - install connector properties
+	 * @display: Pointer to private display structure
+	 * @conn: Pointer to drm connector structure
+	 * Returns: Zero on success
+	 */
+	int (*install_properties)(void *display, struct drm_connector *conn);
 };
 
 /**

+ 3 - 0
msm/sde/sde_kms.c

@@ -1665,6 +1665,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.get_panel_vfp = dsi_display_get_panel_vfp,
 		.get_default_lms = dsi_display_get_default_lms,
 		.cmd_receive = dsi_display_cmd_receive,
+		.install_properties = NULL,
 	};
 	static const struct sde_connector_ops wb_ops = {
 		.post_init =    sde_wb_connector_post_init,
@@ -1681,6 +1682,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.cont_splash_config = NULL,
 		.get_panel_vfp = NULL,
 		.cmd_receive = NULL,
+		.install_properties = NULL,
 	};
 	static const struct sde_connector_ops dp_ops = {
 		.post_init  = dp_connector_post_init,
@@ -1699,6 +1701,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.get_panel_vfp = NULL,
 		.update_pps = dp_connector_update_pps,
 		.cmd_receive = NULL,
+		.install_properties = dp_connector_install_properties,
 	};
 	struct msm_display_info info;
 	struct drm_encoder *encoder;