drm/atomic_helper: Cope with plane->crtc == NULL in disable helper

The drm core can call the plane disable hook multiple times, which
means it can get called when plane->crtc is already NULL. That in turn
means we can't get at the implicit acquire ctx we use in the atomic
helpers for legacy entries points.

We could try to pass drm_modeset_legacy_acquire_ctx a drm_device
pointer so that it can cope with a NULL crtc. But that still doesn't
work since the cursor ioctls (remapped with the universal cursor plane
support code) only grabs the crtc locks. So the global acquire context
isn't set eitehr.

The real solution here would be to bite the bullet and wire up
explicit acquire context parameters to all relevant functions. We need
to do that anyway (to be able to get rid of some small allocations
which we can't cope with failing). But that's a lot of work and better
done once atomic has settled a bit.

So meanwhile just catch this case in the helper and bail out.

Signed-off-by: Jasper St. Pierre <jstpierre@mecheye.net>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
[danvet: Completely rewrite commit message and comment but keep
Jasper's logic and author credits since his patch is the only
short-term solution that works.]
Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 4368581..d981d07 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1275,6 +1275,17 @@
 	struct drm_plane_state *plane_state;
 	int ret = 0;
 
+	/*
+	 * FIXME: Without plane->crtc set we can't get at the implicit legacy
+	 * acquire context. The real fix will be to wire the acquire ctx through
+	 * everywhere we need it, but meanwhile prevent chaos by just skipping
+	 * this noop. The critical case is the cursor ioctls which a) only grab
+	 * crtc/cursor-plane locks (so we need the crtc to get at the right
+	 * acquire context) and b) can try to disable the plane multiple times.
+	 */
+	if (!plane->crtc)
+		return 0;
+
 	state = drm_atomic_state_alloc(plane->dev);
 	if (!state)
 		return -ENOMEM;