All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/14] drm: Add drm/kernel.h header file
@ 2018-09-03 16:54 Daniel Vetter
  2018-09-03 16:54 ` [PATCH 02/14] drm: Drop drmP.h from drm_connector.c Daniel Vetter
                   ` (18 more replies)
  0 siblings, 19 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Sean Paul

We have a bunch of neat little macros all over the place which should
move to kernel.h. But some of them died in bikesheds on lkml, and we
need a decent home for them.

Start out by moving the for_each_if macro there.

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h             |  1 +
 drivers/gpu/drm/i915/intel_display.h        |  2 ++
 drivers/gpu/drm/i915/intel_ringbuffer.h     |  2 ++
 drivers/gpu/drm/nouveau/nouveau_connector.h |  2 ++
 include/drm/drmP.h                          |  3 --
 include/drm/drm_atomic.h                    |  1 +
 include/drm/drm_atomic_helper.h             |  1 +
 include/drm/drm_connector.h                 |  1 +
 include/drm/drm_encoder.h                   |  1 +
 include/drm/drm_plane.h                     |  1 +
 include/drm/kernel.h                        | 32 +++++++++++++++++++++
 11 files changed, 44 insertions(+), 3 deletions(-)
 create mode 100644 include/drm/kernel.h

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 14e562887307..63cd53067cc3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -52,6 +52,7 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_auth.h>
 #include <drm/drm_cache.h>
+#include <drm/kernel.h>
 
 #include "i915_params.h"
 #include "i915_reg.h"
diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
index e20e6a36a748..bb6e8d949ebb 100644
--- a/drivers/gpu/drm/i915/intel_display.h
+++ b/drivers/gpu/drm/i915/intel_display.h
@@ -25,6 +25,8 @@
 #ifndef _INTEL_DISPLAY_H_
 #define _INTEL_DISPLAY_H_
 
+#include <drm/kernel.h>
+
 enum i915_gpio {
 	GPIOA,
 	GPIOB,
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 3f6920dd7880..c06ec8078313 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -2,6 +2,8 @@
 #ifndef _INTEL_RINGBUFFER_H_
 #define _INTEL_RINGBUFFER_H_
 
+#include <drm/kernel.h>
+
 #include <linux/hashtable.h>
 #include <linux/seqlock.h>
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index dc7454e7f19a..fff89cb4a792 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -32,6 +32,8 @@
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/kernel.h>
+
 #include "nouveau_crtc.h"
 #include "nouveau_encoder.h"
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index f7a19c2a7a80..05350424a4d3 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -110,7 +110,4 @@ static inline bool drm_can_sleep(void)
 	return true;
 }
 
-/* helper for handling conditionals in various for_each macros */
-#define for_each_if(condition) if (!(condition)) {} else
-
 #endif
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index da9d95a19580..07b4cb1c9603 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -29,6 +29,7 @@
 #define DRM_ATOMIC_H_
 
 #include <drm/drm_crtc.h>
+#include <drm/kernel.h>
 
 /**
  * struct drm_crtc_commit - track modeset commits on a CRTC
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index f4c7ed876c97..63e736eeb516 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -31,6 +31,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_modeset_helper.h>
+#include <drm/kernel.h>
 
 struct drm_atomic_state;
 struct drm_private_obj;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 97ea41dc678f..95be147ee4db 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/hdmi.h>
 #include <drm/drm_mode_object.h>
+#include <drm/kernel.h>
 
 #include <uapi/drm/drm_mode.h>
 
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 4f597c0730b4..9cb01c764fac 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -28,6 +28,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_mode_object.h>
+#include <drm/kernel.h>
 
 struct drm_encoder;
 
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 16f5b66684ca..2af3f0a7d2e7 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -27,6 +27,7 @@
 #include <linux/ctype.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_color_mgmt.h>
+#include <drm/kernel.h>
 
 struct drm_crtc;
 struct drm_printer;
diff --git a/include/drm/kernel.h b/include/drm/kernel.h
new file mode 100644
index 000000000000..6ea220c0c132
--- /dev/null
+++ b/include/drm/kernel.h
@@ -0,0 +1,32 @@
+/*
+ * Internal Header for the Direct Rendering Manager
+ *
+ * Copyright 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_KERNEL_H_
+#define _DRM_KERNEL_H_
+
+/* helper for handling conditionals in various for_each macros */
+#define for_each_if(condition) if (!(condition)) {} else
+
+#endif
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 02/14] drm: Drop drmP.h from drm_connector.c
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 03/14] drm: drop drmP.h include from drm_plane.c Daniel Vetter
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

Only needed minimal changes in drm_internal.h (for the drm_ioctl_t
type and a few forward declarations), plus a few missing includes in
drm_connector.c.

Yay, the last stage of the drm header cleanup can finally commence!

v2: Compiles now, with drm/kernel.h extracted.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_connector.c | 6 +++++-
 drivers/gpu/drm/drm_internal.h  | 5 +++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 6011d769d50b..526619f963e5 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -20,11 +20,15 @@
  * OF THIS SOFTWARE.
  */
 
-#include <drm/drmP.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_utils.h>
+#include <drm/drm_print.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+
+#include <linux/uaccess.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 40179c5fc6b8..0c4eb4a9ab31 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -21,9 +21,14 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <drm/drm_ioctl.h>
+
 #define DRM_IF_MAJOR 1
 #define DRM_IF_MINOR 4
 
+struct drm_prime_file_private;
+struct dma_buf;
+
 /* drm_file.c */
 extern struct mutex drm_global_mutex;
 struct drm_file *drm_file_alloc(struct drm_minor *minor);
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 03/14] drm: drop drmP.h include from drm_plane.c
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
  2018-09-03 16:54 ` [PATCH 02/14] drm: Drop drmP.h from drm_connector.c Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 04/14] drm: drop drmP.h include from drm_crtc.c Daniel Vetter
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

Just a bit of missing includes and pre declarations.

v2: Compiles now, with drm/kernel.h extracted.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc_internal.h |  8 ++++++++
 drivers/gpu/drm/drm_plane.c         | 11 ++++++++++-
 include/drm/drm_color_mgmt.h        |  1 +
 include/drm/drm_plane.h             |  2 ++
 include/drm/drm_property.h          |  2 ++
 5 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index b61322763394..ff5e0d521c21 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -31,6 +31,14 @@
  * and are not exported to drivers.
  */
 
+enum drm_mode_status;
+enum drm_connector_force;
+
+struct drm_display_mode;
+struct work_struct;
+struct drm_connector;
+struct drm_bridge;
+struct edid;
 
 /* drm_crtc.c */
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 6153cbda239f..36bf3fe9ad21 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -20,8 +20,17 @@
  * OF THIS SOFTWARE.
  */
 
-#include <drm/drmP.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
 #include <drm/drm_plane.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_file.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_vblank.h>
 
 #include "drm_crtc_internal.h"
 
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
index 44f04233e3db..90ef9996d9a4 100644
--- a/include/drm/drm_color_mgmt.h
+++ b/include/drm/drm_color_mgmt.h
@@ -24,6 +24,7 @@
 #define __DRM_COLOR_MGMT_H__
 
 #include <linux/ctype.h>
+#include <drm/drm_property.h>
 
 struct drm_crtc;
 struct drm_plane;
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 2af3f0a7d2e7..fe6c4aee2d08 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -27,6 +27,8 @@
 #include <linux/ctype.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_color_mgmt.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_modeset_lock.h>
 #include <drm/kernel.h>
 
 struct drm_crtc;
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index c030f6ccab99..5b9efff35d6d 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -27,6 +27,8 @@
 #include <linux/ctype.h>
 #include <drm/drm_mode_object.h>
 
+#include <uapi/drm/drm_mode.h>
+
 /**
  * struct drm_property_enum - symbolic values for enumerations
  * @value: numeric property value for this enum entry
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 04/14] drm: drop drmP.h include from drm_crtc.c
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
  2018-09-03 16:54 ` [PATCH 02/14] drm: Drop drmP.h from drm_connector.c Daniel Vetter
  2018-09-03 16:54 ` [PATCH 03/14] drm: drop drmP.h include from drm_plane.c Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 05/14] drm/atomic: trim driver interface/docs Daniel Vetter
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

This is starting to become easy!

v2: Compiles now, with drm/kernel.h extracted.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bae43938c8f6..2f6c877299e4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -34,7 +34,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <linux/dma-fence.h>
-#include <drm/drmP.h>
+#include <linux/uaccess.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fourcc.h>
@@ -42,6 +42,9 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_auth.h>
 #include <drm/drm_debugfs_crc.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
+#include <drm/drm_file.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 05/14] drm/atomic: trim driver interface/docs
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (2 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 04/14] drm: drop drmP.h include from drm_crtc.c Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
       [not found] ` <20180903165439.24845-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Sean Paul, Daniel Vetter

Remove the kerneldoc and EXPORT_SYMBOL which aren't used and really
shouldn't ever be used by drivers directly.

Unfortunately this means we need to move the set_writeback_fb function
around to avoid a forward decl.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
---
 Documentation/gpu/drm-kms.rst |   3 -
 drivers/gpu/drm/drm_atomic.c  | 219 ++++++----------------------------
 include/drm/drm_atomic.h      |   6 -
 3 files changed, 34 insertions(+), 194 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index f8f5bf11a6ca..3a9dd68b97c9 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -287,9 +287,6 @@ Atomic Mode Setting Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
    :export:
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
-   :internal:
-
 CRTC Abstraction
 ================
 
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 151dd7162b3a..29a4e6959358 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -464,30 +464,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
 
-/**
- * drm_atomic_replace_property_blob_from_id - lookup the new blob and replace the old one with it
- * @dev: DRM device
- * @blob: a pointer to the member blob to be replaced
- * @blob_id: ID of the new blob
- * @expected_size: total expected size of the blob data (in bytes)
- * @expected_elem_size: expected element size of the blob data (in bytes)
- * @replaced: did the blob get replaced?
- *
- * Replace @blob with another blob with the ID @blob_id. If @blob_id is zero
- * @blob becomes NULL.
- *
- * If @expected_size is positive the new blob length is expected to be equal
- * to @expected_size bytes. If @expected_elem_size is positive the new blob
- * length is expected to be a multiple of @expected_elem_size bytes. Otherwise
- * an error is returned.
- *
- * @replaced will indicate to the caller whether the blob was replaced or not.
- * If the old and new blobs were in fact the same blob @replaced will be false
- * otherwise it will be true.
- *
- * RETURNS:
- * Zero on success, error code on failure.
- */
 static int
 drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
 					 struct drm_property_blob **blob,
@@ -521,22 +497,7 @@ drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
 	return 0;
 }
 
-/**
- * drm_atomic_crtc_set_property - set property on CRTC
- * @crtc: the drm CRTC to set a property on
- * @state: the state object to update with the new property value
- * @property: the property to set
- * @val: the new property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_crtc_funcs.atomic_set_property for driver properties. To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
-int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		struct drm_crtc_state *state, struct drm_property *property,
 		uint64_t val)
 {
@@ -598,23 +559,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 
 	return 0;
 }
-EXPORT_SYMBOL(drm_atomic_crtc_set_property);
 
-/**
- * drm_atomic_crtc_get_property - get property value from CRTC state
- * @crtc: the drm CRTC to set a property on
- * @state: the state object to get the property value from
- * @property: the property to set
- * @val: return location for the property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_crtc_funcs.atomic_get_property for driver properties. To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
 static int
 drm_atomic_crtc_get_property(struct drm_crtc *crtc,
 		const struct drm_crtc_state *state,
@@ -643,16 +588,6 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
 	return 0;
 }
 
-/**
- * drm_atomic_crtc_check - check crtc state
- * @crtc: crtc to check
- * @state: crtc state to check
- *
- * Provides core sanity checks for crtc state.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
 static int drm_atomic_crtc_check(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
@@ -728,16 +663,6 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
 		crtc->funcs->atomic_print_state(p, state);
 }
 
-/**
- * drm_atomic_connector_check - check connector state
- * @connector: connector to check
- * @state: connector state to check
- *
- * Provides core sanity checks for connector state.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
 static int drm_atomic_connector_check(struct drm_connector *connector,
 		struct drm_connector_state *state)
 {
@@ -923,21 +848,6 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 	return 0;
 }
 
-/**
- * drm_atomic_plane_get_property - get property value from plane state
- * @plane: the drm plane to set a property on
- * @state: the state object to get the property value from
- * @property: the property to set
- * @val: return location for the property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_plane_funcs.atomic_get_property for driver properties.  To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
 static int
 drm_atomic_plane_get_property(struct drm_plane *plane,
 		const struct drm_plane_state *state,
@@ -1328,21 +1238,39 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_connector_state);
 
-/**
- * drm_atomic_connector_set_property - set property on connector.
- * @connector: the drm connector to set a property on
- * @state: the state object to update with the new property value
- * @property: the property to set
- * @val: the new property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_connector_funcs.atomic_set_property for driver properties.  To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
+static struct drm_writeback_job *
+drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
+{
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!conn_state->writeback_job)
+		conn_state->writeback_job =
+			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
+
+	return conn_state->writeback_job;
+}
+
+static int drm_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	struct drm_writeback_job *job =
+		drm_atomic_get_writeback_job(conn_state);
+	if (!job)
+		return -ENOMEM;
+
+	drm_framebuffer_assign(&job->fb, fb);
+
+	if (fb)
+		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
+				 fb->base.id, conn_state);
+	else
+		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
+				 conn_state);
+
+	return 0;
+}
+
 static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		struct drm_connector_state *state, struct drm_property *property,
 		uint64_t val)
@@ -1449,21 +1377,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
 		connector->funcs->atomic_print_state(p, state);
 }
 
-/**
- * drm_atomic_connector_get_property - get property value from connector state
- * @connector: the drm connector to set a property on
- * @state: the state object to get the property value from
- * @property: the property to set
- * @val: return location for the property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_connector_funcs.atomic_get_property for driver properties.  To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
 static int
 drm_atomic_connector_get_property(struct drm_connector *connector,
 		const struct drm_connector_state *state,
@@ -1739,70 +1652,6 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
 
-/*
- * drm_atomic_get_writeback_job - return or allocate a writeback job
- * @conn_state: Connector state to get the job for
- *
- * Writeback jobs have a different lifetime to the atomic state they are
- * associated with. This convenience function takes care of allocating a job
- * if there isn't yet one associated with the connector state, otherwise
- * it just returns the existing job.
- *
- * Returns: The writeback job for the given connector state
- */
-static struct drm_writeback_job *
-drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
-{
-	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
-
-	if (!conn_state->writeback_job)
-		conn_state->writeback_job =
-			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
-
-	return conn_state->writeback_job;
-}
-
-/**
- * drm_atomic_set_writeback_fb_for_connector - set writeback framebuffer
- * @conn_state: atomic state object for the connector
- * @fb: fb to use for the connector
- *
- * This is used to set the framebuffer for a writeback connector, which outputs
- * to a buffer instead of an actual physical connector.
- * Changing the assigned framebuffer requires us to grab a reference to the new
- * fb and drop the reference to the old fb, if there is one. This function
- * takes care of all these details besides updating the pointer in the
- * state object itself.
- *
- * Note: The only way conn_state can already have an fb set is if the commit
- * sets the property more than once.
- *
- * See also: drm_writeback_connector_init()
- *
- * Returns: 0 on success
- */
-int drm_atomic_set_writeback_fb_for_connector(
-		struct drm_connector_state *conn_state,
-		struct drm_framebuffer *fb)
-{
-	struct drm_writeback_job *job =
-		drm_atomic_get_writeback_job(conn_state);
-	if (!job)
-		return -ENOMEM;
-
-	drm_framebuffer_assign(&job->fb, fb);
-
-	if (fb)
-		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
-				 fb->base.id, conn_state);
-	else
-		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
-				 conn_state);
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_writeback_fb_for_connector);
-
 /**
  * drm_atomic_add_affected_connectors - add connectors for crtc
  * @state: atomic state
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 07b4cb1c9603..66e49ef7d3b5 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -374,9 +374,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state);
 struct drm_crtc_state * __must_check
 drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 			  struct drm_crtc *crtc);
-int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
-		struct drm_crtc_state *state, struct drm_property *property,
-		uint64_t val);
 struct drm_plane_state * __must_check
 drm_atomic_get_plane_state(struct drm_atomic_state *state,
 			   struct drm_plane *plane);
@@ -603,9 +600,6 @@ void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
 int __must_check
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 				  struct drm_crtc *crtc);
-int drm_atomic_set_writeback_fb_for_connector(
-		struct drm_connector_state *conn_state,
-		struct drm_framebuffer *fb);
 int __must_check
 drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 				   struct drm_crtc *crtc);
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 06/14] drm: extract drm_atomic_uapi.c
       [not found] ` <20180903165439.24845-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
@ 2018-09-03 16:54   ` Daniel Vetter
  2018-09-04 20:41     ` Rodrigo Vivi
       [not found]     ` <20180903165439.24845-6-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
  0 siblings, 2 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Joonas Lahtinen, Maarten Lankhorst, Rob Clark, Jani Nikula,
	Eric Anholt, Rodrigo Vivi, Sean Paul, Gustavo Padovan,
	Daniel Vetter, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA

This leaves all the commit/check and state handling in drm_atomic.c,
while pulling all the uapi glue and the huge ioctl itself into a
seprate file.

This seems to almost perfectly split the rather big drm_atomic.c file
into 2 equal sizes.

Also adjust the kerneldoc and type a very terse overview text.

v2: Rebase.

v3: Fix tiny typo.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
---
 Documentation/gpu/drm-kms.rst                |   11 +-
 drivers/gpu/drm/Makefile                     |    3 +-
 drivers/gpu/drm/drm_atomic.c                 | 1359 +----------------
 drivers/gpu/drm/drm_atomic_helper.c          |    1 +
 drivers/gpu/drm/drm_atomic_uapi.c            | 1393 ++++++++++++++++++
 drivers/gpu/drm/drm_crtc_helper.c            |    1 +
 drivers/gpu/drm/drm_crtc_internal.h          |    5 +
 drivers/gpu/drm/drm_framebuffer.c            |    1 +
 drivers/gpu/drm/drm_gem_framebuffer_helper.c |    1 +
 drivers/gpu/drm/drm_plane_helper.c           |    1 +
 drivers/gpu/drm/i915/intel_display.c         |    1 +
 drivers/gpu/drm/msm/msm_atomic.c             |    2 +
 drivers/gpu/drm/vc4/vc4_crtc.c               |    1 +
 drivers/gpu/drm/vc4/vc4_plane.c              |    1 +
 include/drm/drm_atomic.h                     |   16 -
 include/drm/drm_atomic_uapi.h                |   58 +
 16 files changed, 1480 insertions(+), 1375 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_atomic_uapi.c
 create mode 100644 include/drm/drm_atomic_uapi.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 3a9dd68b97c9..4b1501b4835b 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -287,6 +287,15 @@ Atomic Mode Setting Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
    :export:
 
+Atomic Mode Setting IOCTL and UAPI Functions
+--------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
+   :export:
+
 CRTC Abstraction
 ================
 
@@ -563,7 +572,7 @@ Tile Group Property
 Explicit Fencing Properties
 ---------------------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
    :doc: explicit fencing properties
 
 Existing KMS Properties
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a6771cef85e2..bc6a16a3c36e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_encoder.o drm_mode_object.o drm_property.o \
 		drm_plane.o drm_color_mgmt.o drm_print.o \
 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
+		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
+		drm_atomic_uapi.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 29a4e6959358..19634e03b78e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -28,6 +28,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_print.h>
 #include <drm/drm_writeback.h>
@@ -309,285 +310,6 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 
-static void set_out_fence_for_crtc(struct drm_atomic_state *state,
-				   struct drm_crtc *crtc, s32 __user *fence_ptr)
-{
-	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
-}
-
-static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
-					  struct drm_crtc *crtc)
-{
-	s32 __user *fence_ptr;
-
-	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
-	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
-
-	return fence_ptr;
-}
-
-static int set_out_fence_for_connector(struct drm_atomic_state *state,
-					struct drm_connector *connector,
-					s32 __user *fence_ptr)
-{
-	unsigned int index = drm_connector_index(connector);
-
-	if (!fence_ptr)
-		return 0;
-
-	if (put_user(-1, fence_ptr))
-		return -EFAULT;
-
-	state->connectors[index].out_fence_ptr = fence_ptr;
-
-	return 0;
-}
-
-static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
-					       struct drm_connector *connector)
-{
-	unsigned int index = drm_connector_index(connector);
-	s32 __user *fence_ptr;
-
-	fence_ptr = state->connectors[index].out_fence_ptr;
-	state->connectors[index].out_fence_ptr = NULL;
-
-	return fence_ptr;
-}
-
-/**
- * drm_atomic_set_mode_for_crtc - set mode for CRTC
- * @state: the CRTC whose incoming state to update
- * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
- *
- * Set a mode (originating from the kernel) on the desired CRTC state and update
- * the enable property.
- *
- * RETURNS:
- * Zero on success, error code on failure. Cannot return -EDEADLK.
- */
-int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
-				 const struct drm_display_mode *mode)
-{
-	struct drm_crtc *crtc = state->crtc;
-	struct drm_mode_modeinfo umode;
-
-	/* Early return for no change. */
-	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
-		return 0;
-
-	drm_property_blob_put(state->mode_blob);
-	state->mode_blob = NULL;
-
-	if (mode) {
-		drm_mode_convert_to_umode(&umode, mode);
-		state->mode_blob =
-			drm_property_create_blob(state->crtc->dev,
-		                                 sizeof(umode),
-		                                 &umode);
-		if (IS_ERR(state->mode_blob))
-			return PTR_ERR(state->mode_blob);
-
-		drm_mode_copy(&state->mode, mode);
-		state->enable = true;
-		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
-				 mode->name, crtc->base.id, crtc->name, state);
-	} else {
-		memset(&state->mode, 0, sizeof(state->mode));
-		state->enable = false;
-		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
-				 crtc->base.id, crtc->name, state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
-
-/**
- * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
- * @state: the CRTC whose incoming state to update
- * @blob: pointer to blob property to use for mode
- *
- * Set a mode (originating from a blob property) on the desired CRTC state.
- * This function will take a reference on the blob property for the CRTC state,
- * and release the reference held on the state's existing mode property, if any
- * was set.
- *
- * RETURNS:
- * Zero on success, error code on failure. Cannot return -EDEADLK.
- */
-int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
-                                      struct drm_property_blob *blob)
-{
-	struct drm_crtc *crtc = state->crtc;
-
-	if (blob == state->mode_blob)
-		return 0;
-
-	drm_property_blob_put(state->mode_blob);
-	state->mode_blob = NULL;
-
-	memset(&state->mode, 0, sizeof(state->mode));
-
-	if (blob) {
-		int ret;
-
-		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
-					 crtc->base.id, crtc->name,
-					 blob->length);
-			return -EINVAL;
-		}
-
-		ret = drm_mode_convert_umode(crtc->dev,
-					     &state->mode, blob->data);
-		if (ret) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
-					 crtc->base.id, crtc->name,
-					 ret, drm_get_mode_status_name(state->mode.status));
-			drm_mode_debug_printmodeline(&state->mode);
-			return -EINVAL;
-		}
-
-		state->mode_blob = drm_property_blob_get(blob);
-		state->enable = true;
-		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
-				 state->mode.name, crtc->base.id, crtc->name,
-				 state);
-	} else {
-		state->enable = false;
-		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
-				 crtc->base.id, crtc->name, state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
-
-static int
-drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
-					 struct drm_property_blob **blob,
-					 uint64_t blob_id,
-					 ssize_t expected_size,
-					 ssize_t expected_elem_size,
-					 bool *replaced)
-{
-	struct drm_property_blob *new_blob = NULL;
-
-	if (blob_id != 0) {
-		new_blob = drm_property_lookup_blob(dev, blob_id);
-		if (new_blob == NULL)
-			return -EINVAL;
-
-		if (expected_size > 0 &&
-		    new_blob->length != expected_size) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-		if (expected_elem_size > 0 &&
-		    new_blob->length % expected_elem_size != 0) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-	}
-
-	*replaced |= drm_property_replace_blob(blob, new_blob);
-	drm_property_blob_put(new_blob);
-
-	return 0;
-}
-
-static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
-		struct drm_crtc_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-	bool replaced = false;
-	int ret;
-
-	if (property == config->prop_active)
-		state->active = val;
-	else if (property == config->prop_mode_id) {
-		struct drm_property_blob *mode =
-			drm_property_lookup_blob(dev, val);
-		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
-		drm_property_blob_put(mode);
-		return ret;
-	} else if (property == config->degamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->degamma_lut,
-					val,
-					-1, sizeof(struct drm_color_lut),
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->ctm_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->ctm,
-					val,
-					sizeof(struct drm_color_ctm), -1,
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->gamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->gamma_lut,
-					val,
-					-1, sizeof(struct drm_color_lut),
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->prop_out_fence_ptr) {
-		s32 __user *fence_ptr = u64_to_user_ptr(val);
-
-		if (!fence_ptr)
-			return 0;
-
-		if (put_user(-1, fence_ptr))
-			return -EFAULT;
-
-		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
-	} else if (crtc->funcs->atomic_set_property) {
-		return crtc->funcs->atomic_set_property(crtc, state, property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 crtc->base.id, crtc->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-drm_atomic_crtc_get_property(struct drm_crtc *crtc,
-		const struct drm_crtc_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_active)
-		*val = state->active;
-	else if (property == config->prop_mode_id)
-		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
-	else if (property == config->degamma_lut_property)
-		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
-	else if (property == config->ctm_property)
-		*val = (state->ctm) ? state->ctm->base.id : 0;
-	else if (property == config->gamma_lut_property)
-		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
-	else if (property == config->prop_out_fence_ptr)
-		*val = 0;
-	else if (crtc->funcs->atomic_get_property)
-		return crtc->funcs->atomic_get_property(crtc, state, property, val);
-	else
-		return -EINVAL;
-
-	return 0;
-}
-
 static int drm_atomic_crtc_check(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
@@ -761,144 +483,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
-/**
- * drm_atomic_plane_set_property - set property on plane
- * @plane: the drm plane to set a property on
- * @state: the state object to update with the new property value
- * @property: the property to set
- * @val: the new property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_plane_funcs.atomic_set_property for driver properties.  To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
-static int drm_atomic_plane_set_property(struct drm_plane *plane,
-		struct drm_plane_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = plane->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_fb_id) {
-		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
-		drm_atomic_set_fb_for_plane(state, fb);
-		if (fb)
-			drm_framebuffer_put(fb);
-	} else if (property == config->prop_in_fence_fd) {
-		if (state->fence)
-			return -EINVAL;
-
-		if (U642I64(val) == -1)
-			return 0;
-
-		state->fence = sync_file_get_fence(val);
-		if (!state->fence)
-			return -EINVAL;
-
-	} else if (property == config->prop_crtc_id) {
-		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
-		return drm_atomic_set_crtc_for_plane(state, crtc);
-	} else if (property == config->prop_crtc_x) {
-		state->crtc_x = U642I64(val);
-	} else if (property == config->prop_crtc_y) {
-		state->crtc_y = U642I64(val);
-	} else if (property == config->prop_crtc_w) {
-		state->crtc_w = val;
-	} else if (property == config->prop_crtc_h) {
-		state->crtc_h = val;
-	} else if (property == config->prop_src_x) {
-		state->src_x = val;
-	} else if (property == config->prop_src_y) {
-		state->src_y = val;
-	} else if (property == config->prop_src_w) {
-		state->src_w = val;
-	} else if (property == config->prop_src_h) {
-		state->src_h = val;
-	} else if (property == plane->alpha_property) {
-		state->alpha = val;
-	} else if (property == plane->blend_mode_property) {
-		state->pixel_blend_mode = val;
-	} else if (property == plane->rotation_property) {
-		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
-			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
-					 plane->base.id, plane->name, val);
-			return -EINVAL;
-		}
-		state->rotation = val;
-	} else if (property == plane->zpos_property) {
-		state->zpos = val;
-	} else if (property == plane->color_encoding_property) {
-		state->color_encoding = val;
-	} else if (property == plane->color_range_property) {
-		state->color_range = val;
-	} else if (plane->funcs->atomic_set_property) {
-		return plane->funcs->atomic_set_property(plane, state,
-				property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 plane->base.id, plane->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-drm_atomic_plane_get_property(struct drm_plane *plane,
-		const struct drm_plane_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = plane->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_fb_id) {
-		*val = (state->fb) ? state->fb->base.id : 0;
-	} else if (property == config->prop_in_fence_fd) {
-		*val = -1;
-	} else if (property == config->prop_crtc_id) {
-		*val = (state->crtc) ? state->crtc->base.id : 0;
-	} else if (property == config->prop_crtc_x) {
-		*val = I642U64(state->crtc_x);
-	} else if (property == config->prop_crtc_y) {
-		*val = I642U64(state->crtc_y);
-	} else if (property == config->prop_crtc_w) {
-		*val = state->crtc_w;
-	} else if (property == config->prop_crtc_h) {
-		*val = state->crtc_h;
-	} else if (property == config->prop_src_x) {
-		*val = state->src_x;
-	} else if (property == config->prop_src_y) {
-		*val = state->src_y;
-	} else if (property == config->prop_src_w) {
-		*val = state->src_w;
-	} else if (property == config->prop_src_h) {
-		*val = state->src_h;
-	} else if (property == plane->alpha_property) {
-		*val = state->alpha;
-	} else if (property == plane->blend_mode_property) {
-		*val = state->pixel_blend_mode;
-	} else if (property == plane->rotation_property) {
-		*val = state->rotation;
-	} else if (property == plane->zpos_property) {
-		*val = state->zpos;
-	} else if (property == plane->color_encoding_property) {
-		*val = state->color_encoding;
-	} else if (property == plane->color_range_property) {
-		*val = state->color_range;
-	} else if (plane->funcs->atomic_get_property) {
-		return plane->funcs->atomic_get_property(plane, state, property, val);
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static bool
 plane_switching_crtc(struct drm_atomic_state *state,
 		     struct drm_plane *plane,
@@ -1238,129 +822,6 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_connector_state);
 
-static struct drm_writeback_job *
-drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
-{
-	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
-
-	if (!conn_state->writeback_job)
-		conn_state->writeback_job =
-			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
-
-	return conn_state->writeback_job;
-}
-
-static int drm_atomic_set_writeback_fb_for_connector(
-		struct drm_connector_state *conn_state,
-		struct drm_framebuffer *fb)
-{
-	struct drm_writeback_job *job =
-		drm_atomic_get_writeback_job(conn_state);
-	if (!job)
-		return -ENOMEM;
-
-	drm_framebuffer_assign(&job->fb, fb);
-
-	if (fb)
-		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
-				 fb->base.id, conn_state);
-	else
-		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
-				 conn_state);
-
-	return 0;
-}
-
-static int drm_atomic_connector_set_property(struct drm_connector *connector,
-		struct drm_connector_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_crtc_id) {
-		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
-		return drm_atomic_set_crtc_for_connector(state, crtc);
-	} else if (property == config->dpms_property) {
-		/* setting DPMS property requires special handling, which
-		 * is done in legacy setprop path for us.  Disallow (for
-		 * now?) atomic writes to DPMS property:
-		 */
-		return -EINVAL;
-	} else if (property == config->tv_select_subconnector_property) {
-		state->tv.subconnector = val;
-	} else if (property == config->tv_left_margin_property) {
-		state->tv.margins.left = val;
-	} else if (property == config->tv_right_margin_property) {
-		state->tv.margins.right = val;
-	} else if (property == config->tv_top_margin_property) {
-		state->tv.margins.top = val;
-	} else if (property == config->tv_bottom_margin_property) {
-		state->tv.margins.bottom = val;
-	} else if (property == config->tv_mode_property) {
-		state->tv.mode = val;
-	} else if (property == config->tv_brightness_property) {
-		state->tv.brightness = val;
-	} else if (property == config->tv_contrast_property) {
-		state->tv.contrast = val;
-	} else if (property == config->tv_flicker_reduction_property) {
-		state->tv.flicker_reduction = val;
-	} else if (property == config->tv_overscan_property) {
-		state->tv.overscan = val;
-	} else if (property == config->tv_saturation_property) {
-		state->tv.saturation = val;
-	} else if (property == config->tv_hue_property) {
-		state->tv.hue = val;
-	} else if (property == config->link_status_property) {
-		/* Never downgrade from GOOD to BAD on userspace's request here,
-		 * only hw issues can do that.
-		 *
-		 * For an atomic property the userspace doesn't need to be able
-		 * to understand all the properties, but needs to be able to
-		 * restore the state it wants on VT switch. So if the userspace
-		 * tries to change the link_status from GOOD to BAD, driver
-		 * silently rejects it and returns a 0. This prevents userspace
-		 * from accidently breaking  the display when it restores the
-		 * state.
-		 */
-		if (state->link_status != DRM_LINK_STATUS_GOOD)
-			state->link_status = val;
-	} else if (property == config->aspect_ratio_property) {
-		state->picture_aspect_ratio = val;
-	} else if (property == config->content_type_property) {
-		state->content_type = val;
-	} else if (property == connector->scaling_mode_property) {
-		state->scaling_mode = val;
-	} else if (property == connector->content_protection_property) {
-		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
-			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
-			return -EINVAL;
-		}
-		state->content_protection = val;
-	} else if (property == config->writeback_fb_id_property) {
-		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
-		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
-		if (fb)
-			drm_framebuffer_put(fb);
-		return ret;
-	} else if (property == config->writeback_out_fence_ptr_property) {
-		s32 __user *fence_ptr = u64_to_user_ptr(val);
-
-		return set_out_fence_for_connector(state->state, connector,
-						   fence_ptr);
-	} else if (connector->funcs->atomic_set_property) {
-		return connector->funcs->atomic_set_property(connector,
-				state, property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 connector->base.id, connector->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static void drm_atomic_connector_print_state(struct drm_printer *p,
 		const struct drm_connector_state *state)
 {
@@ -1377,281 +838,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
 		connector->funcs->atomic_print_state(p, state);
 }
 
-static int
-drm_atomic_connector_get_property(struct drm_connector *connector,
-		const struct drm_connector_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_crtc_id) {
-		*val = (state->crtc) ? state->crtc->base.id : 0;
-	} else if (property == config->dpms_property) {
-		*val = connector->dpms;
-	} else if (property == config->tv_select_subconnector_property) {
-		*val = state->tv.subconnector;
-	} else if (property == config->tv_left_margin_property) {
-		*val = state->tv.margins.left;
-	} else if (property == config->tv_right_margin_property) {
-		*val = state->tv.margins.right;
-	} else if (property == config->tv_top_margin_property) {
-		*val = state->tv.margins.top;
-	} else if (property == config->tv_bottom_margin_property) {
-		*val = state->tv.margins.bottom;
-	} else if (property == config->tv_mode_property) {
-		*val = state->tv.mode;
-	} else if (property == config->tv_brightness_property) {
-		*val = state->tv.brightness;
-	} else if (property == config->tv_contrast_property) {
-		*val = state->tv.contrast;
-	} else if (property == config->tv_flicker_reduction_property) {
-		*val = state->tv.flicker_reduction;
-	} else if (property == config->tv_overscan_property) {
-		*val = state->tv.overscan;
-	} else if (property == config->tv_saturation_property) {
-		*val = state->tv.saturation;
-	} else if (property == config->tv_hue_property) {
-		*val = state->tv.hue;
-	} else if (property == config->link_status_property) {
-		*val = state->link_status;
-	} else if (property == config->aspect_ratio_property) {
-		*val = state->picture_aspect_ratio;
-	} else if (property == config->content_type_property) {
-		*val = state->content_type;
-	} else if (property == connector->scaling_mode_property) {
-		*val = state->scaling_mode;
-	} else if (property == connector->content_protection_property) {
-		*val = state->content_protection;
-	} else if (property == config->writeback_fb_id_property) {
-		/* Writeback framebuffer is one-shot, write and forget */
-		*val = 0;
-	} else if (property == config->writeback_out_fence_ptr_property) {
-		*val = 0;
-	} else if (connector->funcs->atomic_get_property) {
-		return connector->funcs->atomic_get_property(connector,
-				state, property, val);
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int drm_atomic_get_property(struct drm_mode_object *obj,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = property->dev;
-	int ret;
-
-	switch (obj->type) {
-	case DRM_MODE_OBJECT_CONNECTOR: {
-		struct drm_connector *connector = obj_to_connector(obj);
-		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
-		ret = drm_atomic_connector_get_property(connector,
-				connector->state, property, val);
-		break;
-	}
-	case DRM_MODE_OBJECT_CRTC: {
-		struct drm_crtc *crtc = obj_to_crtc(obj);
-		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-		ret = drm_atomic_crtc_get_property(crtc,
-				crtc->state, property, val);
-		break;
-	}
-	case DRM_MODE_OBJECT_PLANE: {
-		struct drm_plane *plane = obj_to_plane(obj);
-		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
-		ret = drm_atomic_plane_get_property(plane,
-				plane->state, property, val);
-		break;
-	}
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-/**
- * drm_atomic_set_crtc_for_plane - set crtc for plane
- * @plane_state: the plane whose incoming state to update
- * @crtc: crtc to use for the plane
- *
- * Changing the assigned crtc for a plane requires us to grab the lock and state
- * for the new crtc, as needed. This function takes care of all these details
- * besides updating the pointer in the state object itself.
- *
- * Returns:
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
- * then the w/w mutex code has detected a deadlock and the entire atomic
- * sequence must be restarted. All other errors are fatal.
- */
-int
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
-			      struct drm_crtc *crtc)
-{
-	struct drm_plane *plane = plane_state->plane;
-	struct drm_crtc_state *crtc_state;
-	/* Nothing to do for same crtc*/
-	if (plane_state->crtc == crtc)
-		return 0;
-	if (plane_state->crtc) {
-		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
-						       plane_state->crtc);
-		if (WARN_ON(IS_ERR(crtc_state)))
-			return PTR_ERR(crtc_state);
-
-		crtc_state->plane_mask &= ~drm_plane_mask(plane);
-	}
-
-	plane_state->crtc = crtc;
-
-	if (crtc) {
-		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
-						       crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-		crtc_state->plane_mask |= drm_plane_mask(plane);
-	}
-
-	if (crtc)
-		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
-				 plane->base.id, plane->name, plane_state,
-				 crtc->base.id, crtc->name);
-	else
-		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
-				 plane->base.id, plane->name, plane_state);
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
-
-/**
- * drm_atomic_set_fb_for_plane - set framebuffer for plane
- * @plane_state: atomic state object for the plane
- * @fb: fb to use for the plane
- *
- * Changing the assigned framebuffer for a plane requires us to grab a reference
- * to the new fb and drop the reference to the old fb, if there is one. This
- * function takes care of all these details besides updating the pointer in the
- * state object itself.
- */
-void
-drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
-			    struct drm_framebuffer *fb)
-{
-	struct drm_plane *plane = plane_state->plane;
-
-	if (fb)
-		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
-				 fb->base.id, plane->base.id, plane->name,
-				 plane_state);
-	else
-		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
-				 plane->base.id, plane->name, plane_state);
-
-	drm_framebuffer_assign(&plane_state->fb, fb);
-}
-EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
-
-/**
- * drm_atomic_set_fence_for_plane - set fence for plane
- * @plane_state: atomic state object for the plane
- * @fence: dma_fence to use for the plane
- *
- * Helper to setup the plane_state fence in case it is not set yet.
- * By using this drivers doesn't need to worry if the user choose
- * implicit or explicit fencing.
- *
- * This function will not set the fence to the state if it was set
- * via explicit fencing interfaces on the atomic ioctl. In that case it will
- * drop the reference to the fence as we are not storing it anywhere.
- * Otherwise, if &drm_plane_state.fence is not set this function we just set it
- * with the received implicit fence. In both cases this function consumes a
- * reference for @fence.
- *
- * This way explicit fencing can be used to overrule implicit fencing, which is
- * important to make explicit fencing use-cases work: One example is using one
- * buffer for 2 screens with different refresh rates. Implicit fencing will
- * clamp rendering to the refresh rate of the slower screen, whereas explicit
- * fence allows 2 independent render and display loops on a single buffer. If a
- * driver allows obeys both implicit and explicit fences for plane updates, then
- * it will break all the benefits of explicit fencing.
- */
-void
-drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
-			       struct dma_fence *fence)
-{
-	if (plane_state->fence) {
-		dma_fence_put(fence);
-		return;
-	}
-
-	plane_state->fence = fence;
-}
-EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
-
-/**
- * drm_atomic_set_crtc_for_connector - set crtc for connector
- * @conn_state: atomic state object for the connector
- * @crtc: crtc to use for the connector
- *
- * Changing the assigned crtc for a connector requires us to grab the lock and
- * state for the new crtc, as needed. This function takes care of all these
- * details besides updating the pointer in the state object itself.
- *
- * Returns:
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
- * then the w/w mutex code has detected a deadlock and the entire atomic
- * sequence must be restarted. All other errors are fatal.
- */
-int
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
-				  struct drm_crtc *crtc)
-{
-	struct drm_connector *connector = conn_state->connector;
-	struct drm_crtc_state *crtc_state;
-
-	if (conn_state->crtc == crtc)
-		return 0;
-
-	if (conn_state->crtc) {
-		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
-							   conn_state->crtc);
-
-		crtc_state->connector_mask &=
-			~drm_connector_mask(conn_state->connector);
-
-		drm_connector_put(conn_state->connector);
-		conn_state->crtc = NULL;
-	}
-
-	if (crtc) {
-		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-
-		crtc_state->connector_mask |=
-			drm_connector_mask(conn_state->connector);
-
-		drm_connector_get(conn_state->connector);
-		conn_state->crtc = crtc;
-
-		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
-				 connector->base.id, connector->name,
-				 conn_state, crtc->base.id, crtc->name);
-	} else {
-		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
-				 connector->base.id, connector->name,
-				 conn_state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
-
 /**
  * drm_atomic_add_affected_connectors - add connectors for crtc
  * @state: atomic state
@@ -1916,7 +1102,7 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
-static void drm_atomic_print_state(const struct drm_atomic_state *state)
+void drm_atomic_print_state(const struct drm_atomic_state *state)
 {
 	struct drm_printer p = drm_info_printer(state->dev->dev);
 	struct drm_plane *plane;
@@ -2023,544 +1209,3 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
 }
 #endif
 
-/*
- * The big monster ioctl
- */
-
-static struct drm_pending_vblank_event *create_vblank_event(
-		struct drm_crtc *crtc, uint64_t user_data)
-{
-	struct drm_pending_vblank_event *e = NULL;
-
-	e = kzalloc(sizeof *e, GFP_KERNEL);
-	if (!e)
-		return NULL;
-
-	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
-	e->event.base.length = sizeof(e->event);
-	e->event.vbl.crtc_id = crtc->base.id;
-	e->event.vbl.user_data = user_data;
-
-	return e;
-}
-
-int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
-				     struct drm_connector *connector,
-				     int mode)
-{
-	struct drm_connector *tmp_connector;
-	struct drm_connector_state *new_conn_state;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int i, ret, old_mode = connector->dpms;
-	bool active = false;
-
-	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
-			       state->acquire_ctx);
-	if (ret)
-		return ret;
-
-	if (mode != DRM_MODE_DPMS_ON)
-		mode = DRM_MODE_DPMS_OFF;
-	connector->dpms = mode;
-
-	crtc = connector->state->crtc;
-	if (!crtc)
-		goto out;
-	ret = drm_atomic_add_affected_connectors(state, crtc);
-	if (ret)
-		goto out;
-
-	crtc_state = drm_atomic_get_crtc_state(state, crtc);
-	if (IS_ERR(crtc_state)) {
-		ret = PTR_ERR(crtc_state);
-		goto out;
-	}
-
-	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
-		if (new_conn_state->crtc != crtc)
-			continue;
-		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
-			active = true;
-			break;
-		}
-	}
-
-	crtc_state->active = active;
-	ret = drm_atomic_commit(state);
-out:
-	if (ret != 0)
-		connector->dpms = old_mode;
-	return ret;
-}
-
-int drm_atomic_set_property(struct drm_atomic_state *state,
-			    struct drm_mode_object *obj,
-			    struct drm_property *prop,
-			    uint64_t prop_value)
-{
-	struct drm_mode_object *ref;
-	int ret;
-
-	if (!drm_property_change_valid_get(prop, prop_value, &ref))
-		return -EINVAL;
-
-	switch (obj->type) {
-	case DRM_MODE_OBJECT_CONNECTOR: {
-		struct drm_connector *connector = obj_to_connector(obj);
-		struct drm_connector_state *connector_state;
-
-		connector_state = drm_atomic_get_connector_state(state, connector);
-		if (IS_ERR(connector_state)) {
-			ret = PTR_ERR(connector_state);
-			break;
-		}
-
-		ret = drm_atomic_connector_set_property(connector,
-				connector_state, prop, prop_value);
-		break;
-	}
-	case DRM_MODE_OBJECT_CRTC: {
-		struct drm_crtc *crtc = obj_to_crtc(obj);
-		struct drm_crtc_state *crtc_state;
-
-		crtc_state = drm_atomic_get_crtc_state(state, crtc);
-		if (IS_ERR(crtc_state)) {
-			ret = PTR_ERR(crtc_state);
-			break;
-		}
-
-		ret = drm_atomic_crtc_set_property(crtc,
-				crtc_state, prop, prop_value);
-		break;
-	}
-	case DRM_MODE_OBJECT_PLANE: {
-		struct drm_plane *plane = obj_to_plane(obj);
-		struct drm_plane_state *plane_state;
-
-		plane_state = drm_atomic_get_plane_state(state, plane);
-		if (IS_ERR(plane_state)) {
-			ret = PTR_ERR(plane_state);
-			break;
-		}
-
-		ret = drm_atomic_plane_set_property(plane,
-				plane_state, prop, prop_value);
-		break;
-	}
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	drm_property_change_valid_put(prop, ref);
-	return ret;
-}
-
-/**
- * DOC: explicit fencing properties
- *
- * Explicit fencing allows userspace to control the buffer synchronization
- * between devices. A Fence or a group of fences are transfered to/from
- * userspace using Sync File fds and there are two DRM properties for that.
- * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
- * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
- *
- * As a contrast, with implicit fencing the kernel keeps track of any
- * ongoing rendering, and automatically ensures that the atomic update waits
- * for any pending rendering to complete. For shared buffers represented with
- * a &struct dma_buf this is tracked in &struct reservation_object.
- * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
- * whereas explicit fencing is what Android wants.
- *
- * "IN_FENCE_FD”:
- *	Use this property to pass a fence that DRM should wait on before
- *	proceeding with the Atomic Commit request and show the framebuffer for
- *	the plane on the screen. The fence can be either a normal fence or a
- *	merged one, the sync_file framework will handle both cases and use a
- *	fence_array if a merged fence is received. Passing -1 here means no
- *	fences to wait on.
- *
- *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
- *	it will only check if the Sync File is a valid one.
- *
- *	On the driver side the fence is stored on the @fence parameter of
- *	&struct drm_plane_state. Drivers which also support implicit fencing
- *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
- *	to make sure there's consistent behaviour between drivers in precedence
- *	of implicit vs. explicit fencing.
- *
- * "OUT_FENCE_PTR”:
- *	Use this property to pass a file descriptor pointer to DRM. Once the
- *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
- *	the file descriptor number of a Sync File. This Sync File contains the
- *	CRTC fence that will be signaled when all framebuffers present on the
- *	Atomic Commit * request for that given CRTC are scanned out on the
- *	screen.
- *
- *	The Atomic Commit request fails if a invalid pointer is passed. If the
- *	Atomic Commit request fails for any other reason the out fence fd
- *	returned will be -1. On a Atomic Commit with the
- *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
- *
- *	Note that out-fences don't have a special interface to drivers and are
- *	internally represented by a &struct drm_pending_vblank_event in struct
- *	&drm_crtc_state, which is also used by the nonblocking atomic commit
- *	helpers and for the DRM event handling for existing userspace.
- */
-
-struct drm_out_fence_state {
-	s32 __user *out_fence_ptr;
-	struct sync_file *sync_file;
-	int fd;
-};
-
-static int setup_out_fence(struct drm_out_fence_state *fence_state,
-			   struct dma_fence *fence)
-{
-	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fence_state->fd < 0)
-		return fence_state->fd;
-
-	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
-		return -EFAULT;
-
-	fence_state->sync_file = sync_file_create(fence);
-	if (!fence_state->sync_file)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int prepare_signaling(struct drm_device *dev,
-				  struct drm_atomic_state *state,
-				  struct drm_mode_atomic *arg,
-				  struct drm_file *file_priv,
-				  struct drm_out_fence_state **fence_state,
-				  unsigned int *num_fences)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	struct drm_connector *conn;
-	struct drm_connector_state *conn_state;
-	int i, c = 0, ret;
-
-	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
-		return 0;
-
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		s32 __user *fence_ptr;
-
-		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
-
-		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
-			struct drm_pending_vblank_event *e;
-
-			e = create_vblank_event(crtc, arg->user_data);
-			if (!e)
-				return -ENOMEM;
-
-			crtc_state->event = e;
-		}
-
-		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-			struct drm_pending_vblank_event *e = crtc_state->event;
-
-			if (!file_priv)
-				continue;
-
-			ret = drm_event_reserve_init(dev, file_priv, &e->base,
-						     &e->event.base);
-			if (ret) {
-				kfree(e);
-				crtc_state->event = NULL;
-				return ret;
-			}
-		}
-
-		if (fence_ptr) {
-			struct dma_fence *fence;
-			struct drm_out_fence_state *f;
-
-			f = krealloc(*fence_state, sizeof(**fence_state) *
-				     (*num_fences + 1), GFP_KERNEL);
-			if (!f)
-				return -ENOMEM;
-
-			memset(&f[*num_fences], 0, sizeof(*f));
-
-			f[*num_fences].out_fence_ptr = fence_ptr;
-			*fence_state = f;
-
-			fence = drm_crtc_create_fence(crtc);
-			if (!fence)
-				return -ENOMEM;
-
-			ret = setup_out_fence(&f[(*num_fences)++], fence);
-			if (ret) {
-				dma_fence_put(fence);
-				return ret;
-			}
-
-			crtc_state->event->base.fence = fence;
-		}
-
-		c++;
-	}
-
-	for_each_new_connector_in_state(state, conn, conn_state, i) {
-		struct drm_writeback_connector *wb_conn;
-		struct drm_writeback_job *job;
-		struct drm_out_fence_state *f;
-		struct dma_fence *fence;
-		s32 __user *fence_ptr;
-
-		fence_ptr = get_out_fence_for_connector(state, conn);
-		if (!fence_ptr)
-			continue;
-
-		job = drm_atomic_get_writeback_job(conn_state);
-		if (!job)
-			return -ENOMEM;
-
-		f = krealloc(*fence_state, sizeof(**fence_state) *
-			     (*num_fences + 1), GFP_KERNEL);
-		if (!f)
-			return -ENOMEM;
-
-		memset(&f[*num_fences], 0, sizeof(*f));
-
-		f[*num_fences].out_fence_ptr = fence_ptr;
-		*fence_state = f;
-
-		wb_conn = drm_connector_to_writeback(conn);
-		fence = drm_writeback_get_out_fence(wb_conn);
-		if (!fence)
-			return -ENOMEM;
-
-		ret = setup_out_fence(&f[(*num_fences)++], fence);
-		if (ret) {
-			dma_fence_put(fence);
-			return ret;
-		}
-
-		job->out_fence = fence;
-	}
-
-	/*
-	 * Having this flag means user mode pends on event which will never
-	 * reach due to lack of at least one CRTC for signaling
-	 */
-	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
-		return -EINVAL;
-
-	return 0;
-}
-
-static void complete_signaling(struct drm_device *dev,
-			       struct drm_atomic_state *state,
-			       struct drm_out_fence_state *fence_state,
-			       unsigned int num_fences,
-			       bool install_fds)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int i;
-
-	if (install_fds) {
-		for (i = 0; i < num_fences; i++)
-			fd_install(fence_state[i].fd,
-				   fence_state[i].sync_file->file);
-
-		kfree(fence_state);
-		return;
-	}
-
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		struct drm_pending_vblank_event *event = crtc_state->event;
-		/*
-		 * Free the allocated event. drm_atomic_helper_setup_commit
-		 * can allocate an event too, so only free it if it's ours
-		 * to prevent a double free in drm_atomic_state_clear.
-		 */
-		if (event && (event->base.fence || event->base.file_priv)) {
-			drm_event_cancel_free(dev, &event->base);
-			crtc_state->event = NULL;
-		}
-	}
-
-	if (!fence_state)
-		return;
-
-	for (i = 0; i < num_fences; i++) {
-		if (fence_state[i].sync_file)
-			fput(fence_state[i].sync_file->file);
-		if (fence_state[i].fd >= 0)
-			put_unused_fd(fence_state[i].fd);
-
-		/* If this fails log error to the user */
-		if (fence_state[i].out_fence_ptr &&
-		    put_user(-1, fence_state[i].out_fence_ptr))
-			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
-	}
-
-	kfree(fence_state);
-}
-
-int drm_mode_atomic_ioctl(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_atomic *arg = data;
-	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
-	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
-	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
-	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
-	unsigned int copied_objs, copied_props;
-	struct drm_atomic_state *state;
-	struct drm_modeset_acquire_ctx ctx;
-	struct drm_out_fence_state *fence_state;
-	int ret = 0;
-	unsigned int i, j, num_fences;
-
-	/* disallow for drivers not supporting atomic: */
-	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
-		return -EINVAL;
-
-	/* disallow for userspace that has not enabled atomic cap (even
-	 * though this may be a bit overkill, since legacy userspace
-	 * wouldn't know how to call this ioctl)
-	 */
-	if (!file_priv->atomic)
-		return -EINVAL;
-
-	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
-		return -EINVAL;
-
-	if (arg->reserved)
-		return -EINVAL;
-
-	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
-			!dev->mode_config.async_page_flip)
-		return -EINVAL;
-
-	/* can't test and expect an event at the same time. */
-	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
-			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
-		return -EINVAL;
-
-	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
-
-	state = drm_atomic_state_alloc(dev);
-	if (!state)
-		return -ENOMEM;
-
-	state->acquire_ctx = &ctx;
-	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
-
-retry:
-	copied_objs = 0;
-	copied_props = 0;
-	fence_state = NULL;
-	num_fences = 0;
-
-	for (i = 0; i < arg->count_objs; i++) {
-		uint32_t obj_id, count_props;
-		struct drm_mode_object *obj;
-
-		if (get_user(obj_id, objs_ptr + copied_objs)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
-		if (!obj) {
-			ret = -ENOENT;
-			goto out;
-		}
-
-		if (!obj->properties) {
-			drm_mode_object_put(obj);
-			ret = -ENOENT;
-			goto out;
-		}
-
-		if (get_user(count_props, count_props_ptr + copied_objs)) {
-			drm_mode_object_put(obj);
-			ret = -EFAULT;
-			goto out;
-		}
-
-		copied_objs++;
-
-		for (j = 0; j < count_props; j++) {
-			uint32_t prop_id;
-			uint64_t prop_value;
-			struct drm_property *prop;
-
-			if (get_user(prop_id, props_ptr + copied_props)) {
-				drm_mode_object_put(obj);
-				ret = -EFAULT;
-				goto out;
-			}
-
-			prop = drm_mode_obj_find_prop_id(obj, prop_id);
-			if (!prop) {
-				drm_mode_object_put(obj);
-				ret = -ENOENT;
-				goto out;
-			}
-
-			if (copy_from_user(&prop_value,
-					   prop_values_ptr + copied_props,
-					   sizeof(prop_value))) {
-				drm_mode_object_put(obj);
-				ret = -EFAULT;
-				goto out;
-			}
-
-			ret = drm_atomic_set_property(state, obj, prop,
-						      prop_value);
-			if (ret) {
-				drm_mode_object_put(obj);
-				goto out;
-			}
-
-			copied_props++;
-		}
-
-		drm_mode_object_put(obj);
-	}
-
-	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
-				&num_fences);
-	if (ret)
-		goto out;
-
-	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
-		ret = drm_atomic_check_only(state);
-	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
-		ret = drm_atomic_nonblocking_commit(state);
-	} else {
-		if (unlikely(drm_debug & DRM_UT_STATE))
-			drm_atomic_print_state(state);
-
-		ret = drm_atomic_commit(state);
-	}
-
-out:
-	complete_signaling(dev, state, fence_state, num_fences, !ret);
-
-	if (ret == -EDEADLK) {
-		drm_atomic_state_clear(state);
-		ret = drm_modeset_backoff(&ctx);
-		if (!ret)
-			goto retry;
-	}
-
-	drm_atomic_state_put(state);
-
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
-
-	return ret;
-}
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index daa04d29f8cc..8469a7e9afe3 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -27,6 +27,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
new file mode 100644
index 000000000000..26690a664ec6
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -0,0 +1,1393 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Copyright (C) 2014 Intel Corp.
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_print.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_writeback.h>
+#include <drm/drm_vblank.h>
+
+#include <linux/dma-fence.h>
+#include <linux/uaccess.h>
+#include <linux/sync_file.h>
+#include <linux/file.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * This file contains the marshalling and demarshalling glue for the atomic UAPI
+ * in all it's form: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
+ * SET_PROPERTY IOCTls. Plus interface functions for compatibility helpers and
+ * drivers which have special needs to construct their own atomic updates, e.g.
+ * for load detect or similiar.
+ */
+
+/**
+ * drm_atomic_set_mode_for_crtc - set mode for CRTC
+ * @state: the CRTC whose incoming state to update
+ * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
+ *
+ * Set a mode (originating from the kernel) on the desired CRTC state and update
+ * the enable property.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure. Cannot return -EDEADLK.
+ */
+int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
+				 const struct drm_display_mode *mode)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_mode_modeinfo umode;
+
+	/* Early return for no change. */
+	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
+		return 0;
+
+	drm_property_blob_put(state->mode_blob);
+	state->mode_blob = NULL;
+
+	if (mode) {
+		drm_mode_convert_to_umode(&umode, mode);
+		state->mode_blob =
+			drm_property_create_blob(state->crtc->dev,
+		                                 sizeof(umode),
+		                                 &umode);
+		if (IS_ERR(state->mode_blob))
+			return PTR_ERR(state->mode_blob);
+
+		drm_mode_copy(&state->mode, mode);
+		state->enable = true;
+		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+				 mode->name, crtc->base.id, crtc->name, state);
+	} else {
+		memset(&state->mode, 0, sizeof(state->mode));
+		state->enable = false;
+		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+				 crtc->base.id, crtc->name, state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
+
+/**
+ * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
+ * @state: the CRTC whose incoming state to update
+ * @blob: pointer to blob property to use for mode
+ *
+ * Set a mode (originating from a blob property) on the desired CRTC state.
+ * This function will take a reference on the blob property for the CRTC state,
+ * and release the reference held on the state's existing mode property, if any
+ * was set.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure. Cannot return -EDEADLK.
+ */
+int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
+                                      struct drm_property_blob *blob)
+{
+	struct drm_crtc *crtc = state->crtc;
+
+	if (blob == state->mode_blob)
+		return 0;
+
+	drm_property_blob_put(state->mode_blob);
+	state->mode_blob = NULL;
+
+	memset(&state->mode, 0, sizeof(state->mode));
+
+	if (blob) {
+		int ret;
+
+		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
+					 crtc->base.id, crtc->name,
+					 blob->length);
+			return -EINVAL;
+		}
+
+		ret = drm_mode_convert_umode(crtc->dev,
+					     &state->mode, blob->data);
+		if (ret) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
+					 crtc->base.id, crtc->name,
+					 ret, drm_get_mode_status_name(state->mode.status));
+			drm_mode_debug_printmodeline(&state->mode);
+			return -EINVAL;
+		}
+
+		state->mode_blob = drm_property_blob_get(blob);
+		state->enable = true;
+		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+				 state->mode.name, crtc->base.id, crtc->name,
+				 state);
+	} else {
+		state->enable = false;
+		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+				 crtc->base.id, crtc->name, state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
+
+/**
+ * drm_atomic_set_crtc_for_plane - set crtc for plane
+ * @plane_state: the plane whose incoming state to update
+ * @crtc: crtc to use for the plane
+ *
+ * Changing the assigned crtc for a plane requires us to grab the lock and state
+ * for the new crtc, as needed. This function takes care of all these details
+ * besides updating the pointer in the state object itself.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+			      struct drm_crtc *crtc)
+{
+	struct drm_plane *plane = plane_state->plane;
+	struct drm_crtc_state *crtc_state;
+	/* Nothing to do for same crtc*/
+	if (plane_state->crtc == crtc)
+		return 0;
+	if (plane_state->crtc) {
+		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
+						       plane_state->crtc);
+		if (WARN_ON(IS_ERR(crtc_state)))
+			return PTR_ERR(crtc_state);
+
+		crtc_state->plane_mask &= ~drm_plane_mask(plane);
+	}
+
+	plane_state->crtc = crtc;
+
+	if (crtc) {
+		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
+						       crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+		crtc_state->plane_mask |= drm_plane_mask(plane);
+	}
+
+	if (crtc)
+		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
+				 plane->base.id, plane->name, plane_state,
+				 crtc->base.id, crtc->name);
+	else
+		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
+				 plane->base.id, plane->name, plane_state);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
+
+/**
+ * drm_atomic_set_fb_for_plane - set framebuffer for plane
+ * @plane_state: atomic state object for the plane
+ * @fb: fb to use for the plane
+ *
+ * Changing the assigned framebuffer for a plane requires us to grab a reference
+ * to the new fb and drop the reference to the old fb, if there is one. This
+ * function takes care of all these details besides updating the pointer in the
+ * state object itself.
+ */
+void
+drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
+			    struct drm_framebuffer *fb)
+{
+	struct drm_plane *plane = plane_state->plane;
+
+	if (fb)
+		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
+				 fb->base.id, plane->base.id, plane->name,
+				 plane_state);
+	else
+		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
+				 plane->base.id, plane->name, plane_state);
+
+	drm_framebuffer_assign(&plane_state->fb, fb);
+}
+EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
+
+/**
+ * drm_atomic_set_fence_for_plane - set fence for plane
+ * @plane_state: atomic state object for the plane
+ * @fence: dma_fence to use for the plane
+ *
+ * Helper to setup the plane_state fence in case it is not set yet.
+ * By using this drivers doesn't need to worry if the user choose
+ * implicit or explicit fencing.
+ *
+ * This function will not set the fence to the state if it was set
+ * via explicit fencing interfaces on the atomic ioctl. In that case it will
+ * drop the reference to the fence as we are not storing it anywhere.
+ * Otherwise, if &drm_plane_state.fence is not set this function we just set it
+ * with the received implicit fence. In both cases this function consumes a
+ * reference for @fence.
+ *
+ * This way explicit fencing can be used to overrule implicit fencing, which is
+ * important to make explicit fencing use-cases work: One example is using one
+ * buffer for 2 screens with different refresh rates. Implicit fencing will
+ * clamp rendering to the refresh rate of the slower screen, whereas explicit
+ * fence allows 2 independent render and display loops on a single buffer. If a
+ * driver allows obeys both implicit and explicit fences for plane updates, then
+ * it will break all the benefits of explicit fencing.
+ */
+void
+drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+			       struct dma_fence *fence)
+{
+	if (plane_state->fence) {
+		dma_fence_put(fence);
+		return;
+	}
+
+	plane_state->fence = fence;
+}
+EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
+
+/**
+ * drm_atomic_set_crtc_for_connector - set crtc for connector
+ * @conn_state: atomic state object for the connector
+ * @crtc: crtc to use for the connector
+ *
+ * Changing the assigned crtc for a connector requires us to grab the lock and
+ * state for the new crtc, as needed. This function takes care of all these
+ * details besides updating the pointer in the state object itself.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
+				  struct drm_crtc *crtc)
+{
+	struct drm_connector *connector = conn_state->connector;
+	struct drm_crtc_state *crtc_state;
+
+	if (conn_state->crtc == crtc)
+		return 0;
+
+	if (conn_state->crtc) {
+		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
+							   conn_state->crtc);
+
+		crtc_state->connector_mask &=
+			~drm_connector_mask(conn_state->connector);
+
+		drm_connector_put(conn_state->connector);
+		conn_state->crtc = NULL;
+	}
+
+	if (crtc) {
+		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		crtc_state->connector_mask |=
+			drm_connector_mask(conn_state->connector);
+
+		drm_connector_get(conn_state->connector);
+		conn_state->crtc = crtc;
+
+		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
+				 connector->base.id, connector->name,
+				 conn_state, crtc->base.id, crtc->name);
+	} else {
+		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
+				 connector->base.id, connector->name,
+				 conn_state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
+
+static void set_out_fence_for_crtc(struct drm_atomic_state *state,
+				   struct drm_crtc *crtc, s32 __user *fence_ptr)
+{
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
+}
+
+static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
+					  struct drm_crtc *crtc)
+{
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,
+					s32 __user *fence_ptr)
+{
+	unsigned int index = drm_connector_index(connector);
+
+	if (!fence_ptr)
+		return 0;
+
+	if (put_user(-1, fence_ptr))
+		return -EFAULT;
+
+	state->connectors[index].out_fence_ptr = fence_ptr;
+
+	return 0;
+}
+
+static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)
+{
+	unsigned int index = drm_connector_index(connector);
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->connectors[index].out_fence_ptr;
+	state->connectors[index].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int
+drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
+					 struct drm_property_blob **blob,
+					 uint64_t blob_id,
+					 ssize_t expected_size,
+					 ssize_t expected_elem_size,
+					 bool *replaced)
+{
+	struct drm_property_blob *new_blob = NULL;
+
+	if (blob_id != 0) {
+		new_blob = drm_property_lookup_blob(dev, blob_id);
+		if (new_blob == NULL)
+			return -EINVAL;
+
+		if (expected_size > 0 &&
+		    new_blob->length != expected_size) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+		if (expected_elem_size > 0 &&
+		    new_blob->length % expected_elem_size != 0) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+	}
+
+	*replaced |= drm_property_replace_blob(blob, new_blob);
+	drm_property_blob_put(new_blob);
+
+	return 0;
+}
+
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
+		struct drm_crtc_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+	bool replaced = false;
+	int ret;
+
+	if (property == config->prop_active)
+		state->active = val;
+	else if (property == config->prop_mode_id) {
+		struct drm_property_blob *mode =
+			drm_property_lookup_blob(dev, val);
+		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
+		drm_property_blob_put(mode);
+		return ret;
+	} else if (property == config->degamma_lut_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->degamma_lut,
+					val,
+					-1, sizeof(struct drm_color_lut),
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->ctm_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->ctm,
+					val,
+					sizeof(struct drm_color_ctm), -1,
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->gamma_lut_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->gamma_lut,
+					val,
+					-1, sizeof(struct drm_color_lut),
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->prop_out_fence_ptr) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		if (!fence_ptr)
+			return 0;
+
+		if (put_user(-1, fence_ptr))
+			return -EFAULT;
+
+		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
+	} else if (crtc->funcs->atomic_set_property) {
+		return crtc->funcs->atomic_set_property(crtc, state, property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 crtc->base.id, crtc->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_crtc_get_property(struct drm_crtc *crtc,
+		const struct drm_crtc_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_active)
+		*val = state->active;
+	else if (property == config->prop_mode_id)
+		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
+	else if (property == config->degamma_lut_property)
+		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
+	else if (property == config->ctm_property)
+		*val = (state->ctm) ? state->ctm->base.id : 0;
+	else if (property == config->gamma_lut_property)
+		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
+	else if (property == config->prop_out_fence_ptr)
+		*val = 0;
+	else if (crtc->funcs->atomic_get_property)
+		return crtc->funcs->atomic_get_property(crtc, state, property, val);
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int drm_atomic_plane_set_property(struct drm_plane *plane,
+		struct drm_plane_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_fb_id) {
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		drm_atomic_set_fb_for_plane(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+	} else if (property == config->prop_in_fence_fd) {
+		if (state->fence)
+			return -EINVAL;
+
+		if (U642I64(val) == -1)
+			return 0;
+
+		state->fence = sync_file_get_fence(val);
+		if (!state->fence)
+			return -EINVAL;
+
+	} else if (property == config->prop_crtc_id) {
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_plane(state, crtc);
+	} else if (property == config->prop_crtc_x) {
+		state->crtc_x = U642I64(val);
+	} else if (property == config->prop_crtc_y) {
+		state->crtc_y = U642I64(val);
+	} else if (property == config->prop_crtc_w) {
+		state->crtc_w = val;
+	} else if (property == config->prop_crtc_h) {
+		state->crtc_h = val;
+	} else if (property == config->prop_src_x) {
+		state->src_x = val;
+	} else if (property == config->prop_src_y) {
+		state->src_y = val;
+	} else if (property == config->prop_src_w) {
+		state->src_w = val;
+	} else if (property == config->prop_src_h) {
+		state->src_h = val;
+	} else if (property == plane->alpha_property) {
+		state->alpha = val;
+	} else if (property == plane->blend_mode_property) {
+		state->pixel_blend_mode = val;
+	} else if (property == plane->rotation_property) {
+		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
+			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
+					 plane->base.id, plane->name, val);
+			return -EINVAL;
+		}
+		state->rotation = val;
+	} else if (property == plane->zpos_property) {
+		state->zpos = val;
+	} else if (property == plane->color_encoding_property) {
+		state->color_encoding = val;
+	} else if (property == plane->color_range_property) {
+		state->color_range = val;
+	} else if (plane->funcs->atomic_set_property) {
+		return plane->funcs->atomic_set_property(plane, state,
+				property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 plane->base.id, plane->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_plane_get_property(struct drm_plane *plane,
+		const struct drm_plane_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_fb_id) {
+		*val = (state->fb) ? state->fb->base.id : 0;
+	} else if (property == config->prop_in_fence_fd) {
+		*val = -1;
+	} else if (property == config->prop_crtc_id) {
+		*val = (state->crtc) ? state->crtc->base.id : 0;
+	} else if (property == config->prop_crtc_x) {
+		*val = I642U64(state->crtc_x);
+	} else if (property == config->prop_crtc_y) {
+		*val = I642U64(state->crtc_y);
+	} else if (property == config->prop_crtc_w) {
+		*val = state->crtc_w;
+	} else if (property == config->prop_crtc_h) {
+		*val = state->crtc_h;
+	} else if (property == config->prop_src_x) {
+		*val = state->src_x;
+	} else if (property == config->prop_src_y) {
+		*val = state->src_y;
+	} else if (property == config->prop_src_w) {
+		*val = state->src_w;
+	} else if (property == config->prop_src_h) {
+		*val = state->src_h;
+	} else if (property == plane->alpha_property) {
+		*val = state->alpha;
+	} else if (property == plane->blend_mode_property) {
+		*val = state->pixel_blend_mode;
+	} else if (property == plane->rotation_property) {
+		*val = state->rotation;
+	} else if (property == plane->zpos_property) {
+		*val = state->zpos;
+	} else if (property == plane->color_encoding_property) {
+		*val = state->color_encoding;
+	} else if (property == plane->color_range_property) {
+		*val = state->color_range;
+	} else if (plane->funcs->atomic_get_property) {
+		return plane->funcs->atomic_get_property(plane, state, property, val);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct drm_writeback_job *
+drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
+{
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!conn_state->writeback_job)
+		conn_state->writeback_job =
+			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
+
+	return conn_state->writeback_job;
+}
+
+static int drm_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	struct drm_writeback_job *job =
+		drm_atomic_get_writeback_job(conn_state);
+	if (!job)
+		return -ENOMEM;
+
+	drm_framebuffer_assign(&job->fb, fb);
+
+	if (fb)
+		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
+				 fb->base.id, conn_state);
+	else
+		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
+				 conn_state);
+
+	return 0;
+}
+
+static int drm_atomic_connector_set_property(struct drm_connector *connector,
+		struct drm_connector_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_crtc_id) {
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_connector(state, crtc);
+	} else if (property == config->dpms_property) {
+		/* setting DPMS property requires special handling, which
+		 * is done in legacy setprop path for us.  Disallow (for
+		 * now?) atomic writes to DPMS property:
+		 */
+		return -EINVAL;
+	} else if (property == config->tv_select_subconnector_property) {
+		state->tv.subconnector = val;
+	} else if (property == config->tv_left_margin_property) {
+		state->tv.margins.left = val;
+	} else if (property == config->tv_right_margin_property) {
+		state->tv.margins.right = val;
+	} else if (property == config->tv_top_margin_property) {
+		state->tv.margins.top = val;
+	} else if (property == config->tv_bottom_margin_property) {
+		state->tv.margins.bottom = val;
+	} else if (property == config->tv_mode_property) {
+		state->tv.mode = val;
+	} else if (property == config->tv_brightness_property) {
+		state->tv.brightness = val;
+	} else if (property == config->tv_contrast_property) {
+		state->tv.contrast = val;
+	} else if (property == config->tv_flicker_reduction_property) {
+		state->tv.flicker_reduction = val;
+	} else if (property == config->tv_overscan_property) {
+		state->tv.overscan = val;
+	} else if (property == config->tv_saturation_property) {
+		state->tv.saturation = val;
+	} else if (property == config->tv_hue_property) {
+		state->tv.hue = val;
+	} else if (property == config->link_status_property) {
+		/* Never downgrade from GOOD to BAD on userspace's request here,
+		 * only hw issues can do that.
+		 *
+		 * For an atomic property the userspace doesn't need to be able
+		 * to understand all the properties, but needs to be able to
+		 * restore the state it wants on VT switch. So if the userspace
+		 * tries to change the link_status from GOOD to BAD, driver
+		 * silently rejects it and returns a 0. This prevents userspace
+		 * from accidently breaking  the display when it restores the
+		 * state.
+		 */
+		if (state->link_status != DRM_LINK_STATUS_GOOD)
+			state->link_status = val;
+	} else if (property == config->aspect_ratio_property) {
+		state->picture_aspect_ratio = val;
+	} else if (property == config->content_type_property) {
+		state->content_type = val;
+	} else if (property == connector->scaling_mode_property) {
+		state->scaling_mode = val;
+	} else if (property == connector->content_protection_property) {
+		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+			return -EINVAL;
+		}
+		state->content_protection = val;
+	} else if (property == config->writeback_fb_id_property) {
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+		return ret;
+	} else if (property == config->writeback_out_fence_ptr_property) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		return set_out_fence_for_connector(state->state, connector,
+						   fence_ptr);
+	} else if (connector->funcs->atomic_set_property) {
+		return connector->funcs->atomic_set_property(connector,
+				state, property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 connector->base.id, connector->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_connector_get_property(struct drm_connector *connector,
+		const struct drm_connector_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_crtc_id) {
+		*val = (state->crtc) ? state->crtc->base.id : 0;
+	} else if (property == config->dpms_property) {
+		*val = connector->dpms;
+	} else if (property == config->tv_select_subconnector_property) {
+		*val = state->tv.subconnector;
+	} else if (property == config->tv_left_margin_property) {
+		*val = state->tv.margins.left;
+	} else if (property == config->tv_right_margin_property) {
+		*val = state->tv.margins.right;
+	} else if (property == config->tv_top_margin_property) {
+		*val = state->tv.margins.top;
+	} else if (property == config->tv_bottom_margin_property) {
+		*val = state->tv.margins.bottom;
+	} else if (property == config->tv_mode_property) {
+		*val = state->tv.mode;
+	} else if (property == config->tv_brightness_property) {
+		*val = state->tv.brightness;
+	} else if (property == config->tv_contrast_property) {
+		*val = state->tv.contrast;
+	} else if (property == config->tv_flicker_reduction_property) {
+		*val = state->tv.flicker_reduction;
+	} else if (property == config->tv_overscan_property) {
+		*val = state->tv.overscan;
+	} else if (property == config->tv_saturation_property) {
+		*val = state->tv.saturation;
+	} else if (property == config->tv_hue_property) {
+		*val = state->tv.hue;
+	} else if (property == config->link_status_property) {
+		*val = state->link_status;
+	} else if (property == config->aspect_ratio_property) {
+		*val = state->picture_aspect_ratio;
+	} else if (property == config->content_type_property) {
+		*val = state->content_type;
+	} else if (property == connector->scaling_mode_property) {
+		*val = state->scaling_mode;
+	} else if (property == connector->content_protection_property) {
+		*val = state->content_protection;
+	} else if (property == config->writeback_fb_id_property) {
+		/* Writeback framebuffer is one-shot, write and forget */
+		*val = 0;
+	} else if (property == config->writeback_out_fence_ptr_property) {
+		*val = 0;
+	} else if (connector->funcs->atomic_get_property) {
+		return connector->funcs->atomic_get_property(connector,
+				state, property, val);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int drm_atomic_get_property(struct drm_mode_object *obj,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = property->dev;
+	int ret;
+
+	switch (obj->type) {
+	case DRM_MODE_OBJECT_CONNECTOR: {
+		struct drm_connector *connector = obj_to_connector(obj);
+		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+		ret = drm_atomic_connector_get_property(connector,
+				connector->state, property, val);
+		break;
+	}
+	case DRM_MODE_OBJECT_CRTC: {
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+		ret = drm_atomic_crtc_get_property(crtc,
+				crtc->state, property, val);
+		break;
+	}
+	case DRM_MODE_OBJECT_PLANE: {
+		struct drm_plane *plane = obj_to_plane(obj);
+		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
+		ret = drm_atomic_plane_get_property(plane,
+				plane->state, property, val);
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * The big monster ioctl
+ */
+
+static struct drm_pending_vblank_event *create_vblank_event(
+		struct drm_crtc *crtc, uint64_t user_data)
+{
+	struct drm_pending_vblank_event *e = NULL;
+
+	e = kzalloc(sizeof *e, GFP_KERNEL);
+	if (!e)
+		return NULL;
+
+	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
+	e->event.base.length = sizeof(e->event);
+	e->event.vbl.crtc_id = crtc->base.id;
+	e->event.vbl.user_data = user_data;
+
+	return e;
+}
+
+int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
+				     struct drm_connector *connector,
+				     int mode)
+{
+	struct drm_connector *tmp_connector;
+	struct drm_connector_state *new_conn_state;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i, ret, old_mode = connector->dpms;
+	bool active = false;
+
+	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
+			       state->acquire_ctx);
+	if (ret)
+		return ret;
+
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+	connector->dpms = mode;
+
+	crtc = connector->state->crtc;
+	if (!crtc)
+		goto out;
+	ret = drm_atomic_add_affected_connectors(state, crtc);
+	if (ret)
+		goto out;
+
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state)) {
+		ret = PTR_ERR(crtc_state);
+		goto out;
+	}
+
+	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
+		if (new_conn_state->crtc != crtc)
+			continue;
+		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
+			active = true;
+			break;
+		}
+	}
+
+	crtc_state->active = active;
+	ret = drm_atomic_commit(state);
+out:
+	if (ret != 0)
+		connector->dpms = old_mode;
+	return ret;
+}
+
+int drm_atomic_set_property(struct drm_atomic_state *state,
+			    struct drm_mode_object *obj,
+			    struct drm_property *prop,
+			    uint64_t prop_value)
+{
+	struct drm_mode_object *ref;
+	int ret;
+
+	if (!drm_property_change_valid_get(prop, prop_value, &ref))
+		return -EINVAL;
+
+	switch (obj->type) {
+	case DRM_MODE_OBJECT_CONNECTOR: {
+		struct drm_connector *connector = obj_to_connector(obj);
+		struct drm_connector_state *connector_state;
+
+		connector_state = drm_atomic_get_connector_state(state, connector);
+		if (IS_ERR(connector_state)) {
+			ret = PTR_ERR(connector_state);
+			break;
+		}
+
+		ret = drm_atomic_connector_set_property(connector,
+				connector_state, prop, prop_value);
+		break;
+	}
+	case DRM_MODE_OBJECT_CRTC: {
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		struct drm_crtc_state *crtc_state;
+
+		crtc_state = drm_atomic_get_crtc_state(state, crtc);
+		if (IS_ERR(crtc_state)) {
+			ret = PTR_ERR(crtc_state);
+			break;
+		}
+
+		ret = drm_atomic_crtc_set_property(crtc,
+				crtc_state, prop, prop_value);
+		break;
+	}
+	case DRM_MODE_OBJECT_PLANE: {
+		struct drm_plane *plane = obj_to_plane(obj);
+		struct drm_plane_state *plane_state;
+
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			ret = PTR_ERR(plane_state);
+			break;
+		}
+
+		ret = drm_atomic_plane_set_property(plane,
+				plane_state, prop, prop_value);
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	drm_property_change_valid_put(prop, ref);
+	return ret;
+}
+
+/**
+ * DOC: explicit fencing properties
+ *
+ * Explicit fencing allows userspace to control the buffer synchronization
+ * between devices. A Fence or a group of fences are transfered to/from
+ * userspace using Sync File fds and there are two DRM properties for that.
+ * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
+ * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
+ *
+ * As a contrast, with implicit fencing the kernel keeps track of any
+ * ongoing rendering, and automatically ensures that the atomic update waits
+ * for any pending rendering to complete. For shared buffers represented with
+ * a &struct dma_buf this is tracked in &struct reservation_object.
+ * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
+ * whereas explicit fencing is what Android wants.
+ *
+ * "IN_FENCE_FD”:
+ *	Use this property to pass a fence that DRM should wait on before
+ *	proceeding with the Atomic Commit request and show the framebuffer for
+ *	the plane on the screen. The fence can be either a normal fence or a
+ *	merged one, the sync_file framework will handle both cases and use a
+ *	fence_array if a merged fence is received. Passing -1 here means no
+ *	fences to wait on.
+ *
+ *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
+ *	it will only check if the Sync File is a valid one.
+ *
+ *	On the driver side the fence is stored on the @fence parameter of
+ *	&struct drm_plane_state. Drivers which also support implicit fencing
+ *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
+ *	to make sure there's consistent behaviour between drivers in precedence
+ *	of implicit vs. explicit fencing.
+ *
+ * "OUT_FENCE_PTR”:
+ *	Use this property to pass a file descriptor pointer to DRM. Once the
+ *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
+ *	the file descriptor number of a Sync File. This Sync File contains the
+ *	CRTC fence that will be signaled when all framebuffers present on the
+ *	Atomic Commit * request for that given CRTC are scanned out on the
+ *	screen.
+ *
+ *	The Atomic Commit request fails if a invalid pointer is passed. If the
+ *	Atomic Commit request fails for any other reason the out fence fd
+ *	returned will be -1. On a Atomic Commit with the
+ *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
+ *
+ *	Note that out-fences don't have a special interface to drivers and are
+ *	internally represented by a &struct drm_pending_vblank_event in struct
+ *	&drm_crtc_state, which is also used by the nonblocking atomic commit
+ *	helpers and for the DRM event handling for existing userspace.
+ */
+
+struct drm_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+static int setup_out_fence(struct drm_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int prepare_signaling(struct drm_device *dev,
+				  struct drm_atomic_state *state,
+				  struct drm_mode_atomic *arg,
+				  struct drm_file *file_priv,
+				  struct drm_out_fence_state **fence_state,
+				  unsigned int *num_fences)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, c = 0, ret;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
+		return 0;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		s32 __user *fence_ptr;
+
+		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
+			struct drm_pending_vblank_event *e;
+
+			e = create_vblank_event(crtc, arg->user_data);
+			if (!e)
+				return -ENOMEM;
+
+			crtc_state->event = e;
+		}
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+			struct drm_pending_vblank_event *e = crtc_state->event;
+
+			if (!file_priv)
+				continue;
+
+			ret = drm_event_reserve_init(dev, file_priv, &e->base,
+						     &e->event.base);
+			if (ret) {
+				kfree(e);
+				crtc_state->event = NULL;
+				return ret;
+			}
+		}
+
+		if (fence_ptr) {
+			struct dma_fence *fence;
+			struct drm_out_fence_state *f;
+
+			f = krealloc(*fence_state, sizeof(**fence_state) *
+				     (*num_fences + 1), GFP_KERNEL);
+			if (!f)
+				return -ENOMEM;
+
+			memset(&f[*num_fences], 0, sizeof(*f));
+
+			f[*num_fences].out_fence_ptr = fence_ptr;
+			*fence_state = f;
+
+			fence = drm_crtc_create_fence(crtc);
+			if (!fence)
+				return -ENOMEM;
+
+			ret = setup_out_fence(&f[(*num_fences)++], fence);
+			if (ret) {
+				dma_fence_put(fence);
+				return ret;
+			}
+
+			crtc_state->event->base.fence = fence;
+		}
+
+		c++;
+	}
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		struct drm_writeback_connector *wb_conn;
+		struct drm_writeback_job *job;
+		struct drm_out_fence_state *f;
+		struct dma_fence *fence;
+		s32 __user *fence_ptr;
+
+		fence_ptr = get_out_fence_for_connector(state, conn);
+		if (!fence_ptr)
+			continue;
+
+		job = drm_atomic_get_writeback_job(conn_state);
+		if (!job)
+			return -ENOMEM;
+
+		f = krealloc(*fence_state, sizeof(**fence_state) *
+			     (*num_fences + 1), GFP_KERNEL);
+		if (!f)
+			return -ENOMEM;
+
+		memset(&f[*num_fences], 0, sizeof(*f));
+
+		f[*num_fences].out_fence_ptr = fence_ptr;
+		*fence_state = f;
+
+		wb_conn = drm_connector_to_writeback(conn);
+		fence = drm_writeback_get_out_fence(wb_conn);
+		if (!fence)
+			return -ENOMEM;
+
+		ret = setup_out_fence(&f[(*num_fences)++], fence);
+		if (ret) {
+			dma_fence_put(fence);
+			return ret;
+		}
+
+		job->out_fence = fence;
+	}
+
+	/*
+	 * Having this flag means user mode pends on event which will never
+	 * reach due to lack of at least one CRTC for signaling
+	 */
+	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void complete_signaling(struct drm_device *dev,
+			       struct drm_atomic_state *state,
+			       struct drm_out_fence_state *fence_state,
+			       unsigned int num_fences,
+			       bool install_fds)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i;
+
+	if (install_fds) {
+		for (i = 0; i < num_fences; i++)
+			fd_install(fence_state[i].fd,
+				   fence_state[i].sync_file->file);
+
+		kfree(fence_state);
+		return;
+	}
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct drm_pending_vblank_event *event = crtc_state->event;
+		/*
+		 * Free the allocated event. drm_atomic_helper_setup_commit
+		 * can allocate an event too, so only free it if it's ours
+		 * to prevent a double free in drm_atomic_state_clear.
+		 */
+		if (event && (event->base.fence || event->base.file_priv)) {
+			drm_event_cancel_free(dev, &event->base);
+			crtc_state->event = NULL;
+		}
+	}
+
+	if (!fence_state)
+		return;
+
+	for (i = 0; i < num_fences; i++) {
+		if (fence_state[i].sync_file)
+			fput(fence_state[i].sync_file->file);
+		if (fence_state[i].fd >= 0)
+			put_unused_fd(fence_state[i].fd);
+
+		/* If this fails log error to the user */
+		if (fence_state[i].out_fence_ptr &&
+		    put_user(-1, fence_state[i].out_fence_ptr))
+			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
+	}
+
+	kfree(fence_state);
+}
+
+int drm_mode_atomic_ioctl(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_atomic *arg = data;
+	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
+	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
+	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
+	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
+	unsigned int copied_objs, copied_props;
+	struct drm_atomic_state *state;
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_out_fence_state *fence_state;
+	int ret = 0;
+	unsigned int i, j, num_fences;
+
+	/* disallow for drivers not supporting atomic: */
+	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+		return -EINVAL;
+
+	/* disallow for userspace that has not enabled atomic cap (even
+	 * though this may be a bit overkill, since legacy userspace
+	 * wouldn't know how to call this ioctl)
+	 */
+	if (!file_priv->atomic)
+		return -EINVAL;
+
+	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
+		return -EINVAL;
+
+	if (arg->reserved)
+		return -EINVAL;
+
+	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
+			!dev->mode_config.async_page_flip)
+		return -EINVAL;
+
+	/* can't test and expect an event at the same time. */
+	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
+			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
+		return -EINVAL;
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = &ctx;
+	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
+
+retry:
+	copied_objs = 0;
+	copied_props = 0;
+	fence_state = NULL;
+	num_fences = 0;
+
+	for (i = 0; i < arg->count_objs; i++) {
+		uint32_t obj_id, count_props;
+		struct drm_mode_object *obj;
+
+		if (get_user(obj_id, objs_ptr + copied_objs)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
+		if (!obj) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (!obj->properties) {
+			drm_mode_object_put(obj);
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (get_user(count_props, count_props_ptr + copied_objs)) {
+			drm_mode_object_put(obj);
+			ret = -EFAULT;
+			goto out;
+		}
+
+		copied_objs++;
+
+		for (j = 0; j < count_props; j++) {
+			uint32_t prop_id;
+			uint64_t prop_value;
+			struct drm_property *prop;
+
+			if (get_user(prop_id, props_ptr + copied_props)) {
+				drm_mode_object_put(obj);
+				ret = -EFAULT;
+				goto out;
+			}
+
+			prop = drm_mode_obj_find_prop_id(obj, prop_id);
+			if (!prop) {
+				drm_mode_object_put(obj);
+				ret = -ENOENT;
+				goto out;
+			}
+
+			if (copy_from_user(&prop_value,
+					   prop_values_ptr + copied_props,
+					   sizeof(prop_value))) {
+				drm_mode_object_put(obj);
+				ret = -EFAULT;
+				goto out;
+			}
+
+			ret = drm_atomic_set_property(state, obj, prop,
+						      prop_value);
+			if (ret) {
+				drm_mode_object_put(obj);
+				goto out;
+			}
+
+			copied_props++;
+		}
+
+		drm_mode_object_put(obj);
+	}
+
+	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
+				&num_fences);
+	if (ret)
+		goto out;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
+		ret = drm_atomic_check_only(state);
+	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
+		ret = drm_atomic_nonblocking_commit(state);
+	} else {
+		if (unlikely(drm_debug & DRM_UT_STATE))
+			drm_atomic_print_state(state);
+
+		ret = drm_atomic_commit(state);
+	}
+
+out:
+	complete_signaling(dev, state, fence_state, num_fences, !ret);
+
+	if (ret == -EDEADLK) {
+		drm_atomic_state_clear(state);
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_atomic_state_put(state);
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5a84c3bc915d..ce75e9506e85 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -35,6 +35,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fourcc.h>
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index ff5e0d521c21..ede20b55d50c 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -204,6 +204,9 @@ struct drm_minor;
 int drm_atomic_debugfs_init(struct drm_minor *minor);
 #endif
 
+void drm_atomic_print_state(const struct drm_atomic_state *state);
+
+/* drm_atomic_uapi.c */
 int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
 				     struct drm_connector *connector,
 				     int mode);
@@ -213,6 +216,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 			    uint64_t prop_value);
 int drm_atomic_get_property(struct drm_mode_object *obj,
 			    struct drm_property *property, uint64_t *val);
+
+/* IOCTL */
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
 
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 781af1d42d76..7ca8c77223cb 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -25,6 +25,7 @@
 #include <drm/drm_auth.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_print.h>
 
 #include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 2810d4131411..7607f9cd6f77 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -16,6 +16,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 621f17643bb0..a393756b664e 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -28,6 +28,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a85a83f31979..85cad16f31ed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -46,6 +46,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_atomic_uapi.h>
 #include <linux/dma_remapping.h>
 #include <linux/reservation.h>
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index c1f1779c980f..4bcdeca7479d 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -15,6 +15,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_atomic_uapi.h>
+
 #include "msm_drv.h"
 #include "msm_gem.h"
 #include "msm_kms.h"
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 0e6a121858d1..3ce136ba8791 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -35,6 +35,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_uapi.h>
 #include <linux/clk.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <linux/component.h>
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 6c6d37aa512a..9dc3fcbd290b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -22,6 +22,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_uapi.h>
 
 #include "uapi/drm/vc4_drm.h"
 #include "vc4_drv.h"
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 66e49ef7d3b5..4aff40886acb 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -584,22 +584,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
 	return plane->state;
 }
 
-int __must_check
-drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
-			     const struct drm_display_mode *mode);
-int __must_check
-drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
-				  struct drm_property_blob *blob);
-int __must_check
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
-			      struct drm_crtc *crtc);
-void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
-				 struct drm_framebuffer *fb);
-void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
-				    struct dma_fence *fence);
-int __must_check
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
-				  struct drm_crtc *crtc);
 int __must_check
 drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 				   struct drm_crtc *crtc);
diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
new file mode 100644
index 000000000000..8cec52ad1277
--- /dev/null
+++ b/include/drm/drm_atomic_uapi.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Copyright (C) 2014 Intel Corp.
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#ifndef DRM_ATOMIC_UAPI_H_
+#define DRM_ATOMIC_UAPI_H_
+
+struct drm_crtc_state;
+struct drm_display_mode;
+struct drm_property_blob;
+struct drm_plane_state;
+struct drm_crtc;
+struct drm_connector_state;
+struct dma_fence;
+struct drm_framebuffer;
+
+int __must_check
+drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
+			     const struct drm_display_mode *mode);
+int __must_check
+drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
+				  struct drm_property_blob *blob);
+int __must_check
+drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+			      struct drm_crtc *crtc);
+void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
+				 struct drm_framebuffer *fb);
+void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+				    struct dma_fence *fence);
+int __must_check
+drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
+				  struct drm_crtc *crtc);
+
+#endif
-- 
2.18.0

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 07/14] drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (4 preceding siblings ...)
       [not found] ` <20180903165439.24845-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC Daniel Vetter
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: Jernej Skrabec, Thomas Hellstrom, VMware Graphics, Sinclair Yeh,
	David Airlie, Intel Graphics Development, Neil Armstrong,
	Archit Taneja, Hans Verkuil, Jani Nikula, Russell King,
	Sean Paul, Laurent Pinchart, Daniel Vetter, Fabio Estevam,
	Daniel Vetter, Pierre-Hugues Husson

It's the default. The exported version was kinda a transition state,
before we made this the default.

To stop new atomic drivers from using it (instead of just relying on
the default) let's unexport it.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: David Airlie <airlied@linux.ie>
Cc: VMware Graphics <linux-graphics-maintainer@vmware.com>
Cc: Sinclair Yeh <syeh@vmware.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Archit Taneja <architt@codeaurora.org>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Jernej Skrabec <jernej.skrabec@siol.net>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Pierre-Hugues Husson <phh@phh.me>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  1 -
 drivers/gpu/drm/drm_atomic_helper.c       | 24 +++++++----------------
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c       |  1 -
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c      |  1 -
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c      |  1 -
 include/drm/drm_atomic_helper.h           |  2 --
 6 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 5971976284bf..0aed51799526 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1957,7 +1957,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
 
 static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
 	.get_modes = dw_hdmi_connector_get_modes,
-	.best_encoder = drm_atomic_helper_best_encoder,
 };
 
 static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 8469a7e9afe3..334b121bd4d9 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -92,6 +92,13 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
 	}
 }
 
+static struct drm_encoder *
+drm_atomic_helper_best_encoder(struct drm_connector *connector)
+{
+	WARN_ON(connector->encoder_ids[1]);
+	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+}
+
 static int handle_conflicting_encoders(struct drm_atomic_state *state,
 				       bool disable_conflicting_encoders)
 {
@@ -3376,23 +3383,6 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
 
-/**
- * drm_atomic_helper_best_encoder - Helper for
- * 	&drm_connector_helper_funcs.best_encoder callback
- * @connector: Connector control structure
- *
- * This is a &drm_connector_helper_funcs.best_encoder callback helper for
- * connectors that support exactly 1 encoder, statically determined at driver
- * init time.
- */
-struct drm_encoder *
-drm_atomic_helper_best_encoder(struct drm_connector *connector)
-{
-	WARN_ON(connector->encoder_ids[1]);
-	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
-}
-EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
-
 /**
  * DOC: atomic state reset and initialization
  *
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 723578117191..4b5378495eea 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -274,7 +274,6 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
 
 static const struct
 drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
-	.best_encoder = drm_atomic_helper_best_encoder,
 };
 
 /*
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index ad0de7f0cd60..4c68ad6f3605 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -389,7 +389,6 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
 
 static const struct
 drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
-	.best_encoder = drm_atomic_helper_best_encoder,
 };
 
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 93f6b96ca7bb..f5b2fe8a7793 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1037,7 +1037,6 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 
 static const struct
 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
-	.best_encoder = drm_atomic_helper_best_encoder,
 };
 
 
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 63e736eeb516..27aef91ca1c3 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -144,8 +144,6 @@ int drm_atomic_helper_page_flip_target(
 				uint32_t flags,
 				uint32_t target,
 				struct drm_modeset_acquire_ctx *ctx);
-struct drm_encoder *
-drm_atomic_helper_best_encoder(struct drm_connector *connector);
 
 /* default implementations for state handling */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (5 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 07/14] drm/atomic-helper: Unexport drm_atomic_helper_best_encoder Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-05 13:45   ` Leo Li
  2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: Andrey Grodzovsky, Leo (Sunpeng) Li, Daniel Vetter,
	Intel Graphics Development, Shirish S, Tony Cheng, Alex Deucher,
	Daniel Vetter, Harry Wentland

For atomic driver this is the default, no need to reimplement it. We
still need to keep the copypasta for not-atomic drivers though, since
no one polished the legacy crtc helpers as much as the atomic ones.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Cc: Tony Cheng <Tony.Cheng@amd.com>
Cc: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
Cc: Shirish S <shirish.s@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 -------------------
 1 file changed, 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index af6adffba788..333f9904f135 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2794,28 +2794,6 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
 	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
 };
 
-static struct drm_encoder *best_encoder(struct drm_connector *connector)
-{
-	int enc_id = connector->encoder_ids[0];
-	struct drm_mode_object *obj;
-	struct drm_encoder *encoder;
-
-	DRM_DEBUG_DRIVER("Finding the best encoder\n");
-
-	/* pick the encoder ids */
-	if (enc_id) {
-		obj = drm_mode_object_find(connector->dev, NULL, enc_id, DRM_MODE_OBJECT_ENCODER);
-		if (!obj) {
-			DRM_ERROR("Couldn't find a matching encoder for our connector\n");
-			return NULL;
-		}
-		encoder = obj_to_encoder(obj);
-		return encoder;
-	}
-	DRM_ERROR("No encoder id\n");
-	return NULL;
-}
-
 static int get_modes(struct drm_connector *connector)
 {
 	return amdgpu_dm_connector_get_modes(connector);
@@ -2934,7 +2912,6 @@ amdgpu_dm_connector_helper_funcs = {
 	 */
 	.get_modes = get_modes,
 	.mode_valid = amdgpu_dm_connector_mode_valid,
-	.best_encoder = best_encoder
 };
 
 static void dm_crtc_helper_disable(struct drm_crtc *crtc)
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 09/14] drm: Update todo.rst
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (6 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 17:24   ` Sam Ravnborg
                     ` (2 more replies)
  2018-09-03 16:54 ` [PATCH 10/14] drm: Extract drm_atomic_state_helper.[hc] Daniel Vetter
                   ` (10 subsequent siblings)
  18 siblings, 3 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development, Sean Paul

- drmP.h is now fully split up.
- vkms is happening (and will gain its own todo and docs under a new
  vkms.rst file real soon)
- legacy cruft is completely hidden now, drm_vblank.c is split out
  from drm_irq.c now.
- best_encoder atomic cleanup is done (it's now the default, not even
  exported anymore)
- bunch of smaller things

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: David Airlie <airlied@linux.ie>
---
 Documentation/gpu/todo.rst | 68 ++++++--------------------------------
 1 file changed, 10 insertions(+), 58 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index a7c150d6b63f..96bfdbc9ebff 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -127,7 +127,8 @@ interfaces to fix these issues:
   the acquire context explicitly on stack and then also pass it down into
   drivers explicitly so that the legacy-on-atomic functions can use them.
 
-  Except for some driver code this is done.
+  Except for some driver code this is done. This task should be finished by
+  adding WARN_ON(!drm_drv_uses_atomic_modeset) in drm_modeset_lock_all().
 
 * A bunch of the vtable hooks are now in the wrong place: DRM has a split
   between core vfunc tables (named ``drm_foo_funcs``), which are used to
@@ -137,13 +138,6 @@ interfaces to fix these issues:
   ``_helper_funcs`` since they are not part of the core ABI. There's a
   ``FIXME`` comment in the kerneldoc for each such case in ``drm_crtc.h``.
 
-* There's a new helper ``drm_atomic_helper_best_encoder()`` which could be
-  used by all atomic drivers which don't select the encoder for a given
-  connector at runtime. That's almost all of them, and would allow us to get
-  rid of a lot of ``best_encoder`` boilerplate in drivers.
-
-  This was almost done, but new drivers added a few more cases again.
-
 Contact: Daniel Vetter
 
 Get rid of dev->struct_mutex from GEM drivers
@@ -164,9 +158,8 @@ private lock. The tricky part is the BO free functions, since those can't
 reliably take that lock any more. Instead state needs to be protected with
 suitable subordinate locks or some cleanup work pushed to a worker thread. For
 performance-critical drivers it might also be better to go with a more
-fine-grained per-buffer object and per-context lockings scheme. Currently the
-following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
-``udl``.
+fine-grained per-buffer object and per-context lockings scheme. Currently only the
+``msm`` driver still use ``struct_mutex``.
 
 Contact: Daniel Vetter, respective driver maintainers
 
@@ -190,7 +183,8 @@ Convert drivers to use simple modeset suspend/resume
 
 Most drivers (except i915 and nouveau) that use
 drm_atomic_helper_suspend/resume() can probably be converted to use
-drm_mode_config_helper_suspend/resume().
+drm_mode_config_helper_suspend/resume(). Also there's still open-coded version
+of the atomic suspend/resume code in older atomic modeset drivers.
 
 Contact: Maintainer of the driver you plan to convert
 
@@ -246,20 +240,10 @@ Core refactorings
 Clean up the DRM header mess
 ----------------------------
 
-Currently the DRM subsystem has only one global header, ``drmP.h``. This is
-used both for functions exported to helper libraries and drivers and functions
-only used internally in the ``drm.ko`` module. The goal would be to move all
-header declarations not needed outside of ``drm.ko`` into
-``drivers/gpu/drm/drm_*_internal.h`` header files. ``EXPORT_SYMBOL`` also
-needs to be dropped for these functions.
-
-This would nicely tie in with the below task to create kerneldoc after the API
-is cleaned up. Or with the "hide legacy cruft better" task.
-
-Note that this is well in progress, but ``drmP.h`` is still huge. The updated
-plan is to switch to per-file driver API headers, which will also structure
-the kerneldoc better. This should also allow more fine-grained ``#include``
-directives.
+The DRM subsystem originally had only one huge globale header, ``drmP.h``. This
+is not split up, but many source files still include it. The remainig part of
+the cleanup work here is to replace any ``#include <drm/drmP.h>`` by only the
+headers needed (and fixing up any missing pre-declarations in the headers).
 
 In the end no .c file should need to include ``drmP.h`` anymore.
 
@@ -278,26 +262,6 @@ See https://dri.freedesktop.org/docs/drm/ for what's there already.
 
 Contact: Daniel Vetter
 
-Hide legacy cruft better
-------------------------
-
-Way back DRM supported only drivers which shadow-attached to PCI devices with
-userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
-of the entire device, you can spot them with the DRIVER_MODESET flag.
-
-Unfortunately there's still large piles of legacy code around which needs to
-be hidden so that driver writers don't accidentally end up using it. And to
-prevent security issues in those legacy IOCTLs from being exploited on modern
-drivers. This has multiple possible subtasks:
-
-* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
-  module and compile it only when one of the legacy drivers is enabled.
-
-This is mostly done, the only thing left is to split up ``drm_irq.c`` into
-legacy cruft and the parts needed by modern KMS drivers.
-
-Contact: Daniel Vetter
-
 Make panic handling work
 ------------------------
 
@@ -398,18 +362,6 @@ the non-i915 specific modeset tests.
 
 Contact: Daniel Vetter
 
-Create a virtual KMS driver for testing (vkms)
-----------------------------------------------
-
-With all the latest helpers it should be fairly simple to create a virtual KMS
-driver useful for testing, or for running X or similar on headless machines
-(to be able to still use the GPU). This would be similar to vgem, but aimed at
-the modeset side.
-
-Once the basics are there there's tons of possibilities to extend it.
-
-Contact: Daniel Vetter
-
 Driver Specific
 ===============
 
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 10/14] drm: Extract drm_atomic_state_helper.[hc]
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (7 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 11/14] drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property Daniel Vetter
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

We already have a separate overview doc for this, makes sense to
untangle it from the overall atomic helpers.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms-helpers.rst     |  19 +-
 drivers/gpu/drm/Makefile                  |   3 +-
 drivers/gpu/drm/drm_atomic_helper.c       | 568 --------------------
 drivers/gpu/drm/drm_atomic_state_helper.c | 603 ++++++++++++++++++++++
 include/drm/drm_atomic_helper.h           |  44 +-
 include/drm/drm_atomic_state_helper.h     |  80 +++
 6 files changed, 700 insertions(+), 617 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_atomic_state_helper.c
 create mode 100644 include/drm/drm_atomic_state_helper.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index f9cfcdcdf024..4b4dc236ef6f 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -59,19 +59,28 @@ Implementing Asynchronous Atomic Commit
 .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
    :doc: implementing nonblocking commit
 
+Helper Functions Reference
+--------------------------
+
+.. kernel-doc:: include/drm/drm_atomic_helper.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
+   :export:
+
 Atomic State Reset and Initialization
 -------------------------------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
    :doc: atomic state reset and initialization
 
-Helper Functions Reference
---------------------------
+Atomic State Helper Reference
+-----------------------------
 
-.. kernel-doc:: include/drm/drm_atomic_helper.h
+.. kernel-doc:: include/drm/drm_atomic_state_helper.h
    :internal:
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_state_helper.c
    :export:
 
 Simple KMS Helper Reference
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index bc6a16a3c36e..576ba985e138 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -36,7 +36,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
 		drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
 		drm_simple_kms_helper.o drm_modeset_helper.o \
-		drm_scdc_helper.o drm_gem_framebuffer_helper.o
+		drm_scdc_helper.o drm_gem_framebuffer_helper.o \
+		drm_atomic_state_helper.o
 
 drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 334b121bd4d9..a5edc8757056 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3382,571 +3382,3 @@ int drm_atomic_helper_page_flip_target(struct drm_crtc *crtc,
 	return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
-
-/**
- * DOC: atomic state reset and initialization
- *
- * Both the drm core and the atomic helpers assume that there is always the full
- * and correct atomic software state for all connectors, CRTCs and planes
- * available. Which is a bit a problem on driver load and also after system
- * suspend. One way to solve this is to have a hardware state read-out
- * infrastructure which reconstructs the full software state (e.g. the i915
- * driver).
- *
- * The simpler solution is to just reset the software state to everything off,
- * which is easiest to do by calling drm_mode_config_reset(). To facilitate this
- * the atomic helpers provide default reset implementations for all hooks.
- *
- * On the upside the precise state tracking of atomic simplifies system suspend
- * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
- * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
- * For other drivers the building blocks are split out, see the documentation
- * for these functions.
- */
-
-/**
- * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
- * @crtc: drm CRTC
- *
- * Resets the atomic state for @crtc by freeing the state pointer (which might
- * be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
-{
-	if (crtc->state)
-		__drm_atomic_helper_crtc_destroy_state(crtc->state);
-
-	kfree(crtc->state);
-	crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
-
-	if (crtc->state)
-		crtc->state->crtc = crtc;
-}
-EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
-
-/**
- * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
- * @crtc: CRTC object
- * @state: atomic CRTC state
- *
- * Copies atomic state from a CRTC's current state and resets inferred values.
- * This is useful for drivers that subclass the CRTC state.
- */
-void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
-					      struct drm_crtc_state *state)
-{
-	memcpy(state, crtc->state, sizeof(*state));
-
-	if (state->mode_blob)
-		drm_property_blob_get(state->mode_blob);
-	if (state->degamma_lut)
-		drm_property_blob_get(state->degamma_lut);
-	if (state->ctm)
-		drm_property_blob_get(state->ctm);
-	if (state->gamma_lut)
-		drm_property_blob_get(state->gamma_lut);
-	state->mode_changed = false;
-	state->active_changed = false;
-	state->planes_changed = false;
-	state->connectors_changed = false;
-	state->color_mgmt_changed = false;
-	state->zpos_changed = false;
-	state->commit = NULL;
-	state->event = NULL;
-	state->pageflip_flags = 0;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
-
-/**
- * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
- * @crtc: drm CRTC
- *
- * Default CRTC state duplicate hook for drivers which don't have their own
- * subclassed CRTC state structure.
- */
-struct drm_crtc_state *
-drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
-{
-	struct drm_crtc_state *state;
-
-	if (WARN_ON(!crtc->state))
-		return NULL;
-
-	state = kmalloc(sizeof(*state), GFP_KERNEL);
-	if (state)
-		__drm_atomic_helper_crtc_duplicate_state(crtc, state);
-
-	return state;
-}
-EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
-
-/**
- * __drm_atomic_helper_crtc_destroy_state - release CRTC state
- * @state: CRTC state object to release
- *
- * Releases all resources stored in the CRTC state without actually freeing
- * the memory of the CRTC state. This is useful for drivers that subclass the
- * CRTC state.
- */
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
-{
-	if (state->commit) {
-		/*
-		 * In the event that a non-blocking commit returns
-		 * -ERESTARTSYS before the commit_tail work is queued, we will
-		 * have an extra reference to the commit object. Release it, if
-		 * the event has not been consumed by the worker.
-		 *
-		 * state->event may be freed, so we can't directly look at
-		 * state->event->base.completion.
-		 */
-		if (state->event && state->commit->abort_completion)
-			drm_crtc_commit_put(state->commit);
-
-		kfree(state->commit->event);
-		state->commit->event = NULL;
-
-		drm_crtc_commit_put(state->commit);
-	}
-
-	drm_property_blob_put(state->mode_blob);
-	drm_property_blob_put(state->degamma_lut);
-	drm_property_blob_put(state->ctm);
-	drm_property_blob_put(state->gamma_lut);
-}
-EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
-
-/**
- * drm_atomic_helper_crtc_destroy_state - default state destroy hook
- * @crtc: drm CRTC
- * @state: CRTC state object to release
- *
- * Default CRTC state destroy hook for drivers which don't have their own
- * subclassed CRTC state structure.
- */
-void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
-					  struct drm_crtc_state *state)
-{
-	__drm_atomic_helper_crtc_destroy_state(state);
-	kfree(state);
-}
-EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
-
-/**
- * __drm_atomic_helper_plane_reset - resets planes state to default values
- * @plane: plane object, must not be NULL
- * @state: atomic plane state, must not be NULL
- *
- * Initializes plane state to default. This is useful for drivers that subclass
- * the plane state.
- */
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
-				     struct drm_plane_state *state)
-{
-	state->plane = plane;
-	state->rotation = DRM_MODE_ROTATE_0;
-
-	/* Reset the alpha value to fully opaque if it matters */
-	if (plane->alpha_property)
-		state->alpha = plane->alpha_property->values[1];
-	state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
-
-	plane->state = state;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
-
-/**
- * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
- * @plane: drm plane
- *
- * Resets the atomic state for @plane by freeing the state pointer (which might
- * be NULL, e.g. at driver load time) and allocating a new empty state object.
- */
-void drm_atomic_helper_plane_reset(struct drm_plane *plane)
-{
-	if (plane->state)
-		__drm_atomic_helper_plane_destroy_state(plane->state);
-
-	kfree(plane->state);
-	plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
-	if (plane->state)
-		__drm_atomic_helper_plane_reset(plane, plane->state);
-}
-EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
-
-/**
- * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
- * @plane: plane object
- * @state: atomic plane state
- *
- * Copies atomic state from a plane's current state. This is useful for
- * drivers that subclass the plane state.
- */
-void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
-					       struct drm_plane_state *state)
-{
-	memcpy(state, plane->state, sizeof(*state));
-
-	if (state->fb)
-		drm_framebuffer_get(state->fb);
-
-	state->fence = NULL;
-	state->commit = NULL;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
-
-/**
- * drm_atomic_helper_plane_duplicate_state - default state duplicate hook
- * @plane: drm plane
- *
- * Default plane state duplicate hook for drivers which don't have their own
- * subclassed plane state structure.
- */
-struct drm_plane_state *
-drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
-{
-	struct drm_plane_state *state;
-
-	if (WARN_ON(!plane->state))
-		return NULL;
-
-	state = kmalloc(sizeof(*state), GFP_KERNEL);
-	if (state)
-		__drm_atomic_helper_plane_duplicate_state(plane, state);
-
-	return state;
-}
-EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
-
-/**
- * __drm_atomic_helper_plane_destroy_state - release plane state
- * @state: plane state object to release
- *
- * Releases all resources stored in the plane state without actually freeing
- * the memory of the plane state. This is useful for drivers that subclass the
- * plane state.
- */
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
-{
-	if (state->fb)
-		drm_framebuffer_put(state->fb);
-
-	if (state->fence)
-		dma_fence_put(state->fence);
-
-	if (state->commit)
-		drm_crtc_commit_put(state->commit);
-}
-EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
-
-/**
- * drm_atomic_helper_plane_destroy_state - default state destroy hook
- * @plane: drm plane
- * @state: plane state object to release
- *
- * Default plane state destroy hook for drivers which don't have their own
- * subclassed plane state structure.
- */
-void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
-					   struct drm_plane_state *state)
-{
-	__drm_atomic_helper_plane_destroy_state(state);
-	kfree(state);
-}
-EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
-
-/**
- * __drm_atomic_helper_connector_reset - reset state on connector
- * @connector: drm connector
- * @conn_state: connector state to assign
- *
- * Initializes the newly allocated @conn_state and assigns it to
- * the &drm_conector->state pointer of @connector, usually required when
- * initializing the drivers or when called from the &drm_connector_funcs.reset
- * hook.
- *
- * This is useful for drivers that subclass the connector state.
- */
-void
-__drm_atomic_helper_connector_reset(struct drm_connector *connector,
-				    struct drm_connector_state *conn_state)
-{
-	if (conn_state)
-		conn_state->connector = connector;
-
-	connector->state = conn_state;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
-
-/**
- * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
- * @connector: drm connector
- *
- * Resets the atomic state for @connector by freeing the state pointer (which
- * might be NULL, e.g. at driver load time) and allocating a new empty state
- * object.
- */
-void drm_atomic_helper_connector_reset(struct drm_connector *connector)
-{
-	struct drm_connector_state *conn_state =
-		kzalloc(sizeof(*conn_state), GFP_KERNEL);
-
-	if (connector->state)
-		__drm_atomic_helper_connector_destroy_state(connector->state);
-
-	kfree(connector->state);
-	__drm_atomic_helper_connector_reset(connector, conn_state);
-}
-EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
-
-/**
- * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
- * @connector: connector object
- * @state: atomic connector state
- *
- * Copies atomic state from a connector's current state. This is useful for
- * drivers that subclass the connector state.
- */
-void
-__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
-					    struct drm_connector_state *state)
-{
-	memcpy(state, connector->state, sizeof(*state));
-	if (state->crtc)
-		drm_connector_get(connector);
-	state->commit = NULL;
-
-	/* Don't copy over a writeback job, they are used only once */
-	state->writeback_job = NULL;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
-
-/**
- * drm_atomic_helper_connector_duplicate_state - default state duplicate hook
- * @connector: drm connector
- *
- * Default connector state duplicate hook for drivers which don't have their own
- * subclassed connector state structure.
- */
-struct drm_connector_state *
-drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
-{
-	struct drm_connector_state *state;
-
-	if (WARN_ON(!connector->state))
-		return NULL;
-
-	state = kmalloc(sizeof(*state), GFP_KERNEL);
-	if (state)
-		__drm_atomic_helper_connector_duplicate_state(connector, state);
-
-	return state;
-}
-EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
-
-/**
- * drm_atomic_helper_duplicate_state - duplicate an atomic state object
- * @dev: DRM device
- * @ctx: lock acquisition context
- *
- * Makes a copy of the current atomic state by looping over all objects and
- * duplicating their respective states. This is used for example by suspend/
- * resume support code to save the state prior to suspend such that it can
- * be restored upon resume.
- *
- * Note that this treats atomic state as persistent between save and restore.
- * Drivers must make sure that this is possible and won't result in confusion
- * or erroneous behaviour.
- *
- * Note that if callers haven't already acquired all modeset locks this might
- * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
- *
- * Returns:
- * A pointer to the copy of the atomic state object on success or an
- * ERR_PTR()-encoded error code on failure.
- *
- * See also:
- * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
- */
-struct drm_atomic_state *
-drm_atomic_helper_duplicate_state(struct drm_device *dev,
-				  struct drm_modeset_acquire_ctx *ctx)
-{
-	struct drm_atomic_state *state;
-	struct drm_connector *conn;
-	struct drm_connector_list_iter conn_iter;
-	struct drm_plane *plane;
-	struct drm_crtc *crtc;
-	int err = 0;
-
-	state = drm_atomic_state_alloc(dev);
-	if (!state)
-		return ERR_PTR(-ENOMEM);
-
-	state->acquire_ctx = ctx;
-
-	drm_for_each_crtc(crtc, dev) {
-		struct drm_crtc_state *crtc_state;
-
-		crtc_state = drm_atomic_get_crtc_state(state, crtc);
-		if (IS_ERR(crtc_state)) {
-			err = PTR_ERR(crtc_state);
-			goto free;
-		}
-	}
-
-	drm_for_each_plane(plane, dev) {
-		struct drm_plane_state *plane_state;
-
-		plane_state = drm_atomic_get_plane_state(state, plane);
-		if (IS_ERR(plane_state)) {
-			err = PTR_ERR(plane_state);
-			goto free;
-		}
-	}
-
-	drm_connector_list_iter_begin(dev, &conn_iter);
-	drm_for_each_connector_iter(conn, &conn_iter) {
-		struct drm_connector_state *conn_state;
-
-		conn_state = drm_atomic_get_connector_state(state, conn);
-		if (IS_ERR(conn_state)) {
-			err = PTR_ERR(conn_state);
-			drm_connector_list_iter_end(&conn_iter);
-			goto free;
-		}
-	}
-	drm_connector_list_iter_end(&conn_iter);
-
-	/* clear the acquire context so that it isn't accidentally reused */
-	state->acquire_ctx = NULL;
-
-free:
-	if (err < 0) {
-		drm_atomic_state_put(state);
-		state = ERR_PTR(err);
-	}
-
-	return state;
-}
-EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
-
-/**
- * __drm_atomic_helper_connector_destroy_state - release connector state
- * @state: connector state object to release
- *
- * Releases all resources stored in the connector state without actually
- * freeing the memory of the connector state. This is useful for drivers that
- * subclass the connector state.
- */
-void
-__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
-{
-	if (state->crtc)
-		drm_connector_put(state->connector);
-
-	if (state->commit)
-		drm_crtc_commit_put(state->commit);
-}
-EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
-
-/**
- * drm_atomic_helper_connector_destroy_state - default state destroy hook
- * @connector: drm connector
- * @state: connector state object to release
- *
- * Default connector state destroy hook for drivers which don't have their own
- * subclassed connector state structure.
- */
-void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
-					  struct drm_connector_state *state)
-{
-	__drm_atomic_helper_connector_destroy_state(state);
-	kfree(state);
-}
-EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
-
-/**
- * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
- * @crtc: CRTC object
- * @red: red correction table
- * @green: green correction table
- * @blue: green correction table
- * @size: size of the tables
- * @ctx: lock acquire context
- *
- * Implements support for legacy gamma correction table for drivers
- * that support color management through the DEGAMMA_LUT/GAMMA_LUT
- * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
- * how the atomic color management and gamma tables work.
- */
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
-				       u16 *red, u16 *green, u16 *blue,
-				       uint32_t size,
-				       struct drm_modeset_acquire_ctx *ctx)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_atomic_state *state;
-	struct drm_crtc_state *crtc_state;
-	struct drm_property_blob *blob = NULL;
-	struct drm_color_lut *blob_data;
-	int i, ret = 0;
-	bool replaced;
-
-	state = drm_atomic_state_alloc(crtc->dev);
-	if (!state)
-		return -ENOMEM;
-
-	blob = drm_property_create_blob(dev,
-					sizeof(struct drm_color_lut) * size,
-					NULL);
-	if (IS_ERR(blob)) {
-		ret = PTR_ERR(blob);
-		blob = NULL;
-		goto fail;
-	}
-
-	/* Prepare GAMMA_LUT with the legacy values. */
-	blob_data = blob->data;
-	for (i = 0; i < size; i++) {
-		blob_data[i].red = red[i];
-		blob_data[i].green = green[i];
-		blob_data[i].blue = blue[i];
-	}
-
-	state->acquire_ctx = ctx;
-	crtc_state = drm_atomic_get_crtc_state(state, crtc);
-	if (IS_ERR(crtc_state)) {
-		ret = PTR_ERR(crtc_state);
-		goto fail;
-	}
-
-	/* Reset DEGAMMA_LUT and CTM properties. */
-	replaced  = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
-	replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
-	replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
-	crtc_state->color_mgmt_changed |= replaced;
-
-	ret = drm_atomic_commit(state);
-
-fail:
-	drm_atomic_state_put(state);
-	drm_property_blob_put(blob);
-	return ret;
-}
-EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
-
-/**
- * __drm_atomic_helper_private_duplicate_state - copy atomic private state
- * @obj: CRTC object
- * @state: new private object state
- *
- * Copies atomic state from a private objects's current state and resets inferred values.
- * This is useful for drivers that subclass the private state.
- */
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
-						     struct drm_private_state *state)
-{
-	memcpy(state, obj->state, sizeof(*state));
-}
-EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
new file mode 100644
index 000000000000..6c6499b9dbea
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_device.h>
+
+#include <linux/slab.h>
+#include <linux/dma-fence.h>
+
+/**
+ * DOC: atomic state reset and initialization
+ *
+ * Both the drm core and the atomic helpers assume that there is always the full
+ * and correct atomic software state for all connectors, CRTCs and planes
+ * available. Which is a bit a problem on driver load and also after system
+ * suspend. One way to solve this is to have a hardware state read-out
+ * infrastructure which reconstructs the full software state (e.g. the i915
+ * driver).
+ *
+ * The simpler solution is to just reset the software state to everything off,
+ * which is easiest to do by calling drm_mode_config_reset(). To facilitate this
+ * the atomic helpers provide default reset implementations for all hooks.
+ *
+ * On the upside the precise state tracking of atomic simplifies system suspend
+ * and resume a lot. For drivers using drm_mode_config_reset() a complete recipe
+ * is implemented in drm_atomic_helper_suspend() and drm_atomic_helper_resume().
+ * For other drivers the building blocks are split out, see the documentation
+ * for these functions.
+ */
+
+/**
+ * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs
+ * @crtc: drm CRTC
+ *
+ * Resets the atomic state for @crtc by freeing the state pointer (which might
+ * be NULL, e.g. at driver load time) and allocating a new empty state object.
+ */
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
+{
+	if (crtc->state)
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+	kfree(crtc->state);
+	crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
+
+	if (crtc->state)
+		crtc->state->crtc = crtc;
+}
+EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
+
+/**
+ * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
+ * @crtc: CRTC object
+ * @state: atomic CRTC state
+ *
+ * Copies atomic state from a CRTC's current state and resets inferred values.
+ * This is useful for drivers that subclass the CRTC state.
+ */
+void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
+					      struct drm_crtc_state *state)
+{
+	memcpy(state, crtc->state, sizeof(*state));
+
+	if (state->mode_blob)
+		drm_property_blob_get(state->mode_blob);
+	if (state->degamma_lut)
+		drm_property_blob_get(state->degamma_lut);
+	if (state->ctm)
+		drm_property_blob_get(state->ctm);
+	if (state->gamma_lut)
+		drm_property_blob_get(state->gamma_lut);
+	state->mode_changed = false;
+	state->active_changed = false;
+	state->planes_changed = false;
+	state->connectors_changed = false;
+	state->color_mgmt_changed = false;
+	state->zpos_changed = false;
+	state->commit = NULL;
+	state->event = NULL;
+	state->pageflip_flags = 0;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
+
+/**
+ * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
+ * @crtc: drm CRTC
+ *
+ * Default CRTC state duplicate hook for drivers which don't have their own
+ * subclassed CRTC state structure.
+ */
+struct drm_crtc_state *
+drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct drm_crtc_state *state;
+
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_crtc_duplicate_state(crtc, state);
+
+	return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
+
+/**
+ * __drm_atomic_helper_crtc_destroy_state - release CRTC state
+ * @state: CRTC state object to release
+ *
+ * Releases all resources stored in the CRTC state without actually freeing
+ * the memory of the CRTC state. This is useful for drivers that subclass the
+ * CRTC state.
+ */
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
+{
+	if (state->commit) {
+		/*
+		 * In the event that a non-blocking commit returns
+		 * -ERESTARTSYS before the commit_tail work is queued, we will
+		 * have an extra reference to the commit object. Release it, if
+		 * the event has not been consumed by the worker.
+		 *
+		 * state->event may be freed, so we can't directly look at
+		 * state->event->base.completion.
+		 */
+		if (state->event && state->commit->abort_completion)
+			drm_crtc_commit_put(state->commit);
+
+		kfree(state->commit->event);
+		state->commit->event = NULL;
+
+		drm_crtc_commit_put(state->commit);
+	}
+
+	drm_property_blob_put(state->mode_blob);
+	drm_property_blob_put(state->degamma_lut);
+	drm_property_blob_put(state->ctm);
+	drm_property_blob_put(state->gamma_lut);
+}
+EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
+
+/**
+ * drm_atomic_helper_crtc_destroy_state - default state destroy hook
+ * @crtc: drm CRTC
+ * @state: CRTC state object to release
+ *
+ * Default CRTC state destroy hook for drivers which don't have their own
+ * subclassed CRTC state structure.
+ */
+void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
+					  struct drm_crtc_state *state)
+{
+	__drm_atomic_helper_crtc_destroy_state(state);
+	kfree(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
+
+/**
+ * __drm_atomic_helper_plane_reset - resets planes state to default values
+ * @plane: plane object, must not be NULL
+ * @state: atomic plane state, must not be NULL
+ *
+ * Initializes plane state to default. This is useful for drivers that subclass
+ * the plane state.
+ */
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
+				     struct drm_plane_state *state)
+{
+	state->plane = plane;
+	state->rotation = DRM_MODE_ROTATE_0;
+
+	/* Reset the alpha value to fully opaque if it matters */
+	if (plane->alpha_property)
+		state->alpha = plane->alpha_property->values[1];
+	state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
+
+	plane->state = state;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_plane_reset);
+
+/**
+ * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes
+ * @plane: drm plane
+ *
+ * Resets the atomic state for @plane by freeing the state pointer (which might
+ * be NULL, e.g. at driver load time) and allocating a new empty state object.
+ */
+void drm_atomic_helper_plane_reset(struct drm_plane *plane)
+{
+	if (plane->state)
+		__drm_atomic_helper_plane_destroy_state(plane->state);
+
+	kfree(plane->state);
+	plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
+	if (plane->state)
+		__drm_atomic_helper_plane_reset(plane, plane->state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
+
+/**
+ * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
+ * @plane: plane object
+ * @state: atomic plane state
+ *
+ * Copies atomic state from a plane's current state. This is useful for
+ * drivers that subclass the plane state.
+ */
+void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
+					       struct drm_plane_state *state)
+{
+	memcpy(state, plane->state, sizeof(*state));
+
+	if (state->fb)
+		drm_framebuffer_get(state->fb);
+
+	state->fence = NULL;
+	state->commit = NULL;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
+
+/**
+ * drm_atomic_helper_plane_duplicate_state - default state duplicate hook
+ * @plane: drm plane
+ *
+ * Default plane state duplicate hook for drivers which don't have their own
+ * subclassed plane state structure.
+ */
+struct drm_plane_state *
+drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct drm_plane_state *state;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_plane_duplicate_state(plane, state);
+
+	return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
+
+/**
+ * __drm_atomic_helper_plane_destroy_state - release plane state
+ * @state: plane state object to release
+ *
+ * Releases all resources stored in the plane state without actually freeing
+ * the memory of the plane state. This is useful for drivers that subclass the
+ * plane state.
+ */
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
+{
+	if (state->fb)
+		drm_framebuffer_put(state->fb);
+
+	if (state->fence)
+		dma_fence_put(state->fence);
+
+	if (state->commit)
+		drm_crtc_commit_put(state->commit);
+}
+EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
+
+/**
+ * drm_atomic_helper_plane_destroy_state - default state destroy hook
+ * @plane: drm plane
+ * @state: plane state object to release
+ *
+ * Default plane state destroy hook for drivers which don't have their own
+ * subclassed plane state structure.
+ */
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
+					   struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
+
+/**
+ * __drm_atomic_helper_connector_reset - reset state on connector
+ * @connector: drm connector
+ * @conn_state: connector state to assign
+ *
+ * Initializes the newly allocated @conn_state and assigns it to
+ * the &drm_conector->state pointer of @connector, usually required when
+ * initializing the drivers or when called from the &drm_connector_funcs.reset
+ * hook.
+ *
+ * This is useful for drivers that subclass the connector state.
+ */
+void
+__drm_atomic_helper_connector_reset(struct drm_connector *connector,
+				    struct drm_connector_state *conn_state)
+{
+	if (conn_state)
+		conn_state->connector = connector;
+
+	connector->state = conn_state;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_connector_reset);
+
+/**
+ * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors
+ * @connector: drm connector
+ *
+ * Resets the atomic state for @connector by freeing the state pointer (which
+ * might be NULL, e.g. at driver load time) and allocating a new empty state
+ * object.
+ */
+void drm_atomic_helper_connector_reset(struct drm_connector *connector)
+{
+	struct drm_connector_state *conn_state =
+		kzalloc(sizeof(*conn_state), GFP_KERNEL);
+
+	if (connector->state)
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+
+	kfree(connector->state);
+	__drm_atomic_helper_connector_reset(connector, conn_state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
+
+/**
+ * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
+ * @connector: connector object
+ * @state: atomic connector state
+ *
+ * Copies atomic state from a connector's current state. This is useful for
+ * drivers that subclass the connector state.
+ */
+void
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					    struct drm_connector_state *state)
+{
+	memcpy(state, connector->state, sizeof(*state));
+	if (state->crtc)
+		drm_connector_get(connector);
+	state->commit = NULL;
+
+	/* Don't copy over a writeback job, they are used only once */
+	state->writeback_job = NULL;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
+
+/**
+ * drm_atomic_helper_connector_duplicate_state - default state duplicate hook
+ * @connector: drm connector
+ *
+ * Default connector state duplicate hook for drivers which don't have their own
+ * subclassed connector state structure.
+ */
+struct drm_connector_state *
+drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
+{
+	struct drm_connector_state *state;
+
+	if (WARN_ON(!connector->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_connector_duplicate_state(connector, state);
+
+	return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
+
+/**
+ * drm_atomic_helper_duplicate_state - duplicate an atomic state object
+ * @dev: DRM device
+ * @ctx: lock acquisition context
+ *
+ * Makes a copy of the current atomic state by looping over all objects and
+ * duplicating their respective states. This is used for example by suspend/
+ * resume support code to save the state prior to suspend such that it can
+ * be restored upon resume.
+ *
+ * Note that this treats atomic state as persistent between save and restore.
+ * Drivers must make sure that this is possible and won't result in confusion
+ * or erroneous behaviour.
+ *
+ * Note that if callers haven't already acquired all modeset locks this might
+ * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
+ *
+ * Returns:
+ * A pointer to the copy of the atomic state object on success or an
+ * ERR_PTR()-encoded error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
+ */
+struct drm_atomic_state *
+drm_atomic_helper_duplicate_state(struct drm_device *dev,
+				  struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_atomic_state *state;
+	struct drm_connector *conn;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	int err = 0;
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+
+	state->acquire_ctx = ctx;
+
+	drm_for_each_crtc(crtc, dev) {
+		struct drm_crtc_state *crtc_state;
+
+		crtc_state = drm_atomic_get_crtc_state(state, crtc);
+		if (IS_ERR(crtc_state)) {
+			err = PTR_ERR(crtc_state);
+			goto free;
+		}
+	}
+
+	drm_for_each_plane(plane, dev) {
+		struct drm_plane_state *plane_state;
+
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			err = PTR_ERR(plane_state);
+			goto free;
+		}
+	}
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+	drm_for_each_connector_iter(conn, &conn_iter) {
+		struct drm_connector_state *conn_state;
+
+		conn_state = drm_atomic_get_connector_state(state, conn);
+		if (IS_ERR(conn_state)) {
+			err = PTR_ERR(conn_state);
+			drm_connector_list_iter_end(&conn_iter);
+			goto free;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	/* clear the acquire context so that it isn't accidentally reused */
+	state->acquire_ctx = NULL;
+
+free:
+	if (err < 0) {
+		drm_atomic_state_put(state);
+		state = ERR_PTR(err);
+	}
+
+	return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
+
+/**
+ * __drm_atomic_helper_connector_destroy_state - release connector state
+ * @state: connector state object to release
+ *
+ * Releases all resources stored in the connector state without actually
+ * freeing the memory of the connector state. This is useful for drivers that
+ * subclass the connector state.
+ */
+void
+__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
+{
+	if (state->crtc)
+		drm_connector_put(state->connector);
+
+	if (state->commit)
+		drm_crtc_commit_put(state->commit);
+}
+EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
+
+/**
+ * drm_atomic_helper_connector_destroy_state - default state destroy hook
+ * @connector: drm connector
+ * @state: connector state object to release
+ *
+ * Default connector state destroy hook for drivers which don't have their own
+ * subclassed connector state structure.
+ */
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state)
+{
+	__drm_atomic_helper_connector_destroy_state(state);
+	kfree(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
+
+/**
+ * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
+ * @crtc: CRTC object
+ * @red: red correction table
+ * @green: green correction table
+ * @blue: green correction table
+ * @size: size of the tables
+ * @ctx: lock acquire context
+ *
+ * Implements support for legacy gamma correction table for drivers
+ * that support color management through the DEGAMMA_LUT/GAMMA_LUT
+ * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
+ * how the atomic color management and gamma tables work.
+ */
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
+				       u16 *red, u16 *green, u16 *blue,
+				       uint32_t size,
+				       struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_atomic_state *state;
+	struct drm_crtc_state *crtc_state;
+	struct drm_property_blob *blob = NULL;
+	struct drm_color_lut *blob_data;
+	int i, ret = 0;
+	bool replaced;
+
+	state = drm_atomic_state_alloc(crtc->dev);
+	if (!state)
+		return -ENOMEM;
+
+	blob = drm_property_create_blob(dev,
+					sizeof(struct drm_color_lut) * size,
+					NULL);
+	if (IS_ERR(blob)) {
+		ret = PTR_ERR(blob);
+		blob = NULL;
+		goto fail;
+	}
+
+	/* Prepare GAMMA_LUT with the legacy values. */
+	blob_data = blob->data;
+	for (i = 0; i < size; i++) {
+		blob_data[i].red = red[i];
+		blob_data[i].green = green[i];
+		blob_data[i].blue = blue[i];
+	}
+
+	state->acquire_ctx = ctx;
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state)) {
+		ret = PTR_ERR(crtc_state);
+		goto fail;
+	}
+
+	/* Reset DEGAMMA_LUT and CTM properties. */
+	replaced  = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
+	replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
+	replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
+	crtc_state->color_mgmt_changed |= replaced;
+
+	ret = drm_atomic_commit(state);
+
+fail:
+	drm_atomic_state_put(state);
+	drm_property_blob_put(blob);
+	return ret;
+}
+EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+
+/**
+ * __drm_atomic_helper_private_duplicate_state - copy atomic private state
+ * @obj: CRTC object
+ * @state: new private object state
+ *
+ * Copies atomic state from a private objects's current state and resets inferred values.
+ * This is useful for drivers that subclass the private state.
+ */
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
+						     struct drm_private_state *state)
+{
+	memcpy(state, obj->state, sizeof(*state));
+}
+EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 27aef91ca1c3..6d6448c97ce0 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -31,6 +31,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_modeset_helper.h>
+#include <drm/drm_atomic_state_helper.h>
 #include <drm/kernel.h>
 
 struct drm_atomic_state;
@@ -145,49 +146,6 @@ int drm_atomic_helper_page_flip_target(
 				uint32_t target,
 				struct drm_modeset_acquire_ctx *ctx);
 
-/* default implementations for state handling */
-void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
-void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
-					      struct drm_crtc_state *state);
-struct drm_crtc_state *
-drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state);
-void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
-					  struct drm_crtc_state *state);
-
-void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
-				     struct drm_plane_state *state);
-void drm_atomic_helper_plane_reset(struct drm_plane *plane);
-void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
-					       struct drm_plane_state *state);
-struct drm_plane_state *
-drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state);
-void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
-					  struct drm_plane_state *state);
-
-void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
-					 struct drm_connector_state *conn_state);
-void drm_atomic_helper_connector_reset(struct drm_connector *connector);
-void
-__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
-					   struct drm_connector_state *state);
-struct drm_connector_state *
-drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
-struct drm_atomic_state *
-drm_atomic_helper_duplicate_state(struct drm_device *dev,
-				  struct drm_modeset_acquire_ctx *ctx);
-void
-__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state);
-void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
-					  struct drm_connector_state *state);
-int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
-				       u16 *red, u16 *green, u16 *blue,
-				       uint32_t size,
-				       struct drm_modeset_acquire_ctx *ctx);
-void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
-						     struct drm_private_state *state);
-
 /**
  * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
  * @plane: the loop cursor
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
new file mode 100644
index 000000000000..5b82ccfdb502
--- /dev/null
+++ b/include/drm/drm_atomic_state_helper.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <linux/types.h>
+
+struct drm_crtc;
+struct drm_crtc_state;
+struct drm_plane;
+struct drm_plane_state;
+struct drm_connector;
+struct drm_connector_state;
+struct drm_private_obj;
+struct drm_private_state;
+struct drm_modeset_acquire_ctx;
+struct drm_device;
+
+void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
+void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
+					      struct drm_crtc_state *state);
+struct drm_crtc_state *
+drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state);
+void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
+					  struct drm_crtc_state *state);
+
+void __drm_atomic_helper_plane_reset(struct drm_plane *plane,
+				     struct drm_plane_state *state);
+void drm_atomic_helper_plane_reset(struct drm_plane *plane);
+void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
+					       struct drm_plane_state *state);
+struct drm_plane_state *
+drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state);
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
+					  struct drm_plane_state *state);
+
+void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
+					 struct drm_connector_state *conn_state);
+void drm_atomic_helper_connector_reset(struct drm_connector *connector);
+void
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					   struct drm_connector_state *state);
+struct drm_connector_state *
+drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
+struct drm_atomic_state *
+drm_atomic_helper_duplicate_state(struct drm_device *dev,
+				  struct drm_modeset_acquire_ctx *ctx);
+void
+__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state);
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state);
+int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
+				       u16 *red, u16 *green, u16 *blue,
+				       uint32_t size,
+				       struct drm_modeset_acquire_ctx *ctx);
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
+						     struct drm_private_state *state);
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 11/14] drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (8 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 10/14] drm: Extract drm_atomic_state_helper.[hc] Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 12/14] drm/vmwgfx: Don't look at state->allow_modeset Daniel Vetter
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: Daniel Vetter, Intel Graphics Development, VMware Graphics,
	Thomas Hellstrom, Sinclair Yeh

The core _does_ the call to drm_atomic_commit for you. That's pretty
much the entire point of having the fancy new atomic_set/get_prop
callbacks.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: VMware Graphics <linux-graphics-maintainer@vmware.com>
Cc: Sinclair Yeh <syeh@vmware.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 0c25bb8faf80..0f7e116a59f0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2309,12 +2309,6 @@ vmw_du_connector_atomic_set_property(struct drm_connector *connector,
 
 	if (property == dev_priv->implicit_placement_property) {
 		vcs->is_implicit = val;
-
-		/*
-		 * We should really be doing a drm_atomic_commit() to
-		 * commit the new state, but since this doesn't cause
-		 * an immedate state change, this is probably ok
-		 */
 		du->is_implicit = vcs->is_implicit;
 	} else {
 		return -EINVAL;
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 12/14] drm/vmwgfx: Don't look at state->allow_modeset
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (9 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 11/14] drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 13/14] drm/atomic: Improve docs for drm_atomic_state->allow_modeset Daniel Vetter
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development

That's purely for the uapi layer to implement the ALLOW_MODESET flag.

Drivers should instead look at the state, e.g. through
drm_atomic_crtc_needs_modeset(), which vmwgfx already does. Also remove
the confusing comment, since checking allow_modeset is at best a micro
optimization.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 0f7e116a59f0..71b7460d140f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1683,14 +1683,6 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	if (!state->allow_modeset)
-		return ret;
-
-	/*
-	 * Legacy path do not set allow_modeset properly like
-	 * @drm_atomic_helper_update_plane, This will result in unnecessary call
-	 * to vmw_kms_check_topology. So extra set of check.
-	 */
 	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 		if (drm_atomic_crtc_needs_modeset(crtc_state))
 			need_modeset = true;
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 13/14] drm/atomic: Improve docs for drm_atomic_state->allow_modeset
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (10 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 12/14] drm/vmwgfx: Don't look at state->allow_modeset Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-03 16:54 ` [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers Daniel Vetter
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

Motivated by vmwgfx digging around in core uapi bits it shouldn't dig
around in.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 include/drm/drm_atomic.h | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4aff40886acb..91d896ec9c10 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -254,7 +254,6 @@ struct __drm_private_objs_state {
  * struct drm_atomic_state - the global state object for atomic updates
  * @ref: count of all references to this state (will not be freed until zero)
  * @dev: parent DRM device
- * @allow_modeset: allow full modeset
  * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
  * @async_update: hint for asynchronous plane update
  * @planes: pointer to array of structures with per-plane data
@@ -273,6 +272,15 @@ struct drm_atomic_state {
 	struct kref ref;
 
 	struct drm_device *dev;
+
+	/**
+	 * @allow_modeset:
+	 *
+	 * Allow full modeset. This is used by the ATOMIC IOCTL handler to
+	 * implement the DRM_MODE_ATOMIC_ALLOW_MODESET flag. Drivers should
+	 * never consult this flag, instead looking at the output of
+	 * drm_atomic_crtc_needs_modeset().
+	 */
 	bool allow_modeset : 1;
 	bool legacy_cursor_update : 1;
 	bool async_update : 1;
-- 
2.18.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (11 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 13/14] drm/atomic: Improve docs for drm_atomic_state->allow_modeset Daniel Vetter
@ 2018-09-03 16:54 ` Daniel Vetter
  2018-09-04 13:45   ` Thomas Hellstrom
  2018-09-03 17:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file Patchwork
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 34+ messages in thread
From: Daniel Vetter @ 2018-09-03 16:54 UTC (permalink / raw)
  To: DRI Development
  Cc: Thomas Hellstrom, Daniel Vetter, Intel Graphics Development,
	VMware Graphics, Daniel Vetter

The idea behind allowing drivers to override legacy ioctls (instead of
using the generic implementations unconditionally) is to handle bugs
in old driver-specific userspace. Like e.g. vmw_kms_set_config does,
to work around some vmwgfx userspace not clearing its ioctl structs
properly.

But you can't use it to augment semantics and put in additional
checks, since from a correctly working userspace's pov there should
not be any difference in behaviour between the legacy and the atomic
paths.

vmwgfx seems to be doing some strange things in its page_flip
handlers. Since I'm not an expert of this codebase just wrap some
FIXME comments around the potentially problematic code.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: VMware Graphics <linux-graphics-maintainer@vmware.com>
Cc: Sinclair Yeh <syeh@vmware.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 4c68ad6f3605..8e692334c3b9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -326,6 +326,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
 	int ret;
 
+	/* FIMXE: This check needs to be moved into ->atomic_check code. */
 	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
 		return -EINVAL;
 
@@ -335,6 +336,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 		return ret;
 	}
 
+	/* FIMXE: This code needs to be moved into ->atomic_commit callbacks. */
 	if (vmw_crtc_to_du(crtc)->is_implicit)
 		vmw_kms_update_implicit_fb(dev_priv, crtc);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index f5b2fe8a7793..1913e086d015 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -501,6 +501,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
 	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
 	int ret;
 
+	/* FIMXE: This check needs to be moved into ->atomic_check code. */
 	if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
 		return -EINVAL;
 
-- 
2.18.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 09/14] drm: Update todo.rst
  2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
@ 2018-09-03 17:24   ` Sam Ravnborg
  2018-09-03 17:38   ` [Intel-gfx] " Emil Velikov
  2018-09-05  8:04   ` [PATCH] " Daniel Vetter
  2 siblings, 0 replies; 34+ messages in thread
From: Sam Ravnborg @ 2018-09-03 17:24 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, Intel Graphics Development, Sean Paul, DRI Development

Hi Daniel.

> -Note that this is well in progress, but ``drmP.h`` is still huge. The updated
> -plan is to switch to per-file driver API headers, which will also structure
> -the kerneldoc better. This should also allow more fine-grained ``#include``
> -directives.
> +The DRM subsystem originally had only one huge globale header, ``drmP.h``. This
globale => global

> +is not split up, but many source files still include it. The remainig part of
remainig => remaining

	Sam
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [Intel-gfx] [PATCH 09/14] drm: Update todo.rst
  2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
  2018-09-03 17:24   ` Sam Ravnborg
@ 2018-09-03 17:38   ` Emil Velikov
  2018-09-04 12:19     ` Daniel Vetter
  2018-09-05  8:04   ` [PATCH] " Daniel Vetter
  2 siblings, 1 reply; 34+ messages in thread
From: Emil Velikov @ 2018-09-03 17:38 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, Intel Graphics Development, Sean Paul, DRI Development

On 3 September 2018 at 17:54, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> -Hide legacy cruft better
> -------------------------
> -
> -Way back DRM supported only drivers which shadow-attached to PCI devices with
> -userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
> -of the entire device, you can spot them with the DRIVER_MODESET flag.
> -
> -Unfortunately there's still large piles of legacy code around which needs to
> -be hidden so that driver writers don't accidentally end up using it. And to
> -prevent security issues in those legacy IOCTLs from being exploited on modern
> -drivers. This has multiple possible subtasks:
> -

> -* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
> -  module and compile it only when one of the legacy drivers is enabled.
> -
This isn't done,

> -This is mostly done, the only thing left is to split up ``drm_irq.c`` into
> -legacy cruft and the parts needed by modern KMS drivers.
> -
... while this one is.

HTH
-Emil
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (12 preceding siblings ...)
  2018-09-03 16:54 ` [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers Daniel Vetter
@ 2018-09-03 17:47 ` Patchwork
  2018-09-03 17:53 ` ✗ Fi.CI.SPARSE: " Patchwork
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-03 17:47 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file
URL   : https://patchwork.freedesktop.org/series/49089/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
a39d30c28e70 drm: Add drm/kernel.h header file
-:139: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#139: 
new file mode 100644

-:144: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#144: FILE: include/drm/kernel.h:1:
+/*

-:173: ERROR:MULTISTATEMENT_MACRO_USE_DO_WHILE: Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects
#173: FILE: include/drm/kernel.h:30:
+#define for_each_if(condition) if (!(condition)) {} else

-:173: WARNING:BRACES: braces {} are not necessary for single statement blocks
#173: FILE: include/drm/kernel.h:30:
+#define for_each_if(condition) if (!(condition)) {} else

total: 1 errors, 3 warnings, 0 checks, 105 lines checked
4e507bab6b77 drm: Drop drmP.h from drm_connector.c
-:56: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 30 lines checked
963a78e5752b drm: drop drmP.h include from drm_plane.c
-:92: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 55 lines checked
acd20948fa62 drm: drop drmP.h include from drm_crtc.c
-:35: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 17 lines checked
d53335198614 drm/atomic: trim driver interface/docs
-:88: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#88: FILE: drivers/gpu/drm/drm_atomic.c:501:
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		struct drm_crtc_state *state, struct drm_property *property,

-:202: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#202: FILE: drivers/gpu/drm/drm_atomic.c:1253:
+static int drm_atomic_set_writeback_fb_for_connector(

-:342: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 2 checks, 301 lines checked
2433899462b1 drm: extract drm_atomic_uapi.c
-:1498: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#1498: 
new file mode 100644

-:1503: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#1503: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1:
+/*

-:1552: WARNING:TYPO_SPELLING: 'similiar' may be misspelled - perhaps 'similar'?
#1552: FILE: drivers/gpu/drm/drm_atomic_uapi.c:50:
+ * for load detect or similiar.

-:1583: ERROR:CODE_INDENT: code indent should use tabs where possible
#1583: FILE: drivers/gpu/drm/drm_atomic_uapi.c:81:
+^I^I                                 sizeof(umode),$

-:1583: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1583: FILE: drivers/gpu/drm/drm_atomic_uapi.c:81:
+			drm_property_create_blob(state->crtc->dev,
+		                                 sizeof(umode),

-:1584: ERROR:CODE_INDENT: code indent should use tabs where possible
#1584: FILE: drivers/gpu/drm/drm_atomic_uapi.c:82:
+^I^I                                 &umode);$

-:1617: ERROR:CODE_INDENT: code indent should use tabs where possible
#1617: FILE: drivers/gpu/drm/drm_atomic_uapi.c:115:
+                                      struct drm_property_blob *blob)$

-:1617: WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1617: FILE: drivers/gpu/drm/drm_atomic_uapi.c:115:
+                                      struct drm_property_blob *blob)$

-:1860: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1860: FILE: drivers/gpu/drm/drm_atomic_uapi.c:358:
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,

-:1900: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!new_blob"
#1900: FILE: drivers/gpu/drm/drm_atomic_uapi.c:398:
+		if (new_blob == NULL)

-:1922: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1922: FILE: drivers/gpu/drm/drm_atomic_uapi.c:420:
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
+		struct drm_crtc_state *state, struct drm_property *property,

-:1930: CHECK:BRACES: braces {} should be used on all arms of this statement
#1930: FILE: drivers/gpu/drm/drm_atomic_uapi.c:428:
+	if (property == config->prop_active)
[...]
+	else if (property == config->prop_mode_id) {
[...]
+	} else if (property == config->degamma_lut_property) {
[...]
+	} else if (property == config->ctm_property) {
[...]
+	} else if (property == config->gamma_lut_property) {
[...]
+	} else if (property == config->prop_out_fence_ptr) {
[...]
+	} else if (crtc->funcs->atomic_set_property) {
[...]
+	} else {
[...]

-:1940: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1940: FILE: drivers/gpu/drm/drm_atomic_uapi.c:438:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->degamma_lut,

-:1948: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1948: FILE: drivers/gpu/drm/drm_atomic_uapi.c:446:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->ctm,

-:1956: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1956: FILE: drivers/gpu/drm/drm_atomic_uapi.c:454:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->gamma_lut,

-:1974: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#1974: FILE: drivers/gpu/drm/drm_atomic_uapi.c:472:
+		return crtc->funcs->atomic_set_property(crtc, state, property, val);
+	} else {

-:1986: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1986: FILE: drivers/gpu/drm/drm_atomic_uapi.c:484:
+drm_atomic_crtc_get_property(struct drm_crtc *crtc,
+		const struct drm_crtc_state *state,

-:2013: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2013: FILE: drivers/gpu/drm/drm_atomic_uapi.c:511:
+static int drm_atomic_plane_set_property(struct drm_plane *plane,
+		struct drm_plane_state *state, struct drm_property *property,

-:2021: WARNING:LINE_SPACING: Missing a blank line after declarations
#2021: FILE: drivers/gpu/drm/drm_atomic_uapi.c:519:
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		drm_atomic_set_fb_for_plane(state, fb);

-:2037: WARNING:LINE_SPACING: Missing a blank line after declarations
#2037: FILE: drivers/gpu/drm/drm_atomic_uapi.c:535:
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_plane(state, crtc);

-:2086: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2086: FILE: drivers/gpu/drm/drm_atomic_uapi.c:584:
+drm_atomic_plane_get_property(struct drm_plane *plane,
+		const struct drm_plane_state *state,

-:2092: WARNING:BRACES: braces {} are not necessary for any arm of this statement
#2092: FILE: drivers/gpu/drm/drm_atomic_uapi.c:590:
+	if (property == config->prop_fb_id) {
[...]
+	} else if (property == config->prop_in_fence_fd) {
[...]
+	} else if (property == config->prop_crtc_id) {
[...]
+	} else if (property == config->prop_crtc_x) {
[...]
+	} else if (property == config->prop_crtc_y) {
[...]
+	} else if (property == config->prop_crtc_w) {
[...]
+	} else if (property == config->prop_crtc_h) {
[...]
+	} else if (property == config->prop_src_x) {
[...]
+	} else if (property == config->prop_src_y) {
[...]
+	} else if (property == config->prop_src_w) {
[...]
+	} else if (property == config->prop_src_h) {
[...]
+	} else if (property == plane->alpha_property) {
[...]
+	} else if (property == plane->blend_mode_property) {
[...]
+	} else if (property == plane->rotation_property) {
[...]
+	} else if (property == plane->zpos_property) {
[...]
+	} else if (property == plane->color_encoding_property) {
[...]
+	} else if (property == plane->color_range_property) {
[...]
+	} else if (plane->funcs->atomic_get_property) {
[...]
+	} else {
[...]

-:2147: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#2147: FILE: drivers/gpu/drm/drm_atomic_uapi.c:645:
+static int drm_atomic_set_writeback_fb_for_connector(

-:2169: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2169: FILE: drivers/gpu/drm/drm_atomic_uapi.c:667:
+static int drm_atomic_connector_set_property(struct drm_connector *connector,
+		struct drm_connector_state *state, struct drm_property *property,

-:2177: WARNING:LINE_SPACING: Missing a blank line after declarations
#2177: FILE: drivers/gpu/drm/drm_atomic_uapi.c:675:
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_connector(state, crtc);

-:2237: WARNING:LINE_SPACING: Missing a blank line after declarations
#2237: FILE: drivers/gpu/drm/drm_atomic_uapi.c:735:
+		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)

-:2260: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2260: FILE: drivers/gpu/drm/drm_atomic_uapi.c:758:
+drm_atomic_connector_get_property(struct drm_connector *connector,
+		const struct drm_connector_state *state,

-:2320: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2320: FILE: drivers/gpu/drm/drm_atomic_uapi.c:818:
+int drm_atomic_get_property(struct drm_mode_object *obj,
+		struct drm_property *property, uint64_t *val)

-:2328: WARNING:LINE_SPACING: Missing a blank line after declarations
#2328: FILE: drivers/gpu/drm/drm_atomic_uapi.c:826:
+		struct drm_connector *connector = obj_to_connector(obj);
+		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));

-:2330: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2330: FILE: drivers/gpu/drm/drm_atomic_uapi.c:828:
+		ret = drm_atomic_connector_get_property(connector,
+				connector->state, property, val);

-:2335: WARNING:LINE_SPACING: Missing a blank line after declarations
#2335: FILE: drivers/gpu/drm/drm_atomic_uapi.c:833:
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));

-:2337: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2337: FILE: drivers/gpu/drm/drm_atomic_uapi.c:835:
+		ret = drm_atomic_crtc_get_property(crtc,
+				crtc->state, property, val);

-:2342: WARNING:LINE_SPACING: Missing a blank line after declarations
#2342: FILE: drivers/gpu/drm/drm_atomic_uapi.c:840:
+		struct drm_plane *plane = obj_to_plane(obj);
+		WARN_ON(!drm_modeset_is_locked(&plane->mutex));

-:2344: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2344: FILE: drivers/gpu/drm/drm_atomic_uapi.c:842:
+		ret = drm_atomic_plane_get_property(plane,
+				plane->state, property, val);

-:2359: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#2359: FILE: drivers/gpu/drm/drm_atomic_uapi.c:857:
+static struct drm_pending_vblank_event *create_vblank_event(

-:2364: WARNING:SIZEOF_PARENTHESIS: sizeof *e should be sizeof(*e)
#2364: FILE: drivers/gpu/drm/drm_atomic_uapi.c:862:
+	e = kzalloc(sizeof *e, GFP_KERNEL);

-:2449: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2449: FILE: drivers/gpu/drm/drm_atomic_uapi.c:947:
+		ret = drm_atomic_connector_set_property(connector,
+				connector_state, prop, prop_value);

-:2463: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2463: FILE: drivers/gpu/drm/drm_atomic_uapi.c:961:
+		ret = drm_atomic_crtc_set_property(crtc,
+				crtc_state, prop, prop_value);

-:2477: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2477: FILE: drivers/gpu/drm/drm_atomic_uapi.c:975:
+		ret = drm_atomic_plane_set_property(plane,
+				plane_state, prop, prop_value);

-:2493: WARNING:TYPO_SPELLING: 'transfered' may be misspelled - perhaps 'transferred'?
#2493: FILE: drivers/gpu/drm/drm_atomic_uapi.c:991:
+ * between devices. A Fence or a group of fences are transfered to/from

-:2565: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2565: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1063:
+static int prepare_signaling(struct drm_device *dev,
+				  struct drm_atomic_state *state,

-:2772: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2772: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1270:
+	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
+			!dev->mode_config.async_page_flip)

-:2777: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2777: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1275:
+	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
+			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))

-:3049: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#3049: FILE: include/drm/drm_atomic_uapi.h:1:
+/*

-:3106: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 3 errors, 17 warnings, 25 checks, 2443 lines checked
a0725c65f9ee drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
-:133: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 72 lines checked
743e2645a0a1 drm/amdgpu: Remove default best_encoder hook from DC
-:58: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 35 lines checked
e8bab7fce24b drm: Update todo.rst
0cac37810f9d drm: Extract drm_atomic_state_helper.[hc]
-:640: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#640: 
new file mode 100644

-:645: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#645: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:1:
+/*

-:959: WARNING:TYPO_SPELLING: 'conector' may be misspelled - perhaps 'connector'?
#959: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:315:
+ * the &drm_conector->state pointer of @connector, usually required when

-:1007: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1007: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:363:
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					    struct drm_connector_state *state)

-:1157: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1157: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:513:
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state)

-:1316: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#1316: FILE: include/drm/drm_atomic_state_helper.h:1:
+/*

-:1373: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1373: FILE: include/drm/drm_atomic_state_helper.h:58:
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
+					  struct drm_plane_state *state);

-:1380: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1380: FILE: include/drm/drm_atomic_state_helper.h:65:
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					   struct drm_connector_state *state);

-:1389: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1389: FILE: include/drm/drm_atomic_state_helper.h:74:
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state);

-:1395: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 5 warnings, 5 checks, 784 lines checked
3f52631f306e drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
a00d9f872f7f drm/vmwgfx: Don't look at state->allow_modeset
835a147156e8 drm/atomic: Improve docs for drm_atomic_state->allow_modeset
-:38: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 22 lines checked
64895f7efd90 drm/vmwgfx: Add FIXME comments for customer page_flip handlers
-:58: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 21 lines checked

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.SPARSE: warning for series starting with [01/14] drm: Add drm/kernel.h header file
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (13 preceding siblings ...)
  2018-09-03 17:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file Patchwork
@ 2018-09-03 17:53 ` Patchwork
  2018-09-03 18:05 ` ✗ Fi.CI.BAT: failure " Patchwork
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-03 17:53 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file
URL   : https://patchwork.freedesktop.org/series/49089/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Commit: drm: Add drm/kernel.h header file
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3686:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3687:16: warning: expression using sizeof(void)

Commit: drm: Drop drmP.h from drm_connector.c
Okay!

Commit: drm: drop drmP.h include from drm_plane.c
Okay!

Commit: drm: drop drmP.h include from drm_crtc.c
Okay!

Commit: drm/atomic: trim driver interface/docs
Okay!

Commit: drm: extract drm_atomic_uapi.c
Okay!

Commit: drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
Okay!

Commit: drm/amdgpu: Remove default best_encoder hook from DC
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3035:6: warning: symbol 'dm_drm_plane_destroy_state' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3826:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3826:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3830:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3830:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3937:58: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3012:6: warning: symbol 'dm_drm_plane_destroy_state' was not declared. Should it be static?
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3803:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3803:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3807:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3807:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3914:58: warning: Using plain integer as NULL pointer

Commit: drm: Update todo.rst
Okay!

Commit: drm: Extract drm_atomic_state_helper.[hc]
Okay!

Commit: drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
Okay!

Commit: drm/vmwgfx: Don't look at state->allow_modeset
Okay!

Commit: drm/atomic: Improve docs for drm_atomic_state->allow_modeset
Okay!

Commit: drm/vmwgfx: Add FIXME comments for customer page_flip handlers
Okay!

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.BAT: failure for series starting with [01/14] drm: Add drm/kernel.h header file
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (14 preceding siblings ...)
  2018-09-03 17:53 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2018-09-03 18:05 ` Patchwork
  2018-09-05  8:09 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file (rev3) Patchwork
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-03 18:05 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file
URL   : https://patchwork.freedesktop.org/series/49089/
State : failure

== Summary ==

= CI Bug Log - changes from CI_DRM_4758 -> Patchwork_10076 =

== Summary - FAILURE ==

  Serious unknown changes coming with Patchwork_10076 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_10076, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/49089/revisions/1/mbox/

== Possible new issues ==

  Here are the unknown changes that may have been introduced in Patchwork_10076:

  === IGT changes ===

    ==== Possible regressions ====

    igt@core_auth@basic-auth:
      fi-kbl-8809g:       PASS -> INCOMPLETE

    
== Known issues ==

  Here are the changes found in Patchwork_10076 that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@gem_exec_suspend@basic-s3:
      fi-blb-e6850:       PASS -> INCOMPLETE (fdo#107718)

    igt@kms_chamelium@hdmi-hpd-fast:
      fi-kbl-7500u:       SKIP -> FAIL (fdo#102672, fdo#103841)

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
      fi-byt-clapper:     PASS -> FAIL (fdo#103191, fdo#107362)

    igt@kms_psr@primary_page_flip:
      fi-cnl-psr:         PASS -> FAIL (fdo#107336)

    igt@kms_setmode@basic-clone-single-crtc:
      fi-ilk-650:         PASS -> DMESG-WARN (fdo#106387)

    igt@prime_vgem@basic-fence-flip:
      fi-ilk-650:         PASS -> FAIL (fdo#104008)

    
  fdo#102672 https://bugs.freedesktop.org/show_bug.cgi?id=102672
  fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
  fdo#103841 https://bugs.freedesktop.org/show_bug.cgi?id=103841
  fdo#104008 https://bugs.freedesktop.org/show_bug.cgi?id=104008
  fdo#106387 https://bugs.freedesktop.org/show_bug.cgi?id=106387
  fdo#107336 https://bugs.freedesktop.org/show_bug.cgi?id=107336
  fdo#107362 https://bugs.freedesktop.org/show_bug.cgi?id=107362
  fdo#107718 https://bugs.freedesktop.org/show_bug.cgi?id=107718


== Participating hosts (53 -> 48) ==

  Missing    (5): fi-ctg-p8600 fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-hsw-4200u 


== Build changes ==

    * Linux: CI_DRM_4758 -> Patchwork_10076

  CI_DRM_4758: 6e3c617fd15ac7bf8259d5741565a78a35004123 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4622: 022be555443eaa3317da6a9a451cf2c9dfcd6ab8 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_10076: 64895f7efd90fea0de1af3dc0a3d892deb4d93c3 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

64895f7efd90 drm/vmwgfx: Add FIXME comments for customer page_flip handlers
835a147156e8 drm/atomic: Improve docs for drm_atomic_state->allow_modeset
a00d9f872f7f drm/vmwgfx: Don't look at state->allow_modeset
3f52631f306e drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
0cac37810f9d drm: Extract drm_atomic_state_helper.[hc]
e8bab7fce24b drm: Update todo.rst
743e2645a0a1 drm/amdgpu: Remove default best_encoder hook from DC
a0725c65f9ee drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
2433899462b1 drm: extract drm_atomic_uapi.c
d53335198614 drm/atomic: trim driver interface/docs
acd20948fa62 drm: drop drmP.h include from drm_crtc.c
963a78e5752b drm: drop drmP.h include from drm_plane.c
4e507bab6b77 drm: Drop drmP.h from drm_connector.c
a39d30c28e70 drm: Add drm/kernel.h header file

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_10076/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 09/14] drm: Update todo.rst
  2018-09-03 17:38   ` [Intel-gfx] " Emil Velikov
@ 2018-09-04 12:19     ` Daniel Vetter
  2018-09-04 20:52       ` Emil Velikov
  0 siblings, 1 reply; 34+ messages in thread
From: Daniel Vetter @ 2018-09-04 12:19 UTC (permalink / raw)
  To: Emil Velikov
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Sean Paul, DRI Development

On Mon, Sep 03, 2018 at 06:38:44PM +0100, Emil Velikov wrote:
> On 3 September 2018 at 17:54, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > -Hide legacy cruft better
> > -------------------------
> > -
> > -Way back DRM supported only drivers which shadow-attached to PCI devices with
> > -userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
> > -of the entire device, you can spot them with the DRIVER_MODESET flag.
> > -
> > -Unfortunately there's still large piles of legacy code around which needs to
> > -be hidden so that driver writers don't accidentally end up using it. And to
> > -prevent security issues in those legacy IOCTLs from being exploited on modern
> > -drivers. This has multiple possible subtasks:
> > -
> 
> > -* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
> > -  module and compile it only when one of the legacy drivers is enabled.
> > -
> This isn't done,

Yup, but I kinda figured I'll give up on this idea. The code is hidden
well enough, I don't think a drm-legacy.ko will buy us much. Except lots
of churn on older driver's Kconfig entries for no purpose.

There's been a patch already a while back to hide the legacy drivers
better, and Dave nacked it. So I'm not really for pushing this idea
anymore as a good task for newbies (which todo.rst tries to collect).

Want me to explain this a bit better in the commit message?
-Daniel

> 
> > -This is mostly done, the only thing left is to split up ``drm_irq.c`` into
> > -legacy cruft and the parts needed by modern KMS drivers.
> > -
> ... while this one is.
> 
> HTH
> -Emil

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers
  2018-09-03 16:54 ` [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers Daniel Vetter
@ 2018-09-04 13:45   ` Thomas Hellstrom
  2018-09-04 14:19     ` Daniel Vetter
  0 siblings, 1 reply; 34+ messages in thread
From: Thomas Hellstrom @ 2018-09-04 13:45 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Daniel Vetter, Intel Graphics Development, VMware Graphics

On 09/03/2018 06:54 PM, Daniel Vetter wrote:
> The idea behind allowing drivers to override legacy ioctls (instead of
> using the generic implementations unconditionally) is to handle bugs
> in old driver-specific userspace. Like e.g. vmw_kms_set_config does,
> to work around some vmwgfx userspace not clearing its ioctl structs
> properly.
>
> But you can't use it to augment semantics and put in additional
> checks, since from a correctly working userspace's pov there should
> not be any difference in behaviour between the legacy and the atomic
> paths.
>
> vmwgfx seems to be doing some strange things in its page_flip
> handlers. Since I'm not an expert of this codebase just wrap some
> FIXME comments around the potentially problematic code.
>
Thanks for the patch, Daniel

Your comments seem valid. We'll try to fix this internally before the 
next merge window rather than to add the FIXMEs

/Thomas

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers
  2018-09-04 13:45   ` Thomas Hellstrom
@ 2018-09-04 14:19     ` Daniel Vetter
  0 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-04 14:19 UTC (permalink / raw)
  To: Thomas Hellstrom
  Cc: Daniel Vetter, Intel Graphics Development, VMware Graphics,
	DRI Development, Sinclair Yeh

On Tue, Sep 4, 2018 at 3:45 PM, Thomas Hellstrom <thellstrom@vmware.com> wrote:
> On 09/03/2018 06:54 PM, Daniel Vetter wrote:
>>
>> The idea behind allowing drivers to override legacy ioctls (instead of
>> using the generic implementations unconditionally) is to handle bugs
>> in old driver-specific userspace. Like e.g. vmw_kms_set_config does,
>> to work around some vmwgfx userspace not clearing its ioctl structs
>> properly.
>>
>> But you can't use it to augment semantics and put in additional
>> checks, since from a correctly working userspace's pov there should
>> not be any difference in behaviour between the legacy and the atomic
>> paths.
>>
>> vmwgfx seems to be doing some strange things in its page_flip
>> handlers. Since I'm not an expert of this codebase just wrap some
>> FIXME comments around the potentially problematic code.
>>
> Thanks for the patch, Daniel
>
> Your comments seem valid. We'll try to fix this internally before the next
> merge window rather than to add the FIXMEs

Sounds all good to me. And if you have questions I'm happy to help out
(and use that generally as an opportunity to improve the docs).

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 06/14] drm: extract drm_atomic_uapi.c
  2018-09-03 16:54   ` [PATCH 06/14] drm: extract drm_atomic_uapi.c Daniel Vetter
@ 2018-09-04 20:41     ` Rodrigo Vivi
  2018-09-05  7:55       ` Daniel Vetter
       [not found]     ` <20180903165439.24845-6-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
  1 sibling, 1 reply; 34+ messages in thread
From: Rodrigo Vivi @ 2018-09-04 20:41 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, Intel Graphics Development, DRI Development,
	Sean Paul, linux-arm-msm, Daniel Vetter, freedreno

On Mon, Sep 03, 2018 at 06:54:31PM +0200, Daniel Vetter wrote:
> This leaves all the commit/check and state handling in drm_atomic.c,
> while pulling all the uapi glue and the huge ioctl itself into a
> seprate file.
> 
> This seems to almost perfectly split the rather big drm_atomic.c file
> into 2 equal sizes.
> 
> Also adjust the kerneldoc and type a very terse overview text.
> 
> v2: Rebase.
> 
> v3: Fix tiny typo.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Gustavo Padovan <gustavo@padovan.org>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: intel-gfx@lists.freedesktop.org
> Cc: linux-arm-msm@vger.kernel.org
> Cc: freedreno@lists.freedesktop.org
> ---
>  Documentation/gpu/drm-kms.rst                |   11 +-
>  drivers/gpu/drm/Makefile                     |    3 +-
>  drivers/gpu/drm/drm_atomic.c                 | 1359 +----------------
>  drivers/gpu/drm/drm_atomic_helper.c          |    1 +
>  drivers/gpu/drm/drm_atomic_uapi.c            | 1393 ++++++++++++++++++
>  drivers/gpu/drm/drm_crtc_helper.c            |    1 +
>  drivers/gpu/drm/drm_crtc_internal.h          |    5 +
>  drivers/gpu/drm/drm_framebuffer.c            |    1 +
>  drivers/gpu/drm/drm_gem_framebuffer_helper.c |    1 +
>  drivers/gpu/drm/drm_plane_helper.c           |    1 +
>  drivers/gpu/drm/i915/intel_display.c         |    1 +
>  drivers/gpu/drm/msm/msm_atomic.c             |    2 +
>  drivers/gpu/drm/vc4/vc4_crtc.c               |    1 +
>  drivers/gpu/drm/vc4/vc4_plane.c              |    1 +
>  include/drm/drm_atomic.h                     |   16 -
>  include/drm/drm_atomic_uapi.h                |   58 +
>  16 files changed, 1480 insertions(+), 1375 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_atomic_uapi.c
>  create mode 100644 include/drm/drm_atomic_uapi.h
> 
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 3a9dd68b97c9..4b1501b4835b 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -287,6 +287,15 @@ Atomic Mode Setting Function Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
>     :export:
>  
> +Atomic Mode Setting IOCTL and UAPI Functions
> +--------------------------------------------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
> +   :doc: overview
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
> +   :export:
> +
>  CRTC Abstraction
>  ================
>  
> @@ -563,7 +572,7 @@ Tile Group Property
>  Explicit Fencing Properties
>  ---------------------------
>  
> -.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
> +.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
>     :doc: explicit fencing properties
>  
>  Existing KMS Properties
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index a6771cef85e2..bc6a16a3c36e 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -18,7 +18,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
>  		drm_encoder.o drm_mode_object.o drm_property.o \
>  		drm_plane.o drm_color_mgmt.o drm_print.o \
>  		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> -		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
> +		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> +		drm_atomic_uapi.o
>  
>  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
>  drm-$(CONFIG_DRM_VM) += drm_vm.o
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 29a4e6959358..19634e03b78e 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -28,6 +28,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_mode.h>
>  #include <drm/drm_print.h>
>  #include <drm/drm_writeback.h>
> @@ -309,285 +310,6 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
>  }
>  EXPORT_SYMBOL(drm_atomic_get_crtc_state);
>  
> -static void set_out_fence_for_crtc(struct drm_atomic_state *state,
> -				   struct drm_crtc *crtc, s32 __user *fence_ptr)
> -{
> -	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
> -}
> -
> -static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
> -					  struct drm_crtc *crtc)
> -{
> -	s32 __user *fence_ptr;
> -
> -	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
> -	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
> -
> -	return fence_ptr;
> -}
> -
> -static int set_out_fence_for_connector(struct drm_atomic_state *state,
> -					struct drm_connector *connector,
> -					s32 __user *fence_ptr)
> -{
> -	unsigned int index = drm_connector_index(connector);
> -
> -	if (!fence_ptr)
> -		return 0;
> -
> -	if (put_user(-1, fence_ptr))
> -		return -EFAULT;
> -
> -	state->connectors[index].out_fence_ptr = fence_ptr;
> -
> -	return 0;
> -}
> -
> -static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
> -					       struct drm_connector *connector)
> -{
> -	unsigned int index = drm_connector_index(connector);
> -	s32 __user *fence_ptr;
> -
> -	fence_ptr = state->connectors[index].out_fence_ptr;
> -	state->connectors[index].out_fence_ptr = NULL;
> -
> -	return fence_ptr;
> -}
> -
> -/**
> - * drm_atomic_set_mode_for_crtc - set mode for CRTC
> - * @state: the CRTC whose incoming state to update
> - * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
> - *
> - * Set a mode (originating from the kernel) on the desired CRTC state and update
> - * the enable property.
> - *
> - * RETURNS:
> - * Zero on success, error code on failure. Cannot return -EDEADLK.
> - */
> -int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> -				 const struct drm_display_mode *mode)
> -{
> -	struct drm_crtc *crtc = state->crtc;
> -	struct drm_mode_modeinfo umode;
> -
> -	/* Early return for no change. */
> -	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
> -		return 0;
> -
> -	drm_property_blob_put(state->mode_blob);
> -	state->mode_blob = NULL;
> -
> -	if (mode) {
> -		drm_mode_convert_to_umode(&umode, mode);
> -		state->mode_blob =
> -			drm_property_create_blob(state->crtc->dev,
> -		                                 sizeof(umode),
> -		                                 &umode);
> -		if (IS_ERR(state->mode_blob))
> -			return PTR_ERR(state->mode_blob);
> -
> -		drm_mode_copy(&state->mode, mode);
> -		state->enable = true;
> -		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> -				 mode->name, crtc->base.id, crtc->name, state);
> -	} else {
> -		memset(&state->mode, 0, sizeof(state->mode));
> -		state->enable = false;
> -		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> -				 crtc->base.id, crtc->name, state);
> -	}
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
> -
> -/**
> - * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
> - * @state: the CRTC whose incoming state to update
> - * @blob: pointer to blob property to use for mode
> - *
> - * Set a mode (originating from a blob property) on the desired CRTC state.
> - * This function will take a reference on the blob property for the CRTC state,
> - * and release the reference held on the state's existing mode property, if any
> - * was set.
> - *
> - * RETURNS:
> - * Zero on success, error code on failure. Cannot return -EDEADLK.
> - */
> -int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> -                                      struct drm_property_blob *blob)
> -{
> -	struct drm_crtc *crtc = state->crtc;
> -
> -	if (blob == state->mode_blob)
> -		return 0;
> -
> -	drm_property_blob_put(state->mode_blob);
> -	state->mode_blob = NULL;
> -
> -	memset(&state->mode, 0, sizeof(state->mode));
> -
> -	if (blob) {
> -		int ret;
> -
> -		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
> -			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
> -					 crtc->base.id, crtc->name,
> -					 blob->length);
> -			return -EINVAL;
> -		}
> -
> -		ret = drm_mode_convert_umode(crtc->dev,
> -					     &state->mode, blob->data);
> -		if (ret) {
> -			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
> -					 crtc->base.id, crtc->name,
> -					 ret, drm_get_mode_status_name(state->mode.status));
> -			drm_mode_debug_printmodeline(&state->mode);
> -			return -EINVAL;
> -		}
> -
> -		state->mode_blob = drm_property_blob_get(blob);
> -		state->enable = true;
> -		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> -				 state->mode.name, crtc->base.id, crtc->name,
> -				 state);
> -	} else {
> -		state->enable = false;
> -		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> -				 crtc->base.id, crtc->name, state);
> -	}
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
> -
> -static int
> -drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
> -					 struct drm_property_blob **blob,
> -					 uint64_t blob_id,
> -					 ssize_t expected_size,
> -					 ssize_t expected_elem_size,
> -					 bool *replaced)
> -{
> -	struct drm_property_blob *new_blob = NULL;
> -
> -	if (blob_id != 0) {
> -		new_blob = drm_property_lookup_blob(dev, blob_id);
> -		if (new_blob == NULL)
> -			return -EINVAL;
> -
> -		if (expected_size > 0 &&
> -		    new_blob->length != expected_size) {
> -			drm_property_blob_put(new_blob);
> -			return -EINVAL;
> -		}
> -		if (expected_elem_size > 0 &&
> -		    new_blob->length % expected_elem_size != 0) {
> -			drm_property_blob_put(new_blob);
> -			return -EINVAL;
> -		}
> -	}
> -
> -	*replaced |= drm_property_replace_blob(blob, new_blob);
> -	drm_property_blob_put(new_blob);
> -
> -	return 0;
> -}
> -
> -static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
> -		struct drm_crtc_state *state, struct drm_property *property,
> -		uint64_t val)
> -{
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -	bool replaced = false;
> -	int ret;
> -
> -	if (property == config->prop_active)
> -		state->active = val;
> -	else if (property == config->prop_mode_id) {
> -		struct drm_property_blob *mode =
> -			drm_property_lookup_blob(dev, val);
> -		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
> -		drm_property_blob_put(mode);
> -		return ret;
> -	} else if (property == config->degamma_lut_property) {
> -		ret = drm_atomic_replace_property_blob_from_id(dev,
> -					&state->degamma_lut,
> -					val,
> -					-1, sizeof(struct drm_color_lut),
> -					&replaced);
> -		state->color_mgmt_changed |= replaced;
> -		return ret;
> -	} else if (property == config->ctm_property) {
> -		ret = drm_atomic_replace_property_blob_from_id(dev,
> -					&state->ctm,
> -					val,
> -					sizeof(struct drm_color_ctm), -1,
> -					&replaced);
> -		state->color_mgmt_changed |= replaced;
> -		return ret;
> -	} else if (property == config->gamma_lut_property) {
> -		ret = drm_atomic_replace_property_blob_from_id(dev,
> -					&state->gamma_lut,
> -					val,
> -					-1, sizeof(struct drm_color_lut),
> -					&replaced);
> -		state->color_mgmt_changed |= replaced;
> -		return ret;
> -	} else if (property == config->prop_out_fence_ptr) {
> -		s32 __user *fence_ptr = u64_to_user_ptr(val);
> -
> -		if (!fence_ptr)
> -			return 0;
> -
> -		if (put_user(-1, fence_ptr))
> -			return -EFAULT;
> -
> -		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
> -	} else if (crtc->funcs->atomic_set_property) {
> -		return crtc->funcs->atomic_set_property(crtc, state, property, val);
> -	} else {
> -		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
> -				 crtc->base.id, crtc->name,
> -				 property->base.id, property->name);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -static int
> -drm_atomic_crtc_get_property(struct drm_crtc *crtc,
> -		const struct drm_crtc_state *state,
> -		struct drm_property *property, uint64_t *val)
> -{
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -
> -	if (property == config->prop_active)
> -		*val = state->active;
> -	else if (property == config->prop_mode_id)
> -		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
> -	else if (property == config->degamma_lut_property)
> -		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
> -	else if (property == config->ctm_property)
> -		*val = (state->ctm) ? state->ctm->base.id : 0;
> -	else if (property == config->gamma_lut_property)
> -		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
> -	else if (property == config->prop_out_fence_ptr)
> -		*val = 0;
> -	else if (crtc->funcs->atomic_get_property)
> -		return crtc->funcs->atomic_get_property(crtc, state, property, val);
> -	else
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
>  static int drm_atomic_crtc_check(struct drm_crtc *crtc,
>  		struct drm_crtc_state *state)
>  {
> @@ -761,144 +483,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
>  }
>  EXPORT_SYMBOL(drm_atomic_get_plane_state);
>  
> -/**
> - * drm_atomic_plane_set_property - set property on plane
> - * @plane: the drm plane to set a property on
> - * @state: the state object to update with the new property value
> - * @property: the property to set
> - * @val: the new property value
> - *
> - * This function handles generic/core properties and calls out to driver's
> - * &drm_plane_funcs.atomic_set_property for driver properties.  To ensure
> - * consistent behavior you must call this function rather than the driver hook
> - * directly.
> - *
> - * RETURNS:
> - * Zero on success, error code on failure
> - */
> -static int drm_atomic_plane_set_property(struct drm_plane *plane,
> -		struct drm_plane_state *state, struct drm_property *property,
> -		uint64_t val)
> -{
> -	struct drm_device *dev = plane->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -
> -	if (property == config->prop_fb_id) {
> -		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> -		drm_atomic_set_fb_for_plane(state, fb);
> -		if (fb)
> -			drm_framebuffer_put(fb);
> -	} else if (property == config->prop_in_fence_fd) {
> -		if (state->fence)
> -			return -EINVAL;
> -
> -		if (U642I64(val) == -1)
> -			return 0;
> -
> -		state->fence = sync_file_get_fence(val);
> -		if (!state->fence)
> -			return -EINVAL;
> -
> -	} else if (property == config->prop_crtc_id) {
> -		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> -		return drm_atomic_set_crtc_for_plane(state, crtc);
> -	} else if (property == config->prop_crtc_x) {
> -		state->crtc_x = U642I64(val);
> -	} else if (property == config->prop_crtc_y) {
> -		state->crtc_y = U642I64(val);
> -	} else if (property == config->prop_crtc_w) {
> -		state->crtc_w = val;
> -	} else if (property == config->prop_crtc_h) {
> -		state->crtc_h = val;
> -	} else if (property == config->prop_src_x) {
> -		state->src_x = val;
> -	} else if (property == config->prop_src_y) {
> -		state->src_y = val;
> -	} else if (property == config->prop_src_w) {
> -		state->src_w = val;
> -	} else if (property == config->prop_src_h) {
> -		state->src_h = val;
> -	} else if (property == plane->alpha_property) {
> -		state->alpha = val;
> -	} else if (property == plane->blend_mode_property) {
> -		state->pixel_blend_mode = val;
> -	} else if (property == plane->rotation_property) {
> -		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
> -			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
> -					 plane->base.id, plane->name, val);
> -			return -EINVAL;
> -		}
> -		state->rotation = val;
> -	} else if (property == plane->zpos_property) {
> -		state->zpos = val;
> -	} else if (property == plane->color_encoding_property) {
> -		state->color_encoding = val;
> -	} else if (property == plane->color_range_property) {
> -		state->color_range = val;
> -	} else if (plane->funcs->atomic_set_property) {
> -		return plane->funcs->atomic_set_property(plane, state,
> -				property, val);
> -	} else {
> -		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> -				 plane->base.id, plane->name,
> -				 property->base.id, property->name);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -static int
> -drm_atomic_plane_get_property(struct drm_plane *plane,
> -		const struct drm_plane_state *state,
> -		struct drm_property *property, uint64_t *val)
> -{
> -	struct drm_device *dev = plane->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -
> -	if (property == config->prop_fb_id) {
> -		*val = (state->fb) ? state->fb->base.id : 0;
> -	} else if (property == config->prop_in_fence_fd) {
> -		*val = -1;
> -	} else if (property == config->prop_crtc_id) {
> -		*val = (state->crtc) ? state->crtc->base.id : 0;
> -	} else if (property == config->prop_crtc_x) {
> -		*val = I642U64(state->crtc_x);
> -	} else if (property == config->prop_crtc_y) {
> -		*val = I642U64(state->crtc_y);
> -	} else if (property == config->prop_crtc_w) {
> -		*val = state->crtc_w;
> -	} else if (property == config->prop_crtc_h) {
> -		*val = state->crtc_h;
> -	} else if (property == config->prop_src_x) {
> -		*val = state->src_x;
> -	} else if (property == config->prop_src_y) {
> -		*val = state->src_y;
> -	} else if (property == config->prop_src_w) {
> -		*val = state->src_w;
> -	} else if (property == config->prop_src_h) {
> -		*val = state->src_h;
> -	} else if (property == plane->alpha_property) {
> -		*val = state->alpha;
> -	} else if (property == plane->blend_mode_property) {
> -		*val = state->pixel_blend_mode;
> -	} else if (property == plane->rotation_property) {
> -		*val = state->rotation;
> -	} else if (property == plane->zpos_property) {
> -		*val = state->zpos;
> -	} else if (property == plane->color_encoding_property) {
> -		*val = state->color_encoding;
> -	} else if (property == plane->color_range_property) {
> -		*val = state->color_range;
> -	} else if (plane->funcs->atomic_get_property) {
> -		return plane->funcs->atomic_get_property(plane, state, property, val);
> -	} else {
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  static bool
>  plane_switching_crtc(struct drm_atomic_state *state,
>  		     struct drm_plane *plane,
> @@ -1238,129 +822,6 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
>  }
>  EXPORT_SYMBOL(drm_atomic_get_connector_state);
>  
> -static struct drm_writeback_job *
> -drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
> -{
> -	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
> -
> -	if (!conn_state->writeback_job)
> -		conn_state->writeback_job =
> -			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
> -
> -	return conn_state->writeback_job;
> -}
> -
> -static int drm_atomic_set_writeback_fb_for_connector(
> -		struct drm_connector_state *conn_state,
> -		struct drm_framebuffer *fb)
> -{
> -	struct drm_writeback_job *job =
> -		drm_atomic_get_writeback_job(conn_state);
> -	if (!job)
> -		return -ENOMEM;
> -
> -	drm_framebuffer_assign(&job->fb, fb);
> -
> -	if (fb)
> -		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
> -				 fb->base.id, conn_state);
> -	else
> -		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
> -				 conn_state);
> -
> -	return 0;
> -}
> -
> -static int drm_atomic_connector_set_property(struct drm_connector *connector,
> -		struct drm_connector_state *state, struct drm_property *property,
> -		uint64_t val)
> -{
> -	struct drm_device *dev = connector->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -
> -	if (property == config->prop_crtc_id) {
> -		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> -		return drm_atomic_set_crtc_for_connector(state, crtc);
> -	} else if (property == config->dpms_property) {
> -		/* setting DPMS property requires special handling, which
> -		 * is done in legacy setprop path for us.  Disallow (for
> -		 * now?) atomic writes to DPMS property:
> -		 */
> -		return -EINVAL;
> -	} else if (property == config->tv_select_subconnector_property) {
> -		state->tv.subconnector = val;
> -	} else if (property == config->tv_left_margin_property) {
> -		state->tv.margins.left = val;
> -	} else if (property == config->tv_right_margin_property) {
> -		state->tv.margins.right = val;
> -	} else if (property == config->tv_top_margin_property) {
> -		state->tv.margins.top = val;
> -	} else if (property == config->tv_bottom_margin_property) {
> -		state->tv.margins.bottom = val;
> -	} else if (property == config->tv_mode_property) {
> -		state->tv.mode = val;
> -	} else if (property == config->tv_brightness_property) {
> -		state->tv.brightness = val;
> -	} else if (property == config->tv_contrast_property) {
> -		state->tv.contrast = val;
> -	} else if (property == config->tv_flicker_reduction_property) {
> -		state->tv.flicker_reduction = val;
> -	} else if (property == config->tv_overscan_property) {
> -		state->tv.overscan = val;
> -	} else if (property == config->tv_saturation_property) {
> -		state->tv.saturation = val;
> -	} else if (property == config->tv_hue_property) {
> -		state->tv.hue = val;
> -	} else if (property == config->link_status_property) {
> -		/* Never downgrade from GOOD to BAD on userspace's request here,
> -		 * only hw issues can do that.
> -		 *
> -		 * For an atomic property the userspace doesn't need to be able
> -		 * to understand all the properties, but needs to be able to
> -		 * restore the state it wants on VT switch. So if the userspace
> -		 * tries to change the link_status from GOOD to BAD, driver
> -		 * silently rejects it and returns a 0. This prevents userspace
> -		 * from accidently breaking  the display when it restores the
> -		 * state.
> -		 */
> -		if (state->link_status != DRM_LINK_STATUS_GOOD)
> -			state->link_status = val;
> -	} else if (property == config->aspect_ratio_property) {
> -		state->picture_aspect_ratio = val;
> -	} else if (property == config->content_type_property) {
> -		state->content_type = val;
> -	} else if (property == connector->scaling_mode_property) {
> -		state->scaling_mode = val;
> -	} else if (property == connector->content_protection_property) {
> -		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
> -			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
> -			return -EINVAL;
> -		}
> -		state->content_protection = val;
> -	} else if (property == config->writeback_fb_id_property) {
> -		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> -		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
> -		if (fb)
> -			drm_framebuffer_put(fb);
> -		return ret;
> -	} else if (property == config->writeback_out_fence_ptr_property) {
> -		s32 __user *fence_ptr = u64_to_user_ptr(val);
> -
> -		return set_out_fence_for_connector(state->state, connector,
> -						   fence_ptr);
> -	} else if (connector->funcs->atomic_set_property) {
> -		return connector->funcs->atomic_set_property(connector,
> -				state, property, val);
> -	} else {
> -		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
> -				 connector->base.id, connector->name,
> -				 property->base.id, property->name);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  static void drm_atomic_connector_print_state(struct drm_printer *p,
>  		const struct drm_connector_state *state)
>  {
> @@ -1377,281 +838,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
>  		connector->funcs->atomic_print_state(p, state);
>  }
>  
> -static int
> -drm_atomic_connector_get_property(struct drm_connector *connector,
> -		const struct drm_connector_state *state,
> -		struct drm_property *property, uint64_t *val)
> -{
> -	struct drm_device *dev = connector->dev;
> -	struct drm_mode_config *config = &dev->mode_config;
> -
> -	if (property == config->prop_crtc_id) {
> -		*val = (state->crtc) ? state->crtc->base.id : 0;
> -	} else if (property == config->dpms_property) {
> -		*val = connector->dpms;
> -	} else if (property == config->tv_select_subconnector_property) {
> -		*val = state->tv.subconnector;
> -	} else if (property == config->tv_left_margin_property) {
> -		*val = state->tv.margins.left;
> -	} else if (property == config->tv_right_margin_property) {
> -		*val = state->tv.margins.right;
> -	} else if (property == config->tv_top_margin_property) {
> -		*val = state->tv.margins.top;
> -	} else if (property == config->tv_bottom_margin_property) {
> -		*val = state->tv.margins.bottom;
> -	} else if (property == config->tv_mode_property) {
> -		*val = state->tv.mode;
> -	} else if (property == config->tv_brightness_property) {
> -		*val = state->tv.brightness;
> -	} else if (property == config->tv_contrast_property) {
> -		*val = state->tv.contrast;
> -	} else if (property == config->tv_flicker_reduction_property) {
> -		*val = state->tv.flicker_reduction;
> -	} else if (property == config->tv_overscan_property) {
> -		*val = state->tv.overscan;
> -	} else if (property == config->tv_saturation_property) {
> -		*val = state->tv.saturation;
> -	} else if (property == config->tv_hue_property) {
> -		*val = state->tv.hue;
> -	} else if (property == config->link_status_property) {
> -		*val = state->link_status;
> -	} else if (property == config->aspect_ratio_property) {
> -		*val = state->picture_aspect_ratio;
> -	} else if (property == config->content_type_property) {
> -		*val = state->content_type;
> -	} else if (property == connector->scaling_mode_property) {
> -		*val = state->scaling_mode;
> -	} else if (property == connector->content_protection_property) {
> -		*val = state->content_protection;
> -	} else if (property == config->writeback_fb_id_property) {
> -		/* Writeback framebuffer is one-shot, write and forget */
> -		*val = 0;
> -	} else if (property == config->writeback_out_fence_ptr_property) {
> -		*val = 0;
> -	} else if (connector->funcs->atomic_get_property) {
> -		return connector->funcs->atomic_get_property(connector,
> -				state, property, val);
> -	} else {
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -int drm_atomic_get_property(struct drm_mode_object *obj,
> -		struct drm_property *property, uint64_t *val)
> -{
> -	struct drm_device *dev = property->dev;
> -	int ret;
> -
> -	switch (obj->type) {
> -	case DRM_MODE_OBJECT_CONNECTOR: {
> -		struct drm_connector *connector = obj_to_connector(obj);
> -		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> -		ret = drm_atomic_connector_get_property(connector,
> -				connector->state, property, val);
> -		break;
> -	}
> -	case DRM_MODE_OBJECT_CRTC: {
> -		struct drm_crtc *crtc = obj_to_crtc(obj);
> -		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
> -		ret = drm_atomic_crtc_get_property(crtc,
> -				crtc->state, property, val);
> -		break;
> -	}
> -	case DRM_MODE_OBJECT_PLANE: {
> -		struct drm_plane *plane = obj_to_plane(obj);
> -		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
> -		ret = drm_atomic_plane_get_property(plane,
> -				plane->state, property, val);
> -		break;
> -	}
> -	default:
> -		ret = -EINVAL;
> -		break;
> -	}
> -
> -	return ret;
> -}
> -
> -/**
> - * drm_atomic_set_crtc_for_plane - set crtc for plane
> - * @plane_state: the plane whose incoming state to update
> - * @crtc: crtc to use for the plane
> - *
> - * Changing the assigned crtc for a plane requires us to grab the lock and state
> - * for the new crtc, as needed. This function takes care of all these details
> - * besides updating the pointer in the state object itself.
> - *
> - * Returns:
> - * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> - * then the w/w mutex code has detected a deadlock and the entire atomic
> - * sequence must be restarted. All other errors are fatal.
> - */
> -int
> -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> -			      struct drm_crtc *crtc)
> -{
> -	struct drm_plane *plane = plane_state->plane;
> -	struct drm_crtc_state *crtc_state;
> -	/* Nothing to do for same crtc*/
> -	if (plane_state->crtc == crtc)
> -		return 0;
> -	if (plane_state->crtc) {
> -		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> -						       plane_state->crtc);
> -		if (WARN_ON(IS_ERR(crtc_state)))
> -			return PTR_ERR(crtc_state);
> -
> -		crtc_state->plane_mask &= ~drm_plane_mask(plane);
> -	}
> -
> -	plane_state->crtc = crtc;
> -
> -	if (crtc) {
> -		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> -						       crtc);
> -		if (IS_ERR(crtc_state))
> -			return PTR_ERR(crtc_state);
> -		crtc_state->plane_mask |= drm_plane_mask(plane);
> -	}
> -
> -	if (crtc)
> -		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
> -				 plane->base.id, plane->name, plane_state,
> -				 crtc->base.id, crtc->name);
> -	else
> -		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
> -				 plane->base.id, plane->name, plane_state);
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
> -
> -/**
> - * drm_atomic_set_fb_for_plane - set framebuffer for plane
> - * @plane_state: atomic state object for the plane
> - * @fb: fb to use for the plane
> - *
> - * Changing the assigned framebuffer for a plane requires us to grab a reference
> - * to the new fb and drop the reference to the old fb, if there is one. This
> - * function takes care of all these details besides updating the pointer in the
> - * state object itself.
> - */
> -void
> -drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> -			    struct drm_framebuffer *fb)
> -{
> -	struct drm_plane *plane = plane_state->plane;
> -
> -	if (fb)
> -		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
> -				 fb->base.id, plane->base.id, plane->name,
> -				 plane_state);
> -	else
> -		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
> -				 plane->base.id, plane->name, plane_state);
> -
> -	drm_framebuffer_assign(&plane_state->fb, fb);
> -}
> -EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
> -
> -/**
> - * drm_atomic_set_fence_for_plane - set fence for plane
> - * @plane_state: atomic state object for the plane
> - * @fence: dma_fence to use for the plane
> - *
> - * Helper to setup the plane_state fence in case it is not set yet.
> - * By using this drivers doesn't need to worry if the user choose
> - * implicit or explicit fencing.
> - *
> - * This function will not set the fence to the state if it was set
> - * via explicit fencing interfaces on the atomic ioctl. In that case it will
> - * drop the reference to the fence as we are not storing it anywhere.
> - * Otherwise, if &drm_plane_state.fence is not set this function we just set it
> - * with the received implicit fence. In both cases this function consumes a
> - * reference for @fence.
> - *
> - * This way explicit fencing can be used to overrule implicit fencing, which is
> - * important to make explicit fencing use-cases work: One example is using one
> - * buffer for 2 screens with different refresh rates. Implicit fencing will
> - * clamp rendering to the refresh rate of the slower screen, whereas explicit
> - * fence allows 2 independent render and display loops on a single buffer. If a
> - * driver allows obeys both implicit and explicit fences for plane updates, then
> - * it will break all the benefits of explicit fencing.
> - */
> -void
> -drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> -			       struct dma_fence *fence)
> -{
> -	if (plane_state->fence) {
> -		dma_fence_put(fence);
> -		return;
> -	}
> -
> -	plane_state->fence = fence;
> -}
> -EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
> -
> -/**
> - * drm_atomic_set_crtc_for_connector - set crtc for connector
> - * @conn_state: atomic state object for the connector
> - * @crtc: crtc to use for the connector
> - *
> - * Changing the assigned crtc for a connector requires us to grab the lock and
> - * state for the new crtc, as needed. This function takes care of all these
> - * details besides updating the pointer in the state object itself.
> - *
> - * Returns:
> - * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> - * then the w/w mutex code has detected a deadlock and the entire atomic
> - * sequence must be restarted. All other errors are fatal.
> - */
> -int
> -drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> -				  struct drm_crtc *crtc)
> -{
> -	struct drm_connector *connector = conn_state->connector;
> -	struct drm_crtc_state *crtc_state;
> -
> -	if (conn_state->crtc == crtc)
> -		return 0;
> -
> -	if (conn_state->crtc) {
> -		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
> -							   conn_state->crtc);
> -
> -		crtc_state->connector_mask &=
> -			~drm_connector_mask(conn_state->connector);
> -
> -		drm_connector_put(conn_state->connector);
> -		conn_state->crtc = NULL;
> -	}
> -
> -	if (crtc) {
> -		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
> -		if (IS_ERR(crtc_state))
> -			return PTR_ERR(crtc_state);
> -
> -		crtc_state->connector_mask |=
> -			drm_connector_mask(conn_state->connector);
> -
> -		drm_connector_get(conn_state->connector);
> -		conn_state->crtc = crtc;
> -
> -		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
> -				 connector->base.id, connector->name,
> -				 conn_state, crtc->base.id, crtc->name);
> -	} else {
> -		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
> -				 connector->base.id, connector->name,
> -				 conn_state);
> -	}
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
> -
>  /**
>   * drm_atomic_add_affected_connectors - add connectors for crtc
>   * @state: atomic state
> @@ -1916,7 +1102,7 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
>  }
>  EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
>  
> -static void drm_atomic_print_state(const struct drm_atomic_state *state)
> +void drm_atomic_print_state(const struct drm_atomic_state *state)
>  {
>  	struct drm_printer p = drm_info_printer(state->dev->dev);
>  	struct drm_plane *plane;
> @@ -2023,544 +1209,3 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
>  }
>  #endif
>  
> -/*
> - * The big monster ioctl
> - */
> -
> -static struct drm_pending_vblank_event *create_vblank_event(
> -		struct drm_crtc *crtc, uint64_t user_data)
> -{
> -	struct drm_pending_vblank_event *e = NULL;
> -
> -	e = kzalloc(sizeof *e, GFP_KERNEL);
> -	if (!e)
> -		return NULL;
> -
> -	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
> -	e->event.base.length = sizeof(e->event);
> -	e->event.vbl.crtc_id = crtc->base.id;
> -	e->event.vbl.user_data = user_data;
> -
> -	return e;
> -}
> -
> -int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> -				     struct drm_connector *connector,
> -				     int mode)
> -{
> -	struct drm_connector *tmp_connector;
> -	struct drm_connector_state *new_conn_state;
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
> -	int i, ret, old_mode = connector->dpms;
> -	bool active = false;
> -
> -	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
> -			       state->acquire_ctx);
> -	if (ret)
> -		return ret;
> -
> -	if (mode != DRM_MODE_DPMS_ON)
> -		mode = DRM_MODE_DPMS_OFF;
> -	connector->dpms = mode;
> -
> -	crtc = connector->state->crtc;
> -	if (!crtc)
> -		goto out;
> -	ret = drm_atomic_add_affected_connectors(state, crtc);
> -	if (ret)
> -		goto out;
> -
> -	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> -	if (IS_ERR(crtc_state)) {
> -		ret = PTR_ERR(crtc_state);
> -		goto out;
> -	}
> -
> -	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
> -		if (new_conn_state->crtc != crtc)
> -			continue;
> -		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
> -			active = true;
> -			break;
> -		}
> -	}
> -
> -	crtc_state->active = active;
> -	ret = drm_atomic_commit(state);
> -out:
> -	if (ret != 0)
> -		connector->dpms = old_mode;
> -	return ret;
> -}
> -
> -int drm_atomic_set_property(struct drm_atomic_state *state,
> -			    struct drm_mode_object *obj,
> -			    struct drm_property *prop,
> -			    uint64_t prop_value)
> -{
> -	struct drm_mode_object *ref;
> -	int ret;
> -
> -	if (!drm_property_change_valid_get(prop, prop_value, &ref))
> -		return -EINVAL;
> -
> -	switch (obj->type) {
> -	case DRM_MODE_OBJECT_CONNECTOR: {
> -		struct drm_connector *connector = obj_to_connector(obj);
> -		struct drm_connector_state *connector_state;
> -
> -		connector_state = drm_atomic_get_connector_state(state, connector);
> -		if (IS_ERR(connector_state)) {
> -			ret = PTR_ERR(connector_state);
> -			break;
> -		}
> -
> -		ret = drm_atomic_connector_set_property(connector,
> -				connector_state, prop, prop_value);
> -		break;
> -	}
> -	case DRM_MODE_OBJECT_CRTC: {
> -		struct drm_crtc *crtc = obj_to_crtc(obj);
> -		struct drm_crtc_state *crtc_state;
> -
> -		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> -		if (IS_ERR(crtc_state)) {
> -			ret = PTR_ERR(crtc_state);
> -			break;
> -		}
> -
> -		ret = drm_atomic_crtc_set_property(crtc,
> -				crtc_state, prop, prop_value);
> -		break;
> -	}
> -	case DRM_MODE_OBJECT_PLANE: {
> -		struct drm_plane *plane = obj_to_plane(obj);
> -		struct drm_plane_state *plane_state;
> -
> -		plane_state = drm_atomic_get_plane_state(state, plane);
> -		if (IS_ERR(plane_state)) {
> -			ret = PTR_ERR(plane_state);
> -			break;
> -		}
> -
> -		ret = drm_atomic_plane_set_property(plane,
> -				plane_state, prop, prop_value);
> -		break;
> -	}
> -	default:
> -		ret = -EINVAL;
> -		break;
> -	}
> -
> -	drm_property_change_valid_put(prop, ref);
> -	return ret;
> -}
> -
> -/**
> - * DOC: explicit fencing properties
> - *
> - * Explicit fencing allows userspace to control the buffer synchronization
> - * between devices. A Fence or a group of fences are transfered to/from
> - * userspace using Sync File fds and there are two DRM properties for that.
> - * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
> - * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
> - *
> - * As a contrast, with implicit fencing the kernel keeps track of any
> - * ongoing rendering, and automatically ensures that the atomic update waits
> - * for any pending rendering to complete. For shared buffers represented with
> - * a &struct dma_buf this is tracked in &struct reservation_object.
> - * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
> - * whereas explicit fencing is what Android wants.
> - *
> - * "IN_FENCE_FD”:
> - *	Use this property to pass a fence that DRM should wait on before
> - *	proceeding with the Atomic Commit request and show the framebuffer for
> - *	the plane on the screen. The fence can be either a normal fence or a
> - *	merged one, the sync_file framework will handle both cases and use a
> - *	fence_array if a merged fence is received. Passing -1 here means no
> - *	fences to wait on.
> - *
> - *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
> - *	it will only check if the Sync File is a valid one.
> - *
> - *	On the driver side the fence is stored on the @fence parameter of
> - *	&struct drm_plane_state. Drivers which also support implicit fencing
> - *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
> - *	to make sure there's consistent behaviour between drivers in precedence
> - *	of implicit vs. explicit fencing.
> - *
> - * "OUT_FENCE_PTR”:
> - *	Use this property to pass a file descriptor pointer to DRM. Once the
> - *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
> - *	the file descriptor number of a Sync File. This Sync File contains the
> - *	CRTC fence that will be signaled when all framebuffers present on the
> - *	Atomic Commit * request for that given CRTC are scanned out on the
> - *	screen.
> - *
> - *	The Atomic Commit request fails if a invalid pointer is passed. If the
> - *	Atomic Commit request fails for any other reason the out fence fd
> - *	returned will be -1. On a Atomic Commit with the
> - *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
> - *
> - *	Note that out-fences don't have a special interface to drivers and are
> - *	internally represented by a &struct drm_pending_vblank_event in struct
> - *	&drm_crtc_state, which is also used by the nonblocking atomic commit
> - *	helpers and for the DRM event handling for existing userspace.
> - */
> -
> -struct drm_out_fence_state {
> -	s32 __user *out_fence_ptr;
> -	struct sync_file *sync_file;
> -	int fd;
> -};
> -
> -static int setup_out_fence(struct drm_out_fence_state *fence_state,
> -			   struct dma_fence *fence)
> -{
> -	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> -	if (fence_state->fd < 0)
> -		return fence_state->fd;
> -
> -	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> -		return -EFAULT;
> -
> -	fence_state->sync_file = sync_file_create(fence);
> -	if (!fence_state->sync_file)
> -		return -ENOMEM;
> -
> -	return 0;
> -}
> -
> -static int prepare_signaling(struct drm_device *dev,
> -				  struct drm_atomic_state *state,
> -				  struct drm_mode_atomic *arg,
> -				  struct drm_file *file_priv,
> -				  struct drm_out_fence_state **fence_state,
> -				  unsigned int *num_fences)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
> -	struct drm_connector *conn;
> -	struct drm_connector_state *conn_state;
> -	int i, c = 0, ret;
> -
> -	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
> -		return 0;
> -
> -	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> -		s32 __user *fence_ptr;
> -
> -		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
> -
> -		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
> -			struct drm_pending_vblank_event *e;
> -
> -			e = create_vblank_event(crtc, arg->user_data);
> -			if (!e)
> -				return -ENOMEM;
> -
> -			crtc_state->event = e;
> -		}
> -
> -		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> -			struct drm_pending_vblank_event *e = crtc_state->event;
> -
> -			if (!file_priv)
> -				continue;
> -
> -			ret = drm_event_reserve_init(dev, file_priv, &e->base,
> -						     &e->event.base);
> -			if (ret) {
> -				kfree(e);
> -				crtc_state->event = NULL;
> -				return ret;
> -			}
> -		}
> -
> -		if (fence_ptr) {
> -			struct dma_fence *fence;
> -			struct drm_out_fence_state *f;
> -
> -			f = krealloc(*fence_state, sizeof(**fence_state) *
> -				     (*num_fences + 1), GFP_KERNEL);
> -			if (!f)
> -				return -ENOMEM;
> -
> -			memset(&f[*num_fences], 0, sizeof(*f));
> -
> -			f[*num_fences].out_fence_ptr = fence_ptr;
> -			*fence_state = f;
> -
> -			fence = drm_crtc_create_fence(crtc);
> -			if (!fence)
> -				return -ENOMEM;
> -
> -			ret = setup_out_fence(&f[(*num_fences)++], fence);
> -			if (ret) {
> -				dma_fence_put(fence);
> -				return ret;
> -			}
> -
> -			crtc_state->event->base.fence = fence;
> -		}
> -
> -		c++;
> -	}
> -
> -	for_each_new_connector_in_state(state, conn, conn_state, i) {
> -		struct drm_writeback_connector *wb_conn;
> -		struct drm_writeback_job *job;
> -		struct drm_out_fence_state *f;
> -		struct dma_fence *fence;
> -		s32 __user *fence_ptr;
> -
> -		fence_ptr = get_out_fence_for_connector(state, conn);
> -		if (!fence_ptr)
> -			continue;
> -
> -		job = drm_atomic_get_writeback_job(conn_state);
> -		if (!job)
> -			return -ENOMEM;
> -
> -		f = krealloc(*fence_state, sizeof(**fence_state) *
> -			     (*num_fences + 1), GFP_KERNEL);
> -		if (!f)
> -			return -ENOMEM;
> -
> -		memset(&f[*num_fences], 0, sizeof(*f));
> -
> -		f[*num_fences].out_fence_ptr = fence_ptr;
> -		*fence_state = f;
> -
> -		wb_conn = drm_connector_to_writeback(conn);
> -		fence = drm_writeback_get_out_fence(wb_conn);
> -		if (!fence)
> -			return -ENOMEM;
> -
> -		ret = setup_out_fence(&f[(*num_fences)++], fence);
> -		if (ret) {
> -			dma_fence_put(fence);
> -			return ret;
> -		}
> -
> -		job->out_fence = fence;
> -	}
> -
> -	/*
> -	 * Having this flag means user mode pends on event which will never
> -	 * reach due to lack of at least one CRTC for signaling
> -	 */
> -	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
> -static void complete_signaling(struct drm_device *dev,
> -			       struct drm_atomic_state *state,
> -			       struct drm_out_fence_state *fence_state,
> -			       unsigned int num_fences,
> -			       bool install_fds)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
> -	int i;
> -
> -	if (install_fds) {
> -		for (i = 0; i < num_fences; i++)
> -			fd_install(fence_state[i].fd,
> -				   fence_state[i].sync_file->file);
> -
> -		kfree(fence_state);
> -		return;
> -	}
> -
> -	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> -		struct drm_pending_vblank_event *event = crtc_state->event;
> -		/*
> -		 * Free the allocated event. drm_atomic_helper_setup_commit
> -		 * can allocate an event too, so only free it if it's ours
> -		 * to prevent a double free in drm_atomic_state_clear.
> -		 */
> -		if (event && (event->base.fence || event->base.file_priv)) {
> -			drm_event_cancel_free(dev, &event->base);
> -			crtc_state->event = NULL;
> -		}
> -	}
> -
> -	if (!fence_state)
> -		return;
> -
> -	for (i = 0; i < num_fences; i++) {
> -		if (fence_state[i].sync_file)
> -			fput(fence_state[i].sync_file->file);
> -		if (fence_state[i].fd >= 0)
> -			put_unused_fd(fence_state[i].fd);
> -
> -		/* If this fails log error to the user */
> -		if (fence_state[i].out_fence_ptr &&
> -		    put_user(-1, fence_state[i].out_fence_ptr))
> -			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
> -	}
> -
> -	kfree(fence_state);
> -}
> -
> -int drm_mode_atomic_ioctl(struct drm_device *dev,
> -			  void *data, struct drm_file *file_priv)
> -{
> -	struct drm_mode_atomic *arg = data;
> -	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
> -	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
> -	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
> -	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
> -	unsigned int copied_objs, copied_props;
> -	struct drm_atomic_state *state;
> -	struct drm_modeset_acquire_ctx ctx;
> -	struct drm_out_fence_state *fence_state;
> -	int ret = 0;
> -	unsigned int i, j, num_fences;
> -
> -	/* disallow for drivers not supporting atomic: */
> -	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
> -		return -EINVAL;
> -
> -	/* disallow for userspace that has not enabled atomic cap (even
> -	 * though this may be a bit overkill, since legacy userspace
> -	 * wouldn't know how to call this ioctl)
> -	 */
> -	if (!file_priv->atomic)
> -		return -EINVAL;
> -
> -	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
> -		return -EINVAL;
> -
> -	if (arg->reserved)
> -		return -EINVAL;
> -
> -	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
> -			!dev->mode_config.async_page_flip)
> -		return -EINVAL;
> -
> -	/* can't test and expect an event at the same time. */
> -	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
> -			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> -		return -EINVAL;
> -
> -	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> -
> -	state = drm_atomic_state_alloc(dev);
> -	if (!state)
> -		return -ENOMEM;
> -
> -	state->acquire_ctx = &ctx;
> -	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
> -
> -retry:
> -	copied_objs = 0;
> -	copied_props = 0;
> -	fence_state = NULL;
> -	num_fences = 0;
> -
> -	for (i = 0; i < arg->count_objs; i++) {
> -		uint32_t obj_id, count_props;
> -		struct drm_mode_object *obj;
> -
> -		if (get_user(obj_id, objs_ptr + copied_objs)) {
> -			ret = -EFAULT;
> -			goto out;
> -		}
> -
> -		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
> -		if (!obj) {
> -			ret = -ENOENT;
> -			goto out;
> -		}
> -
> -		if (!obj->properties) {
> -			drm_mode_object_put(obj);
> -			ret = -ENOENT;
> -			goto out;
> -		}
> -
> -		if (get_user(count_props, count_props_ptr + copied_objs)) {
> -			drm_mode_object_put(obj);
> -			ret = -EFAULT;
> -			goto out;
> -		}
> -
> -		copied_objs++;
> -
> -		for (j = 0; j < count_props; j++) {
> -			uint32_t prop_id;
> -			uint64_t prop_value;
> -			struct drm_property *prop;
> -
> -			if (get_user(prop_id, props_ptr + copied_props)) {
> -				drm_mode_object_put(obj);
> -				ret = -EFAULT;
> -				goto out;
> -			}
> -
> -			prop = drm_mode_obj_find_prop_id(obj, prop_id);
> -			if (!prop) {
> -				drm_mode_object_put(obj);
> -				ret = -ENOENT;
> -				goto out;
> -			}
> -
> -			if (copy_from_user(&prop_value,
> -					   prop_values_ptr + copied_props,
> -					   sizeof(prop_value))) {
> -				drm_mode_object_put(obj);
> -				ret = -EFAULT;
> -				goto out;
> -			}
> -
> -			ret = drm_atomic_set_property(state, obj, prop,
> -						      prop_value);
> -			if (ret) {
> -				drm_mode_object_put(obj);
> -				goto out;
> -			}
> -
> -			copied_props++;
> -		}
> -
> -		drm_mode_object_put(obj);
> -	}
> -
> -	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
> -				&num_fences);
> -	if (ret)
> -		goto out;
> -
> -	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
> -		ret = drm_atomic_check_only(state);
> -	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
> -		ret = drm_atomic_nonblocking_commit(state);
> -	} else {
> -		if (unlikely(drm_debug & DRM_UT_STATE))
> -			drm_atomic_print_state(state);
> -
> -		ret = drm_atomic_commit(state);
> -	}
> -
> -out:
> -	complete_signaling(dev, state, fence_state, num_fences, !ret);
> -
> -	if (ret == -EDEADLK) {
> -		drm_atomic_state_clear(state);
> -		ret = drm_modeset_backoff(&ctx);
> -		if (!ret)
> -			goto retry;
> -	}
> -
> -	drm_atomic_state_put(state);
> -
> -	drm_modeset_drop_locks(&ctx);
> -	drm_modeset_acquire_fini(&ctx);
> -
> -	return ret;
> -}
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index daa04d29f8cc..8469a7e9afe3 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -27,6 +27,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_atomic_helper.h>
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> new file mode 100644
> index 000000000000..26690a664ec6
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -0,0 +1,1393 @@
> +/*
> + * Copyright (C) 2014 Red Hat
> + * Copyright (C) 2014 Intel Corp.
> + * Copyright (C) 2018 Intel Corp.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.

Maybe start a new file with SPDX identifier?

I like the idea of this split...

Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

> + *
> + * Authors:
> + * Rob Clark <robdclark@gmail.com>
> + * Daniel Vetter <daniel.vetter@ffwll.ch>
> + */
> +
> +#include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_writeback.h>
> +#include <drm/drm_vblank.h>
> +
> +#include <linux/dma-fence.h>
> +#include <linux/uaccess.h>
> +#include <linux/sync_file.h>
> +#include <linux/file.h>
> +
> +#include "drm_crtc_internal.h"
> +
> +/**
> + * DOC: overview
> + *
> + * This file contains the marshalling and demarshalling glue for the atomic UAPI
> + * in all it's form: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
> + * SET_PROPERTY IOCTls. Plus interface functions for compatibility helpers and
> + * drivers which have special needs to construct their own atomic updates, e.g.
> + * for load detect or similiar.
> + */
> +
> +/**
> + * drm_atomic_set_mode_for_crtc - set mode for CRTC
> + * @state: the CRTC whose incoming state to update
> + * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
> + *
> + * Set a mode (originating from the kernel) on the desired CRTC state and update
> + * the enable property.
> + *
> + * RETURNS:
> + * Zero on success, error code on failure. Cannot return -EDEADLK.
> + */
> +int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> +				 const struct drm_display_mode *mode)
> +{
> +	struct drm_crtc *crtc = state->crtc;
> +	struct drm_mode_modeinfo umode;
> +
> +	/* Early return for no change. */
> +	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
> +		return 0;
> +
> +	drm_property_blob_put(state->mode_blob);
> +	state->mode_blob = NULL;
> +
> +	if (mode) {
> +		drm_mode_convert_to_umode(&umode, mode);
> +		state->mode_blob =
> +			drm_property_create_blob(state->crtc->dev,
> +		                                 sizeof(umode),
> +		                                 &umode);
> +		if (IS_ERR(state->mode_blob))
> +			return PTR_ERR(state->mode_blob);
> +
> +		drm_mode_copy(&state->mode, mode);
> +		state->enable = true;
> +		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> +				 mode->name, crtc->base.id, crtc->name, state);
> +	} else {
> +		memset(&state->mode, 0, sizeof(state->mode));
> +		state->enable = false;
> +		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> +				 crtc->base.id, crtc->name, state);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
> +
> +/**
> + * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
> + * @state: the CRTC whose incoming state to update
> + * @blob: pointer to blob property to use for mode
> + *
> + * Set a mode (originating from a blob property) on the desired CRTC state.
> + * This function will take a reference on the blob property for the CRTC state,
> + * and release the reference held on the state's existing mode property, if any
> + * was set.
> + *
> + * RETURNS:
> + * Zero on success, error code on failure. Cannot return -EDEADLK.
> + */
> +int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> +                                      struct drm_property_blob *blob)
> +{
> +	struct drm_crtc *crtc = state->crtc;
> +
> +	if (blob == state->mode_blob)
> +		return 0;
> +
> +	drm_property_blob_put(state->mode_blob);
> +	state->mode_blob = NULL;
> +
> +	memset(&state->mode, 0, sizeof(state->mode));
> +
> +	if (blob) {
> +		int ret;
> +
> +		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
> +			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
> +					 crtc->base.id, crtc->name,
> +					 blob->length);
> +			return -EINVAL;
> +		}
> +
> +		ret = drm_mode_convert_umode(crtc->dev,
> +					     &state->mode, blob->data);
> +		if (ret) {
> +			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
> +					 crtc->base.id, crtc->name,
> +					 ret, drm_get_mode_status_name(state->mode.status));
> +			drm_mode_debug_printmodeline(&state->mode);
> +			return -EINVAL;
> +		}
> +
> +		state->mode_blob = drm_property_blob_get(blob);
> +		state->enable = true;
> +		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> +				 state->mode.name, crtc->base.id, crtc->name,
> +				 state);
> +	} else {
> +		state->enable = false;
> +		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> +				 crtc->base.id, crtc->name, state);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
> +
> +/**
> + * drm_atomic_set_crtc_for_plane - set crtc for plane
> + * @plane_state: the plane whose incoming state to update
> + * @crtc: crtc to use for the plane
> + *
> + * Changing the assigned crtc for a plane requires us to grab the lock and state
> + * for the new crtc, as needed. This function takes care of all these details
> + * besides updating the pointer in the state object itself.
> + *
> + * Returns:
> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> + * then the w/w mutex code has detected a deadlock and the entire atomic
> + * sequence must be restarted. All other errors are fatal.
> + */
> +int
> +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> +			      struct drm_crtc *crtc)
> +{
> +	struct drm_plane *plane = plane_state->plane;
> +	struct drm_crtc_state *crtc_state;
> +	/* Nothing to do for same crtc*/
> +	if (plane_state->crtc == crtc)
> +		return 0;
> +	if (plane_state->crtc) {
> +		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> +						       plane_state->crtc);
> +		if (WARN_ON(IS_ERR(crtc_state)))
> +			return PTR_ERR(crtc_state);
> +
> +		crtc_state->plane_mask &= ~drm_plane_mask(plane);
> +	}
> +
> +	plane_state->crtc = crtc;
> +
> +	if (crtc) {
> +		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> +						       crtc);
> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +		crtc_state->plane_mask |= drm_plane_mask(plane);
> +	}
> +
> +	if (crtc)
> +		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
> +				 plane->base.id, plane->name, plane_state,
> +				 crtc->base.id, crtc->name);
> +	else
> +		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
> +				 plane->base.id, plane->name, plane_state);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
> +
> +/**
> + * drm_atomic_set_fb_for_plane - set framebuffer for plane
> + * @plane_state: atomic state object for the plane
> + * @fb: fb to use for the plane
> + *
> + * Changing the assigned framebuffer for a plane requires us to grab a reference
> + * to the new fb and drop the reference to the old fb, if there is one. This
> + * function takes care of all these details besides updating the pointer in the
> + * state object itself.
> + */
> +void
> +drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> +			    struct drm_framebuffer *fb)
> +{
> +	struct drm_plane *plane = plane_state->plane;
> +
> +	if (fb)
> +		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
> +				 fb->base.id, plane->base.id, plane->name,
> +				 plane_state);
> +	else
> +		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
> +				 plane->base.id, plane->name, plane_state);
> +
> +	drm_framebuffer_assign(&plane_state->fb, fb);
> +}
> +EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
> +
> +/**
> + * drm_atomic_set_fence_for_plane - set fence for plane
> + * @plane_state: atomic state object for the plane
> + * @fence: dma_fence to use for the plane
> + *
> + * Helper to setup the plane_state fence in case it is not set yet.
> + * By using this drivers doesn't need to worry if the user choose
> + * implicit or explicit fencing.
> + *
> + * This function will not set the fence to the state if it was set
> + * via explicit fencing interfaces on the atomic ioctl. In that case it will
> + * drop the reference to the fence as we are not storing it anywhere.
> + * Otherwise, if &drm_plane_state.fence is not set this function we just set it
> + * with the received implicit fence. In both cases this function consumes a
> + * reference for @fence.
> + *
> + * This way explicit fencing can be used to overrule implicit fencing, which is
> + * important to make explicit fencing use-cases work: One example is using one
> + * buffer for 2 screens with different refresh rates. Implicit fencing will
> + * clamp rendering to the refresh rate of the slower screen, whereas explicit
> + * fence allows 2 independent render and display loops on a single buffer. If a
> + * driver allows obeys both implicit and explicit fences for plane updates, then
> + * it will break all the benefits of explicit fencing.
> + */
> +void
> +drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> +			       struct dma_fence *fence)
> +{
> +	if (plane_state->fence) {
> +		dma_fence_put(fence);
> +		return;
> +	}
> +
> +	plane_state->fence = fence;
> +}
> +EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
> +
> +/**
> + * drm_atomic_set_crtc_for_connector - set crtc for connector
> + * @conn_state: atomic state object for the connector
> + * @crtc: crtc to use for the connector
> + *
> + * Changing the assigned crtc for a connector requires us to grab the lock and
> + * state for the new crtc, as needed. This function takes care of all these
> + * details besides updating the pointer in the state object itself.
> + *
> + * Returns:
> + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> + * then the w/w mutex code has detected a deadlock and the entire atomic
> + * sequence must be restarted. All other errors are fatal.
> + */
> +int
> +drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> +				  struct drm_crtc *crtc)
> +{
> +	struct drm_connector *connector = conn_state->connector;
> +	struct drm_crtc_state *crtc_state;
> +
> +	if (conn_state->crtc == crtc)
> +		return 0;
> +
> +	if (conn_state->crtc) {
> +		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
> +							   conn_state->crtc);
> +
> +		crtc_state->connector_mask &=
> +			~drm_connector_mask(conn_state->connector);
> +
> +		drm_connector_put(conn_state->connector);
> +		conn_state->crtc = NULL;
> +	}
> +
> +	if (crtc) {
> +		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
> +		if (IS_ERR(crtc_state))
> +			return PTR_ERR(crtc_state);
> +
> +		crtc_state->connector_mask |=
> +			drm_connector_mask(conn_state->connector);
> +
> +		drm_connector_get(conn_state->connector);
> +		conn_state->crtc = crtc;
> +
> +		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
> +				 connector->base.id, connector->name,
> +				 conn_state, crtc->base.id, crtc->name);
> +	} else {
> +		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
> +				 connector->base.id, connector->name,
> +				 conn_state);
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
> +
> +static void set_out_fence_for_crtc(struct drm_atomic_state *state,
> +				   struct drm_crtc *crtc, s32 __user *fence_ptr)
> +{
> +	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
> +}
> +
> +static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
> +					  struct drm_crtc *crtc)
> +{
> +	s32 __user *fence_ptr;
> +
> +	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
> +	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
> +
> +	return fence_ptr;
> +}
> +
> +static int set_out_fence_for_connector(struct drm_atomic_state *state,
> +					struct drm_connector *connector,
> +					s32 __user *fence_ptr)
> +{
> +	unsigned int index = drm_connector_index(connector);
> +
> +	if (!fence_ptr)
> +		return 0;
> +
> +	if (put_user(-1, fence_ptr))
> +		return -EFAULT;
> +
> +	state->connectors[index].out_fence_ptr = fence_ptr;
> +
> +	return 0;
> +}
> +
> +static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
> +					       struct drm_connector *connector)
> +{
> +	unsigned int index = drm_connector_index(connector);
> +	s32 __user *fence_ptr;
> +
> +	fence_ptr = state->connectors[index].out_fence_ptr;
> +	state->connectors[index].out_fence_ptr = NULL;
> +
> +	return fence_ptr;
> +}
> +
> +static int
> +drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
> +					 struct drm_property_blob **blob,
> +					 uint64_t blob_id,
> +					 ssize_t expected_size,
> +					 ssize_t expected_elem_size,
> +					 bool *replaced)
> +{
> +	struct drm_property_blob *new_blob = NULL;
> +
> +	if (blob_id != 0) {
> +		new_blob = drm_property_lookup_blob(dev, blob_id);
> +		if (new_blob == NULL)
> +			return -EINVAL;
> +
> +		if (expected_size > 0 &&
> +		    new_blob->length != expected_size) {
> +			drm_property_blob_put(new_blob);
> +			return -EINVAL;
> +		}
> +		if (expected_elem_size > 0 &&
> +		    new_blob->length % expected_elem_size != 0) {
> +			drm_property_blob_put(new_blob);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	*replaced |= drm_property_replace_blob(blob, new_blob);
> +	drm_property_blob_put(new_blob);
> +
> +	return 0;
> +}
> +
> +static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
> +		struct drm_crtc_state *state, struct drm_property *property,
> +		uint64_t val)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +	bool replaced = false;
> +	int ret;
> +
> +	if (property == config->prop_active)
> +		state->active = val;
> +	else if (property == config->prop_mode_id) {
> +		struct drm_property_blob *mode =
> +			drm_property_lookup_blob(dev, val);
> +		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
> +		drm_property_blob_put(mode);
> +		return ret;
> +	} else if (property == config->degamma_lut_property) {
> +		ret = drm_atomic_replace_property_blob_from_id(dev,
> +					&state->degamma_lut,
> +					val,
> +					-1, sizeof(struct drm_color_lut),
> +					&replaced);
> +		state->color_mgmt_changed |= replaced;
> +		return ret;
> +	} else if (property == config->ctm_property) {
> +		ret = drm_atomic_replace_property_blob_from_id(dev,
> +					&state->ctm,
> +					val,
> +					sizeof(struct drm_color_ctm), -1,
> +					&replaced);
> +		state->color_mgmt_changed |= replaced;
> +		return ret;
> +	} else if (property == config->gamma_lut_property) {
> +		ret = drm_atomic_replace_property_blob_from_id(dev,
> +					&state->gamma_lut,
> +					val,
> +					-1, sizeof(struct drm_color_lut),
> +					&replaced);
> +		state->color_mgmt_changed |= replaced;
> +		return ret;
> +	} else if (property == config->prop_out_fence_ptr) {
> +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> +
> +		if (!fence_ptr)
> +			return 0;
> +
> +		if (put_user(-1, fence_ptr))
> +			return -EFAULT;
> +
> +		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
> +	} else if (crtc->funcs->atomic_set_property) {
> +		return crtc->funcs->atomic_set_property(crtc, state, property, val);
> +	} else {
> +		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
> +				 crtc->base.id, crtc->name,
> +				 property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +drm_atomic_crtc_get_property(struct drm_crtc *crtc,
> +		const struct drm_crtc_state *state,
> +		struct drm_property *property, uint64_t *val)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +
> +	if (property == config->prop_active)
> +		*val = state->active;
> +	else if (property == config->prop_mode_id)
> +		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
> +	else if (property == config->degamma_lut_property)
> +		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
> +	else if (property == config->ctm_property)
> +		*val = (state->ctm) ? state->ctm->base.id : 0;
> +	else if (property == config->gamma_lut_property)
> +		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
> +	else if (property == config->prop_out_fence_ptr)
> +		*val = 0;
> +	else if (crtc->funcs->atomic_get_property)
> +		return crtc->funcs->atomic_get_property(crtc, state, property, val);
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int drm_atomic_plane_set_property(struct drm_plane *plane,
> +		struct drm_plane_state *state, struct drm_property *property,
> +		uint64_t val)
> +{
> +	struct drm_device *dev = plane->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +
> +	if (property == config->prop_fb_id) {
> +		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> +		drm_atomic_set_fb_for_plane(state, fb);
> +		if (fb)
> +			drm_framebuffer_put(fb);
> +	} else if (property == config->prop_in_fence_fd) {
> +		if (state->fence)
> +			return -EINVAL;
> +
> +		if (U642I64(val) == -1)
> +			return 0;
> +
> +		state->fence = sync_file_get_fence(val);
> +		if (!state->fence)
> +			return -EINVAL;
> +
> +	} else if (property == config->prop_crtc_id) {
> +		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> +		return drm_atomic_set_crtc_for_plane(state, crtc);
> +	} else if (property == config->prop_crtc_x) {
> +		state->crtc_x = U642I64(val);
> +	} else if (property == config->prop_crtc_y) {
> +		state->crtc_y = U642I64(val);
> +	} else if (property == config->prop_crtc_w) {
> +		state->crtc_w = val;
> +	} else if (property == config->prop_crtc_h) {
> +		state->crtc_h = val;
> +	} else if (property == config->prop_src_x) {
> +		state->src_x = val;
> +	} else if (property == config->prop_src_y) {
> +		state->src_y = val;
> +	} else if (property == config->prop_src_w) {
> +		state->src_w = val;
> +	} else if (property == config->prop_src_h) {
> +		state->src_h = val;
> +	} else if (property == plane->alpha_property) {
> +		state->alpha = val;
> +	} else if (property == plane->blend_mode_property) {
> +		state->pixel_blend_mode = val;
> +	} else if (property == plane->rotation_property) {
> +		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
> +			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
> +					 plane->base.id, plane->name, val);
> +			return -EINVAL;
> +		}
> +		state->rotation = val;
> +	} else if (property == plane->zpos_property) {
> +		state->zpos = val;
> +	} else if (property == plane->color_encoding_property) {
> +		state->color_encoding = val;
> +	} else if (property == plane->color_range_property) {
> +		state->color_range = val;
> +	} else if (plane->funcs->atomic_set_property) {
> +		return plane->funcs->atomic_set_property(plane, state,
> +				property, val);
> +	} else {
> +		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> +				 plane->base.id, plane->name,
> +				 property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +drm_atomic_plane_get_property(struct drm_plane *plane,
> +		const struct drm_plane_state *state,
> +		struct drm_property *property, uint64_t *val)
> +{
> +	struct drm_device *dev = plane->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +
> +	if (property == config->prop_fb_id) {
> +		*val = (state->fb) ? state->fb->base.id : 0;
> +	} else if (property == config->prop_in_fence_fd) {
> +		*val = -1;
> +	} else if (property == config->prop_crtc_id) {
> +		*val = (state->crtc) ? state->crtc->base.id : 0;
> +	} else if (property == config->prop_crtc_x) {
> +		*val = I642U64(state->crtc_x);
> +	} else if (property == config->prop_crtc_y) {
> +		*val = I642U64(state->crtc_y);
> +	} else if (property == config->prop_crtc_w) {
> +		*val = state->crtc_w;
> +	} else if (property == config->prop_crtc_h) {
> +		*val = state->crtc_h;
> +	} else if (property == config->prop_src_x) {
> +		*val = state->src_x;
> +	} else if (property == config->prop_src_y) {
> +		*val = state->src_y;
> +	} else if (property == config->prop_src_w) {
> +		*val = state->src_w;
> +	} else if (property == config->prop_src_h) {
> +		*val = state->src_h;
> +	} else if (property == plane->alpha_property) {
> +		*val = state->alpha;
> +	} else if (property == plane->blend_mode_property) {
> +		*val = state->pixel_blend_mode;
> +	} else if (property == plane->rotation_property) {
> +		*val = state->rotation;
> +	} else if (property == plane->zpos_property) {
> +		*val = state->zpos;
> +	} else if (property == plane->color_encoding_property) {
> +		*val = state->color_encoding;
> +	} else if (property == plane->color_range_property) {
> +		*val = state->color_range;
> +	} else if (plane->funcs->atomic_get_property) {
> +		return plane->funcs->atomic_get_property(plane, state, property, val);
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct drm_writeback_job *
> +drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
> +{
> +	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
> +
> +	if (!conn_state->writeback_job)
> +		conn_state->writeback_job =
> +			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
> +
> +	return conn_state->writeback_job;
> +}
> +
> +static int drm_atomic_set_writeback_fb_for_connector(
> +		struct drm_connector_state *conn_state,
> +		struct drm_framebuffer *fb)
> +{
> +	struct drm_writeback_job *job =
> +		drm_atomic_get_writeback_job(conn_state);
> +	if (!job)
> +		return -ENOMEM;
> +
> +	drm_framebuffer_assign(&job->fb, fb);
> +
> +	if (fb)
> +		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
> +				 fb->base.id, conn_state);
> +	else
> +		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
> +				 conn_state);
> +
> +	return 0;
> +}
> +
> +static int drm_atomic_connector_set_property(struct drm_connector *connector,
> +		struct drm_connector_state *state, struct drm_property *property,
> +		uint64_t val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +
> +	if (property == config->prop_crtc_id) {
> +		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> +		return drm_atomic_set_crtc_for_connector(state, crtc);
> +	} else if (property == config->dpms_property) {
> +		/* setting DPMS property requires special handling, which
> +		 * is done in legacy setprop path for us.  Disallow (for
> +		 * now?) atomic writes to DPMS property:
> +		 */
> +		return -EINVAL;
> +	} else if (property == config->tv_select_subconnector_property) {
> +		state->tv.subconnector = val;
> +	} else if (property == config->tv_left_margin_property) {
> +		state->tv.margins.left = val;
> +	} else if (property == config->tv_right_margin_property) {
> +		state->tv.margins.right = val;
> +	} else if (property == config->tv_top_margin_property) {
> +		state->tv.margins.top = val;
> +	} else if (property == config->tv_bottom_margin_property) {
> +		state->tv.margins.bottom = val;
> +	} else if (property == config->tv_mode_property) {
> +		state->tv.mode = val;
> +	} else if (property == config->tv_brightness_property) {
> +		state->tv.brightness = val;
> +	} else if (property == config->tv_contrast_property) {
> +		state->tv.contrast = val;
> +	} else if (property == config->tv_flicker_reduction_property) {
> +		state->tv.flicker_reduction = val;
> +	} else if (property == config->tv_overscan_property) {
> +		state->tv.overscan = val;
> +	} else if (property == config->tv_saturation_property) {
> +		state->tv.saturation = val;
> +	} else if (property == config->tv_hue_property) {
> +		state->tv.hue = val;
> +	} else if (property == config->link_status_property) {
> +		/* Never downgrade from GOOD to BAD on userspace's request here,
> +		 * only hw issues can do that.
> +		 *
> +		 * For an atomic property the userspace doesn't need to be able
> +		 * to understand all the properties, but needs to be able to
> +		 * restore the state it wants on VT switch. So if the userspace
> +		 * tries to change the link_status from GOOD to BAD, driver
> +		 * silently rejects it and returns a 0. This prevents userspace
> +		 * from accidently breaking  the display when it restores the
> +		 * state.
> +		 */
> +		if (state->link_status != DRM_LINK_STATUS_GOOD)
> +			state->link_status = val;
> +	} else if (property == config->aspect_ratio_property) {
> +		state->picture_aspect_ratio = val;
> +	} else if (property == config->content_type_property) {
> +		state->content_type = val;
> +	} else if (property == connector->scaling_mode_property) {
> +		state->scaling_mode = val;
> +	} else if (property == connector->content_protection_property) {
> +		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
> +			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
> +			return -EINVAL;
> +		}
> +		state->content_protection = val;
> +	} else if (property == config->writeback_fb_id_property) {
> +		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> +		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
> +		if (fb)
> +			drm_framebuffer_put(fb);
> +		return ret;
> +	} else if (property == config->writeback_out_fence_ptr_property) {
> +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> +
> +		return set_out_fence_for_connector(state->state, connector,
> +						   fence_ptr);
> +	} else if (connector->funcs->atomic_set_property) {
> +		return connector->funcs->atomic_set_property(connector,
> +				state, property, val);
> +	} else {
> +		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
> +				 connector->base.id, connector->name,
> +				 property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +drm_atomic_connector_get_property(struct drm_connector *connector,
> +		const struct drm_connector_state *state,
> +		struct drm_property *property, uint64_t *val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_mode_config *config = &dev->mode_config;
> +
> +	if (property == config->prop_crtc_id) {
> +		*val = (state->crtc) ? state->crtc->base.id : 0;
> +	} else if (property == config->dpms_property) {
> +		*val = connector->dpms;
> +	} else if (property == config->tv_select_subconnector_property) {
> +		*val = state->tv.subconnector;
> +	} else if (property == config->tv_left_margin_property) {
> +		*val = state->tv.margins.left;
> +	} else if (property == config->tv_right_margin_property) {
> +		*val = state->tv.margins.right;
> +	} else if (property == config->tv_top_margin_property) {
> +		*val = state->tv.margins.top;
> +	} else if (property == config->tv_bottom_margin_property) {
> +		*val = state->tv.margins.bottom;
> +	} else if (property == config->tv_mode_property) {
> +		*val = state->tv.mode;
> +	} else if (property == config->tv_brightness_property) {
> +		*val = state->tv.brightness;
> +	} else if (property == config->tv_contrast_property) {
> +		*val = state->tv.contrast;
> +	} else if (property == config->tv_flicker_reduction_property) {
> +		*val = state->tv.flicker_reduction;
> +	} else if (property == config->tv_overscan_property) {
> +		*val = state->tv.overscan;
> +	} else if (property == config->tv_saturation_property) {
> +		*val = state->tv.saturation;
> +	} else if (property == config->tv_hue_property) {
> +		*val = state->tv.hue;
> +	} else if (property == config->link_status_property) {
> +		*val = state->link_status;
> +	} else if (property == config->aspect_ratio_property) {
> +		*val = state->picture_aspect_ratio;
> +	} else if (property == config->content_type_property) {
> +		*val = state->content_type;
> +	} else if (property == connector->scaling_mode_property) {
> +		*val = state->scaling_mode;
> +	} else if (property == connector->content_protection_property) {
> +		*val = state->content_protection;
> +	} else if (property == config->writeback_fb_id_property) {
> +		/* Writeback framebuffer is one-shot, write and forget */
> +		*val = 0;
> +	} else if (property == config->writeback_out_fence_ptr_property) {
> +		*val = 0;
> +	} else if (connector->funcs->atomic_get_property) {
> +		return connector->funcs->atomic_get_property(connector,
> +				state, property, val);
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int drm_atomic_get_property(struct drm_mode_object *obj,
> +		struct drm_property *property, uint64_t *val)
> +{
> +	struct drm_device *dev = property->dev;
> +	int ret;
> +
> +	switch (obj->type) {
> +	case DRM_MODE_OBJECT_CONNECTOR: {
> +		struct drm_connector *connector = obj_to_connector(obj);
> +		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> +		ret = drm_atomic_connector_get_property(connector,
> +				connector->state, property, val);
> +		break;
> +	}
> +	case DRM_MODE_OBJECT_CRTC: {
> +		struct drm_crtc *crtc = obj_to_crtc(obj);
> +		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
> +		ret = drm_atomic_crtc_get_property(crtc,
> +				crtc->state, property, val);
> +		break;
> +	}
> +	case DRM_MODE_OBJECT_PLANE: {
> +		struct drm_plane *plane = obj_to_plane(obj);
> +		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
> +		ret = drm_atomic_plane_get_property(plane,
> +				plane->state, property, val);
> +		break;
> +	}
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +/*
> + * The big monster ioctl
> + */
> +
> +static struct drm_pending_vblank_event *create_vblank_event(
> +		struct drm_crtc *crtc, uint64_t user_data)
> +{
> +	struct drm_pending_vblank_event *e = NULL;
> +
> +	e = kzalloc(sizeof *e, GFP_KERNEL);
> +	if (!e)
> +		return NULL;
> +
> +	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
> +	e->event.base.length = sizeof(e->event);
> +	e->event.vbl.crtc_id = crtc->base.id;
> +	e->event.vbl.user_data = user_data;
> +
> +	return e;
> +}
> +
> +int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> +				     struct drm_connector *connector,
> +				     int mode)
> +{
> +	struct drm_connector *tmp_connector;
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	int i, ret, old_mode = connector->dpms;
> +	bool active = false;
> +
> +	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
> +			       state->acquire_ctx);
> +	if (ret)
> +		return ret;
> +
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +	connector->dpms = mode;
> +
> +	crtc = connector->state->crtc;
> +	if (!crtc)
> +		goto out;
> +	ret = drm_atomic_add_affected_connectors(state, crtc);
> +	if (ret)
> +		goto out;
> +
> +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +	if (IS_ERR(crtc_state)) {
> +		ret = PTR_ERR(crtc_state);
> +		goto out;
> +	}
> +
> +	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
> +		if (new_conn_state->crtc != crtc)
> +			continue;
> +		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
> +			active = true;
> +			break;
> +		}
> +	}
> +
> +	crtc_state->active = active;
> +	ret = drm_atomic_commit(state);
> +out:
> +	if (ret != 0)
> +		connector->dpms = old_mode;
> +	return ret;
> +}
> +
> +int drm_atomic_set_property(struct drm_atomic_state *state,
> +			    struct drm_mode_object *obj,
> +			    struct drm_property *prop,
> +			    uint64_t prop_value)
> +{
> +	struct drm_mode_object *ref;
> +	int ret;
> +
> +	if (!drm_property_change_valid_get(prop, prop_value, &ref))
> +		return -EINVAL;
> +
> +	switch (obj->type) {
> +	case DRM_MODE_OBJECT_CONNECTOR: {
> +		struct drm_connector *connector = obj_to_connector(obj);
> +		struct drm_connector_state *connector_state;
> +
> +		connector_state = drm_atomic_get_connector_state(state, connector);
> +		if (IS_ERR(connector_state)) {
> +			ret = PTR_ERR(connector_state);
> +			break;
> +		}
> +
> +		ret = drm_atomic_connector_set_property(connector,
> +				connector_state, prop, prop_value);
> +		break;
> +	}
> +	case DRM_MODE_OBJECT_CRTC: {
> +		struct drm_crtc *crtc = obj_to_crtc(obj);
> +		struct drm_crtc_state *crtc_state;
> +
> +		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +		if (IS_ERR(crtc_state)) {
> +			ret = PTR_ERR(crtc_state);
> +			break;
> +		}
> +
> +		ret = drm_atomic_crtc_set_property(crtc,
> +				crtc_state, prop, prop_value);
> +		break;
> +	}
> +	case DRM_MODE_OBJECT_PLANE: {
> +		struct drm_plane *plane = obj_to_plane(obj);
> +		struct drm_plane_state *plane_state;
> +
> +		plane_state = drm_atomic_get_plane_state(state, plane);
> +		if (IS_ERR(plane_state)) {
> +			ret = PTR_ERR(plane_state);
> +			break;
> +		}
> +
> +		ret = drm_atomic_plane_set_property(plane,
> +				plane_state, prop, prop_value);
> +		break;
> +	}
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	drm_property_change_valid_put(prop, ref);
> +	return ret;
> +}
> +
> +/**
> + * DOC: explicit fencing properties
> + *
> + * Explicit fencing allows userspace to control the buffer synchronization
> + * between devices. A Fence or a group of fences are transfered to/from
> + * userspace using Sync File fds and there are two DRM properties for that.
> + * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
> + * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
> + *
> + * As a contrast, with implicit fencing the kernel keeps track of any
> + * ongoing rendering, and automatically ensures that the atomic update waits
> + * for any pending rendering to complete. For shared buffers represented with
> + * a &struct dma_buf this is tracked in &struct reservation_object.
> + * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
> + * whereas explicit fencing is what Android wants.
> + *
> + * "IN_FENCE_FD”:
> + *	Use this property to pass a fence that DRM should wait on before
> + *	proceeding with the Atomic Commit request and show the framebuffer for
> + *	the plane on the screen. The fence can be either a normal fence or a
> + *	merged one, the sync_file framework will handle both cases and use a
> + *	fence_array if a merged fence is received. Passing -1 here means no
> + *	fences to wait on.
> + *
> + *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
> + *	it will only check if the Sync File is a valid one.
> + *
> + *	On the driver side the fence is stored on the @fence parameter of
> + *	&struct drm_plane_state. Drivers which also support implicit fencing
> + *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
> + *	to make sure there's consistent behaviour between drivers in precedence
> + *	of implicit vs. explicit fencing.
> + *
> + * "OUT_FENCE_PTR”:
> + *	Use this property to pass a file descriptor pointer to DRM. Once the
> + *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
> + *	the file descriptor number of a Sync File. This Sync File contains the
> + *	CRTC fence that will be signaled when all framebuffers present on the
> + *	Atomic Commit * request for that given CRTC are scanned out on the
> + *	screen.
> + *
> + *	The Atomic Commit request fails if a invalid pointer is passed. If the
> + *	Atomic Commit request fails for any other reason the out fence fd
> + *	returned will be -1. On a Atomic Commit with the
> + *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
> + *
> + *	Note that out-fences don't have a special interface to drivers and are
> + *	internally represented by a &struct drm_pending_vblank_event in struct
> + *	&drm_crtc_state, which is also used by the nonblocking atomic commit
> + *	helpers and for the DRM event handling for existing userspace.
> + */
> +
> +struct drm_out_fence_state {
> +	s32 __user *out_fence_ptr;
> +	struct sync_file *sync_file;
> +	int fd;
> +};
> +
> +static int setup_out_fence(struct drm_out_fence_state *fence_state,
> +			   struct dma_fence *fence)
> +{
> +	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> +	if (fence_state->fd < 0)
> +		return fence_state->fd;
> +
> +	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> +		return -EFAULT;
> +
> +	fence_state->sync_file = sync_file_create(fence);
> +	if (!fence_state->sync_file)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static int prepare_signaling(struct drm_device *dev,
> +				  struct drm_atomic_state *state,
> +				  struct drm_mode_atomic *arg,
> +				  struct drm_file *file_priv,
> +				  struct drm_out_fence_state **fence_state,
> +				  unsigned int *num_fences)
> +{
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_connector *conn;
> +	struct drm_connector_state *conn_state;
> +	int i, c = 0, ret;
> +
> +	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
> +		return 0;
> +
> +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +		s32 __user *fence_ptr;
> +
> +		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
> +
> +		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
> +			struct drm_pending_vblank_event *e;
> +
> +			e = create_vblank_event(crtc, arg->user_data);
> +			if (!e)
> +				return -ENOMEM;
> +
> +			crtc_state->event = e;
> +		}
> +
> +		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> +			struct drm_pending_vblank_event *e = crtc_state->event;
> +
> +			if (!file_priv)
> +				continue;
> +
> +			ret = drm_event_reserve_init(dev, file_priv, &e->base,
> +						     &e->event.base);
> +			if (ret) {
> +				kfree(e);
> +				crtc_state->event = NULL;
> +				return ret;
> +			}
> +		}
> +
> +		if (fence_ptr) {
> +			struct dma_fence *fence;
> +			struct drm_out_fence_state *f;
> +
> +			f = krealloc(*fence_state, sizeof(**fence_state) *
> +				     (*num_fences + 1), GFP_KERNEL);
> +			if (!f)
> +				return -ENOMEM;
> +
> +			memset(&f[*num_fences], 0, sizeof(*f));
> +
> +			f[*num_fences].out_fence_ptr = fence_ptr;
> +			*fence_state = f;
> +
> +			fence = drm_crtc_create_fence(crtc);
> +			if (!fence)
> +				return -ENOMEM;
> +
> +			ret = setup_out_fence(&f[(*num_fences)++], fence);
> +			if (ret) {
> +				dma_fence_put(fence);
> +				return ret;
> +			}
> +
> +			crtc_state->event->base.fence = fence;
> +		}
> +
> +		c++;
> +	}
> +
> +	for_each_new_connector_in_state(state, conn, conn_state, i) {
> +		struct drm_writeback_connector *wb_conn;
> +		struct drm_writeback_job *job;
> +		struct drm_out_fence_state *f;
> +		struct dma_fence *fence;
> +		s32 __user *fence_ptr;
> +
> +		fence_ptr = get_out_fence_for_connector(state, conn);
> +		if (!fence_ptr)
> +			continue;
> +
> +		job = drm_atomic_get_writeback_job(conn_state);
> +		if (!job)
> +			return -ENOMEM;
> +
> +		f = krealloc(*fence_state, sizeof(**fence_state) *
> +			     (*num_fences + 1), GFP_KERNEL);
> +		if (!f)
> +			return -ENOMEM;
> +
> +		memset(&f[*num_fences], 0, sizeof(*f));
> +
> +		f[*num_fences].out_fence_ptr = fence_ptr;
> +		*fence_state = f;
> +
> +		wb_conn = drm_connector_to_writeback(conn);
> +		fence = drm_writeback_get_out_fence(wb_conn);
> +		if (!fence)
> +			return -ENOMEM;
> +
> +		ret = setup_out_fence(&f[(*num_fences)++], fence);
> +		if (ret) {
> +			dma_fence_put(fence);
> +			return ret;
> +		}
> +
> +		job->out_fence = fence;
> +	}
> +
> +	/*
> +	 * Having this flag means user mode pends on event which will never
> +	 * reach due to lack of at least one CRTC for signaling
> +	 */
> +	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void complete_signaling(struct drm_device *dev,
> +			       struct drm_atomic_state *state,
> +			       struct drm_out_fence_state *fence_state,
> +			       unsigned int num_fences,
> +			       bool install_fds)
> +{
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	int i;
> +
> +	if (install_fds) {
> +		for (i = 0; i < num_fences; i++)
> +			fd_install(fence_state[i].fd,
> +				   fence_state[i].sync_file->file);
> +
> +		kfree(fence_state);
> +		return;
> +	}
> +
> +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +		struct drm_pending_vblank_event *event = crtc_state->event;
> +		/*
> +		 * Free the allocated event. drm_atomic_helper_setup_commit
> +		 * can allocate an event too, so only free it if it's ours
> +		 * to prevent a double free in drm_atomic_state_clear.
> +		 */
> +		if (event && (event->base.fence || event->base.file_priv)) {
> +			drm_event_cancel_free(dev, &event->base);
> +			crtc_state->event = NULL;
> +		}
> +	}
> +
> +	if (!fence_state)
> +		return;
> +
> +	for (i = 0; i < num_fences; i++) {
> +		if (fence_state[i].sync_file)
> +			fput(fence_state[i].sync_file->file);
> +		if (fence_state[i].fd >= 0)
> +			put_unused_fd(fence_state[i].fd);
> +
> +		/* If this fails log error to the user */
> +		if (fence_state[i].out_fence_ptr &&
> +		    put_user(-1, fence_state[i].out_fence_ptr))
> +			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
> +	}
> +
> +	kfree(fence_state);
> +}
> +
> +int drm_mode_atomic_ioctl(struct drm_device *dev,
> +			  void *data, struct drm_file *file_priv)
> +{
> +	struct drm_mode_atomic *arg = data;
> +	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
> +	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
> +	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
> +	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
> +	unsigned int copied_objs, copied_props;
> +	struct drm_atomic_state *state;
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_out_fence_state *fence_state;
> +	int ret = 0;
> +	unsigned int i, j, num_fences;
> +
> +	/* disallow for drivers not supporting atomic: */
> +	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
> +		return -EINVAL;
> +
> +	/* disallow for userspace that has not enabled atomic cap (even
> +	 * though this may be a bit overkill, since legacy userspace
> +	 * wouldn't know how to call this ioctl)
> +	 */
> +	if (!file_priv->atomic)
> +		return -EINVAL;
> +
> +	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
> +		return -EINVAL;
> +
> +	if (arg->reserved)
> +		return -EINVAL;
> +
> +	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
> +			!dev->mode_config.async_page_flip)
> +		return -EINVAL;
> +
> +	/* can't test and expect an event at the same time. */
> +	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
> +			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> +		return -EINVAL;
> +
> +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> +
> +	state = drm_atomic_state_alloc(dev);
> +	if (!state)
> +		return -ENOMEM;
> +
> +	state->acquire_ctx = &ctx;
> +	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
> +
> +retry:
> +	copied_objs = 0;
> +	copied_props = 0;
> +	fence_state = NULL;
> +	num_fences = 0;
> +
> +	for (i = 0; i < arg->count_objs; i++) {
> +		uint32_t obj_id, count_props;
> +		struct drm_mode_object *obj;
> +
> +		if (get_user(obj_id, objs_ptr + copied_objs)) {
> +			ret = -EFAULT;
> +			goto out;
> +		}
> +
> +		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
> +		if (!obj) {
> +			ret = -ENOENT;
> +			goto out;
> +		}
> +
> +		if (!obj->properties) {
> +			drm_mode_object_put(obj);
> +			ret = -ENOENT;
> +			goto out;
> +		}
> +
> +		if (get_user(count_props, count_props_ptr + copied_objs)) {
> +			drm_mode_object_put(obj);
> +			ret = -EFAULT;
> +			goto out;
> +		}
> +
> +		copied_objs++;
> +
> +		for (j = 0; j < count_props; j++) {
> +			uint32_t prop_id;
> +			uint64_t prop_value;
> +			struct drm_property *prop;
> +
> +			if (get_user(prop_id, props_ptr + copied_props)) {
> +				drm_mode_object_put(obj);
> +				ret = -EFAULT;
> +				goto out;
> +			}
> +
> +			prop = drm_mode_obj_find_prop_id(obj, prop_id);
> +			if (!prop) {
> +				drm_mode_object_put(obj);
> +				ret = -ENOENT;
> +				goto out;
> +			}
> +
> +			if (copy_from_user(&prop_value,
> +					   prop_values_ptr + copied_props,
> +					   sizeof(prop_value))) {
> +				drm_mode_object_put(obj);
> +				ret = -EFAULT;
> +				goto out;
> +			}
> +
> +			ret = drm_atomic_set_property(state, obj, prop,
> +						      prop_value);
> +			if (ret) {
> +				drm_mode_object_put(obj);
> +				goto out;
> +			}
> +
> +			copied_props++;
> +		}
> +
> +		drm_mode_object_put(obj);
> +	}
> +
> +	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
> +				&num_fences);
> +	if (ret)
> +		goto out;
> +
> +	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
> +		ret = drm_atomic_check_only(state);
> +	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
> +		ret = drm_atomic_nonblocking_commit(state);
> +	} else {
> +		if (unlikely(drm_debug & DRM_UT_STATE))
> +			drm_atomic_print_state(state);
> +
> +		ret = drm_atomic_commit(state);
> +	}
> +
> +out:
> +	complete_signaling(dev, state, fence_state, num_fences, !ret);
> +
> +	if (ret == -EDEADLK) {
> +		drm_atomic_state_clear(state);
> +		ret = drm_modeset_backoff(&ctx);
> +		if (!ret)
> +			goto retry;
> +	}
> +
> +	drm_atomic_state_put(state);
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret;
> +}
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5a84c3bc915d..ce75e9506e85 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -35,6 +35,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_fourcc.h>
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index ff5e0d521c21..ede20b55d50c 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -204,6 +204,9 @@ struct drm_minor;
>  int drm_atomic_debugfs_init(struct drm_minor *minor);
>  #endif
>  
> +void drm_atomic_print_state(const struct drm_atomic_state *state);
> +
> +/* drm_atomic_uapi.c */
>  int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
>  				     struct drm_connector *connector,
>  				     int mode);
> @@ -213,6 +216,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
>  			    uint64_t prop_value);
>  int drm_atomic_get_property(struct drm_mode_object *obj,
>  			    struct drm_property *property, uint64_t *val);
> +
> +/* IOCTL */
>  int drm_mode_atomic_ioctl(struct drm_device *dev,
>  			  void *data, struct drm_file *file_priv);
>  
> diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> index 781af1d42d76..7ca8c77223cb 100644
> --- a/drivers/gpu/drm/drm_framebuffer.c
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -25,6 +25,7 @@
>  #include <drm/drm_auth.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_print.h>
>  
>  #include "drm_internal.h"
> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> index 2810d4131411..7607f9cd6f77 100644
> --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> @@ -16,6 +16,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_framebuffer.h>
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 621f17643bb0..a393756b664e 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -28,6 +28,7 @@
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_atomic_helper.h>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a85a83f31979..85cad16f31ed 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -46,6 +46,7 @@
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_rect.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <linux/dma_remapping.h>
>  #include <linux/reservation.h>
>  
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> index c1f1779c980f..4bcdeca7479d 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -15,6 +15,8 @@
>   * this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <drm/drm_atomic_uapi.h>
> +
>  #include "msm_drv.h"
>  #include "msm_gem.h"
>  #include "msm_kms.h"
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 0e6a121858d1..3ce136ba8791 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -35,6 +35,7 @@
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_atomic_uapi.h>
>  #include <linux/clk.h>
>  #include <drm/drm_fb_cma_helper.h>
>  #include <linux/component.h>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 6c6d37aa512a..9dc3fcbd290b 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -22,6 +22,7 @@
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_fb_cma_helper.h>
>  #include <drm/drm_plane_helper.h>
> +#include <drm/drm_atomic_uapi.h>
>  
>  #include "uapi/drm/vc4_drm.h"
>  #include "vc4_drv.h"
> diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> index 66e49ef7d3b5..4aff40886acb 100644
> --- a/include/drm/drm_atomic.h
> +++ b/include/drm/drm_atomic.h
> @@ -584,22 +584,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
>  	return plane->state;
>  }
>  
> -int __must_check
> -drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> -			     const struct drm_display_mode *mode);
> -int __must_check
> -drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> -				  struct drm_property_blob *blob);
> -int __must_check
> -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> -			      struct drm_crtc *crtc);
> -void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> -				 struct drm_framebuffer *fb);
> -void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> -				    struct dma_fence *fence);
> -int __must_check
> -drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> -				  struct drm_crtc *crtc);
>  int __must_check
>  drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
>  				   struct drm_crtc *crtc);
> diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
> new file mode 100644
> index 000000000000..8cec52ad1277
> --- /dev/null
> +++ b/include/drm/drm_atomic_uapi.h
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright (C) 2014 Red Hat
> + * Copyright (C) 2014 Intel Corp.
> + * Copyright (C) 2018 Intel Corp.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + * Authors:
> + * Rob Clark <robdclark@gmail.com>
> + * Daniel Vetter <daniel.vetter@ffwll.ch>
> + */
> +
> +#ifndef DRM_ATOMIC_UAPI_H_
> +#define DRM_ATOMIC_UAPI_H_
> +
> +struct drm_crtc_state;
> +struct drm_display_mode;
> +struct drm_property_blob;
> +struct drm_plane_state;
> +struct drm_crtc;
> +struct drm_connector_state;
> +struct dma_fence;
> +struct drm_framebuffer;
> +
> +int __must_check
> +drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> +			     const struct drm_display_mode *mode);
> +int __must_check
> +drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> +				  struct drm_property_blob *blob);
> +int __must_check
> +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> +			      struct drm_crtc *crtc);
> +void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> +				 struct drm_framebuffer *fb);
> +void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> +				    struct dma_fence *fence);
> +int __must_check
> +drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> +				  struct drm_crtc *crtc);
> +
> +#endif
> -- 
> 2.18.0
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 09/14] drm: Update todo.rst
  2018-09-04 12:19     ` Daniel Vetter
@ 2018-09-04 20:52       ` Emil Velikov
  0 siblings, 0 replies; 34+ messages in thread
From: Emil Velikov @ 2018-09-04 20:52 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Sean Paul, DRI Development

On 4 September 2018 at 13:19, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Sep 03, 2018 at 06:38:44PM +0100, Emil Velikov wrote:
>> On 3 September 2018 at 17:54, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>>
>> > -Hide legacy cruft better
>> > -------------------------
>> > -
>> > -Way back DRM supported only drivers which shadow-attached to PCI devices with
>> > -userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
>> > -of the entire device, you can spot them with the DRIVER_MODESET flag.
>> > -
>> > -Unfortunately there's still large piles of legacy code around which needs to
>> > -be hidden so that driver writers don't accidentally end up using it. And to
>> > -prevent security issues in those legacy IOCTLs from being exploited on modern
>> > -drivers. This has multiple possible subtasks:
>> > -
>>
>> > -* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
>> > -  module and compile it only when one of the legacy drivers is enabled.
>> > -
>> This isn't done,
>
> Yup, but I kinda figured I'll give up on this idea. The code is hidden
> well enough, I don't think a drm-legacy.ko will buy us much. Except lots
> of churn on older driver's Kconfig entries for no purpose.
>
> There's been a patch already a while back to hide the legacy drivers
> better, and Dave nacked it. So I'm not really for pushing this idea
> anymore as a good task for newbies (which todo.rst tries to collect).
>
> Want me to explain this a bit better in the commit message?

I have sort-of been chipping on that. Now the grand master approach
you've used, but still.
Up-to you if you'd want to drop, but please add a small mention in the
commit message.

Thanks
Emil
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 06/14] drm: extract drm_atomic_uapi.c
  2018-09-04 20:41     ` Rodrigo Vivi
@ 2018-09-05  7:55       ` Daniel Vetter
  0 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-05  7:55 UTC (permalink / raw)
  To: Rodrigo Vivi
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	DRI Development, Sean Paul, Daniel Vetter, freedreno,
	linux-arm-msm

On Tue, Sep 04, 2018 at 01:41:33PM -0700, Rodrigo Vivi wrote:
> Maybe start a new file with SPDX identifier?
> 
> I like the idea of this split...

I just checked, none of the other drm files have them. I'm not sure I want
to start this specific bikeshed, so I think I'll leave it as-is.

> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

Thanks, Daniel

> 
> > + *
> > + * Authors:
> > + * Rob Clark <robdclark@gmail.com>
> > + * Daniel Vetter <daniel.vetter@ffwll.ch>
> > + */
> > +
> > +#include <drm/drm_atomic_uapi.h>
> > +#include <drm/drm_atomic.h>
> > +#include <drm/drm_print.h>
> > +#include <drm/drm_drv.h>
> > +#include <drm/drm_writeback.h>
> > +#include <drm/drm_vblank.h>
> > +
> > +#include <linux/dma-fence.h>
> > +#include <linux/uaccess.h>
> > +#include <linux/sync_file.h>
> > +#include <linux/file.h>
> > +
> > +#include "drm_crtc_internal.h"
> > +
> > +/**
> > + * DOC: overview
> > + *
> > + * This file contains the marshalling and demarshalling glue for the atomic UAPI
> > + * in all it's form: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
> > + * SET_PROPERTY IOCTls. Plus interface functions for compatibility helpers and
> > + * drivers which have special needs to construct their own atomic updates, e.g.
> > + * for load detect or similiar.
> > + */
> > +
> > +/**
> > + * drm_atomic_set_mode_for_crtc - set mode for CRTC
> > + * @state: the CRTC whose incoming state to update
> > + * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
> > + *
> > + * Set a mode (originating from the kernel) on the desired CRTC state and update
> > + * the enable property.
> > + *
> > + * RETURNS:
> > + * Zero on success, error code on failure. Cannot return -EDEADLK.
> > + */
> > +int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> > +				 const struct drm_display_mode *mode)
> > +{
> > +	struct drm_crtc *crtc = state->crtc;
> > +	struct drm_mode_modeinfo umode;
> > +
> > +	/* Early return for no change. */
> > +	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
> > +		return 0;
> > +
> > +	drm_property_blob_put(state->mode_blob);
> > +	state->mode_blob = NULL;
> > +
> > +	if (mode) {
> > +		drm_mode_convert_to_umode(&umode, mode);
> > +		state->mode_blob =
> > +			drm_property_create_blob(state->crtc->dev,
> > +		                                 sizeof(umode),
> > +		                                 &umode);
> > +		if (IS_ERR(state->mode_blob))
> > +			return PTR_ERR(state->mode_blob);
> > +
> > +		drm_mode_copy(&state->mode, mode);
> > +		state->enable = true;
> > +		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> > +				 mode->name, crtc->base.id, crtc->name, state);
> > +	} else {
> > +		memset(&state->mode, 0, sizeof(state->mode));
> > +		state->enable = false;
> > +		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> > +				 crtc->base.id, crtc->name, state);
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
> > +
> > +/**
> > + * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
> > + * @state: the CRTC whose incoming state to update
> > + * @blob: pointer to blob property to use for mode
> > + *
> > + * Set a mode (originating from a blob property) on the desired CRTC state.
> > + * This function will take a reference on the blob property for the CRTC state,
> > + * and release the reference held on the state's existing mode property, if any
> > + * was set.
> > + *
> > + * RETURNS:
> > + * Zero on success, error code on failure. Cannot return -EDEADLK.
> > + */
> > +int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> > +                                      struct drm_property_blob *blob)
> > +{
> > +	struct drm_crtc *crtc = state->crtc;
> > +
> > +	if (blob == state->mode_blob)
> > +		return 0;
> > +
> > +	drm_property_blob_put(state->mode_blob);
> > +	state->mode_blob = NULL;
> > +
> > +	memset(&state->mode, 0, sizeof(state->mode));
> > +
> > +	if (blob) {
> > +		int ret;
> > +
> > +		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
> > +			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
> > +					 crtc->base.id, crtc->name,
> > +					 blob->length);
> > +			return -EINVAL;
> > +		}
> > +
> > +		ret = drm_mode_convert_umode(crtc->dev,
> > +					     &state->mode, blob->data);
> > +		if (ret) {
> > +			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
> > +					 crtc->base.id, crtc->name,
> > +					 ret, drm_get_mode_status_name(state->mode.status));
> > +			drm_mode_debug_printmodeline(&state->mode);
> > +			return -EINVAL;
> > +		}
> > +
> > +		state->mode_blob = drm_property_blob_get(blob);
> > +		state->enable = true;
> > +		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
> > +				 state->mode.name, crtc->base.id, crtc->name,
> > +				 state);
> > +	} else {
> > +		state->enable = false;
> > +		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
> > +				 crtc->base.id, crtc->name, state);
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
> > +
> > +/**
> > + * drm_atomic_set_crtc_for_plane - set crtc for plane
> > + * @plane_state: the plane whose incoming state to update
> > + * @crtc: crtc to use for the plane
> > + *
> > + * Changing the assigned crtc for a plane requires us to grab the lock and state
> > + * for the new crtc, as needed. This function takes care of all these details
> > + * besides updating the pointer in the state object itself.
> > + *
> > + * Returns:
> > + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> > + * then the w/w mutex code has detected a deadlock and the entire atomic
> > + * sequence must be restarted. All other errors are fatal.
> > + */
> > +int
> > +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> > +			      struct drm_crtc *crtc)
> > +{
> > +	struct drm_plane *plane = plane_state->plane;
> > +	struct drm_crtc_state *crtc_state;
> > +	/* Nothing to do for same crtc*/
> > +	if (plane_state->crtc == crtc)
> > +		return 0;
> > +	if (plane_state->crtc) {
> > +		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> > +						       plane_state->crtc);
> > +		if (WARN_ON(IS_ERR(crtc_state)))
> > +			return PTR_ERR(crtc_state);
> > +
> > +		crtc_state->plane_mask &= ~drm_plane_mask(plane);
> > +	}
> > +
> > +	plane_state->crtc = crtc;
> > +
> > +	if (crtc) {
> > +		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
> > +						       crtc);
> > +		if (IS_ERR(crtc_state))
> > +			return PTR_ERR(crtc_state);
> > +		crtc_state->plane_mask |= drm_plane_mask(plane);
> > +	}
> > +
> > +	if (crtc)
> > +		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
> > +				 plane->base.id, plane->name, plane_state,
> > +				 crtc->base.id, crtc->name);
> > +	else
> > +		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
> > +				 plane->base.id, plane->name, plane_state);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
> > +
> > +/**
> > + * drm_atomic_set_fb_for_plane - set framebuffer for plane
> > + * @plane_state: atomic state object for the plane
> > + * @fb: fb to use for the plane
> > + *
> > + * Changing the assigned framebuffer for a plane requires us to grab a reference
> > + * to the new fb and drop the reference to the old fb, if there is one. This
> > + * function takes care of all these details besides updating the pointer in the
> > + * state object itself.
> > + */
> > +void
> > +drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> > +			    struct drm_framebuffer *fb)
> > +{
> > +	struct drm_plane *plane = plane_state->plane;
> > +
> > +	if (fb)
> > +		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
> > +				 fb->base.id, plane->base.id, plane->name,
> > +				 plane_state);
> > +	else
> > +		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
> > +				 plane->base.id, plane->name, plane_state);
> > +
> > +	drm_framebuffer_assign(&plane_state->fb, fb);
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
> > +
> > +/**
> > + * drm_atomic_set_fence_for_plane - set fence for plane
> > + * @plane_state: atomic state object for the plane
> > + * @fence: dma_fence to use for the plane
> > + *
> > + * Helper to setup the plane_state fence in case it is not set yet.
> > + * By using this drivers doesn't need to worry if the user choose
> > + * implicit or explicit fencing.
> > + *
> > + * This function will not set the fence to the state if it was set
> > + * via explicit fencing interfaces on the atomic ioctl. In that case it will
> > + * drop the reference to the fence as we are not storing it anywhere.
> > + * Otherwise, if &drm_plane_state.fence is not set this function we just set it
> > + * with the received implicit fence. In both cases this function consumes a
> > + * reference for @fence.
> > + *
> > + * This way explicit fencing can be used to overrule implicit fencing, which is
> > + * important to make explicit fencing use-cases work: One example is using one
> > + * buffer for 2 screens with different refresh rates. Implicit fencing will
> > + * clamp rendering to the refresh rate of the slower screen, whereas explicit
> > + * fence allows 2 independent render and display loops on a single buffer. If a
> > + * driver allows obeys both implicit and explicit fences for plane updates, then
> > + * it will break all the benefits of explicit fencing.
> > + */
> > +void
> > +drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> > +			       struct dma_fence *fence)
> > +{
> > +	if (plane_state->fence) {
> > +		dma_fence_put(fence);
> > +		return;
> > +	}
> > +
> > +	plane_state->fence = fence;
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
> > +
> > +/**
> > + * drm_atomic_set_crtc_for_connector - set crtc for connector
> > + * @conn_state: atomic state object for the connector
> > + * @crtc: crtc to use for the connector
> > + *
> > + * Changing the assigned crtc for a connector requires us to grab the lock and
> > + * state for the new crtc, as needed. This function takes care of all these
> > + * details besides updating the pointer in the state object itself.
> > + *
> > + * Returns:
> > + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
> > + * then the w/w mutex code has detected a deadlock and the entire atomic
> > + * sequence must be restarted. All other errors are fatal.
> > + */
> > +int
> > +drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> > +				  struct drm_crtc *crtc)
> > +{
> > +	struct drm_connector *connector = conn_state->connector;
> > +	struct drm_crtc_state *crtc_state;
> > +
> > +	if (conn_state->crtc == crtc)
> > +		return 0;
> > +
> > +	if (conn_state->crtc) {
> > +		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
> > +							   conn_state->crtc);
> > +
> > +		crtc_state->connector_mask &=
> > +			~drm_connector_mask(conn_state->connector);
> > +
> > +		drm_connector_put(conn_state->connector);
> > +		conn_state->crtc = NULL;
> > +	}
> > +
> > +	if (crtc) {
> > +		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
> > +		if (IS_ERR(crtc_state))
> > +			return PTR_ERR(crtc_state);
> > +
> > +		crtc_state->connector_mask |=
> > +			drm_connector_mask(conn_state->connector);
> > +
> > +		drm_connector_get(conn_state->connector);
> > +		conn_state->crtc = crtc;
> > +
> > +		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
> > +				 connector->base.id, connector->name,
> > +				 conn_state, crtc->base.id, crtc->name);
> > +	} else {
> > +		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
> > +				 connector->base.id, connector->name,
> > +				 conn_state);
> > +	}
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
> > +
> > +static void set_out_fence_for_crtc(struct drm_atomic_state *state,
> > +				   struct drm_crtc *crtc, s32 __user *fence_ptr)
> > +{
> > +	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
> > +}
> > +
> > +static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
> > +					  struct drm_crtc *crtc)
> > +{
> > +	s32 __user *fence_ptr;
> > +
> > +	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
> > +	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
> > +
> > +	return fence_ptr;
> > +}
> > +
> > +static int set_out_fence_for_connector(struct drm_atomic_state *state,
> > +					struct drm_connector *connector,
> > +					s32 __user *fence_ptr)
> > +{
> > +	unsigned int index = drm_connector_index(connector);
> > +
> > +	if (!fence_ptr)
> > +		return 0;
> > +
> > +	if (put_user(-1, fence_ptr))
> > +		return -EFAULT;
> > +
> > +	state->connectors[index].out_fence_ptr = fence_ptr;
> > +
> > +	return 0;
> > +}
> > +
> > +static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
> > +					       struct drm_connector *connector)
> > +{
> > +	unsigned int index = drm_connector_index(connector);
> > +	s32 __user *fence_ptr;
> > +
> > +	fence_ptr = state->connectors[index].out_fence_ptr;
> > +	state->connectors[index].out_fence_ptr = NULL;
> > +
> > +	return fence_ptr;
> > +}
> > +
> > +static int
> > +drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
> > +					 struct drm_property_blob **blob,
> > +					 uint64_t blob_id,
> > +					 ssize_t expected_size,
> > +					 ssize_t expected_elem_size,
> > +					 bool *replaced)
> > +{
> > +	struct drm_property_blob *new_blob = NULL;
> > +
> > +	if (blob_id != 0) {
> > +		new_blob = drm_property_lookup_blob(dev, blob_id);
> > +		if (new_blob == NULL)
> > +			return -EINVAL;
> > +
> > +		if (expected_size > 0 &&
> > +		    new_blob->length != expected_size) {
> > +			drm_property_blob_put(new_blob);
> > +			return -EINVAL;
> > +		}
> > +		if (expected_elem_size > 0 &&
> > +		    new_blob->length % expected_elem_size != 0) {
> > +			drm_property_blob_put(new_blob);
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> > +	*replaced |= drm_property_replace_blob(blob, new_blob);
> > +	drm_property_blob_put(new_blob);
> > +
> > +	return 0;
> > +}
> > +
> > +static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
> > +		struct drm_crtc_state *state, struct drm_property *property,
> > +		uint64_t val)
> > +{
> > +	struct drm_device *dev = crtc->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +	bool replaced = false;
> > +	int ret;
> > +
> > +	if (property == config->prop_active)
> > +		state->active = val;
> > +	else if (property == config->prop_mode_id) {
> > +		struct drm_property_blob *mode =
> > +			drm_property_lookup_blob(dev, val);
> > +		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
> > +		drm_property_blob_put(mode);
> > +		return ret;
> > +	} else if (property == config->degamma_lut_property) {
> > +		ret = drm_atomic_replace_property_blob_from_id(dev,
> > +					&state->degamma_lut,
> > +					val,
> > +					-1, sizeof(struct drm_color_lut),
> > +					&replaced);
> > +		state->color_mgmt_changed |= replaced;
> > +		return ret;
> > +	} else if (property == config->ctm_property) {
> > +		ret = drm_atomic_replace_property_blob_from_id(dev,
> > +					&state->ctm,
> > +					val,
> > +					sizeof(struct drm_color_ctm), -1,
> > +					&replaced);
> > +		state->color_mgmt_changed |= replaced;
> > +		return ret;
> > +	} else if (property == config->gamma_lut_property) {
> > +		ret = drm_atomic_replace_property_blob_from_id(dev,
> > +					&state->gamma_lut,
> > +					val,
> > +					-1, sizeof(struct drm_color_lut),
> > +					&replaced);
> > +		state->color_mgmt_changed |= replaced;
> > +		return ret;
> > +	} else if (property == config->prop_out_fence_ptr) {
> > +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> > +
> > +		if (!fence_ptr)
> > +			return 0;
> > +
> > +		if (put_user(-1, fence_ptr))
> > +			return -EFAULT;
> > +
> > +		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
> > +	} else if (crtc->funcs->atomic_set_property) {
> > +		return crtc->funcs->atomic_set_property(crtc, state, property, val);
> > +	} else {
> > +		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
> > +				 crtc->base.id, crtc->name,
> > +				 property->base.id, property->name);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +drm_atomic_crtc_get_property(struct drm_crtc *crtc,
> > +		const struct drm_crtc_state *state,
> > +		struct drm_property *property, uint64_t *val)
> > +{
> > +	struct drm_device *dev = crtc->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +
> > +	if (property == config->prop_active)
> > +		*val = state->active;
> > +	else if (property == config->prop_mode_id)
> > +		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
> > +	else if (property == config->degamma_lut_property)
> > +		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
> > +	else if (property == config->ctm_property)
> > +		*val = (state->ctm) ? state->ctm->base.id : 0;
> > +	else if (property == config->gamma_lut_property)
> > +		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
> > +	else if (property == config->prop_out_fence_ptr)
> > +		*val = 0;
> > +	else if (crtc->funcs->atomic_get_property)
> > +		return crtc->funcs->atomic_get_property(crtc, state, property, val);
> > +	else
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +static int drm_atomic_plane_set_property(struct drm_plane *plane,
> > +		struct drm_plane_state *state, struct drm_property *property,
> > +		uint64_t val)
> > +{
> > +	struct drm_device *dev = plane->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +
> > +	if (property == config->prop_fb_id) {
> > +		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> > +		drm_atomic_set_fb_for_plane(state, fb);
> > +		if (fb)
> > +			drm_framebuffer_put(fb);
> > +	} else if (property == config->prop_in_fence_fd) {
> > +		if (state->fence)
> > +			return -EINVAL;
> > +
> > +		if (U642I64(val) == -1)
> > +			return 0;
> > +
> > +		state->fence = sync_file_get_fence(val);
> > +		if (!state->fence)
> > +			return -EINVAL;
> > +
> > +	} else if (property == config->prop_crtc_id) {
> > +		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> > +		return drm_atomic_set_crtc_for_plane(state, crtc);
> > +	} else if (property == config->prop_crtc_x) {
> > +		state->crtc_x = U642I64(val);
> > +	} else if (property == config->prop_crtc_y) {
> > +		state->crtc_y = U642I64(val);
> > +	} else if (property == config->prop_crtc_w) {
> > +		state->crtc_w = val;
> > +	} else if (property == config->prop_crtc_h) {
> > +		state->crtc_h = val;
> > +	} else if (property == config->prop_src_x) {
> > +		state->src_x = val;
> > +	} else if (property == config->prop_src_y) {
> > +		state->src_y = val;
> > +	} else if (property == config->prop_src_w) {
> > +		state->src_w = val;
> > +	} else if (property == config->prop_src_h) {
> > +		state->src_h = val;
> > +	} else if (property == plane->alpha_property) {
> > +		state->alpha = val;
> > +	} else if (property == plane->blend_mode_property) {
> > +		state->pixel_blend_mode = val;
> > +	} else if (property == plane->rotation_property) {
> > +		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
> > +			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
> > +					 plane->base.id, plane->name, val);
> > +			return -EINVAL;
> > +		}
> > +		state->rotation = val;
> > +	} else if (property == plane->zpos_property) {
> > +		state->zpos = val;
> > +	} else if (property == plane->color_encoding_property) {
> > +		state->color_encoding = val;
> > +	} else if (property == plane->color_range_property) {
> > +		state->color_range = val;
> > +	} else if (plane->funcs->atomic_set_property) {
> > +		return plane->funcs->atomic_set_property(plane, state,
> > +				property, val);
> > +	} else {
> > +		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
> > +				 plane->base.id, plane->name,
> > +				 property->base.id, property->name);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +drm_atomic_plane_get_property(struct drm_plane *plane,
> > +		const struct drm_plane_state *state,
> > +		struct drm_property *property, uint64_t *val)
> > +{
> > +	struct drm_device *dev = plane->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +
> > +	if (property == config->prop_fb_id) {
> > +		*val = (state->fb) ? state->fb->base.id : 0;
> > +	} else if (property == config->prop_in_fence_fd) {
> > +		*val = -1;
> > +	} else if (property == config->prop_crtc_id) {
> > +		*val = (state->crtc) ? state->crtc->base.id : 0;
> > +	} else if (property == config->prop_crtc_x) {
> > +		*val = I642U64(state->crtc_x);
> > +	} else if (property == config->prop_crtc_y) {
> > +		*val = I642U64(state->crtc_y);
> > +	} else if (property == config->prop_crtc_w) {
> > +		*val = state->crtc_w;
> > +	} else if (property == config->prop_crtc_h) {
> > +		*val = state->crtc_h;
> > +	} else if (property == config->prop_src_x) {
> > +		*val = state->src_x;
> > +	} else if (property == config->prop_src_y) {
> > +		*val = state->src_y;
> > +	} else if (property == config->prop_src_w) {
> > +		*val = state->src_w;
> > +	} else if (property == config->prop_src_h) {
> > +		*val = state->src_h;
> > +	} else if (property == plane->alpha_property) {
> > +		*val = state->alpha;
> > +	} else if (property == plane->blend_mode_property) {
> > +		*val = state->pixel_blend_mode;
> > +	} else if (property == plane->rotation_property) {
> > +		*val = state->rotation;
> > +	} else if (property == plane->zpos_property) {
> > +		*val = state->zpos;
> > +	} else if (property == plane->color_encoding_property) {
> > +		*val = state->color_encoding;
> > +	} else if (property == plane->color_range_property) {
> > +		*val = state->color_range;
> > +	} else if (plane->funcs->atomic_get_property) {
> > +		return plane->funcs->atomic_get_property(plane, state, property, val);
> > +	} else {
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct drm_writeback_job *
> > +drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
> > +{
> > +	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
> > +
> > +	if (!conn_state->writeback_job)
> > +		conn_state->writeback_job =
> > +			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
> > +
> > +	return conn_state->writeback_job;
> > +}
> > +
> > +static int drm_atomic_set_writeback_fb_for_connector(
> > +		struct drm_connector_state *conn_state,
> > +		struct drm_framebuffer *fb)
> > +{
> > +	struct drm_writeback_job *job =
> > +		drm_atomic_get_writeback_job(conn_state);
> > +	if (!job)
> > +		return -ENOMEM;
> > +
> > +	drm_framebuffer_assign(&job->fb, fb);
> > +
> > +	if (fb)
> > +		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
> > +				 fb->base.id, conn_state);
> > +	else
> > +		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
> > +				 conn_state);
> > +
> > +	return 0;
> > +}
> > +
> > +static int drm_atomic_connector_set_property(struct drm_connector *connector,
> > +		struct drm_connector_state *state, struct drm_property *property,
> > +		uint64_t val)
> > +{
> > +	struct drm_device *dev = connector->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +
> > +	if (property == config->prop_crtc_id) {
> > +		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
> > +		return drm_atomic_set_crtc_for_connector(state, crtc);
> > +	} else if (property == config->dpms_property) {
> > +		/* setting DPMS property requires special handling, which
> > +		 * is done in legacy setprop path for us.  Disallow (for
> > +		 * now?) atomic writes to DPMS property:
> > +		 */
> > +		return -EINVAL;
> > +	} else if (property == config->tv_select_subconnector_property) {
> > +		state->tv.subconnector = val;
> > +	} else if (property == config->tv_left_margin_property) {
> > +		state->tv.margins.left = val;
> > +	} else if (property == config->tv_right_margin_property) {
> > +		state->tv.margins.right = val;
> > +	} else if (property == config->tv_top_margin_property) {
> > +		state->tv.margins.top = val;
> > +	} else if (property == config->tv_bottom_margin_property) {
> > +		state->tv.margins.bottom = val;
> > +	} else if (property == config->tv_mode_property) {
> > +		state->tv.mode = val;
> > +	} else if (property == config->tv_brightness_property) {
> > +		state->tv.brightness = val;
> > +	} else if (property == config->tv_contrast_property) {
> > +		state->tv.contrast = val;
> > +	} else if (property == config->tv_flicker_reduction_property) {
> > +		state->tv.flicker_reduction = val;
> > +	} else if (property == config->tv_overscan_property) {
> > +		state->tv.overscan = val;
> > +	} else if (property == config->tv_saturation_property) {
> > +		state->tv.saturation = val;
> > +	} else if (property == config->tv_hue_property) {
> > +		state->tv.hue = val;
> > +	} else if (property == config->link_status_property) {
> > +		/* Never downgrade from GOOD to BAD on userspace's request here,
> > +		 * only hw issues can do that.
> > +		 *
> > +		 * For an atomic property the userspace doesn't need to be able
> > +		 * to understand all the properties, but needs to be able to
> > +		 * restore the state it wants on VT switch. So if the userspace
> > +		 * tries to change the link_status from GOOD to BAD, driver
> > +		 * silently rejects it and returns a 0. This prevents userspace
> > +		 * from accidently breaking  the display when it restores the
> > +		 * state.
> > +		 */
> > +		if (state->link_status != DRM_LINK_STATUS_GOOD)
> > +			state->link_status = val;
> > +	} else if (property == config->aspect_ratio_property) {
> > +		state->picture_aspect_ratio = val;
> > +	} else if (property == config->content_type_property) {
> > +		state->content_type = val;
> > +	} else if (property == connector->scaling_mode_property) {
> > +		state->scaling_mode = val;
> > +	} else if (property == connector->content_protection_property) {
> > +		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
> > +			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
> > +			return -EINVAL;
> > +		}
> > +		state->content_protection = val;
> > +	} else if (property == config->writeback_fb_id_property) {
> > +		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
> > +		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
> > +		if (fb)
> > +			drm_framebuffer_put(fb);
> > +		return ret;
> > +	} else if (property == config->writeback_out_fence_ptr_property) {
> > +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> > +
> > +		return set_out_fence_for_connector(state->state, connector,
> > +						   fence_ptr);
> > +	} else if (connector->funcs->atomic_set_property) {
> > +		return connector->funcs->atomic_set_property(connector,
> > +				state, property, val);
> > +	} else {
> > +		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
> > +				 connector->base.id, connector->name,
> > +				 property->base.id, property->name);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +drm_atomic_connector_get_property(struct drm_connector *connector,
> > +		const struct drm_connector_state *state,
> > +		struct drm_property *property, uint64_t *val)
> > +{
> > +	struct drm_device *dev = connector->dev;
> > +	struct drm_mode_config *config = &dev->mode_config;
> > +
> > +	if (property == config->prop_crtc_id) {
> > +		*val = (state->crtc) ? state->crtc->base.id : 0;
> > +	} else if (property == config->dpms_property) {
> > +		*val = connector->dpms;
> > +	} else if (property == config->tv_select_subconnector_property) {
> > +		*val = state->tv.subconnector;
> > +	} else if (property == config->tv_left_margin_property) {
> > +		*val = state->tv.margins.left;
> > +	} else if (property == config->tv_right_margin_property) {
> > +		*val = state->tv.margins.right;
> > +	} else if (property == config->tv_top_margin_property) {
> > +		*val = state->tv.margins.top;
> > +	} else if (property == config->tv_bottom_margin_property) {
> > +		*val = state->tv.margins.bottom;
> > +	} else if (property == config->tv_mode_property) {
> > +		*val = state->tv.mode;
> > +	} else if (property == config->tv_brightness_property) {
> > +		*val = state->tv.brightness;
> > +	} else if (property == config->tv_contrast_property) {
> > +		*val = state->tv.contrast;
> > +	} else if (property == config->tv_flicker_reduction_property) {
> > +		*val = state->tv.flicker_reduction;
> > +	} else if (property == config->tv_overscan_property) {
> > +		*val = state->tv.overscan;
> > +	} else if (property == config->tv_saturation_property) {
> > +		*val = state->tv.saturation;
> > +	} else if (property == config->tv_hue_property) {
> > +		*val = state->tv.hue;
> > +	} else if (property == config->link_status_property) {
> > +		*val = state->link_status;
> > +	} else if (property == config->aspect_ratio_property) {
> > +		*val = state->picture_aspect_ratio;
> > +	} else if (property == config->content_type_property) {
> > +		*val = state->content_type;
> > +	} else if (property == connector->scaling_mode_property) {
> > +		*val = state->scaling_mode;
> > +	} else if (property == connector->content_protection_property) {
> > +		*val = state->content_protection;
> > +	} else if (property == config->writeback_fb_id_property) {
> > +		/* Writeback framebuffer is one-shot, write and forget */
> > +		*val = 0;
> > +	} else if (property == config->writeback_out_fence_ptr_property) {
> > +		*val = 0;
> > +	} else if (connector->funcs->atomic_get_property) {
> > +		return connector->funcs->atomic_get_property(connector,
> > +				state, property, val);
> > +	} else {
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int drm_atomic_get_property(struct drm_mode_object *obj,
> > +		struct drm_property *property, uint64_t *val)
> > +{
> > +	struct drm_device *dev = property->dev;
> > +	int ret;
> > +
> > +	switch (obj->type) {
> > +	case DRM_MODE_OBJECT_CONNECTOR: {
> > +		struct drm_connector *connector = obj_to_connector(obj);
> > +		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> > +		ret = drm_atomic_connector_get_property(connector,
> > +				connector->state, property, val);
> > +		break;
> > +	}
> > +	case DRM_MODE_OBJECT_CRTC: {
> > +		struct drm_crtc *crtc = obj_to_crtc(obj);
> > +		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
> > +		ret = drm_atomic_crtc_get_property(crtc,
> > +				crtc->state, property, val);
> > +		break;
> > +	}
> > +	case DRM_MODE_OBJECT_PLANE: {
> > +		struct drm_plane *plane = obj_to_plane(obj);
> > +		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
> > +		ret = drm_atomic_plane_get_property(plane,
> > +				plane->state, property, val);
> > +		break;
> > +	}
> > +	default:
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +/*
> > + * The big monster ioctl
> > + */
> > +
> > +static struct drm_pending_vblank_event *create_vblank_event(
> > +		struct drm_crtc *crtc, uint64_t user_data)
> > +{
> > +	struct drm_pending_vblank_event *e = NULL;
> > +
> > +	e = kzalloc(sizeof *e, GFP_KERNEL);
> > +	if (!e)
> > +		return NULL;
> > +
> > +	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
> > +	e->event.base.length = sizeof(e->event);
> > +	e->event.vbl.crtc_id = crtc->base.id;
> > +	e->event.vbl.user_data = user_data;
> > +
> > +	return e;
> > +}
> > +
> > +int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> > +				     struct drm_connector *connector,
> > +				     int mode)
> > +{
> > +	struct drm_connector *tmp_connector;
> > +	struct drm_connector_state *new_conn_state;
> > +	struct drm_crtc *crtc;
> > +	struct drm_crtc_state *crtc_state;
> > +	int i, ret, old_mode = connector->dpms;
> > +	bool active = false;
> > +
> > +	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
> > +			       state->acquire_ctx);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (mode != DRM_MODE_DPMS_ON)
> > +		mode = DRM_MODE_DPMS_OFF;
> > +	connector->dpms = mode;
> > +
> > +	crtc = connector->state->crtc;
> > +	if (!crtc)
> > +		goto out;
> > +	ret = drm_atomic_add_affected_connectors(state, crtc);
> > +	if (ret)
> > +		goto out;
> > +
> > +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> > +	if (IS_ERR(crtc_state)) {
> > +		ret = PTR_ERR(crtc_state);
> > +		goto out;
> > +	}
> > +
> > +	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
> > +		if (new_conn_state->crtc != crtc)
> > +			continue;
> > +		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
> > +			active = true;
> > +			break;
> > +		}
> > +	}
> > +
> > +	crtc_state->active = active;
> > +	ret = drm_atomic_commit(state);
> > +out:
> > +	if (ret != 0)
> > +		connector->dpms = old_mode;
> > +	return ret;
> > +}
> > +
> > +int drm_atomic_set_property(struct drm_atomic_state *state,
> > +			    struct drm_mode_object *obj,
> > +			    struct drm_property *prop,
> > +			    uint64_t prop_value)
> > +{
> > +	struct drm_mode_object *ref;
> > +	int ret;
> > +
> > +	if (!drm_property_change_valid_get(prop, prop_value, &ref))
> > +		return -EINVAL;
> > +
> > +	switch (obj->type) {
> > +	case DRM_MODE_OBJECT_CONNECTOR: {
> > +		struct drm_connector *connector = obj_to_connector(obj);
> > +		struct drm_connector_state *connector_state;
> > +
> > +		connector_state = drm_atomic_get_connector_state(state, connector);
> > +		if (IS_ERR(connector_state)) {
> > +			ret = PTR_ERR(connector_state);
> > +			break;
> > +		}
> > +
> > +		ret = drm_atomic_connector_set_property(connector,
> > +				connector_state, prop, prop_value);
> > +		break;
> > +	}
> > +	case DRM_MODE_OBJECT_CRTC: {
> > +		struct drm_crtc *crtc = obj_to_crtc(obj);
> > +		struct drm_crtc_state *crtc_state;
> > +
> > +		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> > +		if (IS_ERR(crtc_state)) {
> > +			ret = PTR_ERR(crtc_state);
> > +			break;
> > +		}
> > +
> > +		ret = drm_atomic_crtc_set_property(crtc,
> > +				crtc_state, prop, prop_value);
> > +		break;
> > +	}
> > +	case DRM_MODE_OBJECT_PLANE: {
> > +		struct drm_plane *plane = obj_to_plane(obj);
> > +		struct drm_plane_state *plane_state;
> > +
> > +		plane_state = drm_atomic_get_plane_state(state, plane);
> > +		if (IS_ERR(plane_state)) {
> > +			ret = PTR_ERR(plane_state);
> > +			break;
> > +		}
> > +
> > +		ret = drm_atomic_plane_set_property(plane,
> > +				plane_state, prop, prop_value);
> > +		break;
> > +	}
> > +	default:
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	drm_property_change_valid_put(prop, ref);
> > +	return ret;
> > +}
> > +
> > +/**
> > + * DOC: explicit fencing properties
> > + *
> > + * Explicit fencing allows userspace to control the buffer synchronization
> > + * between devices. A Fence or a group of fences are transfered to/from
> > + * userspace using Sync File fds and there are two DRM properties for that.
> > + * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
> > + * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
> > + *
> > + * As a contrast, with implicit fencing the kernel keeps track of any
> > + * ongoing rendering, and automatically ensures that the atomic update waits
> > + * for any pending rendering to complete. For shared buffers represented with
> > + * a &struct dma_buf this is tracked in &struct reservation_object.
> > + * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
> > + * whereas explicit fencing is what Android wants.
> > + *
> > + * "IN_FENCE_FD”:
> > + *	Use this property to pass a fence that DRM should wait on before
> > + *	proceeding with the Atomic Commit request and show the framebuffer for
> > + *	the plane on the screen. The fence can be either a normal fence or a
> > + *	merged one, the sync_file framework will handle both cases and use a
> > + *	fence_array if a merged fence is received. Passing -1 here means no
> > + *	fences to wait on.
> > + *
> > + *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
> > + *	it will only check if the Sync File is a valid one.
> > + *
> > + *	On the driver side the fence is stored on the @fence parameter of
> > + *	&struct drm_plane_state. Drivers which also support implicit fencing
> > + *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
> > + *	to make sure there's consistent behaviour between drivers in precedence
> > + *	of implicit vs. explicit fencing.
> > + *
> > + * "OUT_FENCE_PTR”:
> > + *	Use this property to pass a file descriptor pointer to DRM. Once the
> > + *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
> > + *	the file descriptor number of a Sync File. This Sync File contains the
> > + *	CRTC fence that will be signaled when all framebuffers present on the
> > + *	Atomic Commit * request for that given CRTC are scanned out on the
> > + *	screen.
> > + *
> > + *	The Atomic Commit request fails if a invalid pointer is passed. If the
> > + *	Atomic Commit request fails for any other reason the out fence fd
> > + *	returned will be -1. On a Atomic Commit with the
> > + *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
> > + *
> > + *	Note that out-fences don't have a special interface to drivers and are
> > + *	internally represented by a &struct drm_pending_vblank_event in struct
> > + *	&drm_crtc_state, which is also used by the nonblocking atomic commit
> > + *	helpers and for the DRM event handling for existing userspace.
> > + */
> > +
> > +struct drm_out_fence_state {
> > +	s32 __user *out_fence_ptr;
> > +	struct sync_file *sync_file;
> > +	int fd;
> > +};
> > +
> > +static int setup_out_fence(struct drm_out_fence_state *fence_state,
> > +			   struct dma_fence *fence)
> > +{
> > +	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> > +	if (fence_state->fd < 0)
> > +		return fence_state->fd;
> > +
> > +	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> > +		return -EFAULT;
> > +
> > +	fence_state->sync_file = sync_file_create(fence);
> > +	if (!fence_state->sync_file)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> > +static int prepare_signaling(struct drm_device *dev,
> > +				  struct drm_atomic_state *state,
> > +				  struct drm_mode_atomic *arg,
> > +				  struct drm_file *file_priv,
> > +				  struct drm_out_fence_state **fence_state,
> > +				  unsigned int *num_fences)
> > +{
> > +	struct drm_crtc *crtc;
> > +	struct drm_crtc_state *crtc_state;
> > +	struct drm_connector *conn;
> > +	struct drm_connector_state *conn_state;
> > +	int i, c = 0, ret;
> > +
> > +	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
> > +		return 0;
> > +
> > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> > +		s32 __user *fence_ptr;
> > +
> > +		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
> > +
> > +		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
> > +			struct drm_pending_vblank_event *e;
> > +
> > +			e = create_vblank_event(crtc, arg->user_data);
> > +			if (!e)
> > +				return -ENOMEM;
> > +
> > +			crtc_state->event = e;
> > +		}
> > +
> > +		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > +			struct drm_pending_vblank_event *e = crtc_state->event;
> > +
> > +			if (!file_priv)
> > +				continue;
> > +
> > +			ret = drm_event_reserve_init(dev, file_priv, &e->base,
> > +						     &e->event.base);
> > +			if (ret) {
> > +				kfree(e);
> > +				crtc_state->event = NULL;
> > +				return ret;
> > +			}
> > +		}
> > +
> > +		if (fence_ptr) {
> > +			struct dma_fence *fence;
> > +			struct drm_out_fence_state *f;
> > +
> > +			f = krealloc(*fence_state, sizeof(**fence_state) *
> > +				     (*num_fences + 1), GFP_KERNEL);
> > +			if (!f)
> > +				return -ENOMEM;
> > +
> > +			memset(&f[*num_fences], 0, sizeof(*f));
> > +
> > +			f[*num_fences].out_fence_ptr = fence_ptr;
> > +			*fence_state = f;
> > +
> > +			fence = drm_crtc_create_fence(crtc);
> > +			if (!fence)
> > +				return -ENOMEM;
> > +
> > +			ret = setup_out_fence(&f[(*num_fences)++], fence);
> > +			if (ret) {
> > +				dma_fence_put(fence);
> > +				return ret;
> > +			}
> > +
> > +			crtc_state->event->base.fence = fence;
> > +		}
> > +
> > +		c++;
> > +	}
> > +
> > +	for_each_new_connector_in_state(state, conn, conn_state, i) {
> > +		struct drm_writeback_connector *wb_conn;
> > +		struct drm_writeback_job *job;
> > +		struct drm_out_fence_state *f;
> > +		struct dma_fence *fence;
> > +		s32 __user *fence_ptr;
> > +
> > +		fence_ptr = get_out_fence_for_connector(state, conn);
> > +		if (!fence_ptr)
> > +			continue;
> > +
> > +		job = drm_atomic_get_writeback_job(conn_state);
> > +		if (!job)
> > +			return -ENOMEM;
> > +
> > +		f = krealloc(*fence_state, sizeof(**fence_state) *
> > +			     (*num_fences + 1), GFP_KERNEL);
> > +		if (!f)
> > +			return -ENOMEM;
> > +
> > +		memset(&f[*num_fences], 0, sizeof(*f));
> > +
> > +		f[*num_fences].out_fence_ptr = fence_ptr;
> > +		*fence_state = f;
> > +
> > +		wb_conn = drm_connector_to_writeback(conn);
> > +		fence = drm_writeback_get_out_fence(wb_conn);
> > +		if (!fence)
> > +			return -ENOMEM;
> > +
> > +		ret = setup_out_fence(&f[(*num_fences)++], fence);
> > +		if (ret) {
> > +			dma_fence_put(fence);
> > +			return ret;
> > +		}
> > +
> > +		job->out_fence = fence;
> > +	}
> > +
> > +	/*
> > +	 * Having this flag means user mode pends on event which will never
> > +	 * reach due to lack of at least one CRTC for signaling
> > +	 */
> > +	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +static void complete_signaling(struct drm_device *dev,
> > +			       struct drm_atomic_state *state,
> > +			       struct drm_out_fence_state *fence_state,
> > +			       unsigned int num_fences,
> > +			       bool install_fds)
> > +{
> > +	struct drm_crtc *crtc;
> > +	struct drm_crtc_state *crtc_state;
> > +	int i;
> > +
> > +	if (install_fds) {
> > +		for (i = 0; i < num_fences; i++)
> > +			fd_install(fence_state[i].fd,
> > +				   fence_state[i].sync_file->file);
> > +
> > +		kfree(fence_state);
> > +		return;
> > +	}
> > +
> > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> > +		struct drm_pending_vblank_event *event = crtc_state->event;
> > +		/*
> > +		 * Free the allocated event. drm_atomic_helper_setup_commit
> > +		 * can allocate an event too, so only free it if it's ours
> > +		 * to prevent a double free in drm_atomic_state_clear.
> > +		 */
> > +		if (event && (event->base.fence || event->base.file_priv)) {
> > +			drm_event_cancel_free(dev, &event->base);
> > +			crtc_state->event = NULL;
> > +		}
> > +	}
> > +
> > +	if (!fence_state)
> > +		return;
> > +
> > +	for (i = 0; i < num_fences; i++) {
> > +		if (fence_state[i].sync_file)
> > +			fput(fence_state[i].sync_file->file);
> > +		if (fence_state[i].fd >= 0)
> > +			put_unused_fd(fence_state[i].fd);
> > +
> > +		/* If this fails log error to the user */
> > +		if (fence_state[i].out_fence_ptr &&
> > +		    put_user(-1, fence_state[i].out_fence_ptr))
> > +			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
> > +	}
> > +
> > +	kfree(fence_state);
> > +}
> > +
> > +int drm_mode_atomic_ioctl(struct drm_device *dev,
> > +			  void *data, struct drm_file *file_priv)
> > +{
> > +	struct drm_mode_atomic *arg = data;
> > +	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
> > +	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
> > +	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
> > +	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
> > +	unsigned int copied_objs, copied_props;
> > +	struct drm_atomic_state *state;
> > +	struct drm_modeset_acquire_ctx ctx;
> > +	struct drm_out_fence_state *fence_state;
> > +	int ret = 0;
> > +	unsigned int i, j, num_fences;
> > +
> > +	/* disallow for drivers not supporting atomic: */
> > +	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
> > +		return -EINVAL;
> > +
> > +	/* disallow for userspace that has not enabled atomic cap (even
> > +	 * though this may be a bit overkill, since legacy userspace
> > +	 * wouldn't know how to call this ioctl)
> > +	 */
> > +	if (!file_priv->atomic)
> > +		return -EINVAL;
> > +
> > +	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
> > +		return -EINVAL;
> > +
> > +	if (arg->reserved)
> > +		return -EINVAL;
> > +
> > +	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
> > +			!dev->mode_config.async_page_flip)
> > +		return -EINVAL;
> > +
> > +	/* can't test and expect an event at the same time. */
> > +	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
> > +			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
> > +		return -EINVAL;
> > +
> > +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
> > +
> > +	state = drm_atomic_state_alloc(dev);
> > +	if (!state)
> > +		return -ENOMEM;
> > +
> > +	state->acquire_ctx = &ctx;
> > +	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
> > +
> > +retry:
> > +	copied_objs = 0;
> > +	copied_props = 0;
> > +	fence_state = NULL;
> > +	num_fences = 0;
> > +
> > +	for (i = 0; i < arg->count_objs; i++) {
> > +		uint32_t obj_id, count_props;
> > +		struct drm_mode_object *obj;
> > +
> > +		if (get_user(obj_id, objs_ptr + copied_objs)) {
> > +			ret = -EFAULT;
> > +			goto out;
> > +		}
> > +
> > +		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
> > +		if (!obj) {
> > +			ret = -ENOENT;
> > +			goto out;
> > +		}
> > +
> > +		if (!obj->properties) {
> > +			drm_mode_object_put(obj);
> > +			ret = -ENOENT;
> > +			goto out;
> > +		}
> > +
> > +		if (get_user(count_props, count_props_ptr + copied_objs)) {
> > +			drm_mode_object_put(obj);
> > +			ret = -EFAULT;
> > +			goto out;
> > +		}
> > +
> > +		copied_objs++;
> > +
> > +		for (j = 0; j < count_props; j++) {
> > +			uint32_t prop_id;
> > +			uint64_t prop_value;
> > +			struct drm_property *prop;
> > +
> > +			if (get_user(prop_id, props_ptr + copied_props)) {
> > +				drm_mode_object_put(obj);
> > +				ret = -EFAULT;
> > +				goto out;
> > +			}
> > +
> > +			prop = drm_mode_obj_find_prop_id(obj, prop_id);
> > +			if (!prop) {
> > +				drm_mode_object_put(obj);
> > +				ret = -ENOENT;
> > +				goto out;
> > +			}
> > +
> > +			if (copy_from_user(&prop_value,
> > +					   prop_values_ptr + copied_props,
> > +					   sizeof(prop_value))) {
> > +				drm_mode_object_put(obj);
> > +				ret = -EFAULT;
> > +				goto out;
> > +			}
> > +
> > +			ret = drm_atomic_set_property(state, obj, prop,
> > +						      prop_value);
> > +			if (ret) {
> > +				drm_mode_object_put(obj);
> > +				goto out;
> > +			}
> > +
> > +			copied_props++;
> > +		}
> > +
> > +		drm_mode_object_put(obj);
> > +	}
> > +
> > +	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
> > +				&num_fences);
> > +	if (ret)
> > +		goto out;
> > +
> > +	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
> > +		ret = drm_atomic_check_only(state);
> > +	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
> > +		ret = drm_atomic_nonblocking_commit(state);
> > +	} else {
> > +		if (unlikely(drm_debug & DRM_UT_STATE))
> > +			drm_atomic_print_state(state);
> > +
> > +		ret = drm_atomic_commit(state);
> > +	}
> > +
> > +out:
> > +	complete_signaling(dev, state, fence_state, num_fences, !ret);
> > +
> > +	if (ret == -EDEADLK) {
> > +		drm_atomic_state_clear(state);
> > +		ret = drm_modeset_backoff(&ctx);
> > +		if (!ret)
> > +			goto retry;
> > +	}
> > +
> > +	drm_atomic_state_put(state);
> > +
> > +	drm_modeset_drop_locks(&ctx);
> > +	drm_modeset_acquire_fini(&ctx);
> > +
> > +	return ret;
> > +}
> > diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> > index 5a84c3bc915d..ce75e9506e85 100644
> > --- a/drivers/gpu/drm/drm_crtc_helper.c
> > +++ b/drivers/gpu/drm/drm_crtc_helper.c
> > @@ -35,6 +35,7 @@
> >  
> >  #include <drm/drmP.h>
> >  #include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_encoder.h>
> >  #include <drm/drm_fourcc.h>
> > diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> > index ff5e0d521c21..ede20b55d50c 100644
> > --- a/drivers/gpu/drm/drm_crtc_internal.h
> > +++ b/drivers/gpu/drm/drm_crtc_internal.h
> > @@ -204,6 +204,9 @@ struct drm_minor;
> >  int drm_atomic_debugfs_init(struct drm_minor *minor);
> >  #endif
> >  
> > +void drm_atomic_print_state(const struct drm_atomic_state *state);
> > +
> > +/* drm_atomic_uapi.c */
> >  int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
> >  				     struct drm_connector *connector,
> >  				     int mode);
> > @@ -213,6 +216,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
> >  			    uint64_t prop_value);
> >  int drm_atomic_get_property(struct drm_mode_object *obj,
> >  			    struct drm_property *property, uint64_t *val);
> > +
> > +/* IOCTL */
> >  int drm_mode_atomic_ioctl(struct drm_device *dev,
> >  			  void *data, struct drm_file *file_priv);
> >  
> > diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> > index 781af1d42d76..7ca8c77223cb 100644
> > --- a/drivers/gpu/drm/drm_framebuffer.c
> > +++ b/drivers/gpu/drm/drm_framebuffer.c
> > @@ -25,6 +25,7 @@
> >  #include <drm/drm_auth.h>
> >  #include <drm/drm_framebuffer.h>
> >  #include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <drm/drm_print.h>
> >  
> >  #include "drm_internal.h"
> > diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> > index 2810d4131411..7607f9cd6f77 100644
> > --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> > +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
> > @@ -16,6 +16,7 @@
> >  
> >  #include <drm/drmP.h>
> >  #include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_fourcc.h>
> >  #include <drm/drm_framebuffer.h>
> > diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> > index 621f17643bb0..a393756b664e 100644
> > --- a/drivers/gpu/drm/drm_plane_helper.c
> > +++ b/drivers/gpu/drm/drm_plane_helper.c
> > @@ -28,6 +28,7 @@
> >  #include <drm/drm_plane_helper.h>
> >  #include <drm/drm_rect.h>
> >  #include <drm/drm_atomic.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_encoder.h>
> >  #include <drm/drm_atomic_helper.h>
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index a85a83f31979..85cad16f31ed 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -46,6 +46,7 @@
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_plane_helper.h>
> >  #include <drm/drm_rect.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <linux/dma_remapping.h>
> >  #include <linux/reservation.h>
> >  
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> > index c1f1779c980f..4bcdeca7479d 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -15,6 +15,8 @@
> >   * this program.  If not, see <http://www.gnu.org/licenses/>.
> >   */
> >  
> > +#include <drm/drm_atomic_uapi.h>
> > +
> >  #include "msm_drv.h"
> >  #include "msm_gem.h"
> >  #include "msm_kms.h"
> > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > index 0e6a121858d1..3ce136ba8791 100644
> > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > @@ -35,6 +35,7 @@
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  #include <linux/clk.h>
> >  #include <drm/drm_fb_cma_helper.h>
> >  #include <linux/component.h>
> > diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> > index 6c6d37aa512a..9dc3fcbd290b 100644
> > --- a/drivers/gpu/drm/vc4/vc4_plane.c
> > +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> > @@ -22,6 +22,7 @@
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_fb_cma_helper.h>
> >  #include <drm/drm_plane_helper.h>
> > +#include <drm/drm_atomic_uapi.h>
> >  
> >  #include "uapi/drm/vc4_drm.h"
> >  #include "vc4_drv.h"
> > diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> > index 66e49ef7d3b5..4aff40886acb 100644
> > --- a/include/drm/drm_atomic.h
> > +++ b/include/drm/drm_atomic.h
> > @@ -584,22 +584,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
> >  	return plane->state;
> >  }
> >  
> > -int __must_check
> > -drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> > -			     const struct drm_display_mode *mode);
> > -int __must_check
> > -drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> > -				  struct drm_property_blob *blob);
> > -int __must_check
> > -drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> > -			      struct drm_crtc *crtc);
> > -void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> > -				 struct drm_framebuffer *fb);
> > -void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> > -				    struct dma_fence *fence);
> > -int __must_check
> > -drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> > -				  struct drm_crtc *crtc);
> >  int __must_check
> >  drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
> >  				   struct drm_crtc *crtc);
> > diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
> > new file mode 100644
> > index 000000000000..8cec52ad1277
> > --- /dev/null
> > +++ b/include/drm/drm_atomic_uapi.h
> > @@ -0,0 +1,58 @@
> > +/*
> > + * Copyright (C) 2014 Red Hat
> > + * Copyright (C) 2014 Intel Corp.
> > + * Copyright (C) 2018 Intel Corp.
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a
> > + * copy of this software and associated documentation files (the "Software"),
> > + * to deal in the Software without restriction, including without limitation
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > + * and/or sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> > + * OTHER DEALINGS IN THE SOFTWARE.
> > + *
> > + * Authors:
> > + * Rob Clark <robdclark@gmail.com>
> > + * Daniel Vetter <daniel.vetter@ffwll.ch>
> > + */
> > +
> > +#ifndef DRM_ATOMIC_UAPI_H_
> > +#define DRM_ATOMIC_UAPI_H_
> > +
> > +struct drm_crtc_state;
> > +struct drm_display_mode;
> > +struct drm_property_blob;
> > +struct drm_plane_state;
> > +struct drm_crtc;
> > +struct drm_connector_state;
> > +struct dma_fence;
> > +struct drm_framebuffer;
> > +
> > +int __must_check
> > +drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
> > +			     const struct drm_display_mode *mode);
> > +int __must_check
> > +drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
> > +				  struct drm_property_blob *blob);
> > +int __must_check
> > +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
> > +			      struct drm_crtc *crtc);
> > +void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
> > +				 struct drm_framebuffer *fb);
> > +void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
> > +				    struct dma_fence *fence);
> > +int __must_check
> > +drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
> > +				  struct drm_crtc *crtc);
> > +
> > +#endif
> > -- 
> > 2.18.0
> > 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH] drm: extract drm_atomic_uapi.c
       [not found]     ` <20180903165439.24845-6-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
@ 2018-09-05  8:00       ` Daniel Vetter
  0 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-05  8:00 UTC (permalink / raw)
  To: DRI Development
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Joonas Lahtinen, Maarten Lankhorst, Rob Clark, Jani Nikula,
	Eric Anholt, Rodrigo Vivi, Sean Paul, Gustavo Padovan,
	Daniel Vetter, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA

This leaves all the commit/check and state handling in drm_atomic.c,
while pulling all the uapi glue and the huge ioctl itself into a
seprate file.

This seems to almost perfectly split the rather big drm_atomic.c file
into 2 equal sizes.

Also adjust the kerneldoc and type a very terse overview text.

v2: Rebase.

v3: Fix tiny typo.

v4:
- Fixup armada, newly converted atomic driver hooray!
- Fixup msm/dpu1, newly added too.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 Documentation/gpu/drm-kms.rst                |   11 +-
 drivers/gpu/drm/Makefile                     |    3 +-
 drivers/gpu/drm/armada/armada_overlay.c      |    1 +
 drivers/gpu/drm/drm_atomic.c                 | 1359 +----------------
 drivers/gpu/drm/drm_atomic_helper.c          |    1 +
 drivers/gpu/drm/drm_atomic_uapi.c            | 1393 ++++++++++++++++++
 drivers/gpu/drm/drm_crtc_helper.c            |    1 +
 drivers/gpu/drm/drm_crtc_internal.h          |    5 +
 drivers/gpu/drm/drm_framebuffer.c            |    1 +
 drivers/gpu/drm/drm_gem_framebuffer_helper.c |    1 +
 drivers/gpu/drm/drm_plane_helper.c           |    1 +
 drivers/gpu/drm/i915/intel_display.c         |    1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c    |    2 +
 drivers/gpu/drm/msm/msm_atomic.c             |    2 +
 drivers/gpu/drm/vc4/vc4_crtc.c               |    1 +
 drivers/gpu/drm/vc4/vc4_plane.c              |    1 +
 include/drm/drm_atomic.h                     |   16 -
 include/drm/drm_atomic_uapi.h                |   58 +
 18 files changed, 1483 insertions(+), 1375 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_atomic_uapi.c
 create mode 100644 include/drm/drm_atomic_uapi.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 3a9dd68b97c9..4b1501b4835b 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -287,6 +287,15 @@ Atomic Mode Setting Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
    :export:
 
+Atomic Mode Setting IOCTL and UAPI Functions
+--------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
+   :doc: overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
+   :export:
+
 CRTC Abstraction
 ================
 
@@ -563,7 +572,7 @@ Tile Group Property
 Explicit Fencing Properties
 ---------------------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
+.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
    :doc: explicit fencing properties
 
 Existing KMS Properties
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a6771cef85e2..bc6a16a3c36e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -18,7 +18,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_encoder.o drm_mode_object.o drm_property.o \
 		drm_plane.o drm_color_mgmt.o drm_print.o \
 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
-		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
+		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
+		drm_atomic_uapi.o
 
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
 drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index eb7dfb65ef47..8d770641fcc4 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -8,6 +8,7 @@
  */
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/armada_drm.h>
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 29a4e6959358..19634e03b78e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -28,6 +28,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_print.h>
 #include <drm/drm_writeback.h>
@@ -309,285 +310,6 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 
-static void set_out_fence_for_crtc(struct drm_atomic_state *state,
-				   struct drm_crtc *crtc, s32 __user *fence_ptr)
-{
-	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
-}
-
-static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
-					  struct drm_crtc *crtc)
-{
-	s32 __user *fence_ptr;
-
-	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
-	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
-
-	return fence_ptr;
-}
-
-static int set_out_fence_for_connector(struct drm_atomic_state *state,
-					struct drm_connector *connector,
-					s32 __user *fence_ptr)
-{
-	unsigned int index = drm_connector_index(connector);
-
-	if (!fence_ptr)
-		return 0;
-
-	if (put_user(-1, fence_ptr))
-		return -EFAULT;
-
-	state->connectors[index].out_fence_ptr = fence_ptr;
-
-	return 0;
-}
-
-static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
-					       struct drm_connector *connector)
-{
-	unsigned int index = drm_connector_index(connector);
-	s32 __user *fence_ptr;
-
-	fence_ptr = state->connectors[index].out_fence_ptr;
-	state->connectors[index].out_fence_ptr = NULL;
-
-	return fence_ptr;
-}
-
-/**
- * drm_atomic_set_mode_for_crtc - set mode for CRTC
- * @state: the CRTC whose incoming state to update
- * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
- *
- * Set a mode (originating from the kernel) on the desired CRTC state and update
- * the enable property.
- *
- * RETURNS:
- * Zero on success, error code on failure. Cannot return -EDEADLK.
- */
-int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
-				 const struct drm_display_mode *mode)
-{
-	struct drm_crtc *crtc = state->crtc;
-	struct drm_mode_modeinfo umode;
-
-	/* Early return for no change. */
-	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
-		return 0;
-
-	drm_property_blob_put(state->mode_blob);
-	state->mode_blob = NULL;
-
-	if (mode) {
-		drm_mode_convert_to_umode(&umode, mode);
-		state->mode_blob =
-			drm_property_create_blob(state->crtc->dev,
-		                                 sizeof(umode),
-		                                 &umode);
-		if (IS_ERR(state->mode_blob))
-			return PTR_ERR(state->mode_blob);
-
-		drm_mode_copy(&state->mode, mode);
-		state->enable = true;
-		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
-				 mode->name, crtc->base.id, crtc->name, state);
-	} else {
-		memset(&state->mode, 0, sizeof(state->mode));
-		state->enable = false;
-		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
-				 crtc->base.id, crtc->name, state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
-
-/**
- * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
- * @state: the CRTC whose incoming state to update
- * @blob: pointer to blob property to use for mode
- *
- * Set a mode (originating from a blob property) on the desired CRTC state.
- * This function will take a reference on the blob property for the CRTC state,
- * and release the reference held on the state's existing mode property, if any
- * was set.
- *
- * RETURNS:
- * Zero on success, error code on failure. Cannot return -EDEADLK.
- */
-int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
-                                      struct drm_property_blob *blob)
-{
-	struct drm_crtc *crtc = state->crtc;
-
-	if (blob == state->mode_blob)
-		return 0;
-
-	drm_property_blob_put(state->mode_blob);
-	state->mode_blob = NULL;
-
-	memset(&state->mode, 0, sizeof(state->mode));
-
-	if (blob) {
-		int ret;
-
-		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
-					 crtc->base.id, crtc->name,
-					 blob->length);
-			return -EINVAL;
-		}
-
-		ret = drm_mode_convert_umode(crtc->dev,
-					     &state->mode, blob->data);
-		if (ret) {
-			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
-					 crtc->base.id, crtc->name,
-					 ret, drm_get_mode_status_name(state->mode.status));
-			drm_mode_debug_printmodeline(&state->mode);
-			return -EINVAL;
-		}
-
-		state->mode_blob = drm_property_blob_get(blob);
-		state->enable = true;
-		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
-				 state->mode.name, crtc->base.id, crtc->name,
-				 state);
-	} else {
-		state->enable = false;
-		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
-				 crtc->base.id, crtc->name, state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
-
-static int
-drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
-					 struct drm_property_blob **blob,
-					 uint64_t blob_id,
-					 ssize_t expected_size,
-					 ssize_t expected_elem_size,
-					 bool *replaced)
-{
-	struct drm_property_blob *new_blob = NULL;
-
-	if (blob_id != 0) {
-		new_blob = drm_property_lookup_blob(dev, blob_id);
-		if (new_blob == NULL)
-			return -EINVAL;
-
-		if (expected_size > 0 &&
-		    new_blob->length != expected_size) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-		if (expected_elem_size > 0 &&
-		    new_blob->length % expected_elem_size != 0) {
-			drm_property_blob_put(new_blob);
-			return -EINVAL;
-		}
-	}
-
-	*replaced |= drm_property_replace_blob(blob, new_blob);
-	drm_property_blob_put(new_blob);
-
-	return 0;
-}
-
-static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
-		struct drm_crtc_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-	bool replaced = false;
-	int ret;
-
-	if (property == config->prop_active)
-		state->active = val;
-	else if (property == config->prop_mode_id) {
-		struct drm_property_blob *mode =
-			drm_property_lookup_blob(dev, val);
-		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
-		drm_property_blob_put(mode);
-		return ret;
-	} else if (property == config->degamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->degamma_lut,
-					val,
-					-1, sizeof(struct drm_color_lut),
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->ctm_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->ctm,
-					val,
-					sizeof(struct drm_color_ctm), -1,
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->gamma_lut_property) {
-		ret = drm_atomic_replace_property_blob_from_id(dev,
-					&state->gamma_lut,
-					val,
-					-1, sizeof(struct drm_color_lut),
-					&replaced);
-		state->color_mgmt_changed |= replaced;
-		return ret;
-	} else if (property == config->prop_out_fence_ptr) {
-		s32 __user *fence_ptr = u64_to_user_ptr(val);
-
-		if (!fence_ptr)
-			return 0;
-
-		if (put_user(-1, fence_ptr))
-			return -EFAULT;
-
-		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
-	} else if (crtc->funcs->atomic_set_property) {
-		return crtc->funcs->atomic_set_property(crtc, state, property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 crtc->base.id, crtc->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-drm_atomic_crtc_get_property(struct drm_crtc *crtc,
-		const struct drm_crtc_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_active)
-		*val = state->active;
-	else if (property == config->prop_mode_id)
-		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
-	else if (property == config->degamma_lut_property)
-		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
-	else if (property == config->ctm_property)
-		*val = (state->ctm) ? state->ctm->base.id : 0;
-	else if (property == config->gamma_lut_property)
-		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
-	else if (property == config->prop_out_fence_ptr)
-		*val = 0;
-	else if (crtc->funcs->atomic_get_property)
-		return crtc->funcs->atomic_get_property(crtc, state, property, val);
-	else
-		return -EINVAL;
-
-	return 0;
-}
-
 static int drm_atomic_crtc_check(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
@@ -761,144 +483,6 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
-/**
- * drm_atomic_plane_set_property - set property on plane
- * @plane: the drm plane to set a property on
- * @state: the state object to update with the new property value
- * @property: the property to set
- * @val: the new property value
- *
- * This function handles generic/core properties and calls out to driver's
- * &drm_plane_funcs.atomic_set_property for driver properties.  To ensure
- * consistent behavior you must call this function rather than the driver hook
- * directly.
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
-static int drm_atomic_plane_set_property(struct drm_plane *plane,
-		struct drm_plane_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = plane->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_fb_id) {
-		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
-		drm_atomic_set_fb_for_plane(state, fb);
-		if (fb)
-			drm_framebuffer_put(fb);
-	} else if (property == config->prop_in_fence_fd) {
-		if (state->fence)
-			return -EINVAL;
-
-		if (U642I64(val) == -1)
-			return 0;
-
-		state->fence = sync_file_get_fence(val);
-		if (!state->fence)
-			return -EINVAL;
-
-	} else if (property == config->prop_crtc_id) {
-		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
-		return drm_atomic_set_crtc_for_plane(state, crtc);
-	} else if (property == config->prop_crtc_x) {
-		state->crtc_x = U642I64(val);
-	} else if (property == config->prop_crtc_y) {
-		state->crtc_y = U642I64(val);
-	} else if (property == config->prop_crtc_w) {
-		state->crtc_w = val;
-	} else if (property == config->prop_crtc_h) {
-		state->crtc_h = val;
-	} else if (property == config->prop_src_x) {
-		state->src_x = val;
-	} else if (property == config->prop_src_y) {
-		state->src_y = val;
-	} else if (property == config->prop_src_w) {
-		state->src_w = val;
-	} else if (property == config->prop_src_h) {
-		state->src_h = val;
-	} else if (property == plane->alpha_property) {
-		state->alpha = val;
-	} else if (property == plane->blend_mode_property) {
-		state->pixel_blend_mode = val;
-	} else if (property == plane->rotation_property) {
-		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
-			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
-					 plane->base.id, plane->name, val);
-			return -EINVAL;
-		}
-		state->rotation = val;
-	} else if (property == plane->zpos_property) {
-		state->zpos = val;
-	} else if (property == plane->color_encoding_property) {
-		state->color_encoding = val;
-	} else if (property == plane->color_range_property) {
-		state->color_range = val;
-	} else if (plane->funcs->atomic_set_property) {
-		return plane->funcs->atomic_set_property(plane, state,
-				property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 plane->base.id, plane->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int
-drm_atomic_plane_get_property(struct drm_plane *plane,
-		const struct drm_plane_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = plane->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_fb_id) {
-		*val = (state->fb) ? state->fb->base.id : 0;
-	} else if (property == config->prop_in_fence_fd) {
-		*val = -1;
-	} else if (property == config->prop_crtc_id) {
-		*val = (state->crtc) ? state->crtc->base.id : 0;
-	} else if (property == config->prop_crtc_x) {
-		*val = I642U64(state->crtc_x);
-	} else if (property == config->prop_crtc_y) {
-		*val = I642U64(state->crtc_y);
-	} else if (property == config->prop_crtc_w) {
-		*val = state->crtc_w;
-	} else if (property == config->prop_crtc_h) {
-		*val = state->crtc_h;
-	} else if (property == config->prop_src_x) {
-		*val = state->src_x;
-	} else if (property == config->prop_src_y) {
-		*val = state->src_y;
-	} else if (property == config->prop_src_w) {
-		*val = state->src_w;
-	} else if (property == config->prop_src_h) {
-		*val = state->src_h;
-	} else if (property == plane->alpha_property) {
-		*val = state->alpha;
-	} else if (property == plane->blend_mode_property) {
-		*val = state->pixel_blend_mode;
-	} else if (property == plane->rotation_property) {
-		*val = state->rotation;
-	} else if (property == plane->zpos_property) {
-		*val = state->zpos;
-	} else if (property == plane->color_encoding_property) {
-		*val = state->color_encoding;
-	} else if (property == plane->color_range_property) {
-		*val = state->color_range;
-	} else if (plane->funcs->atomic_get_property) {
-		return plane->funcs->atomic_get_property(plane, state, property, val);
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static bool
 plane_switching_crtc(struct drm_atomic_state *state,
 		     struct drm_plane *plane,
@@ -1238,129 +822,6 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_connector_state);
 
-static struct drm_writeback_job *
-drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
-{
-	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
-
-	if (!conn_state->writeback_job)
-		conn_state->writeback_job =
-			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
-
-	return conn_state->writeback_job;
-}
-
-static int drm_atomic_set_writeback_fb_for_connector(
-		struct drm_connector_state *conn_state,
-		struct drm_framebuffer *fb)
-{
-	struct drm_writeback_job *job =
-		drm_atomic_get_writeback_job(conn_state);
-	if (!job)
-		return -ENOMEM;
-
-	drm_framebuffer_assign(&job->fb, fb);
-
-	if (fb)
-		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
-				 fb->base.id, conn_state);
-	else
-		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
-				 conn_state);
-
-	return 0;
-}
-
-static int drm_atomic_connector_set_property(struct drm_connector *connector,
-		struct drm_connector_state *state, struct drm_property *property,
-		uint64_t val)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_crtc_id) {
-		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
-		return drm_atomic_set_crtc_for_connector(state, crtc);
-	} else if (property == config->dpms_property) {
-		/* setting DPMS property requires special handling, which
-		 * is done in legacy setprop path for us.  Disallow (for
-		 * now?) atomic writes to DPMS property:
-		 */
-		return -EINVAL;
-	} else if (property == config->tv_select_subconnector_property) {
-		state->tv.subconnector = val;
-	} else if (property == config->tv_left_margin_property) {
-		state->tv.margins.left = val;
-	} else if (property == config->tv_right_margin_property) {
-		state->tv.margins.right = val;
-	} else if (property == config->tv_top_margin_property) {
-		state->tv.margins.top = val;
-	} else if (property == config->tv_bottom_margin_property) {
-		state->tv.margins.bottom = val;
-	} else if (property == config->tv_mode_property) {
-		state->tv.mode = val;
-	} else if (property == config->tv_brightness_property) {
-		state->tv.brightness = val;
-	} else if (property == config->tv_contrast_property) {
-		state->tv.contrast = val;
-	} else if (property == config->tv_flicker_reduction_property) {
-		state->tv.flicker_reduction = val;
-	} else if (property == config->tv_overscan_property) {
-		state->tv.overscan = val;
-	} else if (property == config->tv_saturation_property) {
-		state->tv.saturation = val;
-	} else if (property == config->tv_hue_property) {
-		state->tv.hue = val;
-	} else if (property == config->link_status_property) {
-		/* Never downgrade from GOOD to BAD on userspace's request here,
-		 * only hw issues can do that.
-		 *
-		 * For an atomic property the userspace doesn't need to be able
-		 * to understand all the properties, but needs to be able to
-		 * restore the state it wants on VT switch. So if the userspace
-		 * tries to change the link_status from GOOD to BAD, driver
-		 * silently rejects it and returns a 0. This prevents userspace
-		 * from accidently breaking  the display when it restores the
-		 * state.
-		 */
-		if (state->link_status != DRM_LINK_STATUS_GOOD)
-			state->link_status = val;
-	} else if (property == config->aspect_ratio_property) {
-		state->picture_aspect_ratio = val;
-	} else if (property == config->content_type_property) {
-		state->content_type = val;
-	} else if (property == connector->scaling_mode_property) {
-		state->scaling_mode = val;
-	} else if (property == connector->content_protection_property) {
-		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
-			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
-			return -EINVAL;
-		}
-		state->content_protection = val;
-	} else if (property == config->writeback_fb_id_property) {
-		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
-		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
-		if (fb)
-			drm_framebuffer_put(fb);
-		return ret;
-	} else if (property == config->writeback_out_fence_ptr_property) {
-		s32 __user *fence_ptr = u64_to_user_ptr(val);
-
-		return set_out_fence_for_connector(state->state, connector,
-						   fence_ptr);
-	} else if (connector->funcs->atomic_set_property) {
-		return connector->funcs->atomic_set_property(connector,
-				state, property, val);
-	} else {
-		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
-				 connector->base.id, connector->name,
-				 property->base.id, property->name);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static void drm_atomic_connector_print_state(struct drm_printer *p,
 		const struct drm_connector_state *state)
 {
@@ -1377,281 +838,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
 		connector->funcs->atomic_print_state(p, state);
 }
 
-static int
-drm_atomic_connector_get_property(struct drm_connector *connector,
-		const struct drm_connector_state *state,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_mode_config *config = &dev->mode_config;
-
-	if (property == config->prop_crtc_id) {
-		*val = (state->crtc) ? state->crtc->base.id : 0;
-	} else if (property == config->dpms_property) {
-		*val = connector->dpms;
-	} else if (property == config->tv_select_subconnector_property) {
-		*val = state->tv.subconnector;
-	} else if (property == config->tv_left_margin_property) {
-		*val = state->tv.margins.left;
-	} else if (property == config->tv_right_margin_property) {
-		*val = state->tv.margins.right;
-	} else if (property == config->tv_top_margin_property) {
-		*val = state->tv.margins.top;
-	} else if (property == config->tv_bottom_margin_property) {
-		*val = state->tv.margins.bottom;
-	} else if (property == config->tv_mode_property) {
-		*val = state->tv.mode;
-	} else if (property == config->tv_brightness_property) {
-		*val = state->tv.brightness;
-	} else if (property == config->tv_contrast_property) {
-		*val = state->tv.contrast;
-	} else if (property == config->tv_flicker_reduction_property) {
-		*val = state->tv.flicker_reduction;
-	} else if (property == config->tv_overscan_property) {
-		*val = state->tv.overscan;
-	} else if (property == config->tv_saturation_property) {
-		*val = state->tv.saturation;
-	} else if (property == config->tv_hue_property) {
-		*val = state->tv.hue;
-	} else if (property == config->link_status_property) {
-		*val = state->link_status;
-	} else if (property == config->aspect_ratio_property) {
-		*val = state->picture_aspect_ratio;
-	} else if (property == config->content_type_property) {
-		*val = state->content_type;
-	} else if (property == connector->scaling_mode_property) {
-		*val = state->scaling_mode;
-	} else if (property == connector->content_protection_property) {
-		*val = state->content_protection;
-	} else if (property == config->writeback_fb_id_property) {
-		/* Writeback framebuffer is one-shot, write and forget */
-		*val = 0;
-	} else if (property == config->writeback_out_fence_ptr_property) {
-		*val = 0;
-	} else if (connector->funcs->atomic_get_property) {
-		return connector->funcs->atomic_get_property(connector,
-				state, property, val);
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int drm_atomic_get_property(struct drm_mode_object *obj,
-		struct drm_property *property, uint64_t *val)
-{
-	struct drm_device *dev = property->dev;
-	int ret;
-
-	switch (obj->type) {
-	case DRM_MODE_OBJECT_CONNECTOR: {
-		struct drm_connector *connector = obj_to_connector(obj);
-		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
-		ret = drm_atomic_connector_get_property(connector,
-				connector->state, property, val);
-		break;
-	}
-	case DRM_MODE_OBJECT_CRTC: {
-		struct drm_crtc *crtc = obj_to_crtc(obj);
-		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-		ret = drm_atomic_crtc_get_property(crtc,
-				crtc->state, property, val);
-		break;
-	}
-	case DRM_MODE_OBJECT_PLANE: {
-		struct drm_plane *plane = obj_to_plane(obj);
-		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
-		ret = drm_atomic_plane_get_property(plane,
-				plane->state, property, val);
-		break;
-	}
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-/**
- * drm_atomic_set_crtc_for_plane - set crtc for plane
- * @plane_state: the plane whose incoming state to update
- * @crtc: crtc to use for the plane
- *
- * Changing the assigned crtc for a plane requires us to grab the lock and state
- * for the new crtc, as needed. This function takes care of all these details
- * besides updating the pointer in the state object itself.
- *
- * Returns:
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
- * then the w/w mutex code has detected a deadlock and the entire atomic
- * sequence must be restarted. All other errors are fatal.
- */
-int
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
-			      struct drm_crtc *crtc)
-{
-	struct drm_plane *plane = plane_state->plane;
-	struct drm_crtc_state *crtc_state;
-	/* Nothing to do for same crtc*/
-	if (plane_state->crtc == crtc)
-		return 0;
-	if (plane_state->crtc) {
-		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
-						       plane_state->crtc);
-		if (WARN_ON(IS_ERR(crtc_state)))
-			return PTR_ERR(crtc_state);
-
-		crtc_state->plane_mask &= ~drm_plane_mask(plane);
-	}
-
-	plane_state->crtc = crtc;
-
-	if (crtc) {
-		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
-						       crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-		crtc_state->plane_mask |= drm_plane_mask(plane);
-	}
-
-	if (crtc)
-		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
-				 plane->base.id, plane->name, plane_state,
-				 crtc->base.id, crtc->name);
-	else
-		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
-				 plane->base.id, plane->name, plane_state);
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
-
-/**
- * drm_atomic_set_fb_for_plane - set framebuffer for plane
- * @plane_state: atomic state object for the plane
- * @fb: fb to use for the plane
- *
- * Changing the assigned framebuffer for a plane requires us to grab a reference
- * to the new fb and drop the reference to the old fb, if there is one. This
- * function takes care of all these details besides updating the pointer in the
- * state object itself.
- */
-void
-drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
-			    struct drm_framebuffer *fb)
-{
-	struct drm_plane *plane = plane_state->plane;
-
-	if (fb)
-		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
-				 fb->base.id, plane->base.id, plane->name,
-				 plane_state);
-	else
-		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
-				 plane->base.id, plane->name, plane_state);
-
-	drm_framebuffer_assign(&plane_state->fb, fb);
-}
-EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
-
-/**
- * drm_atomic_set_fence_for_plane - set fence for plane
- * @plane_state: atomic state object for the plane
- * @fence: dma_fence to use for the plane
- *
- * Helper to setup the plane_state fence in case it is not set yet.
- * By using this drivers doesn't need to worry if the user choose
- * implicit or explicit fencing.
- *
- * This function will not set the fence to the state if it was set
- * via explicit fencing interfaces on the atomic ioctl. In that case it will
- * drop the reference to the fence as we are not storing it anywhere.
- * Otherwise, if &drm_plane_state.fence is not set this function we just set it
- * with the received implicit fence. In both cases this function consumes a
- * reference for @fence.
- *
- * This way explicit fencing can be used to overrule implicit fencing, which is
- * important to make explicit fencing use-cases work: One example is using one
- * buffer for 2 screens with different refresh rates. Implicit fencing will
- * clamp rendering to the refresh rate of the slower screen, whereas explicit
- * fence allows 2 independent render and display loops on a single buffer. If a
- * driver allows obeys both implicit and explicit fences for plane updates, then
- * it will break all the benefits of explicit fencing.
- */
-void
-drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
-			       struct dma_fence *fence)
-{
-	if (plane_state->fence) {
-		dma_fence_put(fence);
-		return;
-	}
-
-	plane_state->fence = fence;
-}
-EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
-
-/**
- * drm_atomic_set_crtc_for_connector - set crtc for connector
- * @conn_state: atomic state object for the connector
- * @crtc: crtc to use for the connector
- *
- * Changing the assigned crtc for a connector requires us to grab the lock and
- * state for the new crtc, as needed. This function takes care of all these
- * details besides updating the pointer in the state object itself.
- *
- * Returns:
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
- * then the w/w mutex code has detected a deadlock and the entire atomic
- * sequence must be restarted. All other errors are fatal.
- */
-int
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
-				  struct drm_crtc *crtc)
-{
-	struct drm_connector *connector = conn_state->connector;
-	struct drm_crtc_state *crtc_state;
-
-	if (conn_state->crtc == crtc)
-		return 0;
-
-	if (conn_state->crtc) {
-		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
-							   conn_state->crtc);
-
-		crtc_state->connector_mask &=
-			~drm_connector_mask(conn_state->connector);
-
-		drm_connector_put(conn_state->connector);
-		conn_state->crtc = NULL;
-	}
-
-	if (crtc) {
-		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
-		if (IS_ERR(crtc_state))
-			return PTR_ERR(crtc_state);
-
-		crtc_state->connector_mask |=
-			drm_connector_mask(conn_state->connector);
-
-		drm_connector_get(conn_state->connector);
-		conn_state->crtc = crtc;
-
-		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
-				 connector->base.id, connector->name,
-				 conn_state, crtc->base.id, crtc->name);
-	} else {
-		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
-				 connector->base.id, connector->name,
-				 conn_state);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
-
 /**
  * drm_atomic_add_affected_connectors - add connectors for crtc
  * @state: atomic state
@@ -1916,7 +1102,7 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
 }
 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
-static void drm_atomic_print_state(const struct drm_atomic_state *state)
+void drm_atomic_print_state(const struct drm_atomic_state *state)
 {
 	struct drm_printer p = drm_info_printer(state->dev->dev);
 	struct drm_plane *plane;
@@ -2023,544 +1209,3 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
 }
 #endif
 
-/*
- * The big monster ioctl
- */
-
-static struct drm_pending_vblank_event *create_vblank_event(
-		struct drm_crtc *crtc, uint64_t user_data)
-{
-	struct drm_pending_vblank_event *e = NULL;
-
-	e = kzalloc(sizeof *e, GFP_KERNEL);
-	if (!e)
-		return NULL;
-
-	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
-	e->event.base.length = sizeof(e->event);
-	e->event.vbl.crtc_id = crtc->base.id;
-	e->event.vbl.user_data = user_data;
-
-	return e;
-}
-
-int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
-				     struct drm_connector *connector,
-				     int mode)
-{
-	struct drm_connector *tmp_connector;
-	struct drm_connector_state *new_conn_state;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int i, ret, old_mode = connector->dpms;
-	bool active = false;
-
-	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
-			       state->acquire_ctx);
-	if (ret)
-		return ret;
-
-	if (mode != DRM_MODE_DPMS_ON)
-		mode = DRM_MODE_DPMS_OFF;
-	connector->dpms = mode;
-
-	crtc = connector->state->crtc;
-	if (!crtc)
-		goto out;
-	ret = drm_atomic_add_affected_connectors(state, crtc);
-	if (ret)
-		goto out;
-
-	crtc_state = drm_atomic_get_crtc_state(state, crtc);
-	if (IS_ERR(crtc_state)) {
-		ret = PTR_ERR(crtc_state);
-		goto out;
-	}
-
-	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
-		if (new_conn_state->crtc != crtc)
-			continue;
-		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
-			active = true;
-			break;
-		}
-	}
-
-	crtc_state->active = active;
-	ret = drm_atomic_commit(state);
-out:
-	if (ret != 0)
-		connector->dpms = old_mode;
-	return ret;
-}
-
-int drm_atomic_set_property(struct drm_atomic_state *state,
-			    struct drm_mode_object *obj,
-			    struct drm_property *prop,
-			    uint64_t prop_value)
-{
-	struct drm_mode_object *ref;
-	int ret;
-
-	if (!drm_property_change_valid_get(prop, prop_value, &ref))
-		return -EINVAL;
-
-	switch (obj->type) {
-	case DRM_MODE_OBJECT_CONNECTOR: {
-		struct drm_connector *connector = obj_to_connector(obj);
-		struct drm_connector_state *connector_state;
-
-		connector_state = drm_atomic_get_connector_state(state, connector);
-		if (IS_ERR(connector_state)) {
-			ret = PTR_ERR(connector_state);
-			break;
-		}
-
-		ret = drm_atomic_connector_set_property(connector,
-				connector_state, prop, prop_value);
-		break;
-	}
-	case DRM_MODE_OBJECT_CRTC: {
-		struct drm_crtc *crtc = obj_to_crtc(obj);
-		struct drm_crtc_state *crtc_state;
-
-		crtc_state = drm_atomic_get_crtc_state(state, crtc);
-		if (IS_ERR(crtc_state)) {
-			ret = PTR_ERR(crtc_state);
-			break;
-		}
-
-		ret = drm_atomic_crtc_set_property(crtc,
-				crtc_state, prop, prop_value);
-		break;
-	}
-	case DRM_MODE_OBJECT_PLANE: {
-		struct drm_plane *plane = obj_to_plane(obj);
-		struct drm_plane_state *plane_state;
-
-		plane_state = drm_atomic_get_plane_state(state, plane);
-		if (IS_ERR(plane_state)) {
-			ret = PTR_ERR(plane_state);
-			break;
-		}
-
-		ret = drm_atomic_plane_set_property(plane,
-				plane_state, prop, prop_value);
-		break;
-	}
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	drm_property_change_valid_put(prop, ref);
-	return ret;
-}
-
-/**
- * DOC: explicit fencing properties
- *
- * Explicit fencing allows userspace to control the buffer synchronization
- * between devices. A Fence or a group of fences are transfered to/from
- * userspace using Sync File fds and there are two DRM properties for that.
- * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
- * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
- *
- * As a contrast, with implicit fencing the kernel keeps track of any
- * ongoing rendering, and automatically ensures that the atomic update waits
- * for any pending rendering to complete. For shared buffers represented with
- * a &struct dma_buf this is tracked in &struct reservation_object.
- * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
- * whereas explicit fencing is what Android wants.
- *
- * "IN_FENCE_FD”:
- *	Use this property to pass a fence that DRM should wait on before
- *	proceeding with the Atomic Commit request and show the framebuffer for
- *	the plane on the screen. The fence can be either a normal fence or a
- *	merged one, the sync_file framework will handle both cases and use a
- *	fence_array if a merged fence is received. Passing -1 here means no
- *	fences to wait on.
- *
- *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
- *	it will only check if the Sync File is a valid one.
- *
- *	On the driver side the fence is stored on the @fence parameter of
- *	&struct drm_plane_state. Drivers which also support implicit fencing
- *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
- *	to make sure there's consistent behaviour between drivers in precedence
- *	of implicit vs. explicit fencing.
- *
- * "OUT_FENCE_PTR”:
- *	Use this property to pass a file descriptor pointer to DRM. Once the
- *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
- *	the file descriptor number of a Sync File. This Sync File contains the
- *	CRTC fence that will be signaled when all framebuffers present on the
- *	Atomic Commit * request for that given CRTC are scanned out on the
- *	screen.
- *
- *	The Atomic Commit request fails if a invalid pointer is passed. If the
- *	Atomic Commit request fails for any other reason the out fence fd
- *	returned will be -1. On a Atomic Commit with the
- *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
- *
- *	Note that out-fences don't have a special interface to drivers and are
- *	internally represented by a &struct drm_pending_vblank_event in struct
- *	&drm_crtc_state, which is also used by the nonblocking atomic commit
- *	helpers and for the DRM event handling for existing userspace.
- */
-
-struct drm_out_fence_state {
-	s32 __user *out_fence_ptr;
-	struct sync_file *sync_file;
-	int fd;
-};
-
-static int setup_out_fence(struct drm_out_fence_state *fence_state,
-			   struct dma_fence *fence)
-{
-	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fence_state->fd < 0)
-		return fence_state->fd;
-
-	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
-		return -EFAULT;
-
-	fence_state->sync_file = sync_file_create(fence);
-	if (!fence_state->sync_file)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int prepare_signaling(struct drm_device *dev,
-				  struct drm_atomic_state *state,
-				  struct drm_mode_atomic *arg,
-				  struct drm_file *file_priv,
-				  struct drm_out_fence_state **fence_state,
-				  unsigned int *num_fences)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	struct drm_connector *conn;
-	struct drm_connector_state *conn_state;
-	int i, c = 0, ret;
-
-	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
-		return 0;
-
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		s32 __user *fence_ptr;
-
-		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
-
-		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
-			struct drm_pending_vblank_event *e;
-
-			e = create_vblank_event(crtc, arg->user_data);
-			if (!e)
-				return -ENOMEM;
-
-			crtc_state->event = e;
-		}
-
-		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-			struct drm_pending_vblank_event *e = crtc_state->event;
-
-			if (!file_priv)
-				continue;
-
-			ret = drm_event_reserve_init(dev, file_priv, &e->base,
-						     &e->event.base);
-			if (ret) {
-				kfree(e);
-				crtc_state->event = NULL;
-				return ret;
-			}
-		}
-
-		if (fence_ptr) {
-			struct dma_fence *fence;
-			struct drm_out_fence_state *f;
-
-			f = krealloc(*fence_state, sizeof(**fence_state) *
-				     (*num_fences + 1), GFP_KERNEL);
-			if (!f)
-				return -ENOMEM;
-
-			memset(&f[*num_fences], 0, sizeof(*f));
-
-			f[*num_fences].out_fence_ptr = fence_ptr;
-			*fence_state = f;
-
-			fence = drm_crtc_create_fence(crtc);
-			if (!fence)
-				return -ENOMEM;
-
-			ret = setup_out_fence(&f[(*num_fences)++], fence);
-			if (ret) {
-				dma_fence_put(fence);
-				return ret;
-			}
-
-			crtc_state->event->base.fence = fence;
-		}
-
-		c++;
-	}
-
-	for_each_new_connector_in_state(state, conn, conn_state, i) {
-		struct drm_writeback_connector *wb_conn;
-		struct drm_writeback_job *job;
-		struct drm_out_fence_state *f;
-		struct dma_fence *fence;
-		s32 __user *fence_ptr;
-
-		fence_ptr = get_out_fence_for_connector(state, conn);
-		if (!fence_ptr)
-			continue;
-
-		job = drm_atomic_get_writeback_job(conn_state);
-		if (!job)
-			return -ENOMEM;
-
-		f = krealloc(*fence_state, sizeof(**fence_state) *
-			     (*num_fences + 1), GFP_KERNEL);
-		if (!f)
-			return -ENOMEM;
-
-		memset(&f[*num_fences], 0, sizeof(*f));
-
-		f[*num_fences].out_fence_ptr = fence_ptr;
-		*fence_state = f;
-
-		wb_conn = drm_connector_to_writeback(conn);
-		fence = drm_writeback_get_out_fence(wb_conn);
-		if (!fence)
-			return -ENOMEM;
-
-		ret = setup_out_fence(&f[(*num_fences)++], fence);
-		if (ret) {
-			dma_fence_put(fence);
-			return ret;
-		}
-
-		job->out_fence = fence;
-	}
-
-	/*
-	 * Having this flag means user mode pends on event which will never
-	 * reach due to lack of at least one CRTC for signaling
-	 */
-	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
-		return -EINVAL;
-
-	return 0;
-}
-
-static void complete_signaling(struct drm_device *dev,
-			       struct drm_atomic_state *state,
-			       struct drm_out_fence_state *fence_state,
-			       unsigned int num_fences,
-			       bool install_fds)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	int i;
-
-	if (install_fds) {
-		for (i = 0; i < num_fences; i++)
-			fd_install(fence_state[i].fd,
-				   fence_state[i].sync_file->file);
-
-		kfree(fence_state);
-		return;
-	}
-
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		struct drm_pending_vblank_event *event = crtc_state->event;
-		/*
-		 * Free the allocated event. drm_atomic_helper_setup_commit
-		 * can allocate an event too, so only free it if it's ours
-		 * to prevent a double free in drm_atomic_state_clear.
-		 */
-		if (event && (event->base.fence || event->base.file_priv)) {
-			drm_event_cancel_free(dev, &event->base);
-			crtc_state->event = NULL;
-		}
-	}
-
-	if (!fence_state)
-		return;
-
-	for (i = 0; i < num_fences; i++) {
-		if (fence_state[i].sync_file)
-			fput(fence_state[i].sync_file->file);
-		if (fence_state[i].fd >= 0)
-			put_unused_fd(fence_state[i].fd);
-
-		/* If this fails log error to the user */
-		if (fence_state[i].out_fence_ptr &&
-		    put_user(-1, fence_state[i].out_fence_ptr))
-			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
-	}
-
-	kfree(fence_state);
-}
-
-int drm_mode_atomic_ioctl(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_atomic *arg = data;
-	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
-	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
-	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
-	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
-	unsigned int copied_objs, copied_props;
-	struct drm_atomic_state *state;
-	struct drm_modeset_acquire_ctx ctx;
-	struct drm_out_fence_state *fence_state;
-	int ret = 0;
-	unsigned int i, j, num_fences;
-
-	/* disallow for drivers not supporting atomic: */
-	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
-		return -EINVAL;
-
-	/* disallow for userspace that has not enabled atomic cap (even
-	 * though this may be a bit overkill, since legacy userspace
-	 * wouldn't know how to call this ioctl)
-	 */
-	if (!file_priv->atomic)
-		return -EINVAL;
-
-	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
-		return -EINVAL;
-
-	if (arg->reserved)
-		return -EINVAL;
-
-	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
-			!dev->mode_config.async_page_flip)
-		return -EINVAL;
-
-	/* can't test and expect an event at the same time. */
-	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
-			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
-		return -EINVAL;
-
-	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
-
-	state = drm_atomic_state_alloc(dev);
-	if (!state)
-		return -ENOMEM;
-
-	state->acquire_ctx = &ctx;
-	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
-
-retry:
-	copied_objs = 0;
-	copied_props = 0;
-	fence_state = NULL;
-	num_fences = 0;
-
-	for (i = 0; i < arg->count_objs; i++) {
-		uint32_t obj_id, count_props;
-		struct drm_mode_object *obj;
-
-		if (get_user(obj_id, objs_ptr + copied_objs)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
-		if (!obj) {
-			ret = -ENOENT;
-			goto out;
-		}
-
-		if (!obj->properties) {
-			drm_mode_object_put(obj);
-			ret = -ENOENT;
-			goto out;
-		}
-
-		if (get_user(count_props, count_props_ptr + copied_objs)) {
-			drm_mode_object_put(obj);
-			ret = -EFAULT;
-			goto out;
-		}
-
-		copied_objs++;
-
-		for (j = 0; j < count_props; j++) {
-			uint32_t prop_id;
-			uint64_t prop_value;
-			struct drm_property *prop;
-
-			if (get_user(prop_id, props_ptr + copied_props)) {
-				drm_mode_object_put(obj);
-				ret = -EFAULT;
-				goto out;
-			}
-
-			prop = drm_mode_obj_find_prop_id(obj, prop_id);
-			if (!prop) {
-				drm_mode_object_put(obj);
-				ret = -ENOENT;
-				goto out;
-			}
-
-			if (copy_from_user(&prop_value,
-					   prop_values_ptr + copied_props,
-					   sizeof(prop_value))) {
-				drm_mode_object_put(obj);
-				ret = -EFAULT;
-				goto out;
-			}
-
-			ret = drm_atomic_set_property(state, obj, prop,
-						      prop_value);
-			if (ret) {
-				drm_mode_object_put(obj);
-				goto out;
-			}
-
-			copied_props++;
-		}
-
-		drm_mode_object_put(obj);
-	}
-
-	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
-				&num_fences);
-	if (ret)
-		goto out;
-
-	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
-		ret = drm_atomic_check_only(state);
-	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
-		ret = drm_atomic_nonblocking_commit(state);
-	} else {
-		if (unlikely(drm_debug & DRM_UT_STATE))
-			drm_atomic_print_state(state);
-
-		ret = drm_atomic_commit(state);
-	}
-
-out:
-	complete_signaling(dev, state, fence_state, num_fences, !ret);
-
-	if (ret == -EDEADLK) {
-		drm_atomic_state_clear(state);
-		ret = drm_modeset_backoff(&ctx);
-		if (!ret)
-			goto retry;
-	}
-
-	drm_atomic_state_put(state);
-
-	drm_modeset_drop_locks(&ctx);
-	drm_modeset_acquire_fini(&ctx);
-
-	return ret;
-}
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index daa04d29f8cc..8469a7e9afe3 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -27,6 +27,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
new file mode 100644
index 000000000000..26690a664ec6
--- /dev/null
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -0,0 +1,1393 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Copyright (C) 2014 Intel Corp.
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_print.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_writeback.h>
+#include <drm/drm_vblank.h>
+
+#include <linux/dma-fence.h>
+#include <linux/uaccess.h>
+#include <linux/sync_file.h>
+#include <linux/file.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * This file contains the marshalling and demarshalling glue for the atomic UAPI
+ * in all it's form: The monster ATOMIC IOCTL itself, code for GET_PROPERTY and
+ * SET_PROPERTY IOCTls. Plus interface functions for compatibility helpers and
+ * drivers which have special needs to construct their own atomic updates, e.g.
+ * for load detect or similiar.
+ */
+
+/**
+ * drm_atomic_set_mode_for_crtc - set mode for CRTC
+ * @state: the CRTC whose incoming state to update
+ * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
+ *
+ * Set a mode (originating from the kernel) on the desired CRTC state and update
+ * the enable property.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure. Cannot return -EDEADLK.
+ */
+int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
+				 const struct drm_display_mode *mode)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_mode_modeinfo umode;
+
+	/* Early return for no change. */
+	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
+		return 0;
+
+	drm_property_blob_put(state->mode_blob);
+	state->mode_blob = NULL;
+
+	if (mode) {
+		drm_mode_convert_to_umode(&umode, mode);
+		state->mode_blob =
+			drm_property_create_blob(state->crtc->dev,
+		                                 sizeof(umode),
+		                                 &umode);
+		if (IS_ERR(state->mode_blob))
+			return PTR_ERR(state->mode_blob);
+
+		drm_mode_copy(&state->mode, mode);
+		state->enable = true;
+		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+				 mode->name, crtc->base.id, crtc->name, state);
+	} else {
+		memset(&state->mode, 0, sizeof(state->mode));
+		state->enable = false;
+		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+				 crtc->base.id, crtc->name, state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
+
+/**
+ * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
+ * @state: the CRTC whose incoming state to update
+ * @blob: pointer to blob property to use for mode
+ *
+ * Set a mode (originating from a blob property) on the desired CRTC state.
+ * This function will take a reference on the blob property for the CRTC state,
+ * and release the reference held on the state's existing mode property, if any
+ * was set.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure. Cannot return -EDEADLK.
+ */
+int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
+                                      struct drm_property_blob *blob)
+{
+	struct drm_crtc *crtc = state->crtc;
+
+	if (blob == state->mode_blob)
+		return 0;
+
+	drm_property_blob_put(state->mode_blob);
+	state->mode_blob = NULL;
+
+	memset(&state->mode, 0, sizeof(state->mode));
+
+	if (blob) {
+		int ret;
+
+		if (blob->length != sizeof(struct drm_mode_modeinfo)) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] bad mode blob length: %zu\n",
+					 crtc->base.id, crtc->name,
+					 blob->length);
+			return -EINVAL;
+		}
+
+		ret = drm_mode_convert_umode(crtc->dev,
+					     &state->mode, blob->data);
+		if (ret) {
+			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n",
+					 crtc->base.id, crtc->name,
+					 ret, drm_get_mode_status_name(state->mode.status));
+			drm_mode_debug_printmodeline(&state->mode);
+			return -EINVAL;
+		}
+
+		state->mode_blob = drm_property_blob_get(blob);
+		state->enable = true;
+		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
+				 state->mode.name, crtc->base.id, crtc->name,
+				 state);
+	} else {
+		state->enable = false;
+		DRM_DEBUG_ATOMIC("Set [NOMODE] for [CRTC:%d:%s] state %p\n",
+				 crtc->base.id, crtc->name, state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
+
+/**
+ * drm_atomic_set_crtc_for_plane - set crtc for plane
+ * @plane_state: the plane whose incoming state to update
+ * @crtc: crtc to use for the plane
+ *
+ * Changing the assigned crtc for a plane requires us to grab the lock and state
+ * for the new crtc, as needed. This function takes care of all these details
+ * besides updating the pointer in the state object itself.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+			      struct drm_crtc *crtc)
+{
+	struct drm_plane *plane = plane_state->plane;
+	struct drm_crtc_state *crtc_state;
+	/* Nothing to do for same crtc*/
+	if (plane_state->crtc == crtc)
+		return 0;
+	if (plane_state->crtc) {
+		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
+						       plane_state->crtc);
+		if (WARN_ON(IS_ERR(crtc_state)))
+			return PTR_ERR(crtc_state);
+
+		crtc_state->plane_mask &= ~drm_plane_mask(plane);
+	}
+
+	plane_state->crtc = crtc;
+
+	if (crtc) {
+		crtc_state = drm_atomic_get_crtc_state(plane_state->state,
+						       crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+		crtc_state->plane_mask |= drm_plane_mask(plane);
+	}
+
+	if (crtc)
+		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [CRTC:%d:%s]\n",
+				 plane->base.id, plane->name, plane_state,
+				 crtc->base.id, crtc->name);
+	else
+		DRM_DEBUG_ATOMIC("Link [PLANE:%d:%s] state %p to [NOCRTC]\n",
+				 plane->base.id, plane->name, plane_state);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
+
+/**
+ * drm_atomic_set_fb_for_plane - set framebuffer for plane
+ * @plane_state: atomic state object for the plane
+ * @fb: fb to use for the plane
+ *
+ * Changing the assigned framebuffer for a plane requires us to grab a reference
+ * to the new fb and drop the reference to the old fb, if there is one. This
+ * function takes care of all these details besides updating the pointer in the
+ * state object itself.
+ */
+void
+drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
+			    struct drm_framebuffer *fb)
+{
+	struct drm_plane *plane = plane_state->plane;
+
+	if (fb)
+		DRM_DEBUG_ATOMIC("Set [FB:%d] for [PLANE:%d:%s] state %p\n",
+				 fb->base.id, plane->base.id, plane->name,
+				 plane_state);
+	else
+		DRM_DEBUG_ATOMIC("Set [NOFB] for [PLANE:%d:%s] state %p\n",
+				 plane->base.id, plane->name, plane_state);
+
+	drm_framebuffer_assign(&plane_state->fb, fb);
+}
+EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
+
+/**
+ * drm_atomic_set_fence_for_plane - set fence for plane
+ * @plane_state: atomic state object for the plane
+ * @fence: dma_fence to use for the plane
+ *
+ * Helper to setup the plane_state fence in case it is not set yet.
+ * By using this drivers doesn't need to worry if the user choose
+ * implicit or explicit fencing.
+ *
+ * This function will not set the fence to the state if it was set
+ * via explicit fencing interfaces on the atomic ioctl. In that case it will
+ * drop the reference to the fence as we are not storing it anywhere.
+ * Otherwise, if &drm_plane_state.fence is not set this function we just set it
+ * with the received implicit fence. In both cases this function consumes a
+ * reference for @fence.
+ *
+ * This way explicit fencing can be used to overrule implicit fencing, which is
+ * important to make explicit fencing use-cases work: One example is using one
+ * buffer for 2 screens with different refresh rates. Implicit fencing will
+ * clamp rendering to the refresh rate of the slower screen, whereas explicit
+ * fence allows 2 independent render and display loops on a single buffer. If a
+ * driver allows obeys both implicit and explicit fences for plane updates, then
+ * it will break all the benefits of explicit fencing.
+ */
+void
+drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+			       struct dma_fence *fence)
+{
+	if (plane_state->fence) {
+		dma_fence_put(fence);
+		return;
+	}
+
+	plane_state->fence = fence;
+}
+EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
+
+/**
+ * drm_atomic_set_crtc_for_connector - set crtc for connector
+ * @conn_state: atomic state object for the connector
+ * @crtc: crtc to use for the connector
+ *
+ * Changing the assigned crtc for a connector requires us to grab the lock and
+ * state for the new crtc, as needed. This function takes care of all these
+ * details besides updating the pointer in the state object itself.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
+				  struct drm_crtc *crtc)
+{
+	struct drm_connector *connector = conn_state->connector;
+	struct drm_crtc_state *crtc_state;
+
+	if (conn_state->crtc == crtc)
+		return 0;
+
+	if (conn_state->crtc) {
+		crtc_state = drm_atomic_get_new_crtc_state(conn_state->state,
+							   conn_state->crtc);
+
+		crtc_state->connector_mask &=
+			~drm_connector_mask(conn_state->connector);
+
+		drm_connector_put(conn_state->connector);
+		conn_state->crtc = NULL;
+	}
+
+	if (crtc) {
+		crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
+		if (IS_ERR(crtc_state))
+			return PTR_ERR(crtc_state);
+
+		crtc_state->connector_mask |=
+			drm_connector_mask(conn_state->connector);
+
+		drm_connector_get(conn_state->connector);
+		conn_state->crtc = crtc;
+
+		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [CRTC:%d:%s]\n",
+				 connector->base.id, connector->name,
+				 conn_state, crtc->base.id, crtc->name);
+	} else {
+		DRM_DEBUG_ATOMIC("Link [CONNECTOR:%d:%s] state %p to [NOCRTC]\n",
+				 connector->base.id, connector->name,
+				 conn_state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
+
+static void set_out_fence_for_crtc(struct drm_atomic_state *state,
+				   struct drm_crtc *crtc, s32 __user *fence_ptr)
+{
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
+}
+
+static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
+					  struct drm_crtc *crtc)
+{
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,
+					s32 __user *fence_ptr)
+{
+	unsigned int index = drm_connector_index(connector);
+
+	if (!fence_ptr)
+		return 0;
+
+	if (put_user(-1, fence_ptr))
+		return -EFAULT;
+
+	state->connectors[index].out_fence_ptr = fence_ptr;
+
+	return 0;
+}
+
+static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)
+{
+	unsigned int index = drm_connector_index(connector);
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->connectors[index].out_fence_ptr;
+	state->connectors[index].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int
+drm_atomic_replace_property_blob_from_id(struct drm_device *dev,
+					 struct drm_property_blob **blob,
+					 uint64_t blob_id,
+					 ssize_t expected_size,
+					 ssize_t expected_elem_size,
+					 bool *replaced)
+{
+	struct drm_property_blob *new_blob = NULL;
+
+	if (blob_id != 0) {
+		new_blob = drm_property_lookup_blob(dev, blob_id);
+		if (new_blob == NULL)
+			return -EINVAL;
+
+		if (expected_size > 0 &&
+		    new_blob->length != expected_size) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+		if (expected_elem_size > 0 &&
+		    new_blob->length % expected_elem_size != 0) {
+			drm_property_blob_put(new_blob);
+			return -EINVAL;
+		}
+	}
+
+	*replaced |= drm_property_replace_blob(blob, new_blob);
+	drm_property_blob_put(new_blob);
+
+	return 0;
+}
+
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
+		struct drm_crtc_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+	bool replaced = false;
+	int ret;
+
+	if (property == config->prop_active)
+		state->active = val;
+	else if (property == config->prop_mode_id) {
+		struct drm_property_blob *mode =
+			drm_property_lookup_blob(dev, val);
+		ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
+		drm_property_blob_put(mode);
+		return ret;
+	} else if (property == config->degamma_lut_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->degamma_lut,
+					val,
+					-1, sizeof(struct drm_color_lut),
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->ctm_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->ctm,
+					val,
+					sizeof(struct drm_color_ctm), -1,
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->gamma_lut_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->gamma_lut,
+					val,
+					-1, sizeof(struct drm_color_lut),
+					&replaced);
+		state->color_mgmt_changed |= replaced;
+		return ret;
+	} else if (property == config->prop_out_fence_ptr) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		if (!fence_ptr)
+			return 0;
+
+		if (put_user(-1, fence_ptr))
+			return -EFAULT;
+
+		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
+	} else if (crtc->funcs->atomic_set_property) {
+		return crtc->funcs->atomic_set_property(crtc, state, property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 crtc->base.id, crtc->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_crtc_get_property(struct drm_crtc *crtc,
+		const struct drm_crtc_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_active)
+		*val = state->active;
+	else if (property == config->prop_mode_id)
+		*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
+	else if (property == config->degamma_lut_property)
+		*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
+	else if (property == config->ctm_property)
+		*val = (state->ctm) ? state->ctm->base.id : 0;
+	else if (property == config->gamma_lut_property)
+		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
+	else if (property == config->prop_out_fence_ptr)
+		*val = 0;
+	else if (crtc->funcs->atomic_get_property)
+		return crtc->funcs->atomic_get_property(crtc, state, property, val);
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int drm_atomic_plane_set_property(struct drm_plane *plane,
+		struct drm_plane_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_fb_id) {
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		drm_atomic_set_fb_for_plane(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+	} else if (property == config->prop_in_fence_fd) {
+		if (state->fence)
+			return -EINVAL;
+
+		if (U642I64(val) == -1)
+			return 0;
+
+		state->fence = sync_file_get_fence(val);
+		if (!state->fence)
+			return -EINVAL;
+
+	} else if (property == config->prop_crtc_id) {
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_plane(state, crtc);
+	} else if (property == config->prop_crtc_x) {
+		state->crtc_x = U642I64(val);
+	} else if (property == config->prop_crtc_y) {
+		state->crtc_y = U642I64(val);
+	} else if (property == config->prop_crtc_w) {
+		state->crtc_w = val;
+	} else if (property == config->prop_crtc_h) {
+		state->crtc_h = val;
+	} else if (property == config->prop_src_x) {
+		state->src_x = val;
+	} else if (property == config->prop_src_y) {
+		state->src_y = val;
+	} else if (property == config->prop_src_w) {
+		state->src_w = val;
+	} else if (property == config->prop_src_h) {
+		state->src_h = val;
+	} else if (property == plane->alpha_property) {
+		state->alpha = val;
+	} else if (property == plane->blend_mode_property) {
+		state->pixel_blend_mode = val;
+	} else if (property == plane->rotation_property) {
+		if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) {
+			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] bad rotation bitmask: 0x%llx\n",
+					 plane->base.id, plane->name, val);
+			return -EINVAL;
+		}
+		state->rotation = val;
+	} else if (property == plane->zpos_property) {
+		state->zpos = val;
+	} else if (property == plane->color_encoding_property) {
+		state->color_encoding = val;
+	} else if (property == plane->color_range_property) {
+		state->color_range = val;
+	} else if (plane->funcs->atomic_set_property) {
+		return plane->funcs->atomic_set_property(plane, state,
+				property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 plane->base.id, plane->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_plane_get_property(struct drm_plane *plane,
+		const struct drm_plane_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_fb_id) {
+		*val = (state->fb) ? state->fb->base.id : 0;
+	} else if (property == config->prop_in_fence_fd) {
+		*val = -1;
+	} else if (property == config->prop_crtc_id) {
+		*val = (state->crtc) ? state->crtc->base.id : 0;
+	} else if (property == config->prop_crtc_x) {
+		*val = I642U64(state->crtc_x);
+	} else if (property == config->prop_crtc_y) {
+		*val = I642U64(state->crtc_y);
+	} else if (property == config->prop_crtc_w) {
+		*val = state->crtc_w;
+	} else if (property == config->prop_crtc_h) {
+		*val = state->crtc_h;
+	} else if (property == config->prop_src_x) {
+		*val = state->src_x;
+	} else if (property == config->prop_src_y) {
+		*val = state->src_y;
+	} else if (property == config->prop_src_w) {
+		*val = state->src_w;
+	} else if (property == config->prop_src_h) {
+		*val = state->src_h;
+	} else if (property == plane->alpha_property) {
+		*val = state->alpha;
+	} else if (property == plane->blend_mode_property) {
+		*val = state->pixel_blend_mode;
+	} else if (property == plane->rotation_property) {
+		*val = state->rotation;
+	} else if (property == plane->zpos_property) {
+		*val = state->zpos;
+	} else if (property == plane->color_encoding_property) {
+		*val = state->color_encoding;
+	} else if (property == plane->color_range_property) {
+		*val = state->color_range;
+	} else if (plane->funcs->atomic_get_property) {
+		return plane->funcs->atomic_get_property(plane, state, property, val);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct drm_writeback_job *
+drm_atomic_get_writeback_job(struct drm_connector_state *conn_state)
+{
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!conn_state->writeback_job)
+		conn_state->writeback_job =
+			kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL);
+
+	return conn_state->writeback_job;
+}
+
+static int drm_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	struct drm_writeback_job *job =
+		drm_atomic_get_writeback_job(conn_state);
+	if (!job)
+		return -ENOMEM;
+
+	drm_framebuffer_assign(&job->fb, fb);
+
+	if (fb)
+		DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n",
+				 fb->base.id, conn_state);
+	else
+		DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n",
+				 conn_state);
+
+	return 0;
+}
+
+static int drm_atomic_connector_set_property(struct drm_connector *connector,
+		struct drm_connector_state *state, struct drm_property *property,
+		uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_crtc_id) {
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_connector(state, crtc);
+	} else if (property == config->dpms_property) {
+		/* setting DPMS property requires special handling, which
+		 * is done in legacy setprop path for us.  Disallow (for
+		 * now?) atomic writes to DPMS property:
+		 */
+		return -EINVAL;
+	} else if (property == config->tv_select_subconnector_property) {
+		state->tv.subconnector = val;
+	} else if (property == config->tv_left_margin_property) {
+		state->tv.margins.left = val;
+	} else if (property == config->tv_right_margin_property) {
+		state->tv.margins.right = val;
+	} else if (property == config->tv_top_margin_property) {
+		state->tv.margins.top = val;
+	} else if (property == config->tv_bottom_margin_property) {
+		state->tv.margins.bottom = val;
+	} else if (property == config->tv_mode_property) {
+		state->tv.mode = val;
+	} else if (property == config->tv_brightness_property) {
+		state->tv.brightness = val;
+	} else if (property == config->tv_contrast_property) {
+		state->tv.contrast = val;
+	} else if (property == config->tv_flicker_reduction_property) {
+		state->tv.flicker_reduction = val;
+	} else if (property == config->tv_overscan_property) {
+		state->tv.overscan = val;
+	} else if (property == config->tv_saturation_property) {
+		state->tv.saturation = val;
+	} else if (property == config->tv_hue_property) {
+		state->tv.hue = val;
+	} else if (property == config->link_status_property) {
+		/* Never downgrade from GOOD to BAD on userspace's request here,
+		 * only hw issues can do that.
+		 *
+		 * For an atomic property the userspace doesn't need to be able
+		 * to understand all the properties, but needs to be able to
+		 * restore the state it wants on VT switch. So if the userspace
+		 * tries to change the link_status from GOOD to BAD, driver
+		 * silently rejects it and returns a 0. This prevents userspace
+		 * from accidently breaking  the display when it restores the
+		 * state.
+		 */
+		if (state->link_status != DRM_LINK_STATUS_GOOD)
+			state->link_status = val;
+	} else if (property == config->aspect_ratio_property) {
+		state->picture_aspect_ratio = val;
+	} else if (property == config->content_type_property) {
+		state->content_type = val;
+	} else if (property == connector->scaling_mode_property) {
+		state->scaling_mode = val;
+	} else if (property == connector->content_protection_property) {
+		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+			return -EINVAL;
+		}
+		state->content_protection = val;
+	} else if (property == config->writeback_fb_id_property) {
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+		return ret;
+	} else if (property == config->writeback_out_fence_ptr_property) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		return set_out_fence_for_connector(state->state, connector,
+						   fence_ptr);
+	} else if (connector->funcs->atomic_set_property) {
+		return connector->funcs->atomic_set_property(connector,
+				state, property, val);
+	} else {
+		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+				 connector->base.id, connector->name,
+				 property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+drm_atomic_connector_get_property(struct drm_connector *connector,
+		const struct drm_connector_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (property == config->prop_crtc_id) {
+		*val = (state->crtc) ? state->crtc->base.id : 0;
+	} else if (property == config->dpms_property) {
+		*val = connector->dpms;
+	} else if (property == config->tv_select_subconnector_property) {
+		*val = state->tv.subconnector;
+	} else if (property == config->tv_left_margin_property) {
+		*val = state->tv.margins.left;
+	} else if (property == config->tv_right_margin_property) {
+		*val = state->tv.margins.right;
+	} else if (property == config->tv_top_margin_property) {
+		*val = state->tv.margins.top;
+	} else if (property == config->tv_bottom_margin_property) {
+		*val = state->tv.margins.bottom;
+	} else if (property == config->tv_mode_property) {
+		*val = state->tv.mode;
+	} else if (property == config->tv_brightness_property) {
+		*val = state->tv.brightness;
+	} else if (property == config->tv_contrast_property) {
+		*val = state->tv.contrast;
+	} else if (property == config->tv_flicker_reduction_property) {
+		*val = state->tv.flicker_reduction;
+	} else if (property == config->tv_overscan_property) {
+		*val = state->tv.overscan;
+	} else if (property == config->tv_saturation_property) {
+		*val = state->tv.saturation;
+	} else if (property == config->tv_hue_property) {
+		*val = state->tv.hue;
+	} else if (property == config->link_status_property) {
+		*val = state->link_status;
+	} else if (property == config->aspect_ratio_property) {
+		*val = state->picture_aspect_ratio;
+	} else if (property == config->content_type_property) {
+		*val = state->content_type;
+	} else if (property == connector->scaling_mode_property) {
+		*val = state->scaling_mode;
+	} else if (property == connector->content_protection_property) {
+		*val = state->content_protection;
+	} else if (property == config->writeback_fb_id_property) {
+		/* Writeback framebuffer is one-shot, write and forget */
+		*val = 0;
+	} else if (property == config->writeback_out_fence_ptr_property) {
+		*val = 0;
+	} else if (connector->funcs->atomic_get_property) {
+		return connector->funcs->atomic_get_property(connector,
+				state, property, val);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int drm_atomic_get_property(struct drm_mode_object *obj,
+		struct drm_property *property, uint64_t *val)
+{
+	struct drm_device *dev = property->dev;
+	int ret;
+
+	switch (obj->type) {
+	case DRM_MODE_OBJECT_CONNECTOR: {
+		struct drm_connector *connector = obj_to_connector(obj);
+		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+		ret = drm_atomic_connector_get_property(connector,
+				connector->state, property, val);
+		break;
+	}
+	case DRM_MODE_OBJECT_CRTC: {
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+		ret = drm_atomic_crtc_get_property(crtc,
+				crtc->state, property, val);
+		break;
+	}
+	case DRM_MODE_OBJECT_PLANE: {
+		struct drm_plane *plane = obj_to_plane(obj);
+		WARN_ON(!drm_modeset_is_locked(&plane->mutex));
+		ret = drm_atomic_plane_get_property(plane,
+				plane->state, property, val);
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * The big monster ioctl
+ */
+
+static struct drm_pending_vblank_event *create_vblank_event(
+		struct drm_crtc *crtc, uint64_t user_data)
+{
+	struct drm_pending_vblank_event *e = NULL;
+
+	e = kzalloc(sizeof *e, GFP_KERNEL);
+	if (!e)
+		return NULL;
+
+	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
+	e->event.base.length = sizeof(e->event);
+	e->event.vbl.crtc_id = crtc->base.id;
+	e->event.vbl.user_data = user_data;
+
+	return e;
+}
+
+int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
+				     struct drm_connector *connector,
+				     int mode)
+{
+	struct drm_connector *tmp_connector;
+	struct drm_connector_state *new_conn_state;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i, ret, old_mode = connector->dpms;
+	bool active = false;
+
+	ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
+			       state->acquire_ctx);
+	if (ret)
+		return ret;
+
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+	connector->dpms = mode;
+
+	crtc = connector->state->crtc;
+	if (!crtc)
+		goto out;
+	ret = drm_atomic_add_affected_connectors(state, crtc);
+	if (ret)
+		goto out;
+
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state)) {
+		ret = PTR_ERR(crtc_state);
+		goto out;
+	}
+
+	for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
+		if (new_conn_state->crtc != crtc)
+			continue;
+		if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
+			active = true;
+			break;
+		}
+	}
+
+	crtc_state->active = active;
+	ret = drm_atomic_commit(state);
+out:
+	if (ret != 0)
+		connector->dpms = old_mode;
+	return ret;
+}
+
+int drm_atomic_set_property(struct drm_atomic_state *state,
+			    struct drm_mode_object *obj,
+			    struct drm_property *prop,
+			    uint64_t prop_value)
+{
+	struct drm_mode_object *ref;
+	int ret;
+
+	if (!drm_property_change_valid_get(prop, prop_value, &ref))
+		return -EINVAL;
+
+	switch (obj->type) {
+	case DRM_MODE_OBJECT_CONNECTOR: {
+		struct drm_connector *connector = obj_to_connector(obj);
+		struct drm_connector_state *connector_state;
+
+		connector_state = drm_atomic_get_connector_state(state, connector);
+		if (IS_ERR(connector_state)) {
+			ret = PTR_ERR(connector_state);
+			break;
+		}
+
+		ret = drm_atomic_connector_set_property(connector,
+				connector_state, prop, prop_value);
+		break;
+	}
+	case DRM_MODE_OBJECT_CRTC: {
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		struct drm_crtc_state *crtc_state;
+
+		crtc_state = drm_atomic_get_crtc_state(state, crtc);
+		if (IS_ERR(crtc_state)) {
+			ret = PTR_ERR(crtc_state);
+			break;
+		}
+
+		ret = drm_atomic_crtc_set_property(crtc,
+				crtc_state, prop, prop_value);
+		break;
+	}
+	case DRM_MODE_OBJECT_PLANE: {
+		struct drm_plane *plane = obj_to_plane(obj);
+		struct drm_plane_state *plane_state;
+
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state)) {
+			ret = PTR_ERR(plane_state);
+			break;
+		}
+
+		ret = drm_atomic_plane_set_property(plane,
+				plane_state, prop, prop_value);
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	drm_property_change_valid_put(prop, ref);
+	return ret;
+}
+
+/**
+ * DOC: explicit fencing properties
+ *
+ * Explicit fencing allows userspace to control the buffer synchronization
+ * between devices. A Fence or a group of fences are transfered to/from
+ * userspace using Sync File fds and there are two DRM properties for that.
+ * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
+ * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
+ *
+ * As a contrast, with implicit fencing the kernel keeps track of any
+ * ongoing rendering, and automatically ensures that the atomic update waits
+ * for any pending rendering to complete. For shared buffers represented with
+ * a &struct dma_buf this is tracked in &struct reservation_object.
+ * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
+ * whereas explicit fencing is what Android wants.
+ *
+ * "IN_FENCE_FD”:
+ *	Use this property to pass a fence that DRM should wait on before
+ *	proceeding with the Atomic Commit request and show the framebuffer for
+ *	the plane on the screen. The fence can be either a normal fence or a
+ *	merged one, the sync_file framework will handle both cases and use a
+ *	fence_array if a merged fence is received. Passing -1 here means no
+ *	fences to wait on.
+ *
+ *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
+ *	it will only check if the Sync File is a valid one.
+ *
+ *	On the driver side the fence is stored on the @fence parameter of
+ *	&struct drm_plane_state. Drivers which also support implicit fencing
+ *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
+ *	to make sure there's consistent behaviour between drivers in precedence
+ *	of implicit vs. explicit fencing.
+ *
+ * "OUT_FENCE_PTR”:
+ *	Use this property to pass a file descriptor pointer to DRM. Once the
+ *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
+ *	the file descriptor number of a Sync File. This Sync File contains the
+ *	CRTC fence that will be signaled when all framebuffers present on the
+ *	Atomic Commit * request for that given CRTC are scanned out on the
+ *	screen.
+ *
+ *	The Atomic Commit request fails if a invalid pointer is passed. If the
+ *	Atomic Commit request fails for any other reason the out fence fd
+ *	returned will be -1. On a Atomic Commit with the
+ *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
+ *
+ *	Note that out-fences don't have a special interface to drivers and are
+ *	internally represented by a &struct drm_pending_vblank_event in struct
+ *	&drm_crtc_state, which is also used by the nonblocking atomic commit
+ *	helpers and for the DRM event handling for existing userspace.
+ */
+
+struct drm_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+static int setup_out_fence(struct drm_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int prepare_signaling(struct drm_device *dev,
+				  struct drm_atomic_state *state,
+				  struct drm_mode_atomic *arg,
+				  struct drm_file *file_priv,
+				  struct drm_out_fence_state **fence_state,
+				  unsigned int *num_fences)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, c = 0, ret;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
+		return 0;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		s32 __user *fence_ptr;
+
+		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
+			struct drm_pending_vblank_event *e;
+
+			e = create_vblank_event(crtc, arg->user_data);
+			if (!e)
+				return -ENOMEM;
+
+			crtc_state->event = e;
+		}
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+			struct drm_pending_vblank_event *e = crtc_state->event;
+
+			if (!file_priv)
+				continue;
+
+			ret = drm_event_reserve_init(dev, file_priv, &e->base,
+						     &e->event.base);
+			if (ret) {
+				kfree(e);
+				crtc_state->event = NULL;
+				return ret;
+			}
+		}
+
+		if (fence_ptr) {
+			struct dma_fence *fence;
+			struct drm_out_fence_state *f;
+
+			f = krealloc(*fence_state, sizeof(**fence_state) *
+				     (*num_fences + 1), GFP_KERNEL);
+			if (!f)
+				return -ENOMEM;
+
+			memset(&f[*num_fences], 0, sizeof(*f));
+
+			f[*num_fences].out_fence_ptr = fence_ptr;
+			*fence_state = f;
+
+			fence = drm_crtc_create_fence(crtc);
+			if (!fence)
+				return -ENOMEM;
+
+			ret = setup_out_fence(&f[(*num_fences)++], fence);
+			if (ret) {
+				dma_fence_put(fence);
+				return ret;
+			}
+
+			crtc_state->event->base.fence = fence;
+		}
+
+		c++;
+	}
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		struct drm_writeback_connector *wb_conn;
+		struct drm_writeback_job *job;
+		struct drm_out_fence_state *f;
+		struct dma_fence *fence;
+		s32 __user *fence_ptr;
+
+		fence_ptr = get_out_fence_for_connector(state, conn);
+		if (!fence_ptr)
+			continue;
+
+		job = drm_atomic_get_writeback_job(conn_state);
+		if (!job)
+			return -ENOMEM;
+
+		f = krealloc(*fence_state, sizeof(**fence_state) *
+			     (*num_fences + 1), GFP_KERNEL);
+		if (!f)
+			return -ENOMEM;
+
+		memset(&f[*num_fences], 0, sizeof(*f));
+
+		f[*num_fences].out_fence_ptr = fence_ptr;
+		*fence_state = f;
+
+		wb_conn = drm_connector_to_writeback(conn);
+		fence = drm_writeback_get_out_fence(wb_conn);
+		if (!fence)
+			return -ENOMEM;
+
+		ret = setup_out_fence(&f[(*num_fences)++], fence);
+		if (ret) {
+			dma_fence_put(fence);
+			return ret;
+		}
+
+		job->out_fence = fence;
+	}
+
+	/*
+	 * Having this flag means user mode pends on event which will never
+	 * reach due to lack of at least one CRTC for signaling
+	 */
+	if (c == 0 && (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void complete_signaling(struct drm_device *dev,
+			       struct drm_atomic_state *state,
+			       struct drm_out_fence_state *fence_state,
+			       unsigned int num_fences,
+			       bool install_fds)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i;
+
+	if (install_fds) {
+		for (i = 0; i < num_fences; i++)
+			fd_install(fence_state[i].fd,
+				   fence_state[i].sync_file->file);
+
+		kfree(fence_state);
+		return;
+	}
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct drm_pending_vblank_event *event = crtc_state->event;
+		/*
+		 * Free the allocated event. drm_atomic_helper_setup_commit
+		 * can allocate an event too, so only free it if it's ours
+		 * to prevent a double free in drm_atomic_state_clear.
+		 */
+		if (event && (event->base.fence || event->base.file_priv)) {
+			drm_event_cancel_free(dev, &event->base);
+			crtc_state->event = NULL;
+		}
+	}
+
+	if (!fence_state)
+		return;
+
+	for (i = 0; i < num_fences; i++) {
+		if (fence_state[i].sync_file)
+			fput(fence_state[i].sync_file->file);
+		if (fence_state[i].fd >= 0)
+			put_unused_fd(fence_state[i].fd);
+
+		/* If this fails log error to the user */
+		if (fence_state[i].out_fence_ptr &&
+		    put_user(-1, fence_state[i].out_fence_ptr))
+			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
+	}
+
+	kfree(fence_state);
+}
+
+int drm_mode_atomic_ioctl(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_atomic *arg = data;
+	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
+	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
+	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
+	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
+	unsigned int copied_objs, copied_props;
+	struct drm_atomic_state *state;
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_out_fence_state *fence_state;
+	int ret = 0;
+	unsigned int i, j, num_fences;
+
+	/* disallow for drivers not supporting atomic: */
+	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+		return -EINVAL;
+
+	/* disallow for userspace that has not enabled atomic cap (even
+	 * though this may be a bit overkill, since legacy userspace
+	 * wouldn't know how to call this ioctl)
+	 */
+	if (!file_priv->atomic)
+		return -EINVAL;
+
+	if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS)
+		return -EINVAL;
+
+	if (arg->reserved)
+		return -EINVAL;
+
+	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
+			!dev->mode_config.async_page_flip)
+		return -EINVAL;
+
+	/* can't test and expect an event at the same time. */
+	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
+			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
+		return -EINVAL;
+
+	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = &ctx;
+	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
+
+retry:
+	copied_objs = 0;
+	copied_props = 0;
+	fence_state = NULL;
+	num_fences = 0;
+
+	for (i = 0; i < arg->count_objs; i++) {
+		uint32_t obj_id, count_props;
+		struct drm_mode_object *obj;
+
+		if (get_user(obj_id, objs_ptr + copied_objs)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
+		if (!obj) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (!obj->properties) {
+			drm_mode_object_put(obj);
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (get_user(count_props, count_props_ptr + copied_objs)) {
+			drm_mode_object_put(obj);
+			ret = -EFAULT;
+			goto out;
+		}
+
+		copied_objs++;
+
+		for (j = 0; j < count_props; j++) {
+			uint32_t prop_id;
+			uint64_t prop_value;
+			struct drm_property *prop;
+
+			if (get_user(prop_id, props_ptr + copied_props)) {
+				drm_mode_object_put(obj);
+				ret = -EFAULT;
+				goto out;
+			}
+
+			prop = drm_mode_obj_find_prop_id(obj, prop_id);
+			if (!prop) {
+				drm_mode_object_put(obj);
+				ret = -ENOENT;
+				goto out;
+			}
+
+			if (copy_from_user(&prop_value,
+					   prop_values_ptr + copied_props,
+					   sizeof(prop_value))) {
+				drm_mode_object_put(obj);
+				ret = -EFAULT;
+				goto out;
+			}
+
+			ret = drm_atomic_set_property(state, obj, prop,
+						      prop_value);
+			if (ret) {
+				drm_mode_object_put(obj);
+				goto out;
+			}
+
+			copied_props++;
+		}
+
+		drm_mode_object_put(obj);
+	}
+
+	ret = prepare_signaling(dev, state, arg, file_priv, &fence_state,
+				&num_fences);
+	if (ret)
+		goto out;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
+		ret = drm_atomic_check_only(state);
+	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
+		ret = drm_atomic_nonblocking_commit(state);
+	} else {
+		if (unlikely(drm_debug & DRM_UT_STATE))
+			drm_atomic_print_state(state);
+
+		ret = drm_atomic_commit(state);
+	}
+
+out:
+	complete_signaling(dev, state, fence_state, num_fences, !ret);
+
+	if (ret == -EDEADLK) {
+		drm_atomic_state_clear(state);
+		ret = drm_modeset_backoff(&ctx);
+		if (!ret)
+			goto retry;
+	}
+
+	drm_atomic_state_put(state);
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5a84c3bc915d..ce75e9506e85 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -35,6 +35,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fourcc.h>
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index ff5e0d521c21..ede20b55d50c 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -204,6 +204,9 @@ struct drm_minor;
 int drm_atomic_debugfs_init(struct drm_minor *minor);
 #endif
 
+void drm_atomic_print_state(const struct drm_atomic_state *state);
+
+/* drm_atomic_uapi.c */
 int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
 				     struct drm_connector *connector,
 				     int mode);
@@ -213,6 +216,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 			    uint64_t prop_value);
 int drm_atomic_get_property(struct drm_mode_object *obj,
 			    struct drm_property *property, uint64_t *val);
+
+/* IOCTL */
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
 
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 781af1d42d76..7ca8c77223cb 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -25,6 +25,7 @@
 #include <drm/drm_auth.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_print.h>
 
 #include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 2810d4131411..7607f9cd6f77 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -16,6 +16,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 621f17643bb0..a393756b664e 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -28,6 +28,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_atomic_uapi.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a85a83f31979..85cad16f31ed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -46,6 +46,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_atomic_uapi.h>
 #include <linux/dma_remapping.h>
 #include <linux/reservation.h>
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index b640e39ebaca..015341e2dd4c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -21,6 +21,8 @@
 #include <linux/debugfs.h>
 #include <linux/dma-buf.h>
 
+#include <drm/drm_atomic_uapi.h>
+
 #include "msm_drv.h"
 #include "dpu_kms.h"
 #include "dpu_formats.h"
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index c1f1779c980f..4bcdeca7479d 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -15,6 +15,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_atomic_uapi.h>
+
 #include "msm_drv.h"
 #include "msm_gem.h"
 #include "msm_kms.h"
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 0e6a121858d1..3ce136ba8791 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -35,6 +35,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_uapi.h>
 #include <linux/clk.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <linux/component.h>
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 6c6d37aa512a..9dc3fcbd290b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -22,6 +22,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_uapi.h>
 
 #include "uapi/drm/vc4_drm.h"
 #include "vc4_drv.h"
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 66e49ef7d3b5..4aff40886acb 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -584,22 +584,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
 	return plane->state;
 }
 
-int __must_check
-drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
-			     const struct drm_display_mode *mode);
-int __must_check
-drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
-				  struct drm_property_blob *blob);
-int __must_check
-drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
-			      struct drm_crtc *crtc);
-void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
-				 struct drm_framebuffer *fb);
-void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
-				    struct dma_fence *fence);
-int __must_check
-drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
-				  struct drm_crtc *crtc);
 int __must_check
 drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 				   struct drm_crtc *crtc);
diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
new file mode 100644
index 000000000000..8cec52ad1277
--- /dev/null
+++ b/include/drm/drm_atomic_uapi.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Copyright (C) 2014 Intel Corp.
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#ifndef DRM_ATOMIC_UAPI_H_
+#define DRM_ATOMIC_UAPI_H_
+
+struct drm_crtc_state;
+struct drm_display_mode;
+struct drm_property_blob;
+struct drm_plane_state;
+struct drm_crtc;
+struct drm_connector_state;
+struct dma_fence;
+struct drm_framebuffer;
+
+int __must_check
+drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
+			     const struct drm_display_mode *mode);
+int __must_check
+drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
+				  struct drm_property_blob *blob);
+int __must_check
+drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
+			      struct drm_crtc *crtc);
+void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
+				 struct drm_framebuffer *fb);
+void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+				    struct dma_fence *fence);
+int __must_check
+drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
+				  struct drm_crtc *crtc);
+
+#endif
-- 
2.19.0.rc1

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH] drm: Update todo.rst
  2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
  2018-09-03 17:24   ` Sam Ravnborg
  2018-09-03 17:38   ` [Intel-gfx] " Emil Velikov
@ 2018-09-05  8:04   ` Daniel Vetter
  2 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-05  8:04 UTC (permalink / raw)
  To: DRI Development
  Cc: David Airlie, Daniel Vetter, Intel Graphics Development,
	Emil Velikov, Sean Paul, Sam Ravnborg

- drmP.h is now fully split up.
- vkms is happening (and will gain its own todo and docs under a new
  vkms.rst file real soon)
- legacy cruft is completely hidden now, drm_vblank.c is split out
  from drm_irq.c now. I've decided to drop the task to split out
  drm_legacy.ko, partially because Dave already rejected a patch to
  hide the old dri1 drivers better. Current state feels good enough to
  me.
- best_encoder atomic cleanup is done (it's now the default, not even
  exported anymore)
- bunch of smaller things

v2:
- Explain why the drm_legacy.ko task is dropped (Emil).
- typos (Sam).

Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: David Airlie <airlied@linux.ie>
---
 Documentation/gpu/todo.rst | 68 ++++++--------------------------------
 1 file changed, 10 insertions(+), 58 deletions(-)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index a7c150d6b63f..44e42415d2f3 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -127,7 +127,8 @@ interfaces to fix these issues:
   the acquire context explicitly on stack and then also pass it down into
   drivers explicitly so that the legacy-on-atomic functions can use them.
 
-  Except for some driver code this is done.
+  Except for some driver code this is done. This task should be finished by
+  adding WARN_ON(!drm_drv_uses_atomic_modeset) in drm_modeset_lock_all().
 
 * A bunch of the vtable hooks are now in the wrong place: DRM has a split
   between core vfunc tables (named ``drm_foo_funcs``), which are used to
@@ -137,13 +138,6 @@ interfaces to fix these issues:
   ``_helper_funcs`` since they are not part of the core ABI. There's a
   ``FIXME`` comment in the kerneldoc for each such case in ``drm_crtc.h``.
 
-* There's a new helper ``drm_atomic_helper_best_encoder()`` which could be
-  used by all atomic drivers which don't select the encoder for a given
-  connector at runtime. That's almost all of them, and would allow us to get
-  rid of a lot of ``best_encoder`` boilerplate in drivers.
-
-  This was almost done, but new drivers added a few more cases again.
-
 Contact: Daniel Vetter
 
 Get rid of dev->struct_mutex from GEM drivers
@@ -164,9 +158,8 @@ private lock. The tricky part is the BO free functions, since those can't
 reliably take that lock any more. Instead state needs to be protected with
 suitable subordinate locks or some cleanup work pushed to a worker thread. For
 performance-critical drivers it might also be better to go with a more
-fine-grained per-buffer object and per-context lockings scheme. Currently the
-following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
-``udl``.
+fine-grained per-buffer object and per-context lockings scheme. Currently only the
+``msm`` driver still use ``struct_mutex``.
 
 Contact: Daniel Vetter, respective driver maintainers
 
@@ -190,7 +183,8 @@ Convert drivers to use simple modeset suspend/resume
 
 Most drivers (except i915 and nouveau) that use
 drm_atomic_helper_suspend/resume() can probably be converted to use
-drm_mode_config_helper_suspend/resume().
+drm_mode_config_helper_suspend/resume(). Also there's still open-coded version
+of the atomic suspend/resume code in older atomic modeset drivers.
 
 Contact: Maintainer of the driver you plan to convert
 
@@ -246,20 +240,10 @@ Core refactorings
 Clean up the DRM header mess
 ----------------------------
 
-Currently the DRM subsystem has only one global header, ``drmP.h``. This is
-used both for functions exported to helper libraries and drivers and functions
-only used internally in the ``drm.ko`` module. The goal would be to move all
-header declarations not needed outside of ``drm.ko`` into
-``drivers/gpu/drm/drm_*_internal.h`` header files. ``EXPORT_SYMBOL`` also
-needs to be dropped for these functions.
-
-This would nicely tie in with the below task to create kerneldoc after the API
-is cleaned up. Or with the "hide legacy cruft better" task.
-
-Note that this is well in progress, but ``drmP.h`` is still huge. The updated
-plan is to switch to per-file driver API headers, which will also structure
-the kerneldoc better. This should also allow more fine-grained ``#include``
-directives.
+The DRM subsystem originally had only one huge global header, ``drmP.h``. This
+is not split up, but many source files still include it. The remaining part of
+the cleanup work here is to replace any ``#include <drm/drmP.h>`` by only the
+headers needed (and fixing up any missing pre-declarations in the headers).
 
 In the end no .c file should need to include ``drmP.h`` anymore.
 
@@ -278,26 +262,6 @@ See https://dri.freedesktop.org/docs/drm/ for what's there already.
 
 Contact: Daniel Vetter
 
-Hide legacy cruft better
-------------------------
-
-Way back DRM supported only drivers which shadow-attached to PCI devices with
-userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
-of the entire device, you can spot them with the DRIVER_MODESET flag.
-
-Unfortunately there's still large piles of legacy code around which needs to
-be hidden so that driver writers don't accidentally end up using it. And to
-prevent security issues in those legacy IOCTLs from being exploited on modern
-drivers. This has multiple possible subtasks:
-
-* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
-  module and compile it only when one of the legacy drivers is enabled.
-
-This is mostly done, the only thing left is to split up ``drm_irq.c`` into
-legacy cruft and the parts needed by modern KMS drivers.
-
-Contact: Daniel Vetter
-
 Make panic handling work
 ------------------------
 
@@ -398,18 +362,6 @@ the non-i915 specific modeset tests.
 
 Contact: Daniel Vetter
 
-Create a virtual KMS driver for testing (vkms)
-----------------------------------------------
-
-With all the latest helpers it should be fairly simple to create a virtual KMS
-driver useful for testing, or for running X or similar on headless machines
-(to be able to still use the GPU). This would be similar to vgem, but aimed at
-the modeset side.
-
-Once the basics are there there's tons of possibilities to extend it.
-
-Contact: Daniel Vetter
-
 Driver Specific
 ===============
 
-- 
2.19.0.rc1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (15 preceding siblings ...)
  2018-09-03 18:05 ` ✗ Fi.CI.BAT: failure " Patchwork
@ 2018-09-05  8:09 ` Patchwork
  2018-09-05  8:15 ` ✗ Fi.CI.SPARSE: " Patchwork
  2018-09-05  8:26 ` ✗ Fi.CI.BAT: failure " Patchwork
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-05  8:09 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
URL   : https://patchwork.freedesktop.org/series/49089/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
e970ce2437df drm: Add drm/kernel.h header file
-:139: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#139: 
new file mode 100644

-:144: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#144: FILE: include/drm/kernel.h:1:
+/*

-:173: ERROR:MULTISTATEMENT_MACRO_USE_DO_WHILE: Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects
#173: FILE: include/drm/kernel.h:30:
+#define for_each_if(condition) if (!(condition)) {} else

-:173: WARNING:BRACES: braces {} are not necessary for single statement blocks
#173: FILE: include/drm/kernel.h:30:
+#define for_each_if(condition) if (!(condition)) {} else

total: 1 errors, 3 warnings, 0 checks, 105 lines checked
588c213298c7 drm: Drop drmP.h from drm_connector.c
-:56: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 30 lines checked
366d2a3d6810 drm: drop drmP.h include from drm_plane.c
-:92: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 55 lines checked
cf71204f81b5 drm: drop drmP.h include from drm_crtc.c
-:35: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 17 lines checked
ea63e12f667d drm/atomic: trim driver interface/docs
-:88: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#88: FILE: drivers/gpu/drm/drm_atomic.c:501:
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 		struct drm_crtc_state *state, struct drm_property *property,

-:202: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#202: FILE: drivers/gpu/drm/drm_atomic.c:1253:
+static int drm_atomic_set_writeback_fb_for_connector(

-:342: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 2 checks, 301 lines checked
25a007cf2a24 drm: extract drm_atomic_uapi.c
-:1515: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#1515: 
new file mode 100644

-:1520: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#1520: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1:
+/*

-:1569: WARNING:TYPO_SPELLING: 'similiar' may be misspelled - perhaps 'similar'?
#1569: FILE: drivers/gpu/drm/drm_atomic_uapi.c:50:
+ * for load detect or similiar.

-:1600: ERROR:CODE_INDENT: code indent should use tabs where possible
#1600: FILE: drivers/gpu/drm/drm_atomic_uapi.c:81:
+^I^I                                 sizeof(umode),$

-:1600: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1600: FILE: drivers/gpu/drm/drm_atomic_uapi.c:81:
+			drm_property_create_blob(state->crtc->dev,
+		                                 sizeof(umode),

-:1601: ERROR:CODE_INDENT: code indent should use tabs where possible
#1601: FILE: drivers/gpu/drm/drm_atomic_uapi.c:82:
+^I^I                                 &umode);$

-:1634: ERROR:CODE_INDENT: code indent should use tabs where possible
#1634: FILE: drivers/gpu/drm/drm_atomic_uapi.c:115:
+                                      struct drm_property_blob *blob)$

-:1634: WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1634: FILE: drivers/gpu/drm/drm_atomic_uapi.c:115:
+                                      struct drm_property_blob *blob)$

-:1877: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1877: FILE: drivers/gpu/drm/drm_atomic_uapi.c:358:
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,

-:1917: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!new_blob"
#1917: FILE: drivers/gpu/drm/drm_atomic_uapi.c:398:
+		if (new_blob == NULL)

-:1939: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1939: FILE: drivers/gpu/drm/drm_atomic_uapi.c:420:
+static int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
+		struct drm_crtc_state *state, struct drm_property *property,

-:1947: CHECK:BRACES: braces {} should be used on all arms of this statement
#1947: FILE: drivers/gpu/drm/drm_atomic_uapi.c:428:
+	if (property == config->prop_active)
[...]
+	else if (property == config->prop_mode_id) {
[...]
+	} else if (property == config->degamma_lut_property) {
[...]
+	} else if (property == config->ctm_property) {
[...]
+	} else if (property == config->gamma_lut_property) {
[...]
+	} else if (property == config->prop_out_fence_ptr) {
[...]
+	} else if (crtc->funcs->atomic_set_property) {
[...]
+	} else {
[...]

-:1957: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1957: FILE: drivers/gpu/drm/drm_atomic_uapi.c:438:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->degamma_lut,

-:1965: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1965: FILE: drivers/gpu/drm/drm_atomic_uapi.c:446:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->ctm,

-:1973: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1973: FILE: drivers/gpu/drm/drm_atomic_uapi.c:454:
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->gamma_lut,

-:1991: WARNING:UNNECESSARY_ELSE: else is not generally useful after a break or return
#1991: FILE: drivers/gpu/drm/drm_atomic_uapi.c:472:
+		return crtc->funcs->atomic_set_property(crtc, state, property, val);
+	} else {

-:2003: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2003: FILE: drivers/gpu/drm/drm_atomic_uapi.c:484:
+drm_atomic_crtc_get_property(struct drm_crtc *crtc,
+		const struct drm_crtc_state *state,

-:2030: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2030: FILE: drivers/gpu/drm/drm_atomic_uapi.c:511:
+static int drm_atomic_plane_set_property(struct drm_plane *plane,
+		struct drm_plane_state *state, struct drm_property *property,

-:2038: WARNING:LINE_SPACING: Missing a blank line after declarations
#2038: FILE: drivers/gpu/drm/drm_atomic_uapi.c:519:
+		struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
+		drm_atomic_set_fb_for_plane(state, fb);

-:2054: WARNING:LINE_SPACING: Missing a blank line after declarations
#2054: FILE: drivers/gpu/drm/drm_atomic_uapi.c:535:
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_plane(state, crtc);

-:2103: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2103: FILE: drivers/gpu/drm/drm_atomic_uapi.c:584:
+drm_atomic_plane_get_property(struct drm_plane *plane,
+		const struct drm_plane_state *state,

-:2109: WARNING:BRACES: braces {} are not necessary for any arm of this statement
#2109: FILE: drivers/gpu/drm/drm_atomic_uapi.c:590:
+	if (property == config->prop_fb_id) {
[...]
+	} else if (property == config->prop_in_fence_fd) {
[...]
+	} else if (property == config->prop_crtc_id) {
[...]
+	} else if (property == config->prop_crtc_x) {
[...]
+	} else if (property == config->prop_crtc_y) {
[...]
+	} else if (property == config->prop_crtc_w) {
[...]
+	} else if (property == config->prop_crtc_h) {
[...]
+	} else if (property == config->prop_src_x) {
[...]
+	} else if (property == config->prop_src_y) {
[...]
+	} else if (property == config->prop_src_w) {
[...]
+	} else if (property == config->prop_src_h) {
[...]
+	} else if (property == plane->alpha_property) {
[...]
+	} else if (property == plane->blend_mode_property) {
[...]
+	} else if (property == plane->rotation_property) {
[...]
+	} else if (property == plane->zpos_property) {
[...]
+	} else if (property == plane->color_encoding_property) {
[...]
+	} else if (property == plane->color_range_property) {
[...]
+	} else if (plane->funcs->atomic_get_property) {
[...]
+	} else {
[...]

-:2164: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#2164: FILE: drivers/gpu/drm/drm_atomic_uapi.c:645:
+static int drm_atomic_set_writeback_fb_for_connector(

-:2186: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2186: FILE: drivers/gpu/drm/drm_atomic_uapi.c:667:
+static int drm_atomic_connector_set_property(struct drm_connector *connector,
+		struct drm_connector_state *state, struct drm_property *property,

-:2194: WARNING:LINE_SPACING: Missing a blank line after declarations
#2194: FILE: drivers/gpu/drm/drm_atomic_uapi.c:675:
+		struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
+		return drm_atomic_set_crtc_for_connector(state, crtc);

-:2254: WARNING:LINE_SPACING: Missing a blank line after declarations
#2254: FILE: drivers/gpu/drm/drm_atomic_uapi.c:735:
+		int ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)

-:2277: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2277: FILE: drivers/gpu/drm/drm_atomic_uapi.c:758:
+drm_atomic_connector_get_property(struct drm_connector *connector,
+		const struct drm_connector_state *state,

-:2337: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2337: FILE: drivers/gpu/drm/drm_atomic_uapi.c:818:
+int drm_atomic_get_property(struct drm_mode_object *obj,
+		struct drm_property *property, uint64_t *val)

-:2345: WARNING:LINE_SPACING: Missing a blank line after declarations
#2345: FILE: drivers/gpu/drm/drm_atomic_uapi.c:826:
+		struct drm_connector *connector = obj_to_connector(obj);
+		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));

-:2347: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2347: FILE: drivers/gpu/drm/drm_atomic_uapi.c:828:
+		ret = drm_atomic_connector_get_property(connector,
+				connector->state, property, val);

-:2352: WARNING:LINE_SPACING: Missing a blank line after declarations
#2352: FILE: drivers/gpu/drm/drm_atomic_uapi.c:833:
+		struct drm_crtc *crtc = obj_to_crtc(obj);
+		WARN_ON(!drm_modeset_is_locked(&crtc->mutex));

-:2354: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2354: FILE: drivers/gpu/drm/drm_atomic_uapi.c:835:
+		ret = drm_atomic_crtc_get_property(crtc,
+				crtc->state, property, val);

-:2359: WARNING:LINE_SPACING: Missing a blank line after declarations
#2359: FILE: drivers/gpu/drm/drm_atomic_uapi.c:840:
+		struct drm_plane *plane = obj_to_plane(obj);
+		WARN_ON(!drm_modeset_is_locked(&plane->mutex));

-:2361: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2361: FILE: drivers/gpu/drm/drm_atomic_uapi.c:842:
+		ret = drm_atomic_plane_get_property(plane,
+				plane->state, property, val);

-:2376: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#2376: FILE: drivers/gpu/drm/drm_atomic_uapi.c:857:
+static struct drm_pending_vblank_event *create_vblank_event(

-:2381: WARNING:SIZEOF_PARENTHESIS: sizeof *e should be sizeof(*e)
#2381: FILE: drivers/gpu/drm/drm_atomic_uapi.c:862:
+	e = kzalloc(sizeof *e, GFP_KERNEL);

-:2466: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2466: FILE: drivers/gpu/drm/drm_atomic_uapi.c:947:
+		ret = drm_atomic_connector_set_property(connector,
+				connector_state, prop, prop_value);

-:2480: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2480: FILE: drivers/gpu/drm/drm_atomic_uapi.c:961:
+		ret = drm_atomic_crtc_set_property(crtc,
+				crtc_state, prop, prop_value);

-:2494: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2494: FILE: drivers/gpu/drm/drm_atomic_uapi.c:975:
+		ret = drm_atomic_plane_set_property(plane,
+				plane_state, prop, prop_value);

-:2510: WARNING:TYPO_SPELLING: 'transfered' may be misspelled - perhaps 'transferred'?
#2510: FILE: drivers/gpu/drm/drm_atomic_uapi.c:991:
+ * between devices. A Fence or a group of fences are transfered to/from

-:2582: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2582: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1063:
+static int prepare_signaling(struct drm_device *dev,
+				  struct drm_atomic_state *state,

-:2789: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2789: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1270:
+	if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
+			!dev->mode_config.async_page_flip)

-:2794: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2794: FILE: drivers/gpu/drm/drm_atomic_uapi.c:1275:
+	if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) &&
+			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))

-:3079: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#3079: FILE: include/drm/drm_atomic_uapi.h:1:
+/*

-:3136: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 3 errors, 17 warnings, 25 checks, 2458 lines checked
b5f0b053f233 drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
-:133: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 72 lines checked
3aa591636f5c drm/amdgpu: Remove default best_encoder hook from DC
-:58: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 35 lines checked
2c3678735344 drm: Update todo.rst
d22eafa841a8 drm: Extract drm_atomic_state_helper.[hc]
-:640: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#640: 
new file mode 100644

-:645: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#645: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:1:
+/*

-:959: WARNING:TYPO_SPELLING: 'conector' may be misspelled - perhaps 'connector'?
#959: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:315:
+ * the &drm_conector->state pointer of @connector, usually required when

-:1007: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1007: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:363:
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					    struct drm_connector_state *state)

-:1157: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1157: FILE: drivers/gpu/drm/drm_atomic_state_helper.c:513:
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state)

-:1316: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#1316: FILE: include/drm/drm_atomic_state_helper.h:1:
+/*

-:1373: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1373: FILE: include/drm/drm_atomic_state_helper.h:58:
+void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
+					  struct drm_plane_state *state);

-:1380: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1380: FILE: include/drm/drm_atomic_state_helper.h:65:
+__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
+					   struct drm_connector_state *state);

-:1389: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1389: FILE: include/drm/drm_atomic_state_helper.h:74:
+void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
+					  struct drm_connector_state *state);

-:1395: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 5 warnings, 5 checks, 784 lines checked
86b71ea21976 drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
86da054cc810 drm/vmwgfx: Don't look at state->allow_modeset
1ce582c81c7a drm/atomic: Improve docs for drm_atomic_state->allow_modeset
-:38: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 22 lines checked
95f8dc58d440 drm/vmwgfx: Add FIXME comments for customer page_flip handlers
-:58: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Daniel Vetter <daniel.vetter@ffwll.ch>'

total: 0 errors, 1 warnings, 0 checks, 21 lines checked

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.SPARSE: warning for series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (16 preceding siblings ...)
  2018-09-05  8:09 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file (rev3) Patchwork
@ 2018-09-05  8:15 ` Patchwork
  2018-09-05  8:26 ` ✗ Fi.CI.BAT: failure " Patchwork
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-05  8:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
URL   : https://patchwork.freedesktop.org/series/49089/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Commit: drm: Add drm/kernel.h header file
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3686:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3687:16: warning: expression using sizeof(void)

Commit: drm: Drop drmP.h from drm_connector.c
Okay!

Commit: drm: drop drmP.h include from drm_plane.c
Okay!

Commit: drm: drop drmP.h include from drm_crtc.c
Okay!

Commit: drm/atomic: trim driver interface/docs
Okay!

Commit: drm: extract drm_atomic_uapi.c
Okay!

Commit: drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
Okay!

Commit: drm/amdgpu: Remove default best_encoder hook from DC
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3035:6: warning: symbol 'dm_drm_plane_destroy_state' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3826:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3826:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3830:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3830:27: warning: expression using sizeof(void)
-drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3937:58: warning: Using plain integer as NULL pointer
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3012:6: warning: symbol 'dm_drm_plane_destroy_state' was not declared. Should it be static?
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3803:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3803:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3807:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3807:27: warning: expression using sizeof(void)
+drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:3914:58: warning: Using plain integer as NULL pointer

Commit: drm: Update todo.rst
Okay!

Commit: drm: Extract drm_atomic_state_helper.[hc]
Okay!

Commit: drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
Okay!

Commit: drm/vmwgfx: Don't look at state->allow_modeset
Okay!

Commit: drm/atomic: Improve docs for drm_atomic_state->allow_modeset
Okay!

Commit: drm/vmwgfx: Add FIXME comments for customer page_flip handlers
Okay!

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* ✗ Fi.CI.BAT: failure for series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
  2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
                   ` (17 preceding siblings ...)
  2018-09-05  8:15 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2018-09-05  8:26 ` Patchwork
  18 siblings, 0 replies; 34+ messages in thread
From: Patchwork @ 2018-09-05  8:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/14] drm: Add drm/kernel.h header file (rev3)
URL   : https://patchwork.freedesktop.org/series/49089/
State : failure

== Summary ==

= CI Bug Log - changes from CI_DRM_4770 -> Patchwork_10087 =

== Summary - FAILURE ==

  Serious unknown changes coming with Patchwork_10087 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_10087, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/49089/revisions/3/mbox/

== Possible new issues ==

  Here are the unknown changes that may have been introduced in Patchwork_10087:

  === IGT changes ===

    ==== Possible regressions ====

    igt@core_auth@basic-auth:
      fi-kbl-8809g:       PASS -> INCOMPLETE

    
    ==== Warnings ====

    igt@pm_rpm@module-reload:
      fi-hsw-4770r:       SKIP -> PASS

    
== Known issues ==

  Here are the changes found in Patchwork_10087 that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@kms_frontbuffer_tracking@basic:
      fi-hsw-peppy:       PASS -> DMESG-WARN (fdo#102614)

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c:
      fi-bxt-dsi:         PASS -> INCOMPLETE (fdo#103927)

    
    ==== Possible fixes ====

    igt@drv_module_reload@basic-reload-inject:
      fi-hsw-4770r:       DMESG-WARN (fdo#107425) -> PASS

    igt@gem_exec_suspend@basic-s4-devices:
      fi-kbl-7500u:       DMESG-WARN (fdo#105128, fdo#107139) -> PASS

    igt@kms_frontbuffer_tracking@basic:
      fi-byt-clapper:     FAIL (fdo#103167) -> PASS

    igt@prime_vgem@basic-fence-flip:
      fi-ilk-650:         FAIL (fdo#104008) -> PASS

    
  fdo#102614 https://bugs.freedesktop.org/show_bug.cgi?id=102614
  fdo#103167 https://bugs.freedesktop.org/show_bug.cgi?id=103167
  fdo#103927 https://bugs.freedesktop.org/show_bug.cgi?id=103927
  fdo#104008 https://bugs.freedesktop.org/show_bug.cgi?id=104008
  fdo#105128 https://bugs.freedesktop.org/show_bug.cgi?id=105128
  fdo#107139 https://bugs.freedesktop.org/show_bug.cgi?id=107139
  fdo#107425 https://bugs.freedesktop.org/show_bug.cgi?id=107425


== Participating hosts (50 -> 45) ==

  Missing    (5): fi-ctg-p8600 fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-hsw-4200u 


== Build changes ==

    * Linux: CI_DRM_4770 -> Patchwork_10087

  CI_DRM_4770: 0c3535cf60140d017a5df73d84d06e8b1a5b5d3b @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4627: e0c3033a57d85c0d2eb33af0451afa16edc79f10 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_10087: 95f8dc58d440e7bcde203b0b10ad99e0455dfa6e @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

95f8dc58d440 drm/vmwgfx: Add FIXME comments for customer page_flip handlers
1ce582c81c7a drm/atomic: Improve docs for drm_atomic_state->allow_modeset
86da054cc810 drm/vmwgfx: Don't look at state->allow_modeset
86b71ea21976 drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property
d22eafa841a8 drm: Extract drm_atomic_state_helper.[hc]
2c3678735344 drm: Update todo.rst
3aa591636f5c drm/amdgpu: Remove default best_encoder hook from DC
b5f0b053f233 drm/atomic-helper: Unexport drm_atomic_helper_best_encoder
25a007cf2a24 drm: extract drm_atomic_uapi.c
ea63e12f667d drm/atomic: trim driver interface/docs
cf71204f81b5 drm: drop drmP.h include from drm_crtc.c
366d2a3d6810 drm: drop drmP.h include from drm_plane.c
588c213298c7 drm: Drop drmP.h from drm_connector.c
e970ce2437df drm: Add drm/kernel.h header file

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_10087/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC
  2018-09-03 16:54 ` [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC Daniel Vetter
@ 2018-09-05 13:45   ` Leo Li
  2018-09-05 13:48     ` Daniel Vetter
  0 siblings, 1 reply; 34+ messages in thread
From: Leo Li @ 2018-09-05 13:45 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Andrey Grodzovsky, Tony Cheng, Intel Graphics Development,
	Shirish S, Alex Deucher, Daniel Vetter, Harry Wentland



On 2018-09-03 12:54 PM, Daniel Vetter wrote:
> For atomic driver this is the default, no need to reimplement it. We
> still need to keep the copypasta for not-atomic drivers though, since
> no one polished the legacy crtc helpers as much as the atomic ones.

Thanks for the patch! It seems I made an identical change here:
https://lists.freedesktop.org/archives/amd-gfx/2018-August/026064.html

One line difference though. I wasn't aware that the default is used when
.best_encoder is null, so I just hooked it to the default helper.

If it's OK with you, I'll do a follow-up to drop the hook, so we don't
have two conflicting patches in flight.

Leo

> 
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
> Cc: Tony Cheng <Tony.Cheng@amd.com>
> Cc: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
> Cc: Shirish S <shirish.s@amd.com>
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 -------------------
>   1 file changed, 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index af6adffba788..333f9904f135 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -2794,28 +2794,6 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
>   	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
>   };
>   
> -static struct drm_encoder *best_encoder(struct drm_connector *connector)
> -{
> -	int enc_id = connector->encoder_ids[0];
> -	struct drm_mode_object *obj;
> -	struct drm_encoder *encoder;
> -
> -	DRM_DEBUG_DRIVER("Finding the best encoder\n");
> -
> -	/* pick the encoder ids */
> -	if (enc_id) {
> -		obj = drm_mode_object_find(connector->dev, NULL, enc_id, DRM_MODE_OBJECT_ENCODER);
> -		if (!obj) {
> -			DRM_ERROR("Couldn't find a matching encoder for our connector\n");
> -			return NULL;
> -		}
> -		encoder = obj_to_encoder(obj);
> -		return encoder;
> -	}
> -	DRM_ERROR("No encoder id\n");
> -	return NULL;
> -}
> -
>   static int get_modes(struct drm_connector *connector)
>   {
>   	return amdgpu_dm_connector_get_modes(connector);
> @@ -2934,7 +2912,6 @@ amdgpu_dm_connector_helper_funcs = {
>   	 */
>   	.get_modes = get_modes,
>   	.mode_valid = amdgpu_dm_connector_mode_valid,
> -	.best_encoder = best_encoder
>   };
>   
>   static void dm_crtc_helper_disable(struct drm_crtc *crtc)
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC
  2018-09-05 13:45   ` Leo Li
@ 2018-09-05 13:48     ` Daniel Vetter
  2018-09-06 16:33       ` Deucher, Alexander
  0 siblings, 1 reply; 34+ messages in thread
From: Daniel Vetter @ 2018-09-05 13:48 UTC (permalink / raw)
  To: Leo Li
  Cc: Andrey Grodzovsky, Tony Cheng, Intel Graphics Development,
	DRI Development, Shirish S, Alex Deucher, Daniel Vetter,
	Harry Wentland

On Wed, Sep 5, 2018 at 3:45 PM, Leo Li <sunpeng.li@amd.com> wrote:
>
>
> On 2018-09-03 12:54 PM, Daniel Vetter wrote:
>>
>> For atomic driver this is the default, no need to reimplement it. We
>> still need to keep the copypasta for not-atomic drivers though, since
>> no one polished the legacy crtc helpers as much as the atomic ones.
>
>
> Thanks for the patch! It seems I made an identical change here:
> https://lists.freedesktop.org/archives/amd-gfx/2018-August/026064.html
>
> One line difference though. I wasn't aware that the default is used when
> .best_encoder is null, so I just hooked it to the default helper.
>
> If it's OK with you, I'll do a follow-up to drop the hook, so we don't
> have two conflicting patches in flight.

I have a follow-up patches to unexport the helper, so would be good if
Alex sends out the pull request so I can sort this all out in
drm-misc-next. I don't want to split up the patch series if possible.
Or we just deal with the conflict, it's minor.

Alex?
-Daniel

> Leo
>
>
>>
>> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Harry Wentland <harry.wentland@amd.com>
>> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
>> Cc: Tony Cheng <Tony.Cheng@amd.com>
>> Cc: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
>> Cc: Shirish S <shirish.s@amd.com>
>> ---
>>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 -------------------
>>   1 file changed, 23 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index af6adffba788..333f9904f135 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -2794,28 +2794,6 @@ static const struct drm_connector_funcs
>> amdgpu_dm_connector_funcs = {
>>         .atomic_get_property = amdgpu_dm_connector_atomic_get_property
>>   };
>>   -static struct drm_encoder *best_encoder(struct drm_connector
>> *connector)
>> -{
>> -       int enc_id = connector->encoder_ids[0];
>> -       struct drm_mode_object *obj;
>> -       struct drm_encoder *encoder;
>> -
>> -       DRM_DEBUG_DRIVER("Finding the best encoder\n");
>> -
>> -       /* pick the encoder ids */
>> -       if (enc_id) {
>> -               obj = drm_mode_object_find(connector->dev, NULL, enc_id,
>> DRM_MODE_OBJECT_ENCODER);
>> -               if (!obj) {
>> -                       DRM_ERROR("Couldn't find a matching encoder for
>> our connector\n");
>> -                       return NULL;
>> -               }
>> -               encoder = obj_to_encoder(obj);
>> -               return encoder;
>> -       }
>> -       DRM_ERROR("No encoder id\n");
>> -       return NULL;
>> -}
>> -
>>   static int get_modes(struct drm_connector *connector)
>>   {
>>         return amdgpu_dm_connector_get_modes(connector);
>> @@ -2934,7 +2912,6 @@ amdgpu_dm_connector_helper_funcs = {
>>          */
>>         .get_modes = get_modes,
>>         .mode_valid = amdgpu_dm_connector_mode_valid,
>> -       .best_encoder = best_encoder
>>   };
>>     static void dm_crtc_helper_disable(struct drm_crtc *crtc)
>>
>



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

* RE: [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC
  2018-09-05 13:48     ` Daniel Vetter
@ 2018-09-06 16:33       ` Deucher, Alexander
  2018-09-06 22:12         ` Daniel Vetter
  0 siblings, 1 reply; 34+ messages in thread
From: Deucher, Alexander @ 2018-09-06 16:33 UTC (permalink / raw)
  To: Daniel Vetter, Li, Sun peng (Leo)
  Cc: Cheng, Tony, Intel Graphics Development, DRI Development, S,
	Shirish, Daniel Vetter

> -----Original Message-----
> From: Daniel Vetter <daniel.vetter@ffwll.ch>
> Sent: Wednesday, September 5, 2018 9:48 AM
> To: Li, Sun peng (Leo) <Sunpeng.Li@amd.com>
> Cc: DRI Development <dri-devel@lists.freedesktop.org>; Intel Graphics
> Development <intel-gfx@lists.freedesktop.org>; Daniel Vetter
> <daniel.vetter@intel.com>; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Wentland, Harry
> <Harry.Wentland@amd.com>; Grodzovsky, Andrey
> <Andrey.Grodzovsky@amd.com>; Cheng, Tony <Tony.Cheng@amd.com>; S,
> Shirish <Shirish.S@amd.com>
> Subject: Re: [PATCH 08/14] drm/amdgpu: Remove default best_encoder
> hook from DC
> 
> On Wed, Sep 5, 2018 at 3:45 PM, Leo Li <sunpeng.li@amd.com> wrote:
> >
> >
> > On 2018-09-03 12:54 PM, Daniel Vetter wrote:
> >>
> >> For atomic driver this is the default, no need to reimplement it. We
> >> still need to keep the copypasta for not-atomic drivers though, since
> >> no one polished the legacy crtc helpers as much as the atomic ones.
> >
> >
> > Thanks for the patch! It seems I made an identical change here:
> > https://lists.freedesktop.org/archives/amd-gfx/2018-August/026064.html
> >
> > One line difference though. I wasn't aware that the default is used
> > when .best_encoder is null, so I just hooked it to the default helper.
> >
> > If it's OK with you, I'll do a follow-up to drop the hook, so we don't
> > have two conflicting patches in flight.
> 
> I have a follow-up patches to unexport the helper, so would be good if Alex
> sends out the pull request so I can sort this all out in drm-misc-next. I don't
> want to split up the patch series if possible.
> Or we just deal with the conflict, it's minor.
> 
> Alex?

I'm planning to send the PR next week when I'm back in the office.  I can drop Leo's patch when I send the PR if that makes things easier.

Alex

> -Daniel
> 
> > Leo
> >
> >
> >>
> >> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> >> Cc: Alex Deucher <alexander.deucher@amd.com>
> >> Cc: Harry Wentland <harry.wentland@amd.com>
> >> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
> >> Cc: Tony Cheng <Tony.Cheng@amd.com>
> >> Cc: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
> >> Cc: Shirish S <shirish.s@amd.com>
> >> ---
> >>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ----------------
> ---
> >>   1 file changed, 23 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> index af6adffba788..333f9904f135 100644
> >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> >> @@ -2794,28 +2794,6 @@ static const struct drm_connector_funcs
> >> amdgpu_dm_connector_funcs = {
> >>         .atomic_get_property =
> amdgpu_dm_connector_atomic_get_property
> >>   };
> >>   -static struct drm_encoder *best_encoder(struct drm_connector
> >> *connector)
> >> -{
> >> -       int enc_id = connector->encoder_ids[0];
> >> -       struct drm_mode_object *obj;
> >> -       struct drm_encoder *encoder;
> >> -
> >> -       DRM_DEBUG_DRIVER("Finding the best encoder\n");
> >> -
> >> -       /* pick the encoder ids */
> >> -       if (enc_id) {
> >> -               obj = drm_mode_object_find(connector->dev, NULL, enc_id,
> >> DRM_MODE_OBJECT_ENCODER);
> >> -               if (!obj) {
> >> -                       DRM_ERROR("Couldn't find a matching encoder for
> >> our connector\n");
> >> -                       return NULL;
> >> -               }
> >> -               encoder = obj_to_encoder(obj);
> >> -               return encoder;
> >> -       }
> >> -       DRM_ERROR("No encoder id\n");
> >> -       return NULL;
> >> -}
> >> -
> >>   static int get_modes(struct drm_connector *connector)
> >>   {
> >>         return amdgpu_dm_connector_get_modes(connector);
> >> @@ -2934,7 +2912,6 @@ amdgpu_dm_connector_helper_funcs = {
> >>          */
> >>         .get_modes = get_modes,
> >>         .mode_valid = amdgpu_dm_connector_mode_valid,
> >> -       .best_encoder = best_encoder
> >>   };
> >>     static void dm_crtc_helper_disable(struct drm_crtc *crtc)
> >>
> >
> 
> 
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC
  2018-09-06 16:33       ` Deucher, Alexander
@ 2018-09-06 22:12         ` Daniel Vetter
  0 siblings, 0 replies; 34+ messages in thread
From: Daniel Vetter @ 2018-09-06 22:12 UTC (permalink / raw)
  To: Deucher, Alexander
  Cc: Grodzovsky, Andrey, Li, Sun peng (Leo),
	Cheng, Tony, Intel Graphics Development, DRI Development, S,
	Shirish, Daniel Vetter, Wentland, Harry

On Thu, Sep 6, 2018 at 6:33 PM, Deucher, Alexander
<Alexander.Deucher@amd.com> wrote:
>> -----Original Message-----
>> From: Daniel Vetter <daniel.vetter@ffwll.ch>
>> Sent: Wednesday, September 5, 2018 9:48 AM
>> To: Li, Sun peng (Leo) <Sunpeng.Li@amd.com>
>> Cc: DRI Development <dri-devel@lists.freedesktop.org>; Intel Graphics
>> Development <intel-gfx@lists.freedesktop.org>; Daniel Vetter
>> <daniel.vetter@intel.com>; Deucher, Alexander
>> <Alexander.Deucher@amd.com>; Wentland, Harry
>> <Harry.Wentland@amd.com>; Grodzovsky, Andrey
>> <Andrey.Grodzovsky@amd.com>; Cheng, Tony <Tony.Cheng@amd.com>; S,
>> Shirish <Shirish.S@amd.com>
>> Subject: Re: [PATCH 08/14] drm/amdgpu: Remove default best_encoder
>> hook from DC
>>
>> On Wed, Sep 5, 2018 at 3:45 PM, Leo Li <sunpeng.li@amd.com> wrote:
>> >
>> >
>> > On 2018-09-03 12:54 PM, Daniel Vetter wrote:
>> >>
>> >> For atomic driver this is the default, no need to reimplement it. We
>> >> still need to keep the copypasta for not-atomic drivers though, since
>> >> no one polished the legacy crtc helpers as much as the atomic ones.
>> >
>> >
>> > Thanks for the patch! It seems I made an identical change here:
>> > https://lists.freedesktop.org/archives/amd-gfx/2018-August/026064.html
>> >
>> > One line difference though. I wasn't aware that the default is used
>> > when .best_encoder is null, so I just hooked it to the default helper.
>> >
>> > If it's OK with you, I'll do a follow-up to drop the hook, so we don't
>> > have two conflicting patches in flight.
>>
>> I have a follow-up patches to unexport the helper, so would be good if Alex
>> sends out the pull request so I can sort this all out in drm-misc-next. I don't
>> want to split up the patch series if possible.
>> Or we just deal with the conflict, it's minor.
>>
>> Alex?
>
> I'm planning to send the PR next week when I'm back in the office.  I can drop Leo's patch when I send the PR if that makes things easier.

I'm happy to rebase, just go ahead. I've added a bunch more patches to
my helper cleanup series anyway, so will take a bit longer to get all
landed.
-Daniel

>
> Alex
>
>> -Daniel
>>
>> > Leo
>> >
>> >
>> >>
>> >> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
>> >> Cc: Alex Deucher <alexander.deucher@amd.com>
>> >> Cc: Harry Wentland <harry.wentland@amd.com>
>> >> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
>> >> Cc: Tony Cheng <Tony.Cheng@amd.com>
>> >> Cc: "Leo (Sunpeng) Li" <sunpeng.li@amd.com>
>> >> Cc: Shirish S <shirish.s@amd.com>
>> >> ---
>> >>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ----------------
>> ---
>> >>   1 file changed, 23 deletions(-)
>> >>
>> >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> >> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> >> index af6adffba788..333f9904f135 100644
>> >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> >> @@ -2794,28 +2794,6 @@ static const struct drm_connector_funcs
>> >> amdgpu_dm_connector_funcs = {
>> >>         .atomic_get_property =
>> amdgpu_dm_connector_atomic_get_property
>> >>   };
>> >>   -static struct drm_encoder *best_encoder(struct drm_connector
>> >> *connector)
>> >> -{
>> >> -       int enc_id = connector->encoder_ids[0];
>> >> -       struct drm_mode_object *obj;
>> >> -       struct drm_encoder *encoder;
>> >> -
>> >> -       DRM_DEBUG_DRIVER("Finding the best encoder\n");
>> >> -
>> >> -       /* pick the encoder ids */
>> >> -       if (enc_id) {
>> >> -               obj = drm_mode_object_find(connector->dev, NULL, enc_id,
>> >> DRM_MODE_OBJECT_ENCODER);
>> >> -               if (!obj) {
>> >> -                       DRM_ERROR("Couldn't find a matching encoder for
>> >> our connector\n");
>> >> -                       return NULL;
>> >> -               }
>> >> -               encoder = obj_to_encoder(obj);
>> >> -               return encoder;
>> >> -       }
>> >> -       DRM_ERROR("No encoder id\n");
>> >> -       return NULL;
>> >> -}
>> >> -
>> >>   static int get_modes(struct drm_connector *connector)
>> >>   {
>> >>         return amdgpu_dm_connector_get_modes(connector);
>> >> @@ -2934,7 +2912,6 @@ amdgpu_dm_connector_helper_funcs = {
>> >>          */
>> >>         .get_modes = get_modes,
>> >>         .mode_valid = amdgpu_dm_connector_mode_valid,
>> >> -       .best_encoder = best_encoder
>> >>   };
>> >>     static void dm_crtc_helper_disable(struct drm_crtc *crtc)
>> >>
>> >
>>
>>
>>
>> --
>> Daniel Vetter
>> Software Engineer, Intel Corporation
>> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2018-09-06 22:12 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-03 16:54 [PATCH 01/14] drm: Add drm/kernel.h header file Daniel Vetter
2018-09-03 16:54 ` [PATCH 02/14] drm: Drop drmP.h from drm_connector.c Daniel Vetter
2018-09-03 16:54 ` [PATCH 03/14] drm: drop drmP.h include from drm_plane.c Daniel Vetter
2018-09-03 16:54 ` [PATCH 04/14] drm: drop drmP.h include from drm_crtc.c Daniel Vetter
2018-09-03 16:54 ` [PATCH 05/14] drm/atomic: trim driver interface/docs Daniel Vetter
     [not found] ` <20180903165439.24845-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2018-09-03 16:54   ` [PATCH 06/14] drm: extract drm_atomic_uapi.c Daniel Vetter
2018-09-04 20:41     ` Rodrigo Vivi
2018-09-05  7:55       ` Daniel Vetter
     [not found]     ` <20180903165439.24845-6-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2018-09-05  8:00       ` [PATCH] " Daniel Vetter
2018-09-03 16:54 ` [PATCH 07/14] drm/atomic-helper: Unexport drm_atomic_helper_best_encoder Daniel Vetter
2018-09-03 16:54 ` [PATCH 08/14] drm/amdgpu: Remove default best_encoder hook from DC Daniel Vetter
2018-09-05 13:45   ` Leo Li
2018-09-05 13:48     ` Daniel Vetter
2018-09-06 16:33       ` Deucher, Alexander
2018-09-06 22:12         ` Daniel Vetter
2018-09-03 16:54 ` [PATCH 09/14] drm: Update todo.rst Daniel Vetter
2018-09-03 17:24   ` Sam Ravnborg
2018-09-03 17:38   ` [Intel-gfx] " Emil Velikov
2018-09-04 12:19     ` Daniel Vetter
2018-09-04 20:52       ` Emil Velikov
2018-09-05  8:04   ` [PATCH] " Daniel Vetter
2018-09-03 16:54 ` [PATCH 10/14] drm: Extract drm_atomic_state_helper.[hc] Daniel Vetter
2018-09-03 16:54 ` [PATCH 11/14] drm/vmwgfx: Remove confused comment from vmw_du_connector_atomic_set_property Daniel Vetter
2018-09-03 16:54 ` [PATCH 12/14] drm/vmwgfx: Don't look at state->allow_modeset Daniel Vetter
2018-09-03 16:54 ` [PATCH 13/14] drm/atomic: Improve docs for drm_atomic_state->allow_modeset Daniel Vetter
2018-09-03 16:54 ` [PATCH 14/14] drm/vmwgfx: Add FIXME comments for customer page_flip handlers Daniel Vetter
2018-09-04 13:45   ` Thomas Hellstrom
2018-09-04 14:19     ` Daniel Vetter
2018-09-03 17:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file Patchwork
2018-09-03 17:53 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-09-03 18:05 ` ✗ Fi.CI.BAT: failure " Patchwork
2018-09-05  8:09 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/14] drm: Add drm/kernel.h header file (rev3) Patchwork
2018-09-05  8:15 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-09-05  8:26 ` ✗ Fi.CI.BAT: failure " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.