From patchwork Thu Feb 22 20:06:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10236329 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 331BC60349 for ; Thu, 22 Feb 2018 20:21:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2693728BB8 for ; Thu, 22 Feb 2018 20:21:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 735AA28E24; Thu, 22 Feb 2018 20:21:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CB20B28EA0 for ; Thu, 22 Feb 2018 20:21:19 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 340C96EC6A; Thu, 22 Feb 2018 20:21:19 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id B91C36EC69 for ; Thu, 22 Feb 2018 20:21:17 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:34576 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1eox91-0004nQ-PS; Thu, 22 Feb 2018 21:07:07 +0100 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Thu, 22 Feb 2018 21:06:44 +0100 Message-Id: <20180222200653.19453-4-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180222200653.19453-1-noralf@tronnes.org> References: <20180222200653.19453-1-noralf@tronnes.org> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC v3 03/12] drm: Make ioctls available for in-kernel clients part 1 X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= , laurent.pinchart@ideasonboard.com, dh.herrmann@gmail.com Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 --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