diff mbox

[RFC,v3,03/12] drm: Make ioctls available for in-kernel clients part 1

Message ID 20180222200653.19453-4-noralf@tronnes.org (mailing list archive)
State New, archived
Headers show

Commit Message

Noralf Trønnes Feb. 22, 2018, 8:06 p.m. UTC
This is part 1 of making ioctls useable for in-kernel clients.
Make an ioctl wrapper function that calls a function that can be used by
in-kernel clients.

It adjusts the following functions to handle kernel buffers:
- drm_mode_getresources()
- drm_mode_setcrtc()
- drm_mode_getconnector()
- drm_mode_dirtyfb_ioctl()

There is no functional change from the userspace side.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_connector.c     | 50 +++++++++++++++--------
 drivers/gpu/drm/drm_crtc.c          | 32 ++++++++++-----
 drivers/gpu/drm/drm_crtc_internal.h | 23 ++++++++---
 drivers/gpu/drm/drm_framebuffer.c   | 56 +++++++++++++++----------
 drivers/gpu/drm/drm_ioctl.c         |  6 +--
 drivers/gpu/drm/drm_mode_config.c   | 81 +++++++++++++++++++++++++------------
 6 files changed, 164 insertions(+), 84 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b3cde897cd80..57c9c27ceb05 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1544,10 +1544,10 @@  static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
 	return true;
 }
 
-int drm_mode_getconnector(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
+int drm_mode_getconnector(struct drm_device *dev,
+			  struct drm_mode_get_connector *out_resp,
+			  struct drm_file *file_priv, bool user)
 {
-	struct drm_mode_get_connector *out_resp = data;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_display_mode *mode;
@@ -1556,9 +1556,10 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 	int ret = 0;
 	int copied = 0;
 	int i;
-	struct drm_mode_modeinfo u_mode;
-	struct drm_mode_modeinfo __user *mode_ptr;
-	uint32_t __user *encoder_ptr;
+	struct drm_mode_modeinfo __user *mode_ptr_user;
+	struct drm_mode_modeinfo u_mode, *mode_ptr;
+	uint32_t __user *encoder_ptr_user;
+	u32 *encoder_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -1575,13 +1576,18 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 
 	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
 		copied = 0;
-		encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
+		encoder_ptr_user = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
+		encoder_ptr = (u32 *)(unsigned long)(out_resp->encoders_ptr);
 		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 			if (connector->encoder_ids[i] != 0) {
-				if (put_user(connector->encoder_ids[i],
-					     encoder_ptr + copied)) {
-					ret = -EFAULT;
-					goto out;
+				if (user) {
+					if (put_user(connector->encoder_ids[i],
+						     encoder_ptr_user + copied)) {
+						ret = -EFAULT;
+						goto out;
+					}
+				} else {
+					encoder_ptr[copied] = connector->encoder_ids[i];
 				}
 				copied++;
 			}
@@ -1616,18 +1622,23 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 	 */
 	if ((out_resp->count_modes >= mode_count) && mode_count) {
 		copied = 0;
-		mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
+		mode_ptr_user = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
+		mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr;
 		list_for_each_entry(mode, &connector->modes, head) {
 			if (!drm_mode_expose_to_userspace(mode, file_priv))
 				continue;
 
 			drm_mode_convert_to_umode(&u_mode, mode);
-			if (copy_to_user(mode_ptr + copied,
-					 &u_mode, sizeof(u_mode))) {
-				ret = -EFAULT;
-				mutex_unlock(&dev->mode_config.mutex);
+			if (user) {
+				if (copy_to_user(mode_ptr_user + copied,
+						 &u_mode, sizeof(u_mode))) {
+					ret = -EFAULT;
+					mutex_unlock(&dev->mode_config.mutex);
 
-				goto out;
+					goto out;
+				}
+			} else {
+				mode_ptr[copied] = u_mode;
 			}
 			copied++;
 		}
@@ -1656,6 +1667,11 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 	return ret;
 }
 
+int drm_mode_getconnector_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	return drm_mode_getconnector(dev, data, file_priv, true);
+}
 
 /**
  * DOC: Tile group
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 353e24fcde9e..c9ab1cc6b412 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -538,21 +538,21 @@  EXPORT_SYMBOL(drm_crtc_check_viewport);
 /**
  * drm_mode_setcrtc - set CRTC configuration
  * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
+ * @crtc_req: pointer to request structure
+ * @file_priv: drm file
+ * @user: True if called form userspace, false from in-kernel client
  *
- * Build a new CRTC configuration based on user request.
+ * Build a new CRTC configuration based on request.
  *
- * Called by the user via ioctl.
+ * Called by the user via ioctl, or by an in-kernel client.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_setcrtc(struct drm_device *dev, void *data,
-		     struct drm_file *file_priv)
+int drm_mode_setcrtc(struct drm_device *dev, struct drm_mode_crtc *crtc_req,
+		     struct drm_file *file_priv, bool user)
 {
 	struct drm_mode_config *config = &dev->mode_config;
-	struct drm_mode_crtc *crtc_req = data;
 	struct drm_crtc *crtc;
 	struct drm_connector **connector_set = NULL, *connector;
 	struct drm_framebuffer *fb = NULL;
@@ -678,10 +678,14 @@  int drm_mode_setcrtc(struct drm_device *dev, void *data,
 
 		for (i = 0; i < crtc_req->count_connectors; i++) {
 			connector_set[i] = NULL;
-			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
-			if (get_user(out_id, &set_connectors_ptr[i])) {
-				ret = -EFAULT;
-				goto out;
+			if (user) {
+				set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
+				if (get_user(out_id, &set_connectors_ptr[i])) {
+					ret = -EFAULT;
+					goto out;
+				}
+			} else {
+				out_id = ((u32 *)(unsigned long)crtc_req->set_connectors_ptr)[i];
 			}
 
 			connector = drm_connector_lookup(dev, file_priv, out_id);
@@ -732,6 +736,12 @@  int drm_mode_setcrtc(struct drm_device *dev, void *data,
 	return ret;
 }
 
+int drm_mode_setcrtc_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	return drm_mode_setcrtc(dev, data, file_priv, true);
+}
+
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
 			       struct drm_property *property,
 			       uint64_t value)
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index af00f42ba269..29c59ce7e56e 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -45,20 +45,26 @@  void drm_crtc_unregister_all(struct drm_device *dev);
 
 struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc);
 
+int drm_mode_setcrtc(struct drm_device *dev, struct drm_mode_crtc *crtc_req,
+		     struct drm_file *file_priv, bool user);
+
 /* IOCTLs */
 int drm_mode_getcrtc(struct drm_device *dev,
 		     void *data, struct drm_file *file_priv);
-int drm_mode_setcrtc(struct drm_device *dev,
-		     void *data, struct drm_file *file_priv);
+int drm_mode_setcrtc_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv);
 
 
 /* drm_mode_config.c */
 int drm_modeset_register_all(struct drm_device *dev);
 void drm_modeset_unregister_all(struct drm_device *dev);
+int drm_mode_getresources(struct drm_device *dev,
+			  struct drm_mode_card_res *card_res,
+			  struct drm_file *file_priv, bool user);
 
 /* IOCTLs */
-int drm_mode_getresources(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv);
+int drm_mode_getresources_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
 
 
 /* drm_dumb_buffers.c */
@@ -143,12 +149,15 @@  int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
 int drm_connector_create_standard_properties(struct drm_device *dev);
 const char *drm_get_connector_force_name(enum drm_connector_force force);
 void drm_connector_free_work_fn(struct work_struct *work);
+int drm_mode_getconnector(struct drm_device *dev,
+			  struct drm_mode_get_connector *out_resp,
+			  struct drm_file *file_priv, bool user);
 
 /* IOCTL */
 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
 					  void *data, struct drm_file *file_priv);
-int drm_mode_getconnector(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv);
+int drm_mode_getconnector_ioctl(struct drm_device *dev,
+				void *data, struct drm_file *file_priv);
 
 /* drm_framebuffer.c */
 struct drm_framebuffer *
@@ -161,6 +170,8 @@  int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
 				     const struct drm_framebuffer *fb);
 void drm_fb_release(struct drm_file *file_priv);
 
+int drm_mode_dirtyfb(struct drm_device *dev, struct drm_mode_fb_dirty_cmd *req,
+		     struct drm_file *file_priv, bool user);
 
 /* IOCTL */
 int drm_mode_addfb(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 5a13ff29f4f0..e918c7124dcd 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -486,10 +486,11 @@  int drm_mode_getfb(struct drm_device *dev,
 }
 
 /**
- * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
+ * drm_mode_dirtyfb - flush frontbuffer rendering on an FB
+ * @dev: drm device
+ * @r: pointer to request structure
+ * @file_priv: drm file
+ * @user: true if called form userspace, false if called by in-kernel client
  *
  * Lookup the FB and flush out the damaged area supplied by userspace as a clip
  * rectangle list. Generic userspace which does frontbuffer rendering must call
@@ -499,17 +500,16 @@  int drm_mode_getfb(struct drm_device *dev,
  * Modesetting drivers which always update the frontbuffer do not need to
  * implement the corresponding &drm_framebuffer_funcs.dirty callback.
  *
- * Called by the user via ioctl.
+ * Called by the user via ioctl, or by an in-kernel client.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv)
+int drm_mode_dirtyfb(struct drm_device *dev, struct drm_mode_fb_dirty_cmd *r,
+		     struct drm_file *file_priv, bool user)
 {
 	struct drm_clip_rect __user *clips_ptr;
 	struct drm_clip_rect *clips = NULL;
-	struct drm_mode_fb_dirty_cmd *r = data;
 	struct drm_framebuffer *fb;
 	unsigned flags;
 	int num_clips;
@@ -523,9 +523,8 @@  int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 		return -ENOENT;
 
 	num_clips = r->num_clips;
-	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
 
-	if (!num_clips != !clips_ptr) {
+	if (!num_clips != !r->clips_ptr) {
 		ret = -EINVAL;
 		goto out_err1;
 	}
@@ -538,22 +537,28 @@  int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 		goto out_err1;
 	}
 
-	if (num_clips && clips_ptr) {
+	if (num_clips && r->clips_ptr) {
 		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
 			ret = -EINVAL;
 			goto out_err1;
 		}
-		clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
-		if (!clips) {
-			ret = -ENOMEM;
-			goto out_err1;
-		}
 
-		ret = copy_from_user(clips, clips_ptr,
-				     num_clips * sizeof(*clips));
-		if (ret) {
-			ret = -EFAULT;
-			goto out_err2;
+		if (user) {
+			clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
+			clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+			if (!clips) {
+				ret = -ENOMEM;
+				goto out_err1;
+			}
+
+			ret = copy_from_user(clips, clips_ptr,
+					     num_clips * sizeof(*clips));
+			if (ret) {
+				ret = -EFAULT;
+				goto out_err2;
+			}
+		} else {
+			clips = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
 		}
 	}
 
@@ -565,13 +570,20 @@  int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 	}
 
 out_err2:
-	kfree(clips);
+	if (user)
+		kfree(clips);
 out_err1:
 	drm_framebuffer_put(fb);
 
 	return ret;
 }
 
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	return drm_mode_dirtyfb(dev, data, file_priv, true);
+}
+
 /**
  * drm_fb_release - remove and free the FBs on this file
  * @priv: drm file for the ioctl
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index af782911c505..346b8060df7c 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -613,21 +613,21 @@  static const struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index e5c653357024..a5c092e4a099 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -81,19 +81,20 @@  void drm_modeset_unregister_all(struct drm_device *dev)
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_getresources(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
+int drm_mode_getresources(struct drm_device *dev,
+			  struct drm_mode_card_res *card_res,
+			  struct drm_file *file_priv, bool user)
 {
-	struct drm_mode_card_res *card_res = data;
 	struct drm_framebuffer *fb;
 	struct drm_connector *connector;
 	struct drm_crtc *crtc;
 	struct drm_encoder *encoder;
 	int count, ret = 0;
-	uint32_t __user *fb_id;
-	uint32_t __user *crtc_id;
-	uint32_t __user *connector_id;
-	uint32_t __user *encoder_id;
+	uint32_t __user *fb_id_user;
+	uint32_t __user *crtc_id_user;
+	uint32_t __user *connector_id_user;
+	uint32_t __user *encoder_id_user;
+	u32 *fb_id, *crtc_id, *connector_id, *encoder_id;
 	struct drm_connector_list_iter conn_iter;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -102,12 +103,18 @@  int drm_mode_getresources(struct drm_device *dev, void *data,
 
 	mutex_lock(&file_priv->fbs_lock);
 	count = 0;
-	fb_id = u64_to_user_ptr(card_res->fb_id_ptr);
+	fb_id_user = u64_to_user_ptr(card_res->fb_id_ptr);
+	fb_id = (u32 *)(unsigned long)(card_res->fb_id_ptr);
 	list_for_each_entry(fb, &file_priv->fbs, filp_head) {
-		if (count < card_res->count_fbs &&
-		    put_user(fb->base.id, fb_id + count)) {
-			mutex_unlock(&file_priv->fbs_lock);
-			return -EFAULT;
+		if (count < card_res->count_fbs) {
+			if (user) {
+				if (put_user(fb->base.id, fb_id_user + count)) {
+					mutex_unlock(&file_priv->fbs_lock);
+					return -EFAULT;
+				}
+			} else {
+				fb_id[count] = fb->base.id;
+			}
 		}
 		count++;
 	}
@@ -120,36 +127,54 @@  int drm_mode_getresources(struct drm_device *dev, void *data,
 	card_res->min_width = dev->mode_config.min_width;
 
 	count = 0;
-	crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
+	crtc_id_user = u64_to_user_ptr(card_res->crtc_id_ptr);
+	crtc_id = (u32 *)(unsigned long)(card_res->crtc_id_ptr);
 	drm_for_each_crtc(crtc, dev) {
 		if (drm_lease_held(file_priv, crtc->base.id)) {
-			if (count < card_res->count_crtcs &&
-			    put_user(crtc->base.id, crtc_id + count))
-				return -EFAULT;
+			if (count < card_res->count_crtcs) {
+				if (user) {
+					if (put_user(crtc->base.id, crtc_id_user + count))
+						return -EFAULT;
+				} else {
+					crtc_id[count] = crtc->base.id;
+				}
+			}
 			count++;
 		}
 	}
 	card_res->count_crtcs = count;
 
 	count = 0;
-	encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
+	encoder_id_user = u64_to_user_ptr(card_res->encoder_id_ptr);
+	encoder_id = (u32 *)(unsigned long)(card_res->encoder_id_ptr);
 	drm_for_each_encoder(encoder, dev) {
-		if (count < card_res->count_encoders &&
-		    put_user(encoder->base.id, encoder_id + count))
-			return -EFAULT;
+		if (count < card_res->count_encoders) {
+			if (user) {
+				if (put_user(encoder->base.id, encoder_id_user + count))
+					return -EFAULT;
+			} else {
+				encoder_id[count] = encoder->base.id;
+			}
+		}
 		count++;
 	}
 	card_res->count_encoders = count;
 
 	drm_connector_list_iter_begin(dev, &conn_iter);
 	count = 0;
-	connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
+	connector_id_user = u64_to_user_ptr(card_res->connector_id_ptr);
+	connector_id = (u32 *)(unsigned long)(card_res->connector_id_ptr);
 	drm_for_each_connector_iter(connector, &conn_iter) {
 		if (drm_lease_held(file_priv, connector->base.id)) {
-			if (count < card_res->count_connectors &&
-			    put_user(connector->base.id, connector_id + count)) {
-				drm_connector_list_iter_end(&conn_iter);
-				return -EFAULT;
+			if (count < card_res->count_connectors) {
+				if (user) {
+					if (put_user(connector->base.id, connector_id_user + count)) {
+						drm_connector_list_iter_end(&conn_iter);
+						return -EFAULT;
+					}
+				} else {
+					connector_id[count] = connector->base.id;
+				}
 			}
 			count++;
 		}
@@ -160,6 +185,12 @@  int drm_mode_getresources(struct drm_device *dev, void *data,
 	return ret;
 }
 
+int drm_mode_getresources_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	return drm_mode_getresources(dev, data, file_priv, true);
+}
+
 /**
  * drm_mode_config_reset - call ->reset callbacks
  * @dev: drm device