aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Anderson <dianders@chromium.org>2016-03-07 17:00:52 -0500
committerMark Yao <mark.yao@rock-chips.com>2016-03-28 02:48:32 -0400
commit328b51c0f5a07f3ee891ff012eb7f454be9d17c0 (patch)
treee80c90ed0aa607fb16da161091eab81f3a78e9be
parent948cf42700b15fc65ec4cc3ac52a8bbeb84b87ef (diff)
drm/rockchip: vop: Fix vop crtc cleanup
This fixes a few problems in the vop crtc cleanup (handling error paths and cleanup upon exit): * The vop_create_crtc() error path had an unsafe version of the iterator used for iterating over all planes (though it was destroying planes in the iterator so should have used the safe version) * vop_destroy_crtc() - wasn't calling vop_plane_destroy(), which made slub_debug unhappy, at least if we ended up running this due to a deferred probe. * In vop_create_crtc() if we were missing the "port" device tree node we would fail but not return an error (found by code inspection). Fix these problems. Signed-off-by: Douglas Anderson <dianders@chromium.org>
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 12854ac9d542..a619f120f801 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1142,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop)
1142 const struct vop_data *vop_data = vop->data; 1142 const struct vop_data *vop_data = vop->data;
1143 struct device *dev = vop->dev; 1143 struct device *dev = vop->dev;
1144 struct drm_device *drm_dev = vop->drm_dev; 1144 struct drm_device *drm_dev = vop->drm_dev;
1145 struct drm_plane *primary = NULL, *cursor = NULL, *plane; 1145 struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
1146 struct drm_crtc *crtc = &vop->crtc; 1146 struct drm_crtc *crtc = &vop->crtc;
1147 struct device_node *port; 1147 struct device_node *port;
1148 int ret; 1148 int ret;
@@ -1182,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop)
1182 ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, 1182 ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
1183 &vop_crtc_funcs, NULL); 1183 &vop_crtc_funcs, NULL);
1184 if (ret) 1184 if (ret)
1185 return ret; 1185 goto err_cleanup_planes;
1186 1186
1187 drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); 1187 drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
1188 1188
@@ -1215,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop)
1215 if (!port) { 1215 if (!port) {
1216 DRM_ERROR("no port node found in %s\n", 1216 DRM_ERROR("no port node found in %s\n",
1217 dev->of_node->full_name); 1217 dev->of_node->full_name);
1218 ret = -ENOENT;
1218 goto err_cleanup_crtc; 1219 goto err_cleanup_crtc;
1219 } 1220 }
1220 1221
@@ -1228,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop)
1228err_cleanup_crtc: 1229err_cleanup_crtc:
1229 drm_crtc_cleanup(crtc); 1230 drm_crtc_cleanup(crtc);
1230err_cleanup_planes: 1231err_cleanup_planes:
1231 list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) 1232 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1233 head)
1232 drm_plane_cleanup(plane); 1234 drm_plane_cleanup(plane);
1233 return ret; 1235 return ret;
1234} 1236}
@@ -1236,9 +1238,28 @@ err_cleanup_planes:
1236static void vop_destroy_crtc(struct vop *vop) 1238static void vop_destroy_crtc(struct vop *vop)
1237{ 1239{
1238 struct drm_crtc *crtc = &vop->crtc; 1240 struct drm_crtc *crtc = &vop->crtc;
1241 struct drm_device *drm_dev = vop->drm_dev;
1242 struct drm_plane *plane, *tmp;
1239 1243
1240 rockchip_unregister_crtc_funcs(crtc); 1244 rockchip_unregister_crtc_funcs(crtc);
1241 of_node_put(crtc->port); 1245 of_node_put(crtc->port);
1246
1247 /*
1248 * We need to cleanup the planes now. Why?
1249 *
1250 * The planes are "&vop->win[i].base". That means the memory is
1251 * all part of the big "struct vop" chunk of memory. That memory
1252 * was devm allocated and associated with this component. We need to
1253 * free it ourselves before vop_unbind() finishes.
1254 */
1255 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1256 head)
1257 vop_plane_destroy(plane);
1258
1259 /*
1260 * Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
1261 * references the CRTC.
1262 */
1242 drm_crtc_cleanup(crtc); 1263 drm_crtc_cleanup(crtc);
1243} 1264}
1244 1265