mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	drm: Stop updating plane->crtc/fb/old_fb on atomic drivers
Stop playing around with plane->crtc/fb/old_fb with atomic drivers. Make life a lot simpler when we don't have to do the magic old_fb vs. fb dance around plane updates. That way we can't risk plane->fb getting out of sync with plane->state->fb and we're less likely to leak any refcounts as well. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180525185045.29689-14-ville.syrjala@linux.intel.com Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
		
							parent
							
								
									2f958af7fc
								
							
						
					
					
						commit
						e00fb8564e
					
				
					 8 changed files with 24 additions and 87 deletions
				
			
		|  | @ -692,6 +692,11 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, | |||
| 
 | ||||
| 	WARN_ON(!state->acquire_ctx); | ||||
| 
 | ||||
| 	/* the legacy pointers should never be set */ | ||||
| 	WARN_ON(plane->fb); | ||||
| 	WARN_ON(plane->old_fb); | ||||
| 	WARN_ON(plane->crtc); | ||||
| 
 | ||||
| 	plane_state = drm_atomic_get_existing_plane_state(state, plane); | ||||
| 	if (plane_state) | ||||
| 		return plane_state; | ||||
|  | @ -2039,45 +2044,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state, | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers. | ||||
|  * | ||||
|  * @dev: drm device to check. | ||||
|  * @plane_mask: plane mask for planes that were updated. | ||||
|  * @ret: return value, can be -EDEADLK for a retry. | ||||
|  * | ||||
|  * Before doing an update &drm_plane.old_fb is set to &drm_plane.fb, but before | ||||
|  * dropping the locks old_fb needs to be set to NULL and plane->fb updated. This | ||||
|  * is a common operation for each atomic update, so this call is split off as a | ||||
|  * helper. | ||||
|  */ | ||||
| void drm_atomic_clean_old_fb(struct drm_device *dev, | ||||
| 			     unsigned plane_mask, | ||||
| 			     int ret) | ||||
| { | ||||
| 	struct drm_plane *plane; | ||||
| 
 | ||||
| 	/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
 | ||||
| 	 * locks (ie. while it is still safe to deref plane->state).  We | ||||
| 	 * need to do this here because the driver entry points cannot | ||||
| 	 * distinguish between legacy and atomic ioctls. | ||||
| 	 */ | ||||
| 	drm_for_each_plane_mask(plane, dev, plane_mask) { | ||||
| 		if (ret == 0) { | ||||
| 			struct drm_framebuffer *new_fb = plane->state->fb; | ||||
| 			if (new_fb) | ||||
| 				drm_framebuffer_get(new_fb); | ||||
| 			plane->fb = new_fb; | ||||
| 			plane->crtc = plane->state->crtc; | ||||
| 
 | ||||
| 			if (plane->old_fb) | ||||
| 				drm_framebuffer_put(plane->old_fb); | ||||
| 		} | ||||
| 		plane->old_fb = NULL; | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL(drm_atomic_clean_old_fb); | ||||
| 
 | ||||
| /**
 | ||||
|  * DOC: explicit fencing properties | ||||
|  * | ||||
|  | @ -2298,9 +2264,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
| 	unsigned int copied_objs, copied_props; | ||||
| 	struct drm_atomic_state *state; | ||||
| 	struct drm_modeset_acquire_ctx ctx; | ||||
| 	struct drm_plane *plane; | ||||
| 	struct drm_out_fence_state *fence_state; | ||||
| 	unsigned plane_mask; | ||||
| 	int ret = 0; | ||||
| 	unsigned int i, j, num_fences; | ||||
| 
 | ||||
|  | @ -2340,7 +2304,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
| 	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); | ||||
| 
 | ||||
| retry: | ||||
| 	plane_mask = 0; | ||||
| 	copied_objs = 0; | ||||
| 	copied_props = 0; | ||||
| 	fence_state = NULL; | ||||
|  | @ -2411,12 +2374,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
| 			copied_props++; | ||||
| 		} | ||||
| 
 | ||||
| 		if (obj->type == DRM_MODE_OBJECT_PLANE && count_props && | ||||
| 		    !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) { | ||||
| 			plane = obj_to_plane(obj); | ||||
| 			plane_mask |= (1 << drm_plane_index(plane)); | ||||
| 			plane->old_fb = plane->fb; | ||||
| 		} | ||||
| 		drm_mode_object_put(obj); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -2437,8 +2394,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||||
| 
 | ||||
| 	complete_crtc_signaling(dev, state, fence_state, num_fences, !ret); | ||||
| 
 | ||||
| 	if (ret == -EDEADLK) { | ||||
|  |  | |||
|  | @ -2914,7 +2914,6 @@ static int __drm_atomic_helper_disable_all(struct drm_device *dev, | |||
| 	struct drm_plane *plane; | ||||
| 	struct drm_crtc_state *crtc_state; | ||||
| 	struct drm_crtc *crtc; | ||||
| 	unsigned plane_mask = 0; | ||||
| 	int ret, i; | ||||
| 
 | ||||
| 	state = drm_atomic_state_alloc(dev); | ||||
|  | @ -2957,17 +2956,10 @@ static int __drm_atomic_helper_disable_all(struct drm_device *dev, | |||
| 			goto free; | ||||
| 
 | ||||
| 		drm_atomic_set_fb_for_plane(plane_state, NULL); | ||||
| 
 | ||||
| 		if (clean_old_fbs) { | ||||
| 			plane->old_fb = plane->fb; | ||||
| 			plane_mask |= BIT(drm_plane_index(plane)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ret = drm_atomic_commit(state); | ||||
| free: | ||||
| 	if (plane_mask) | ||||
| 		drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||||
| 	drm_atomic_state_put(state); | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -3129,13 +3121,8 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, | |||
| 
 | ||||
| 	state->acquire_ctx = ctx; | ||||
| 
 | ||||
| 	for_each_new_plane_in_state(state, plane, new_plane_state, i) { | ||||
| 		WARN_ON(plane->crtc != new_plane_state->crtc); | ||||
| 		WARN_ON(plane->fb != new_plane_state->fb); | ||||
| 		WARN_ON(plane->old_fb); | ||||
| 
 | ||||
| 	for_each_new_plane_in_state(state, plane, new_plane_state, i) | ||||
| 		state->planes[i].old_state = plane->state; | ||||
| 	} | ||||
| 
 | ||||
| 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) | ||||
| 		state->crtcs[i].old_state = crtc->state; | ||||
|  |  | |||
|  | @ -479,8 +479,12 @@ static int __drm_mode_set_config_internal(struct drm_mode_set *set, | |||
| 
 | ||||
| 	ret = crtc->funcs->set_config(set, ctx); | ||||
| 	if (ret == 0) { | ||||
| 		crtc->primary->crtc = fb ? crtc : NULL; | ||||
| 		crtc->primary->fb = fb; | ||||
| 		struct drm_plane *plane = crtc->primary; | ||||
| 
 | ||||
| 		if (!plane->state) { | ||||
| 			plane->crtc = fb ? crtc : NULL; | ||||
| 			plane->fb = fb; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	drm_for_each_crtc(tmp, crtc->dev) { | ||||
|  |  | |||
|  | @ -368,7 +368,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ | |||
| 	struct drm_plane *plane; | ||||
| 	struct drm_atomic_state *state; | ||||
| 	int i, ret; | ||||
| 	unsigned int plane_mask; | ||||
| 	struct drm_modeset_acquire_ctx ctx; | ||||
| 
 | ||||
| 	drm_modeset_acquire_init(&ctx, 0); | ||||
|  | @ -381,7 +380,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ | |||
| 
 | ||||
| 	state->acquire_ctx = &ctx; | ||||
| retry: | ||||
| 	plane_mask = 0; | ||||
| 	drm_for_each_plane(plane, dev) { | ||||
| 		plane_state = drm_atomic_get_plane_state(state, plane); | ||||
| 		if (IS_ERR(plane_state)) { | ||||
|  | @ -391,9 +389,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ | |||
| 
 | ||||
| 		plane_state->rotation = DRM_MODE_ROTATE_0; | ||||
| 
 | ||||
| 		plane->old_fb = plane->fb; | ||||
| 		plane_mask |= 1 << drm_plane_index(plane); | ||||
| 
 | ||||
| 		/* disable non-primary: */ | ||||
| 		if (plane->type == DRM_PLANE_TYPE_PRIMARY) | ||||
| 			continue; | ||||
|  | @ -430,8 +425,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ | |||
| 	ret = drm_atomic_commit(state); | ||||
| 
 | ||||
| out_state: | ||||
| 	drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||||
| 
 | ||||
| 	if (ret == -EDEADLK) | ||||
| 		goto backoff; | ||||
| 
 | ||||
|  |  | |||
|  | @ -836,8 +836,6 @@ static int atomic_remove_fb(struct drm_framebuffer *fb) | |||
| 			goto unlock; | ||||
| 
 | ||||
| 		plane_mask |= BIT(drm_plane_index(plane)); | ||||
| 
 | ||||
| 		plane->old_fb = plane->fb; | ||||
| 	} | ||||
| 
 | ||||
| 	/* This list is only filled when disable_crtcs is set. */ | ||||
|  | @ -852,9 +850,6 @@ static int atomic_remove_fb(struct drm_framebuffer *fb) | |||
| 		ret = drm_atomic_commit(state); | ||||
| 
 | ||||
| unlock: | ||||
| 	if (plane_mask) | ||||
| 		drm_atomic_clean_old_fb(dev, plane_mask, ret); | ||||
| 
 | ||||
| 	if (ret == -EDEADLK) { | ||||
| 		drm_atomic_state_clear(state); | ||||
| 		drm_modeset_backoff(&ctx); | ||||
|  |  | |||
|  | @ -651,9 +651,11 @@ static int __setplane_internal(struct drm_plane *plane, | |||
| 					 crtc_x, crtc_y, crtc_w, crtc_h, | ||||
| 					 src_x, src_y, src_w, src_h, ctx); | ||||
| 	if (!ret) { | ||||
| 		plane->crtc = crtc; | ||||
| 		plane->fb = fb; | ||||
| 		drm_framebuffer_get(plane->fb); | ||||
| 		if (!plane->state) { | ||||
| 			plane->crtc = crtc; | ||||
| 			plane->fb = fb; | ||||
| 			drm_framebuffer_get(plane->fb); | ||||
| 		} | ||||
| 	} else { | ||||
| 		plane->old_fb = NULL; | ||||
| 	} | ||||
|  | @ -1093,8 +1095,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
| 		/* Keep the old fb, don't unref it. */ | ||||
| 		plane->old_fb = NULL; | ||||
| 	} else { | ||||
| 		plane->fb = fb; | ||||
| 		drm_framebuffer_get(fb); | ||||
| 		if (!plane->state) { | ||||
| 			plane->fb = fb; | ||||
| 			drm_framebuffer_get(fb); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
|  |  | |||
|  | @ -502,6 +502,7 @@ EXPORT_SYMBOL(drm_plane_helper_update); | |||
| int drm_plane_helper_disable(struct drm_plane *plane) | ||||
| { | ||||
| 	struct drm_plane_state *plane_state; | ||||
| 	struct drm_framebuffer *old_fb; | ||||
| 
 | ||||
| 	/* crtc helpers love to call disable functions for already disabled hw
 | ||||
| 	 * functions. So cope with that. */ | ||||
|  | @ -521,8 +522,9 @@ int drm_plane_helper_disable(struct drm_plane *plane) | |||
| 	plane_state->plane = plane; | ||||
| 
 | ||||
| 	plane_state->crtc = NULL; | ||||
| 	old_fb = plane_state->fb; | ||||
| 	drm_atomic_set_fb_for_plane(plane_state, NULL); | ||||
| 
 | ||||
| 	return drm_plane_helper_commit(plane, plane_state, plane->fb); | ||||
| 	return drm_plane_helper_commit(plane, plane_state, old_fb); | ||||
| } | ||||
| EXPORT_SYMBOL(drm_plane_helper_disable); | ||||
|  |  | |||
|  | @ -601,9 +601,6 @@ int __must_check | |||
| drm_atomic_add_affected_planes(struct drm_atomic_state *state, | ||||
| 			       struct drm_crtc *crtc); | ||||
| 
 | ||||
| void | ||||
| drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret); | ||||
| 
 | ||||
| int __must_check drm_atomic_check_only(struct drm_atomic_state *state); | ||||
| int __must_check drm_atomic_commit(struct drm_atomic_state *state); | ||||
| int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Ville Syrjälä
						Ville Syrjälä