From 9522cd138240ee52f884f5975911385d8c8be42d Mon Sep 17 00:00:00 2001 From: Rajkumar Subbiah Date: Fri, 10 Jul 2020 22:20:20 -0400 Subject: [PATCH] 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 --- msm/dp/dp_drm.c | 31 +++++++++++++++++++++++++++++++ msm/dp/dp_drm.h | 14 ++++++++++++++ msm/dp/dp_mst_drm.c | 1 + msm/sde/sde_connector.c | 6 ++---- msm/sde/sde_connector.h | 8 ++++++++ msm/sde/sde_kms.c | 3 +++ 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 43bd72ad6891..3abe14e9161e 100644 --- a/msm/dp/dp_drm.c +++ b/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; +} diff --git a/msm/dp/dp_drm.h b/msm/dp/dp_drm.h index 5e3fdf19a343..5d7462cd20f8 100644 --- a/msm/dp/dp_drm.h +++ b/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_ */ diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index 77ece8fbcf24..a8b6617efe2c 100644 --- a/msm/dp/dp_mst_drm.c +++ b/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; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 759b1bf5b30d..77c3a45ea08d 100644 --- a/msm/sde/sde_connector.c +++ b/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, diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 41407892dbf4..03c7f306d186 100644 --- a/msm/sde/sde_connector.h +++ b/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); }; /** diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index a47b043d560f..5c8c7417cad2 100644 --- a/msm/sde/sde_kms.c +++ b/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;