From c394c2b08e247c32ef292b75fd8b34312465f8ae Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 10 Jun 2014 08:28:08 -0700 Subject: drm: Refactor framebuffer creation to allow internal use (v2) Refactor DRM framebuffer creation into a new function that returns a struct drm_framebuffer directly. The upcoming universal cursor support will want to create framebuffers internally to wrap cursor buffers, so we want to be able to share that framebuffer creation with the drm_mode_addfb2 ioctl handler. v2: Take struct drm_mode_fb_cmd2 parameter directly rather than void* Reviewed-by: Daniel Vetter Signed-off-by: Matt Roper Reviewed-by: Pallavi G Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 69 ++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe94cc10cd35..5a88267fa8dd 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -41,6 +41,10 @@ #include "drm_crtc_internal.h" +static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, + struct drm_mode_fb_cmd2 *r, + struct drm_file *file_priv); + /** * drm_modeset_lock_all - take all modeset locks * @dev: drm device @@ -2827,56 +2831,38 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) return 0; } -/** - * drm_mode_addfb2 - add an FB to the graphics configuration - * @dev: drm device for the ioctl - * @data: data pointer for the ioctl - * @file_priv: drm file for the ioctl call - * - * Add a new FB to the specified CRTC, given a user request with format. This is - * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers - * and uses fourcc codes as pixel format specifiers. - * - * Called by the user via ioctl. - * - * Returns: - * Zero on success, errno on failure. - */ -int drm_mode_addfb2(struct drm_device *dev, - void *data, struct drm_file *file_priv) +static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, + struct drm_mode_fb_cmd2 *r, + struct drm_file *file_priv) { - struct drm_mode_fb_cmd2 *r = data; struct drm_mode_config *config = &dev->mode_config; struct drm_framebuffer *fb; int ret; - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - if (r->flags & ~DRM_MODE_FB_INTERLACED) { DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); - return -EINVAL; + return ERR_PTR(-EINVAL); } if ((config->min_width > r->width) || (r->width > config->max_width)) { DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", r->width, config->min_width, config->max_width); - return -EINVAL; + return ERR_PTR(-EINVAL); } if ((config->min_height > r->height) || (r->height > config->max_height)) { DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", r->height, config->min_height, config->max_height); - return -EINVAL; + return ERR_PTR(-EINVAL); } ret = framebuffer_check(r); if (ret) - return ret; + return ERR_PTR(ret); fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (IS_ERR(fb)) { DRM_DEBUG_KMS("could not create framebuffer\n"); - return PTR_ERR(fb); + return fb; } mutex_lock(&file_priv->fbs_lock); @@ -2885,8 +2871,37 @@ int drm_mode_addfb2(struct drm_device *dev, DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); mutex_unlock(&file_priv->fbs_lock); + return fb; +} - return ret; +/** + * drm_mode_addfb2 - add an FB to the graphics configuration + * @dev: drm device for the ioctl + * @data: data pointer for the ioctl + * @file_priv: drm file for the ioctl call + * + * Add a new FB to the specified CRTC, given a user request with format. This is + * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers + * and uses fourcc codes as pixel format specifiers. + * + * Called by the user via ioctl. + * + * Returns: + * Zero on success, errno on failure. + */ +int drm_mode_addfb2(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_framebuffer *fb; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + fb = add_framebuffer_internal(dev, data, file_priv); + if (IS_ERR(fb)) + return PTR_ERR(fb); + + return 0; } /** -- cgit v1.2.3 From b36552b32aa9c69e83a3a20bda56379fb9e52435 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 10 Jun 2014 08:28:09 -0700 Subject: drm: Refactor setplane to allow internal use (v3) Refactor DRM setplane code into a new setplane_internal() function that takes DRM objects directly as parameters rather than looking them up by ID. We'll use this in a future patch when we implement legacy cursor ioctls on top of the universal plane interface. v3: - Move integer overflow checking from setplane_internal to setplane ioctl. The upcoming legacy cursor support via universal planes needs to maintain current cursor ioctl semantics and not return error for these extreme values (found via intel-gpu-tools kms_cursor_crc test). v2: - Allow planes to be disabled without a valid crtc again (and add mention of this to setplane's kerneldoc, since it doesn't seem to be mentioned anywhere else). - Reformat some parameter line wrap Reviewed-by: Daniel Vetter Signed-off-by: Matt Roper Reviewed-by: Pallavi G Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 176 ++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 74 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5a88267fa8dd..27eae03bd38e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2122,45 +2122,32 @@ out: return ret; } -/** - * drm_mode_setplane - configure a plane's configuration - * @dev: DRM device - * @data: ioctl data* - * @file_priv: DRM file info +/* + * setplane_internal - setplane handler for internal callers * - * Set plane configuration, including placement, fb, scaling, and other factors. - * Or pass a NULL fb to disable. + * Note that we assume an extra reference has already been taken on fb. If the + * update fails, this reference will be dropped before return; if it succeeds, + * the previous framebuffer (if any) will be unreferenced instead. * - * Returns: - * Zero on success, errno on failure. + * src_{x,y,w,h} are provided in 16.16 fixed point format */ -int drm_mode_setplane(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int setplane_internal(struct drm_crtc *crtc, + struct drm_plane *plane, + struct drm_framebuffer *fb, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + /* src_{x,y,w,h} values are 16.16 fixed point */ + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) { - struct drm_mode_set_plane *plane_req = data; - struct drm_plane *plane; - struct drm_crtc *crtc; - struct drm_framebuffer *fb = NULL, *old_fb = NULL; + struct drm_device *dev = crtc->dev; + struct drm_framebuffer *old_fb = NULL; int ret = 0; unsigned int fb_width, fb_height; int i; - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - - /* - * First, find the plane, crtc, and fb objects. If not available, - * we don't bother to call the driver. - */ - plane = drm_plane_find(dev, plane_req->plane_id); - if (!plane) { - DRM_DEBUG_KMS("Unknown plane ID %d\n", - plane_req->plane_id); - return -ENOENT; - } - /* No fb means shut it down */ - if (!plane_req->fb_id) { + if (!fb) { drm_modeset_lock_all(dev); old_fb = plane->fb; ret = plane->funcs->disable_plane(plane); @@ -2174,14 +2161,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - crtc = drm_crtc_find(dev, plane_req->crtc_id); - if (!crtc) { - DRM_DEBUG_KMS("Unknown crtc ID %d\n", - plane_req->crtc_id); - ret = -ENOENT; - goto out; - } - /* Check whether this plane is usable on this CRTC */ if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { DRM_DEBUG_KMS("Invalid crtc for plane\n"); @@ -2189,14 +2168,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - fb = drm_framebuffer_lookup(dev, plane_req->fb_id); - if (!fb) { - DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", - plane_req->fb_id); - ret = -ENOENT; - goto out; - } - /* Check whether this plane supports the fb pixel format. */ for (i = 0; i < plane->format_count; i++) if (fb->pixel_format == plane->format_types[i]) @@ -2212,43 +2183,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data, fb_height = fb->height << 16; /* Make sure source coordinates are inside the fb. */ - if (plane_req->src_w > fb_width || - plane_req->src_x > fb_width - plane_req->src_w || - plane_req->src_h > fb_height || - plane_req->src_y > fb_height - plane_req->src_h) { + if (src_w > fb_width || + src_x > fb_width - src_w || + src_h > fb_height || + src_y > fb_height - src_h) { DRM_DEBUG_KMS("Invalid source coordinates " "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", - plane_req->src_w >> 16, - ((plane_req->src_w & 0xffff) * 15625) >> 10, - plane_req->src_h >> 16, - ((plane_req->src_h & 0xffff) * 15625) >> 10, - plane_req->src_x >> 16, - ((plane_req->src_x & 0xffff) * 15625) >> 10, - plane_req->src_y >> 16, - ((plane_req->src_y & 0xffff) * 15625) >> 10); + src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, + src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, + src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, + src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); ret = -ENOSPC; goto out; } - /* Give drivers some help against integer overflows */ - if (plane_req->crtc_w > INT_MAX || - plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || - plane_req->crtc_h > INT_MAX || - plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { - DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", - plane_req->crtc_w, plane_req->crtc_h, - plane_req->crtc_x, plane_req->crtc_y); - ret = -ERANGE; - goto out; - } - drm_modeset_lock_all(dev); old_fb = plane->fb; ret = plane->funcs->update_plane(plane, crtc, fb, - plane_req->crtc_x, plane_req->crtc_y, - plane_req->crtc_w, plane_req->crtc_h, - plane_req->src_x, plane_req->src_y, - plane_req->src_w, plane_req->src_h); + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); if (!ret) { plane->crtc = crtc; plane->fb = fb; @@ -2265,6 +2218,81 @@ out: drm_framebuffer_unreference(old_fb); return ret; + +} + +/** + * drm_mode_setplane - configure a plane's configuration + * @dev: DRM device + * @data: ioctl data* + * @file_priv: DRM file info + * + * Set plane configuration, including placement, fb, scaling, and other factors. + * Or pass a NULL fb to disable (planes may be disabled without providing a + * valid crtc). + * + * Returns: + * Zero on success, errno on failure. + */ +int drm_mode_setplane(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_set_plane *plane_req = data; + struct drm_mode_object *obj; + struct drm_plane *plane; + struct drm_crtc *crtc = NULL; + struct drm_framebuffer *fb = NULL; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + /* Give drivers some help against integer overflows */ + if (plane_req->crtc_w > INT_MAX || + plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || + plane_req->crtc_h > INT_MAX || + plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { + DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", + plane_req->crtc_w, plane_req->crtc_h, + plane_req->crtc_x, plane_req->crtc_y); + return -ERANGE; + } + + /* + * First, find the plane, crtc, and fb objects. If not available, + * we don't bother to call the driver. + */ + obj = drm_mode_object_find(dev, plane_req->plane_id, + DRM_MODE_OBJECT_PLANE); + if (!obj) { + DRM_DEBUG_KMS("Unknown plane ID %d\n", + plane_req->plane_id); + return -ENOENT; + } + plane = obj_to_plane(obj); + + if (plane_req->fb_id) { + fb = drm_framebuffer_lookup(dev, plane_req->fb_id); + if (!fb) { + DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", + plane_req->fb_id); + return -ENOENT; + } + + obj = drm_mode_object_find(dev, plane_req->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_DEBUG_KMS("Unknown crtc ID %d\n", + plane_req->crtc_id); + return -ENOENT; + } + crtc = obj_to_crtc(obj); + } + + return setplane_internal(crtc, plane, fb, + plane_req->crtc_x, plane_req->crtc_y, + plane_req->crtc_w, plane_req->crtc_h, + plane_req->src_x, plane_req->src_y, + plane_req->src_w, plane_req->src_h); } /** -- cgit v1.2.3 From 161d0dc1dccb17ff7a38f462c7c0d4ef8bcc5662 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 10 Jun 2014 08:28:10 -0700 Subject: drm: Support legacy cursor ioctls via universal planes when possible (v4) If drivers support universal planes and have registered a cursor plane with the DRM core, we should use that universal plane support when handling legacy cursor ioctls. Drivers that transition to universal planes won't have to maintain separate legacy ioctl handling; drivers that don't transition to universal planes will continue to operate without any change to behavior. Note that there's a bit of a mismatch between the legacy cursor ioctls and the universal plane API's --- legacy ioctl's use driver buffer handles directly whereas the universal plane API takes drm_framebuffers. Since there's no way to recover the driver handle from a drm_framebuffer, we can implement legacy ioctl's in terms of universal plane interfaces, but cannot implement universal plane interfaces in terms of legacy ioctls. Specifically, there's no way to create a general cursor helper in the way we previously created a primary plane helper. It's important to land this patch before any patches that add universal cursor support to individual drivers so that drivers don't have to worry about juggling two different styles of reference counting for cursor buffers when userspace mixes and matches legacy and universal cursor calls. With this patch, a driver that switches to universal cursor support may assume that all cursor buffers are wrapped in a drm_framebuffer and can rely on framebuffer reference counting for all cursor operations. v4: - Add comments pointing out setplane_internal's reference-eating semantics. v3: - Drop drm_mode_rmfb() call that is no longer needed now that we're using setplane_internal(), which takes care of deref'ing the appropriate framebuffer. v2: - Use new add_framebuffer_internal() function to create framebuffer rather than trying to call directly into the ioctl interface and look up the handle returned. - Use new setplane_internal() function to update the cursor plane rather than calling through the ioctl interface. Note that since we're no longer looking up an fb_id, no extra reference will be taken here. - Grab extra reference to fb under lock in !BO case to avoid issues where racing userspace could cause the fb to be destroyed out from under us after we grab the fb pointer. Reviewed-by: Daniel Vetter Signed-off-by: Matt Roper Reviewed-by: Pallavi G Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 4 ++ 2 files changed, 111 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 27eae03bd38e..b5bce5b6bf61 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2288,6 +2288,10 @@ int drm_mode_setplane(struct drm_device *dev, void *data, crtc = obj_to_crtc(obj); } + /* + * setplane_internal will take care of deref'ing either the old or new + * framebuffer depending on success. + */ return setplane_internal(crtc, plane, fb, plane_req->crtc_x, plane_req->crtc_y, plane_req->crtc_w, plane_req->crtc_h, @@ -2541,6 +2545,102 @@ out: return ret; } +/** + * drm_mode_cursor_universal - translate legacy cursor ioctl call into a + * universal plane handler call + * @crtc: crtc to update cursor for + * @req: data pointer for the ioctl + * @file_priv: drm file for the ioctl call + * + * Legacy cursor ioctl's work directly with driver buffer handles. To + * translate legacy ioctl calls into universal plane handler calls, we need to + * wrap the native buffer handle in a drm_framebuffer. + * + * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB + * buffer with a pitch of 4*width; the universal plane interface should be used + * directly in cases where the hardware can support other buffer settings and + * userspace wants to make use of these capabilities. + * + * Returns: + * Zero on success, errno on failure. + */ +static int drm_mode_cursor_universal(struct drm_crtc *crtc, + struct drm_mode_cursor2 *req, + struct drm_file *file_priv) +{ + struct drm_device *dev = crtc->dev; + struct drm_framebuffer *fb = NULL; + struct drm_mode_fb_cmd2 fbreq = { + .width = req->width, + .height = req->height, + .pixel_format = DRM_FORMAT_ARGB8888, + .pitches = { req->width * 4 }, + .handles = { req->handle }, + }; + int32_t crtc_x, crtc_y; + uint32_t crtc_w = 0, crtc_h = 0; + uint32_t src_w = 0, src_h = 0; + int ret = 0; + + BUG_ON(!crtc->cursor); + + /* + * Obtain fb we'll be using (either new or existing) and take an extra + * reference to it if fb != null. setplane will take care of dropping + * the reference if the plane update fails. + */ + if (req->flags & DRM_MODE_CURSOR_BO) { + if (req->handle) { + fb = add_framebuffer_internal(dev, &fbreq, file_priv); + if (IS_ERR(fb)) { + DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); + return PTR_ERR(fb); + } + + drm_framebuffer_reference(fb); + } else { + fb = NULL; + } + } else { + mutex_lock(&dev->mode_config.mutex); + fb = crtc->cursor->fb; + if (fb) + drm_framebuffer_reference(fb); + mutex_unlock(&dev->mode_config.mutex); + } + + if (req->flags & DRM_MODE_CURSOR_MOVE) { + crtc_x = req->x; + crtc_y = req->y; + } else { + crtc_x = crtc->cursor_x; + crtc_y = crtc->cursor_y; + } + + if (fb) { + crtc_w = fb->width; + crtc_h = fb->height; + src_w = fb->width << 16; + src_h = fb->height << 16; + } + + /* + * setplane_internal will take care of deref'ing either the old or new + * framebuffer depending on success. + */ + ret = setplane_internal(crtc, crtc->cursor, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + 0, 0, src_w, src_h); + + /* Update successful; save new cursor position, if necessary */ + if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { + crtc->cursor_x = req->x; + crtc->cursor_y = req->y; + } + + return ret; +} + static int drm_mode_cursor_common(struct drm_device *dev, struct drm_mode_cursor2 *req, struct drm_file *file_priv) @@ -2560,6 +2660,13 @@ static int drm_mode_cursor_common(struct drm_device *dev, return -ENOENT; } + /* + * If this crtc has a universal cursor plane, call that plane's update + * handler rather than using legacy cursor handlers. + */ + if (crtc->cursor) + return drm_mode_cursor_universal(crtc, req, file_priv); + drm_modeset_lock(&crtc->mutex, NULL); if (req->flags & DRM_MODE_CURSOR_BO) { if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 251b75e6bf7a..b8c7a9a8cb6b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -331,6 +331,10 @@ struct drm_crtc { struct drm_plane *primary; struct drm_plane *cursor; + /* position of cursor plane on crtc */ + int cursor_x; + int cursor_y; + /* Temporary tracking of the old fb while a modeset is ongoing. Used * by drm_mode_set_config_internal to implement correct refcounting. */ struct drm_framebuffer *old_fb; -- cgit v1.2.3 From 17cfd91f3985f23f92b8c7cba3307a2b630feb95 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Jun 2014 15:22:28 +0100 Subject: drm: Avoid NULL deference when disabling a plane from userspace To disable a plane, userspace passes in an framebuffer id of 0. This causes us to pass CRTC == NULL to setplane_internal, who promptly deferences it to grab the struct drm_device. Oops. [ 1296.467327] BUG: unable to handle kernel NULL pointer dereference at (null) [ 1296.467332] IP: [] setplane_internal+0x11/0x280 [ 1296.467338] *pde = 00000000 [ 1296.467341] Oops: 0000 [#1] SMP [ 1296.467344] Modules linked in: ccm bnep bluetooth snd_hda_codec_hdmi snd_hda_codec_idt snd_hda_codec_generic snd_hda_intel arc4 iwldvm snd_hda_controller snd_hda_codec mac80211 snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer iwlwifi sdhci_pci snd cfg80211 x86_pkg_temp_thermal hp_wmi sdhci sparse_keymap mmc_core crc32c_intel rfkill microcode hp_accel lpc_ich lis3lv02d wmi mfd_core serio_raw input_polldev soundcore e1000e ptp pps_core [ 1296.467367] CPU: 1 PID: 672 Comm: Xorg Tainted: G W 3.15.0-rc8+ #351 [ 1296.467369] Hardware name: Hewlett-Packard HP ProBook 6360b/1620, BIOS 68SCF Ver. B.42 12/29/2010 [ 1296.467371] task: f423b5c0 ti: c2332000 task.ti: c2332000 [ 1296.467374] EIP: 0060:[] EFLAGS: 00013286 CPU: 1 [ 1296.467376] EIP is at setplane_internal+0x11/0x280 [ 1296.467378] EAX: 00000000 EBX: c2333e90 ECX: 00000000 EDX: f3165600 [ 1296.467380] ESI: f430f400 EDI: 00000000 EBP: c2333e14 ESP: c2333dd4 [ 1296.467382] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 1296.467384] CR0: 80050033 CR2: 00000000 CR3: 00159000 CR4: 000407d0 [ 1296.467385] Stack: [ 1296.467387] 000200da 00000002 c2333de8 c15dc4a0 f430f400 c2333e00 c134c54f eeeeeeee [ 1296.467391] f430f400 00000007 f416b480 c2333e14 00000000 c2333e90 f430f400 00000000 [ 1296.467396] c2333e4c c1350aed 00000000 00000000 00000000 00000000 00000000 00000000 [ 1296.467400] Call Trace: [ 1296.467406] [] ? mutex_lock+0x10/0x28 [ 1296.467408] [] ? _object_find+0x5f/0x90 [ 1296.467413] [] drm_mode_setplane+0x10d/0x1f0 [ 1296.467416] [] ? drm_mode_getplane+0x100/0x100 [ 1296.467420] [] drm_ioctl+0x1bd/0x4f0 [ 1296.467423] [] ? drm_mode_getplane+0x100/0x100 [ 1296.467427] [] ? handle_mm_fault+0x5d3/0xb30 [ 1296.467431] [] ? tlb_finish_mmu+0x11/0x40 [ 1296.467435] [] ? drm_ioctl_flags+0x40/0x40 [ 1296.467438] [] do_vfs_ioctl+0x2f2/0x4d0 [ 1296.467443] [] ? inode_has_perm.isra.32+0x32/0x40 [ 1296.467446] [] ? file_has_perm+0x7f/0x90 [ 1296.467449] [] ? selinux_file_ioctl+0x4c/0xf0 [ 1296.467452] [] SyS_ioctl+0x60/0x90 [ 1296.467456] [] sysenter_do_call+0x12/0x22 [ 1296.467457] Code: 3f cf ff eb dd ba 3f 00 00 00 b8 d9 c9 7f c1 e8 e6 3f cf ff eb d9 8d 74 26 00 55 89 e5 57 56 53 83 ec 34 66 66 66 66 90 89 45 f0 <8b> 00 85 c9 89 d6 89 cb 89 45 ec 0f 84 16 01 00 00 8b 45 f0 e8 [ 1296.467485] EIP: [] setplane_internal+0x11/0x280 SS:ESP 0068:c2 Fixes regression from commit b02fd7fd8a541c3d590bfdda23365a927b507ceb Author: Matt Roper Date: Tue Jun 10 08:28:10 2014 -0700 drm: Support legacy cursor ioctls via universal planes when possible (v4) While at it move the plane parameter to the first position in setplane_internal since that's the main object we're manipulating. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Pallavi G Cc: Matt Roper Reviewed-by: Matt Roper [danvet: Add note about parameter reordering.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b5bce5b6bf61..d86d254693e4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2131,8 +2131,8 @@ out: * * src_{x,y,w,h} are provided in 16.16 fixed point format */ -static int setplane_internal(struct drm_crtc *crtc, - struct drm_plane *plane, +static int setplane_internal(struct drm_plane *plane, + struct drm_crtc *crtc, struct drm_framebuffer *fb, int32_t crtc_x, int32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h, @@ -2140,7 +2140,7 @@ static int setplane_internal(struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = plane->dev; struct drm_framebuffer *old_fb = NULL; int ret = 0; unsigned int fb_width, fb_height; @@ -2292,7 +2292,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, * setplane_internal will take care of deref'ing either the old or new * framebuffer depending on success. */ - return setplane_internal(crtc, plane, fb, + return setplane_internal(plane, crtc, fb, plane_req->crtc_x, plane_req->crtc_y, plane_req->crtc_w, plane_req->crtc_h, plane_req->src_x, plane_req->src_y, @@ -2628,7 +2628,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, * setplane_internal will take care of deref'ing either the old or new * framebuffer depending on success. */ - ret = setplane_internal(crtc, crtc->cursor, fb, + ret = setplane_internal(crtc->cursor, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, 0, 0, src_w, src_h); -- cgit v1.2.3 From fc1d3e44ef7c1db93384150fdbf8948dcf949f15 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 10 Jun 2014 08:28:11 -0700 Subject: drm: Allow drivers to register cursor planes with crtc Universal plane support had placeholders for cursor planes, but didn't actually do anything with them. Save the cursor plane reference inside the crtc and update the cursor plane parameter from void* to drm_plane. Reviewed-by: Daniel Vetter Signed-off-by: Matt Roper Reviewed-by: Pallavi G Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 5 ++++- include/drm/drm_crtc.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d86d254693e4..41c7212081b8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -727,7 +727,7 @@ DEFINE_WW_CLASS(crtc_ww_class); */ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, - void *cursor, + struct drm_plane *cursor, const struct drm_crtc_funcs *funcs) { struct drm_mode_config *config = &dev->mode_config; @@ -752,8 +752,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, config->num_crtc++; crtc->primary = primary; + crtc->cursor = cursor; if (primary) primary->possible_crtcs = 1 << drm_crtc_index(crtc); + if (cursor) + cursor->possible_crtcs = 1 << drm_crtc_index(crtc); out: drm_modeset_unlock_all(dev); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b8c7a9a8cb6b..4ee7e26a012f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -856,7 +856,7 @@ struct drm_prop_enum_list { extern int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary, - void *cursor, + struct drm_plane *cursor, const struct drm_crtc_funcs *funcs); extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, -- cgit v1.2.3 From 34ea3d386347cd6de4c2fa2491dd85c9e753e7e4 Mon Sep 17 00:00:00 2001 From: Thomas Wood Date: Thu, 29 May 2014 16:57:41 +0100 Subject: drm: add register and unregister functions for connectors Introduce generic functions to register and unregister connectors. This provides a common place to add and remove associated user space interfaces. Signed-off-by: Thomas Wood Reviewed-by: David Herrmann Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 6 +++--- drivers/gpu/drm/armada/armada_output.c | 4 ++-- drivers/gpu/drm/ast/ast_mode.c | 4 ++-- drivers/gpu/drm/bridge/ptn3460.c | 2 +- drivers/gpu/drm/drm_crtc.c | 30 ++++++++++++++++++++++++++- drivers/gpu/drm/drm_sysfs.c | 2 -- drivers/gpu/drm/exynos/exynos_dp_core.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_connector.c | 6 +++--- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 2 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 ++-- drivers/gpu/drm/gma500/cdv_intel_dp.c | 4 ++-- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 4 ++-- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 4 ++-- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 4 ++-- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 2 +- drivers/gpu/drm/gma500/oaktrail_lvds.c | 2 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 ++-- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 2 +- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 10 ++++----- drivers/gpu/drm/i915/intel_tv.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_connector.c | 4 ++-- drivers/gpu/drm/qxl/qxl_display.c | 4 ++-- drivers/gpu/drm/radeon/radeon_connectors.c | 6 +++--- drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 4 ++-- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +++--- drivers/gpu/drm/tegra/output.c | 4 ++-- drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 2 +- drivers/gpu/drm/udl/udl_connector.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 +- drivers/staging/imx-drm/imx-drm-core.c | 6 +++--- include/drm/drm_crtc.h | 2 ++ 49 files changed, 110 insertions(+), 82 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 7df3134ebc0e..b314a42bb18c 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -1610,7 +1610,7 @@ int max_width, max_height; The connector is then registered with a call to drm_connector_init with a pointer to the connector functions and a connector type, and exposed through sysfs with a call to - drm_sysfs_connector_add. + drm_connector_register. Supported connector types are @@ -1768,7 +1768,7 @@ int max_width, max_height; (drm_encoder_cleanup) and connectors (drm_connector_cleanup). Furthermore, connectors that have been added to sysfs must be removed by a call to - drm_sysfs_connector_remove before calling + drm_connector_unregister before calling drm_connector_cleanup. @@ -1813,7 +1813,7 @@ void intel_crt_init(struct drm_device *dev) drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); }]]> In the example above (taken from the i915 driver), a CRTC, connector and diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c index d685a5421485..abbc309fe539 100644 --- a/drivers/gpu/drm/armada/armada_output.c +++ b/drivers/gpu/drm/armada/armada_output.c @@ -48,7 +48,7 @@ static void armada_drm_connector_destroy(struct drm_connector *conn) { struct armada_connector *dconn = drm_to_armada_conn(conn); - drm_sysfs_connector_remove(conn); + drm_connector_unregister(conn); drm_connector_cleanup(conn); kfree(dconn); } @@ -141,7 +141,7 @@ int armada_output_create(struct drm_device *dev, if (ret) goto err_conn; - ret = drm_sysfs_connector_add(&dconn->conn); + ret = drm_connector_register(&dconn->conn); if (ret) goto err_sysfs; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 114aee941d46..9896286ed262 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -829,7 +829,7 @@ static void ast_connector_destroy(struct drm_connector *connector) { struct ast_connector *ast_connector = to_ast_connector(connector); ast_i2c_destroy(ast_connector->i2c); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -871,7 +871,7 @@ static int ast_connector_init(struct drm_device *dev) connector->interlace_allowed = 0; connector->doublescan_allowed = 0; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); connector->polled = DRM_CONNECTOR_POLL_CONNECT; diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c index 98fd17ae4916..d466696ed5e8 100644 --- a/drivers/gpu/drm/bridge/ptn3460.c +++ b/drivers/gpu/drm/bridge/ptn3460.c @@ -328,7 +328,7 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, } drm_connector_helper_add(&ptn_bridge->connector, &ptn3460_connector_helper_funcs); - drm_sysfs_connector_add(&ptn_bridge->connector); + drm_connector_register(&ptn_bridge->connector); drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder); return 0; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe94cc10cd35..c50c827cefb6 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -920,6 +920,34 @@ void drm_connector_cleanup(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_cleanup); +/** + * drm_connector_register - register a connector + * @connector: the connector to register + * + * Register userspace interfaces for a connector + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_connector_register(struct drm_connector *connector) +{ + return drm_sysfs_connector_add(connector); +} +EXPORT_SYMBOL(drm_connector_register); + +/** + * drm_connector_unregister - unregister a connector + * @connector: the connector to unregister + * + * Unregister userspace interfaces for a connector + */ +void drm_connector_unregister(struct drm_connector *connector) +{ + drm_sysfs_connector_remove(connector); +} +EXPORT_SYMBOL(drm_connector_unregister); + + /** * drm_connector_unplug_all - unregister connector userspace interfaces * @dev: drm device @@ -934,7 +962,7 @@ void drm_connector_unplug_all(struct drm_device *dev) /* taking the mode config mutex ends up in a clash with sysfs */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); } EXPORT_SYMBOL(drm_connector_unplug_all); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 369b26278e76..7827dad8fcf4 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -438,7 +438,6 @@ err_out_files: out: return ret; } -EXPORT_SYMBOL(drm_sysfs_connector_add); /** * drm_sysfs_connector_remove - remove an connector device from sysfs @@ -468,7 +467,6 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) device_unregister(connector->kdev); connector->kdev = NULL; } -EXPORT_SYMBOL(drm_sysfs_connector_remove); /** * drm_sysfs_hotplug_event - generate a DRM uevent diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index a8ffc8c1477b..86dc69d9eabb 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -1018,7 +1018,7 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, } drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 9a16dbe121d1..25c788832e2e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -185,7 +185,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector) struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(exynos_connector); } @@ -230,7 +230,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, drm_connector_init(dev, connector, &exynos_connector_funcs, type); drm_connector_helper_add(connector, &exynos_connector_helper_funcs); - err = drm_sysfs_connector_add(connector); + err = drm_connector_register(connector); if (err) goto err_connector; @@ -250,7 +250,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, return connector; err_sysfs: - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); err_connector: drm_connector_cleanup(connector); kfree(exynos_connector); diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 482127f633c5..4693531ebd48 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -48,7 +48,7 @@ exynos_dpi_detect(struct drm_connector *connector, bool force) static void exynos_dpi_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -117,7 +117,7 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display, } drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 6302aa64f6c1..2df3592166de 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1246,7 +1246,7 @@ static int exynos_dsi_create_connector(struct exynos_drm_display *display, } drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 2fb8705d6461..9528d81d8004 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -562,7 +562,7 @@ static int vidi_create_connector(struct exynos_drm_display *display, } drm_connector_helper_add(connector, &vidi_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index c104d0c9b385..dd565c4e5b4d 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1129,7 +1129,7 @@ static int hdmi_create_connector(struct exynos_drm_display *display, } drm_connector_helper_add(connector, &hdmi_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index c18268cd516e..248c33a35ebf 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -192,7 +192,7 @@ static void cdv_intel_crt_destroy(struct drm_connector *connector) struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->ddc_bus); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -304,7 +304,7 @@ void cdv_intel_crt_init(struct drm_device *dev, drm_connector_helper_add(connector, &cdv_intel_crt_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; failed_ddc: diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 9ff30c2efadb..a4cc0e60a1be 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1713,7 +1713,7 @@ cdv_intel_dp_destroy(struct drm_connector *connector) } } i2c_del_adapter(&intel_dp->adapter); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1847,7 +1847,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev connector->interlace_allowed = false; connector->doublescan_allowed = false; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); /* Set up the DDC bus. */ switch (output_reg) { diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index b99084b3f706..4268bf210034 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -248,7 +248,7 @@ static void cdv_hdmi_destroy(struct drm_connector *connector) if (gma_encoder->i2c_bus) psb_intel_i2c_destroy(gma_encoder->i2c_bus); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -356,7 +356,7 @@ void cdv_hdmi_init(struct drm_device *dev, hdmi_priv->hdmi_i2c_adapter = &(gma_encoder->i2c_bus->adapter); hdmi_priv->dev = dev; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; failed_ddc: diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 8ecc920fc26d..0b770396548c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -446,7 +446,7 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector) if (gma_encoder->i2c_bus) psb_intel_i2c_destroy(gma_encoder->i2c_bus); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -774,7 +774,7 @@ void cdv_intel_lvds_init(struct drm_device *dev, out: mutex_unlock(&dev->mode_config.mutex); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index 6e91b20ce2e5..abf2248da61e 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -318,7 +318,7 @@ static void mdfld_dsi_connector_destroy(struct drm_connector *connector) if (!dsi_connector) return; - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); sender = dsi_connector->pkg_sender; mdfld_dsi_pkg_sender_destroy(sender); @@ -597,7 +597,7 @@ void mdfld_dsi_output_init(struct drm_device *dev, dsi_config->encoder = encoder; encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; /*TODO: add code to destroy outputs on error*/ diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index cf018ddcc5a6..e6f5c620a0a2 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -665,7 +665,7 @@ void oaktrail_hdmi_init(struct drm_device *dev, connector->display_info.subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = false; connector->doublescan_allowed = false; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); dev_info(dev->dev, "HDMI initialised.\n"); return; diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 9b099468a5db..0d39da6e8b7a 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -404,7 +404,7 @@ void oaktrail_lvds_init(struct drm_device *dev, out: mutex_unlock(&dev->mode_config.mutex); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index d7778d0472c1..88aad95bde09 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -563,7 +563,7 @@ void psb_intel_lvds_destroy(struct drm_connector *connector) if (lvds_priv->ddc_bus) psb_intel_i2c_destroy(lvds_priv->ddc_bus); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -829,7 +829,7 @@ void psb_intel_lvds_init(struct drm_device *dev, */ out: mutex_unlock(&dev->mode_config.mutex); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index deeb0829b129..0be96fdb5e28 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1682,7 +1682,7 @@ static void psb_intel_sdvo_destroy(struct drm_connector *connector) psb_intel_sdvo_connector->tv_format); psb_intel_sdvo_destroy_enhance_property(connector); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -2071,7 +2071,7 @@ psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector, connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; gma_connector_attach_encoder(&connector->base, &encoder->base); - drm_sysfs_connector_add(&connector->base.base); + drm_connector_register(&connector->base.base); } static void diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 5a045d3bd77e..8da5ef9f4828 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -869,7 +869,7 @@ void intel_crt_init(struct drm_device *dev) drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); if (!I915_HAS_HOTPLUG(dev)) intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index efd3cf50cb0f..dbabaec6ae2d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12234,7 +12234,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector) struct drm_connector *connector = &intel_connector->base; intel_panel_destroy_backlight(connector); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); } void intel_modeset_cleanup(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 52fda950fd2a..99f033f69189 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4246,7 +4246,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, edp_panel_vdd_work); intel_connector_attach_encoder(intel_connector, intel_encoder); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); if (HAS_DDI(dev)) intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; @@ -4289,7 +4289,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, edp_panel_vdd_off_sync(intel_dp); drm_modeset_unlock(&dev->mode_config.connection_mutex); } - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); return false; } diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 02f99d768d49..7c07ee07a8ee 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -742,7 +742,7 @@ bool intel_dsi_init(struct drm_device *dev) intel_connector_attach_encoder(intel_connector, intel_encoder); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev); if (!fixed_mode) { diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a3631c0a5c28..3fb71a04e14f 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -558,7 +558,7 @@ void intel_dvo_init(struct drm_device *dev) intel_dvo->panel_wants_dither = true; } - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index eee2bbec2958..0b603102cb3b 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1490,7 +1490,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi_add_properties(intel_hdmi, connector); intel_connector_attach_encoder(intel_connector, intel_encoder); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written * 0xd. Failure to do so will result in spurious interrupts being diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 23126023aeba..4d29a83fd163 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -1097,7 +1097,7 @@ out: DRM_DEBUG_KMS("lid notifier registration failed\n"); lvds_connector->lid_notifier.notifier_call = NULL; } - drm_sysfs_connector_add(connector); + drm_connector_register(connector); intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); intel_panel_setup_backlight(connector); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 6a4d5bc17697..e0be8ae75c15 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2431,7 +2431,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector, connector->base.unregister = intel_sdvo_connector_unregister; intel_connector_attach_encoder(&connector->base, &encoder->base); - ret = drm_sysfs_connector_add(drm_connector); + ret = drm_connector_register(drm_connector); if (ret < 0) goto err1; @@ -2444,7 +2444,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector, return 0; err2: - drm_sysfs_connector_remove(drm_connector); + drm_connector_unregister(drm_connector); err1: drm_connector_cleanup(drm_connector); @@ -2557,7 +2557,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) return true; err: - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); intel_sdvo_destroy(connector); return false; } @@ -2636,7 +2636,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) return true; err: - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); intel_sdvo_destroy(connector); return false; } @@ -2709,7 +2709,7 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { if (intel_attached_encoder(connector) == &intel_sdvo->base) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); intel_sdvo_destroy(connector); } } diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 67c6c9a2eb1c..e211eef4b7e4 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1680,5 +1680,5 @@ intel_tv_init(struct drm_device *dev) drm_object_attach_property(&connector->base, dev->mode_config.tv_bottom_margin_property, intel_tv->margin[TV_MARGIN_BOTTOM]); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a034ed408252..f9fe390920f1 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1621,7 +1621,7 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev) drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); mga_connector->i2c = mgag200_i2c_create(dev); if (!mga_connector->i2c) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index e56a6196867c..56c64c14c9b0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -298,7 +298,7 @@ static void hdmi_connector_destroy(struct drm_connector *connector) hdp_disable(hdmi_connector); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); hdmi_unreference(hdmi_connector->hdmi); @@ -408,7 +408,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi) connector->interlace_allowed = 1; connector->doublescan_allowed = 0; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); ret = hpd_enable(hdmi_connector); if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1fa222e8f007..680f46d007a0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -104,7 +104,7 @@ nouveau_connector_destroy(struct drm_connector *connector) struct nouveau_connector *nv_connector = nouveau_connector(connector); nouveau_event_ref(NULL, &nv_connector->hpd); kfree(nv_connector->edid); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); if (nv_connector->aux.transfer) drm_dp_aux_unregister(&nv_connector->aux); @@ -1236,6 +1236,6 @@ nouveau_connector_create(struct drm_device *dev, int index) INIT_WORK(&nv_connector->work, nouveau_connector_hotplug_work); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return connector; } diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 86f4ead0441d..36bc5cc80816 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -130,7 +130,7 @@ static void omap_connector_destroy(struct drm_connector *connector) struct omap_dss_device *dssdev = omap_connector->dssdev; DBG("%s", omap_connector->dssdev->name); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(omap_connector); @@ -307,7 +307,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, connector->interlace_allowed = 1; connector->doublescan_allowed = 0; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return connector; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 5d7ea2461852..b8ced08b6291 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -835,7 +835,7 @@ static void qxl_conn_destroy(struct drm_connector *connector) struct qxl_output *qxl_output = drm_connector_to_qxl_output(connector); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(qxl_output); } @@ -902,7 +902,7 @@ static int qdev_output_init(struct drm_device *dev, int num_output) drm_object_attach_property(&connector->base, qdev->hotplug_mode_update_property, 0); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 933c5c39654d..5b1a611c30eb 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -737,7 +737,7 @@ static void radeon_connector_destroy(struct drm_connector *connector) if (radeon_connector->edid) kfree(radeon_connector->edid); kfree(radeon_connector->con_priv); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -2038,7 +2038,7 @@ radeon_add_atom_connector(struct drm_device *dev, connector->polled = DRM_CONNECTOR_POLL_HPD; connector->display_info.subpixel_order = subpixel_order; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); if (has_aux) radeon_dp_aux_init(radeon_connector); @@ -2199,5 +2199,5 @@ radeon_add_legacy_connector(struct drm_device *dev, } else connector->polled = DRM_CONNECTOR_POLL_HPD; connector->display_info.subpixel_order = subpixel_order; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c index 289048d1c7b2..21426bd234eb 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c @@ -64,7 +64,7 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { static void rcar_du_lvds_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -105,7 +105,7 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, return ret; drm_connector_helper_add(connector, &connector_helper_funcs); - ret = drm_sysfs_connector_add(connector); + ret = drm_connector_register(connector); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c index ccfe64c7188f..8af3944d31b9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c @@ -32,7 +32,7 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { static void rcar_du_vga_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -70,7 +70,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, return ret; drm_connector_helper_add(connector, &connector_helper_funcs); - ret = drm_sysfs_connector_add(connector); + ret = drm_connector_register(connector); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index faf176b2daf9..47875de89010 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -692,7 +692,7 @@ static void shmob_drm_connector_destroy(struct drm_connector *connector) struct shmob_drm_connector *scon = to_shmob_connector(connector); shmob_drm_backlight_exit(scon); - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); } @@ -726,7 +726,7 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, return ret; drm_connector_helper_add(connector, &connector_helper_funcs); - ret = drm_sysfs_connector_add(connector); + ret = drm_connector_register(connector); if (ret < 0) goto err_cleanup; @@ -749,7 +749,7 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, err_backlight: shmob_drm_backlight_exit(&sdev->connector); err_sysfs: - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); err_cleanup: drm_connector_cleanup(connector); return ret; diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index a3e4f1eca6f7..446837e955b6 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -105,7 +105,7 @@ static void drm_connector_clear(struct drm_connector *connector) static void tegra_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); drm_connector_clear(connector); } @@ -318,7 +318,7 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); drm_mode_connector_attach_encoder(&output->connector, &output->encoder); - drm_sysfs_connector_add(&output->connector); + drm_connector_register(&output->connector); output->encoder.possible_crtcs = 0x3; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 86c67329b605..0c0bce7e9007 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -247,7 +247,7 @@ static struct drm_connector *panel_connector_create(struct drm_device *dev, if (ret) goto fail; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return connector; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 595068ba2d5e..c578d144ce6d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -261,7 +261,7 @@ static struct drm_connector *slave_connector_create(struct drm_device *dev, if (ret) goto fail; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return connector; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index c38b56b268ac..5324dfd0b5ed 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -261,7 +261,7 @@ static struct drm_connector *tfp410_connector_create(struct drm_device *dev, if (ret) goto fail; - drm_sysfs_connector_add(connector); + drm_connector_register(connector); return connector; diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index b44d548c56f8..dea38ab6c47d 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -124,7 +124,7 @@ static int udl_connector_set_property(struct drm_connector *connector, static void udl_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -154,7 +154,7 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_DVII); drm_connector_helper_add(connector, &udl_connector_helper_funcs); - drm_sysfs_connector_add(connector); + drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); drm_object_attach_property(&connector->base, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 8f3edc4710f2..1a024e3b7285 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -75,7 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du) vmw_surface_unreference(&du->cursor_surface); if (du->cursor_dmabuf) vmw_dmabuf_unreference(&du->cursor_dmabuf); - drm_sysfs_connector_remove(&du->connector); + drm_connector_unregister(&du->connector); drm_crtc_cleanup(&du->crtc); drm_encoder_cleanup(&du->encoder); drm_connector_cleanup(&du->connector); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index b2b9bd23aeee..15e185ae4c99 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -371,7 +371,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) encoder->possible_crtcs = (1 << unit); encoder->possible_clones = 0; - (void) drm_sysfs_connector_add(connector); + (void) drm_connector_register(connector); drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index a95d3a0cabe4..b295463a60b3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -467,7 +467,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) encoder->possible_crtcs = (1 << unit); encoder->possible_clones = 0; - (void) drm_sysfs_connector_add(connector); + (void) drm_connector_register(connector); drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index def8280d7ee6..6f54ff4f9372 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -202,7 +202,7 @@ static const struct file_operations imx_drm_driver_fops = { void imx_drm_connector_destroy(struct drm_connector *connector) { - drm_sysfs_connector_remove(connector); + drm_connector_unregister(connector); drm_connector_cleanup(connector); } EXPORT_SYMBOL_GPL(imx_drm_connector_destroy); @@ -293,10 +293,10 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) * userspace will expect to be able to access DRM at this point. */ list_for_each_entry(connector, &drm->mode_config.connector_list, head) { - ret = drm_sysfs_connector_add(connector); + ret = drm_connector_register(connector); if (ret) { dev_err(drm->dev, - "[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n", + "[CONNECTOR:%d:%s] drm_connector_register failed: %d\n", connector->base.id, connector->name, ret); goto err_unbind; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 251b75e6bf7a..5512c9968d77 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -878,6 +878,8 @@ extern int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type); +int drm_connector_register(struct drm_connector *connector); +void drm_connector_unregister(struct drm_connector *connector); extern void drm_connector_cleanup(struct drm_connector *connector); /* helper to unplug all connectors from sysfs for device */ -- cgit v1.2.3 From 30f6570798f6c897df4f1f2c676d803728bfec27 Mon Sep 17 00:00:00 2001 From: Thomas Wood Date: Wed, 18 Jun 2014 17:52:32 +0100 Subject: drm/debugfs: add a "force" file per connector Add a file to debugfs for each connector to enable modification of the "force" connector attribute. This allows connectors to be enabled or disabled for testing and debugging purposes. v2: Add stricter value checking and clean up debugfs_entry if file creation fails in drm_debugfs_connector_add. (David Herrmann) Signed-off-by: Thomas Wood Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 17 ++++++- drivers/gpu/drm/drm_debugfs.c | 114 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 11 ++++ include/drm/drm_crtc.h | 2 + 4 files changed, 143 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c50c827cefb6..c304e5650bc8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -881,6 +881,8 @@ int drm_connector_init(struct drm_device *dev, drm_object_attach_property(&connector->base, dev->mode_config.dpms_property, 0); + connector->debugfs_entry = NULL; + out_put: if (ret) drm_mode_object_put(dev, &connector->base); @@ -931,7 +933,19 @@ EXPORT_SYMBOL(drm_connector_cleanup); */ int drm_connector_register(struct drm_connector *connector) { - return drm_sysfs_connector_add(connector); + int ret; + + ret = drm_sysfs_connector_add(connector); + if (ret) + return ret; + + ret = drm_debugfs_connector_add(connector); + if (ret) { + drm_sysfs_connector_remove(connector); + return ret; + } + + return 0; } EXPORT_SYMBOL(drm_connector_register); @@ -944,6 +958,7 @@ EXPORT_SYMBOL(drm_connector_register); void drm_connector_unregister(struct drm_connector *connector) { drm_sysfs_connector_remove(connector); + drm_debugfs_connector_remove(connector); } EXPORT_SYMBOL(drm_connector_unregister); diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index b4b51d46f339..8ab3f3e38643 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -237,5 +237,119 @@ int drm_debugfs_cleanup(struct drm_minor *minor) return 0; } +static int connector_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + const char *status; + + switch (connector->force) { + case DRM_FORCE_ON: + status = "on\n"; + break; + + case DRM_FORCE_ON_DIGITAL: + status = "digital\n"; + break; + + case DRM_FORCE_OFF: + status = "off\n"; + break; + + case DRM_FORCE_UNSPECIFIED: + status = "unspecified\n"; + break; + + default: + return 0; + } + + seq_puts(m, status); + + return 0; +} + +static int connector_open(struct inode *inode, struct file *file) +{ + struct drm_connector *dev = inode->i_private; + + return single_open(file, connector_show, dev); +} + +static ssize_t connector_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_connector *connector = m->private; + char buf[12]; + + if (len > sizeof(buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, len)) + return -EFAULT; + + buf[len] = '\0'; + + if (!strcmp(buf, "on")) + connector->force = DRM_FORCE_ON; + else if (!strcmp(buf, "digital")) + connector->force = DRM_FORCE_ON_DIGITAL; + else if (!strcmp(buf, "off")) + connector->force = DRM_FORCE_OFF; + else if (!strcmp(buf, "unspecified")) + connector->force = DRM_FORCE_UNSPECIFIED; + else + return -EINVAL; + + return len; +} + +static const struct file_operations drm_connector_fops = { + .owner = THIS_MODULE, + .open = connector_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = connector_write +}; + +int drm_debugfs_connector_add(struct drm_connector *connector) +{ + struct drm_minor *minor = connector->dev->primary; + struct dentry *root, *ent; + + if (!minor->debugfs_root) + return -1; + + root = debugfs_create_dir(connector->name, minor->debugfs_root); + if (!root) + return -ENOMEM; + + connector->debugfs_entry = root; + + /* force */ + ent = debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector, + &drm_connector_fops); + if (!ent) + goto error; + + return 0; + +error: + debugfs_remove_recursive(connector->debugfs_entry); + connector->debugfs_entry = NULL; + return -ENOMEM; +} + +void drm_debugfs_connector_remove(struct drm_connector *connector) +{ + if (!connector->debugfs_entry) + return; + + debugfs_remove_recursive(connector->debugfs_entry); + + connector->debugfs_entry = NULL; +} + #endif /* CONFIG_DEBUG_FS */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8af71a8e2c00..57ecc421b19c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1419,6 +1419,8 @@ extern int drm_debugfs_create_files(const struct drm_info_list *files, extern int drm_debugfs_remove_files(const struct drm_info_list *files, int count, struct drm_minor *minor); extern int drm_debugfs_cleanup(struct drm_minor *minor); +extern int drm_debugfs_connector_add(struct drm_connector *connector); +extern void drm_debugfs_connector_remove(struct drm_connector *connector); #else static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root) @@ -1443,6 +1445,15 @@ static inline int drm_debugfs_cleanup(struct drm_minor *minor) { return 0; } + +static inline int drm_debugfs_connector_add(struct drm_connector *connector) +{ + return 0; +} +static inline void drm_debugfs_connector_remove(struct drm_connector *connector) +{ +} + #endif /* Info file support */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 5512c9968d77..d4b0a6a4ad9b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -545,6 +545,8 @@ struct drm_connector { int audio_latency[2]; int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ unsigned bad_edid_counter; + + struct dentry *debugfs_entry; }; /** -- cgit v1.2.3 From 4cf2b28146713d39f78bd62002a8ab00075c63b7 Mon Sep 17 00:00:00 2001 From: Thomas Wood Date: Wed, 18 Jun 2014 17:52:33 +0100 Subject: drm/debugfs: add an "edid_override" file per connector Add a file to debugfs for each connector to allow the EDID to be overridden. v2: Copy ubuf before accessing it and reject invalid length data. (David Herrmann) Ensure override_edid is reset when a new EDID value is written. (David Herrmann) Fix the debugfs file permissions. (David Herrmann) Signed-off-by: Thomas Wood Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 4 +++ drivers/gpu/drm/drm_debugfs.c | 68 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 9 ++++- include/drm/drm_crtc.h | 1 + 4 files changed, 81 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c304e5650bc8..7db6251c38e7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3763,6 +3763,10 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct drm_device *dev = connector->dev; int ret, size; + /* ignore requests to set edid when overridden */ + if (connector->override_edid) + return 0; + if (connector->edid_blob_ptr) drm_property_destroy_blob(dev, connector->edid_blob_ptr); diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 8ab3f3e38643..13bd42923dd4 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -35,6 +35,7 @@ #include #include #include +#include #if defined(CONFIG_DEBUG_FS) @@ -304,6 +305,67 @@ static ssize_t connector_write(struct file *file, const char __user *ubuf, return len; } +static int edid_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct drm_property_blob *edid = connector->edid_blob_ptr; + + if (connector->override_edid && edid) + seq_write(m, edid->data, edid->length); + + return 0; +} + +static int edid_open(struct inode *inode, struct file *file) +{ + struct drm_connector *dev = inode->i_private; + + return single_open(file, edid_show, dev); +} + +static ssize_t edid_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_connector *connector = m->private; + char *buf; + struct edid *edid; + int ret; + + buf = memdup_user(ubuf, len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + edid = (struct edid *) buf; + + if (len == 5 && !strncmp(buf, "reset", 5)) { + connector->override_edid = false; + ret = drm_mode_connector_update_edid_property(connector, NULL); + } else if (len < EDID_LENGTH || + EDID_LENGTH * (1 + edid->extensions) > len) + ret = -EINVAL; + else { + connector->override_edid = false; + ret = drm_mode_connector_update_edid_property(connector, edid); + if (!ret) + connector->override_edid = true; + } + + kfree(buf); + + return (ret) ? ret : len; +} + +static const struct file_operations drm_edid_fops = { + .owner = THIS_MODULE, + .open = edid_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = edid_write +}; + + static const struct file_operations drm_connector_fops = { .owner = THIS_MODULE, .open = connector_open, @@ -333,6 +395,12 @@ int drm_debugfs_connector_add(struct drm_connector *connector) if (!ent) goto error; + /* edid */ + ent = debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root, + connector, &drm_edid_fops); + if (!ent) + goto error; + return 0; error: diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index d22676b89cbb..db7d250f7ac7 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -130,7 +130,14 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect count = drm_load_edid_firmware(connector); if (count == 0) #endif - count = (*connector_funcs->get_modes)(connector); + { + if (connector->override_edid) { + struct edid *edid = (struct edid *) connector->edid_blob_ptr->data; + + count = drm_add_edid_modes(connector, edid); + } else + count = (*connector_funcs->get_modes)(connector); + } if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d4b0a6a4ad9b..857bbb1551f8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -533,6 +533,7 @@ struct drm_connector { /* forced on connector */ enum drm_connector_force force; + bool override_edid; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; struct drm_encoder *encoder; /* currently active encoder */ -- cgit v1.2.3 From 2390cd11bfbe8d2b1b28c4e0f01fe7e122f7196d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2014 14:01:29 +1000 Subject: drm/crtc: add interface to reinitialise the legacy mode group This can be called to update things after dynamic connectors/encoders are created/deleted. Reviewed-by: Todd Previte Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 9 +++++++++ include/drm/drm_crtc.h | 1 + 2 files changed, 10 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7db6251c38e7..f939b058953c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1513,6 +1513,15 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, } EXPORT_SYMBOL(drm_mode_group_init_legacy_group); +void drm_reinit_primary_mode_group(struct drm_device *dev) +{ + drm_modeset_lock_all(dev); + drm_mode_group_destroy(&dev->primary->mode_group); + drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); + drm_modeset_unlock_all(dev); +} +EXPORT_SYMBOL(drm_reinit_primary_mode_group); + /** * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo * @out: drm_mode_modeinfo struct to return to the user diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 857bbb1551f8..eb0f6f36385e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -942,6 +942,7 @@ extern const char *drm_get_tv_select_name(int val); extern void drm_fb_release(struct drm_file *file_priv); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern void drm_mode_group_destroy(struct drm_mode_group *group); +extern void drm_reinit_primary_mode_group(struct drm_device *dev); extern bool drm_probe_ddc(struct i2c_adapter *adapter); extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); -- cgit v1.2.3 From 43aba7eb0dc052d84e88f3569ea3f030868d49b2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Jun 2014 14:01:31 +1000 Subject: drm: add a path blob property This property will be used by the MST code to provide userspace with a path to parse so it can recognise connectors around hotplugs. Reviewed-by: Todd Previte Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 26 ++++++++++++++++++++++++++ include/drm/drm_crtc.h | 5 +++++ 2 files changed, 31 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f939b058953c..bd7422676638 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1257,6 +1257,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { struct drm_property *edid; struct drm_property *dpms; + struct drm_property *dev_path; /* * Standard properties (apply to all connectors) @@ -1271,6 +1272,12 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) ARRAY_SIZE(drm_dpms_enum_list)); dev->mode_config.dpms_property = dpms; + dev_path = drm_property_create(dev, + DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_IMMUTABLE, + "PATH", 0); + dev->mode_config.path_property = dev_path; + return 0; } @@ -3755,6 +3762,25 @@ done: return ret; } +int drm_mode_connector_set_path_property(struct drm_connector *connector, + char *path) +{ + struct drm_device *dev = connector->dev; + int ret, size; + size = strlen(path) + 1; + + connector->path_blob_ptr = drm_property_create_blob(connector->dev, + size, path); + if (!connector->path_blob_ptr) + return -EINVAL; + + ret = drm_object_property_set_value(&connector->base, + dev->mode_config.path_property, + connector->path_blob_ptr->base.id); + return ret; +} +EXPORT_SYMBOL(drm_mode_connector_set_path_property); + /** * drm_mode_connector_update_edid_property - update the edid property of a connector * @connector: drm connector diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index eb0f6f36385e..4da62072701c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -524,6 +524,8 @@ struct drm_connector { struct drm_property_blob *edid_blob_ptr; struct drm_object_properties properties; + struct drm_property_blob *path_blob_ptr; + uint8_t polled; /* DRM_CONNECTOR_POLL_* */ /* requested DPMS state */ @@ -803,6 +805,7 @@ struct drm_mode_config { struct list_head property_blob_list; struct drm_property *edid_property; struct drm_property *dpms_property; + struct drm_property *path_property; struct drm_property *plane_type_property; /* DVI-I properties */ @@ -952,6 +955,8 @@ extern void drm_mode_config_init(struct drm_device *dev); extern void drm_mode_config_reset(struct drm_device *dev); extern void drm_mode_config_cleanup(struct drm_device *dev); +extern int drm_mode_connector_set_path_property(struct drm_connector *connector, + char *path); extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct edid *edid); -- cgit v1.2.3 From 7689ffb32fa314cc6f128b433b5a285f2699cb70 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Jul 2014 10:31:52 +0530 Subject: drm: Add support_bits parameter to drm_property_create_bitmask() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make drm_property_create_bitmask() a bit more generic by allowing the caller to specify which bits are in fact supported. This allows multiple callers to use the same enum list, but still create different versions of the same property with different list of supported bits. v2: Populate values[] array as non-sparse Make supported_bits 64bit Fix up omapdrm call site (Rob) Cc: dri-devel@lists.freedesktop.org Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Reviewed-by: Sagar Kamble Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 17 +++++++++++++---- drivers/gpu/drm/omapdrm/omap_plane.c | 5 ++++- include/drm/drm_crtc.h | 3 ++- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 41c7212081b8..2fbee61d632d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3395,19 +3395,28 @@ EXPORT_SYMBOL(drm_property_create_enum); struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, - int num_values) + int num_props, + uint64_t supported_bits) { struct drm_property *property; - int i, ret; + int i, ret, index = 0; + int num_values = hweight64(supported_bits); flags |= DRM_MODE_PROP_BITMASK; property = drm_property_create(dev, flags, name, num_values); if (!property) return NULL; + for (i = 0; i < num_props; i++) { + if (!(supported_bits & (1ULL << props[i].type))) + continue; - for (i = 0; i < num_values; i++) { - ret = drm_property_add_enum(property, i, + if (WARN_ON(index >= num_values)) { + drm_property_destroy(dev, property); + return NULL; + } + + ret = drm_property_add_enum(property, index++, props[i].type, props[i].name); if (ret) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 3cf31ee59aac..aff06e7a4e5f 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -317,7 +317,10 @@ void omap_plane_install_properties(struct drm_plane *plane, { DRM_REFLECT_Y, "reflect-y" }, }; prop = drm_property_create_bitmask(dev, 0, "rotation", - props, ARRAY_SIZE(props)); + props, ARRAY_SIZE(props), + BIT(DRM_ROTATE_0) | BIT(DRM_ROTATE_90) | + BIT(DRM_ROTATE_180) | BIT(DRM_ROTATE_270) | + BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y)); if (prop == NULL) return; priv->rotation_prop = prop; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bfc7235a9c0e..cb4850a2b0c1 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1006,7 +1006,8 @@ extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int struct drm_property *drm_property_create_bitmask(struct drm_device *dev, int flags, const char *name, const struct drm_prop_enum_list *props, - int num_values); + int num_props, + uint64_t supported_bits); struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, const char *name, uint64_t min, uint64_t max); -- cgit v1.2.3 From c1df5f3c2d665f1a5b365d1e352e99832f188fda Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Jul 2014 10:31:53 +0530 Subject: drm: Add drm_mode_create_rotation_property() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a function to create a standards compliant rotation property. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 18 ++++++++++++++++++ include/drm/drm_crtc.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2fbee61d632d..f224d4d1c0ed 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4959,3 +4959,21 @@ void drm_mode_config_cleanup(struct drm_device *dev) drm_modeset_lock_fini(&dev->mode_config.connection_mutex); } EXPORT_SYMBOL(drm_mode_config_cleanup); + +struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, + unsigned int supported_rotations) +{ + static const struct drm_prop_enum_list props[] = { + { DRM_ROTATE_0, "rotate-0" }, + { DRM_ROTATE_90, "rotate-90" }, + { DRM_ROTATE_180, "rotate-180" }, + { DRM_ROTATE_270, "rotate-270" }, + { DRM_REFLECT_X, "reflect-x" }, + { DRM_REFLECT_Y, "reflect-y" }, + }; + + return drm_property_create_bitmask(dev, 0, "rotation", + props, ARRAY_SIZE(props), + supported_rotations); +} +EXPORT_SYMBOL(drm_mode_create_rotation_property); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index cb4850a2b0c1..f7b383bcb6b6 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1113,6 +1113,8 @@ extern int drm_format_plane_cpp(uint32_t format, int plane); extern int drm_format_horz_chroma_subsampling(uint32_t format); extern int drm_format_vert_chroma_subsampling(uint32_t format); extern const char *drm_get_format_name(uint32_t format); +extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, + unsigned int supported_rotations); /* Helpers */ -- cgit v1.2.3 From 3c9855f6dc1c68f7c4028f49bd8e3df7e4faae67 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 8 Jul 2014 10:31:56 +0530 Subject: drm: Add drm_rotation_simplify() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_rotation_simplify() can be used to eliminate unsupported rotation flags. It will check if any unsupported flags are present, and if so it will modify the rotation to an alternate form by adding 180 degrees to rotation angle, and flipping the reflect x and y bits. The hope is that this identity transform will eliminate the unsupported flags. Of course that might not result in any more supported rotation, so the caller is still responsible for checking the result afterwards. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 30 ++++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 2 ++ 2 files changed, 32 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f224d4d1c0ed..89bab66558ef 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4841,6 +4841,36 @@ int drm_format_vert_chroma_subsampling(uint32_t format) } EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); +/** + * drm_rotation_simplify() - Try to simplify the rotation + * @rotation: Rotation to be simplified + * @supported_rotations: Supported rotations + * + * Attempt to simplify the rotation to a form that is supported. + * Eg. if the hardware supports everything except DRM_REFLECT_X + * one could call this function like this: + * + * drm_rotation_simplify(rotation, BIT(DRM_ROTATE_0) | + * BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) | + * BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_Y)); + * + * to eliminate the DRM_ROTATE_X flag. Depending on what kind of + * transforms the hardware supports, this function may not + * be able to produce a supported transform, so the caller should + * check the result afterwards. + */ +unsigned int drm_rotation_simplify(unsigned int rotation, + unsigned int supported_rotations) +{ + if (rotation & ~supported_rotations) { + rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y); + rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4); + } + + return rotation; +} +EXPORT_SYMBOL(drm_rotation_simplify); + /** * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f7b383bcb6b6..08ed55e02762 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1115,6 +1115,8 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format); extern const char *drm_get_format_name(uint32_t format); extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, unsigned int supported_rotations); +extern unsigned int drm_rotation_simplify(unsigned int rotation, + unsigned int supported_rotations); /* Helpers */ -- cgit v1.2.3 From 2aa9d2bc8cc3ab32ea0d15ec9005f25b1af3465a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 26 Jun 2014 21:37:20 +0200 Subject: drm: Fix function names in kerneldoc The drm_property_create_enum(), drm_property_create_bitmask() and drm_property_create_range() contain the wrong name in the kerneldoc comment. This is probably simply a copy/paste mistake. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c808a092d824..1ccf5cb9aa86 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3388,7 +3388,7 @@ fail: EXPORT_SYMBOL(drm_property_create); /** - * drm_property_create - create a new enumeration property type + * drm_property_create_enum - create a new enumeration property type * @dev: drm device * @flags: flags specifying the property type * @name: name of the property @@ -3434,7 +3434,7 @@ struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, EXPORT_SYMBOL(drm_property_create_enum); /** - * drm_property_create - create a new bitmask property type + * drm_property_create_bitmask - create a new bitmask property type * @dev: drm device * @flags: flags specifying the property type * @name: name of the property @@ -3496,7 +3496,7 @@ static struct drm_property *property_create_range(struct drm_device *dev, } /** - * drm_property_create - create a new ranged property type + * drm_property_create_range - create a new ranged property type * @dev: drm device * @flags: flags specifying the property type * @name: name of the property -- cgit v1.2.3 From ff587e45a1a1690f5cd713a2782672c579460365 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Wed, 11 Jun 2014 10:46:48 +0530 Subject: drm/crtc: Add property for aspect ratio Added a property to enable user space to set aspect ratio. This patch contains declaration of the property and code to create the property. v2: Thierry's review comments. - Made aspect ratio enum generic instead of HDMI/CEA specfic - Removed usage of temporary aspect_ratio variable v3: Thierry's review comments. - Fixed indentation v4: Thierry's review comments. - Return ENOMEM when property creation fails Signed-off-by: Vandana Kannan Cc: Thierry Reding Reviewed-by: Thierry Reding Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 33 +++++++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 2 ++ include/uapi/drm/drm_mode.h | 5 +++++ 3 files changed, 40 insertions(+) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 89bab66558ef..f0a777747907 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -182,6 +182,12 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { DRM_MODE_SCALE_ASPECT, "Full aspect" }, }; +static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { + { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" }, + { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" }, + { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, +}; + /* * Non-global properties, but "required" for certain connectors. */ @@ -1390,6 +1396,33 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); +/** + * drm_mode_create_aspect_ratio_property - create aspect ratio property + * @dev: DRM device + * + * Called by a driver the first time it's needed, must be attached to desired + * connectors. + * + * Returns: + * Zero on success, errno on failure. + */ +int drm_mode_create_aspect_ratio_property(struct drm_device *dev) +{ + if (dev->mode_config.aspect_ratio_property) + return 0; + + dev->mode_config.aspect_ratio_property = + drm_property_create_enum(dev, 0, "aspect ratio", + drm_aspect_ratio_enum_list, + ARRAY_SIZE(drm_aspect_ratio_enum_list)); + + if (dev->mode_config.aspect_ratio_property == NULL) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property); + /** * drm_mode_create_dirty_property - create dirty property * @dev: DRM device diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 08ed55e02762..be7114e76d1b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -835,6 +835,7 @@ struct drm_mode_config { /* Optional properties */ struct drm_property *scaling_mode_property; + struct drm_property *aspect_ratio_property; struct drm_property *dirty_info_property; /* dumb ioctl parameters */ @@ -1023,6 +1024,7 @@ extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats, char *formats[]); extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); +extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index def54f9e07ca..a0db2d4aa5f0 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -88,6 +88,11 @@ #define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ #define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ +/* Picture aspect ratio options */ +#define DRM_MODE_PICTURE_ASPECT_NONE 0 +#define DRM_MODE_PICTURE_ASPECT_4_3 1 +#define DRM_MODE_PICTURE_ASPECT_16_9 2 + /* Dithering mode options */ #define DRM_MODE_DITHERING_OFF 0 #define DRM_MODE_DITHERING_ON 1 -- cgit v1.2.3 From 2ee39452fa2fff1e8edb954ccb7e0daee9646557 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 24 Jul 2014 11:53:45 +1000 Subject: drm: close race in connector registration (v2) Daniel pointed out with hotplug that userspace could be trying to oops us as root for lols, and that to be correct we shouldn't register the object with the idr before we have fully set the connector object up. His proposed solution was a lot more life changing, this seemed like a simpler proposition to me, get the connector object id from the idr, but don't register the object until the drm_connector_register callback. The open question is whether the drm_mode_object_register needs a bigger lock than just the idr one, but I can't see why it would, but I can be locking challenged. v2: fix bool noreg into sane - add comment. Reviewed-by: Daniel Vetter Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 48 +++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 1ccf5cb9aa86..c3a5a8f0825b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -361,6 +361,32 @@ const char *drm_get_format_name(uint32_t format) } EXPORT_SYMBOL(drm_get_format_name); +/* + * Internal function to assign a slot in the object idr and optionally + * register the object into the idr. + */ +static int drm_mode_object_get_reg(struct drm_device *dev, + struct drm_mode_object *obj, + uint32_t obj_type, + bool register_obj) +{ + int ret; + + mutex_lock(&dev->mode_config.idr_mutex); + ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL); + if (ret >= 0) { + /* + * Set up the object linking under the protection of the idr + * lock so that other users can't see inconsistent state. + */ + obj->id = ret; + obj->type = obj_type; + } + mutex_unlock(&dev->mode_config.idr_mutex); + + return ret < 0 ? ret : 0; +} + /** * drm_mode_object_get - allocate a new modeset identifier * @dev: DRM device @@ -379,21 +405,15 @@ EXPORT_SYMBOL(drm_get_format_name); int drm_mode_object_get(struct drm_device *dev, struct drm_mode_object *obj, uint32_t obj_type) { - int ret; + return drm_mode_object_get_reg(dev, obj, obj_type, true); +} +static void drm_mode_object_register(struct drm_device *dev, + struct drm_mode_object *obj) +{ mutex_lock(&dev->mode_config.idr_mutex); - ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL); - if (ret >= 0) { - /* - * Set up the object linking under the protection of the idr - * lock so that other users can't see inconsistent state. - */ - obj->id = ret; - obj->type = obj_type; - } + idr_replace(&dev->mode_config.crtc_idr, obj, obj->id); mutex_unlock(&dev->mode_config.idr_mutex); - - return ret < 0 ? ret : 0; } /** @@ -849,7 +869,7 @@ int drm_connector_init(struct drm_device *dev, drm_modeset_lock_all(dev); - ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); + ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false); if (ret) goto out_unlock; @@ -942,6 +962,8 @@ int drm_connector_register(struct drm_connector *connector) { int ret; + drm_mode_object_register(connector->dev, &connector->base); + ret = drm_sysfs_connector_add(connector); if (ret) return ret; -- cgit v1.2.3 From 168c02ec06f891990617cee2abbba70858c071e7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 24 Jul 2014 12:12:45 +0200 Subject: drm: Fix race when checking for fb in the generic kms obj lookup In my review of commit 98f75de40e9d83c3a90d294b8fd25fa2874212a9 Author: Rob Clark Date: Fri May 30 11:37:03 2014 -0400 drm: add object property typ I asked for a check to make sure that we never leak an fb from the generic mode object lookup since those have completely different lifetime rules. Rob added it, but outside of the idr mutex, which means that our dereference of obj->type can already chase free'd memory. Somehow I didn't spot this, so fix this asap. v2: Simplify the conditionals as suggested by Chris. Cc: Rob Clark Cc: Chris Wilson Signed-off-by: Daniel Vetter Reviewed-by: Rob Clark Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3c4a62169f28..fa2be249999c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -446,8 +446,12 @@ static struct drm_mode_object *_object_find(struct drm_device *dev, mutex_lock(&dev->mode_config.idr_mutex); obj = idr_find(&dev->mode_config.crtc_idr, id); - if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) || - (obj->id != id)) + if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) + obj = NULL; + if (obj && obj->id != id) + obj = NULL; + /* don't leak out unref'd fb's */ + if (obj && (obj->type == DRM_MODE_OBJECT_FB)) obj = NULL; mutex_unlock(&dev->mode_config.idr_mutex); @@ -474,9 +478,6 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, * function.*/ WARN_ON(type == DRM_MODE_OBJECT_FB); obj = _object_find(dev, id, type); - /* don't leak out unref'd fb's */ - if (obj && (obj->type == DRM_MODE_OBJECT_FB)) - obj = NULL; return obj; } EXPORT_SYMBOL(drm_mode_object_find); -- cgit v1.2.3 From 48ba813701eb14b3008edefef4a0789b328e278c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 22 Jul 2014 18:46:09 +0200 Subject: drm: drop redundant drm_file->is_master The drm_file->is_master field is redundant as it's equivalent to: drm_file->master && drm_file->master == drm_file->minor->master 1) "=>" Whenever we set drm_file->is_master, we also set: drm_file->minor->master = drm_file->master; Whenever we clear drm_file->is_master, we also call: drm_master_put(&drm_file->minor->master); which implicitly clears it to NULL. 2) "<=" minor->master cannot be set if it is non-NULL. Therefore, it stays as is unless a file drops it. If minor->master is NULL, it is only set by places that also adjust drm_file->is_master. Therefore, we can safely drop is_master and replace it by an inline helper that matches: drm_file->master && drm_file->master == drm_file->minor->master Reviewed-by: Alex Deucher Reviewed-by: Daniel Vetter Signed-off-by: David Herrmann --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_drv.c | 2 +- drivers/gpu/drm/drm_fops.c | 4 +--- drivers/gpu/drm/drm_lock.c | 2 +- drivers/gpu/drm/drm_stub.c | 10 +++------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/staging/imx-drm/imx-drm-core.c | 2 +- include/drm/drmP.h | 19 ++++++++++++++++--- 9 files changed, 27 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3c4a62169f28..670b5eb13c87 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3243,7 +3243,7 @@ int drm_mode_getfb(struct drm_device *dev, r->bpp = fb->bits_per_pixel; r->pitch = fb->pitches[0]; if (fb->funcs->create_handle) { - if (file_priv->is_master || capable(CAP_SYS_ADMIN) || + if (drm_is_master(file_priv) || capable(CAP_SYS_ADMIN) || drm_is_control_client(file_priv)) { ret = fb->funcs->create_handle(fb, file_priv, &r->handle); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 0cc182745e31..7aa8121d1323 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -307,7 +307,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) return -EACCES; /* MASTER is only for master or control clients */ - if (unlikely((flags & DRM_MASTER) && !file_priv->is_master && + if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) && !drm_is_control_client(file_priv))) return -EACCES; diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 55143f7747f3..53435e07fa8d 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -233,7 +233,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) goto out_close; } - priv->is_master = 1; /* take another reference for the copy in the local file priv */ priv->master = drm_master_get(priv->minor->master); priv->authenticated = 1; @@ -461,7 +460,7 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&dev->master_mutex); - if (file_priv->is_master) { + if (drm_is_master(file_priv)) { struct drm_master *master = file_priv->master; struct drm_file *temp; @@ -497,7 +496,6 @@ int drm_release(struct inode *inode, struct file *filp) /* drop the master reference held by the file priv */ if (file_priv->master) drm_master_put(&file_priv->master); - file_priv->is_master = 0; mutex_unlock(&dev->master_mutex); mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index f6452682141b..786401cd5f60 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -111,7 +111,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* don't set the block all signals on the master process for now * really probably not the correct answer but lets us debug xkb * xserver for now */ - if (!file_priv->is_master) { + if (!drm_is_master(file_priv)) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGTSTP); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 233ea208c9fe..18c9b3d8201e 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -177,7 +177,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, int ret = 0; mutex_lock(&dev->master_mutex); - if (file_priv->is_master) + if (drm_is_master(file_priv)) goto out_unlock; if (file_priv->minor->master) { @@ -191,13 +191,10 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, } file_priv->minor->master = drm_master_get(file_priv->master); - file_priv->is_master = 1; if (dev->driver->master_set) { ret = dev->driver->master_set(dev, file_priv, false); - if (unlikely(ret != 0)) { - file_priv->is_master = 0; + if (unlikely(ret != 0)) drm_master_put(&file_priv->minor->master); - } } out_unlock: @@ -211,7 +208,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, int ret = -EINVAL; mutex_lock(&dev->master_mutex); - if (!file_priv->is_master) + if (!drm_is_master(file_priv)) goto out_unlock; if (!file_priv->minor->master) @@ -221,7 +218,6 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, if (dev->driver->master_drop) dev->driver->master_drop(dev, file_priv, false); drm_master_put(&file_priv->minor->master); - file_priv->is_master = 0; out_unlock: mutex_unlock(&dev->master_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 60998fc4e5b2..2dd19da6b4b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1260,7 +1260,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, flags = 0; if (args->flags & I915_EXEC_SECURE) { - if (!file->is_master || !capable(CAP_SYS_ADMIN)) + if (!drm_is_master(file) || !capable(CAP_SYS_ADMIN)) return -EPERM; flags |= I915_DISPATCH_SECURE; @@ -1369,7 +1369,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ret = i915_parse_cmds(ring, batch_obj, args->batch_start_offset, - file->is_master); + drm_is_master(file)); if (ret) goto err; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 18b54acacfbb..63c4d6f0281e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -990,7 +990,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev, if (unlikely(ret != 0)) return ERR_PTR(-ERESTARTSYS); - if (file_priv->is_master) { + if (drm_is_master(file_priv)) { mutex_unlock(&dev->master_mutex); return NULL; } diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 6f54ff4f9372..72913b299047 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -182,7 +182,7 @@ static void imx_drm_driver_preclose(struct drm_device *drm, { int i; - if (!file->is_master) + if (!drm_is_master(file)) return; for (i = 0; i < MAX_CRTC; i++) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 80889982d196..6ede53712d7b 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -387,8 +387,6 @@ struct drm_prime_file_private { struct drm_file { unsigned always_authenticated :1; unsigned authenticated :1; - /* Whether we're master for a minor. Protected by master_mutex */ - unsigned is_master :1; /* true when the client has asked us to expose stereo 3D mode flags */ unsigned stereo_allowed :1; /* @@ -1034,7 +1032,7 @@ struct drm_device { /** \name Locks */ /*@{ */ struct mutex struct_mutex; /**< For others */ - struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */ + struct mutex master_mutex; /**< For drm_minor::master */ /*@} */ /** \name Usage Counters */ @@ -1172,6 +1170,21 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv) return file_priv->minor->type == DRM_MINOR_LEGACY; } +/** + * drm_is_master() - Check whether a DRM open-file is DRM-Master + * @file: DRM open-file context + * + * This checks whether a DRM open-file context is owner of the master context + * attached to it. If a file owns a master context, it's called DRM-Master. + * Per DRM device, only one such file can be DRM-Master at a time. + * + * Returns: True if the file is DRM-Master, otherwise false. + */ +static inline bool drm_is_master(const struct drm_file *file) +{ + return file->master && file->master == file->minor->master; +} + /******************************************************************/ /** \name Internal function definitions */ /*@{*/ -- cgit v1.2.3 From 7963e9db1b1f842fdc53309baa8714d38e9f5681 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 8 Aug 2014 07:30:53 +1000 Subject: Revert "drm: drop redundant drm_file->is_master" This reverts commit 48ba813701eb14b3008edefef4a0789b328e278c. Thanks to Chris: "drm_file->is_master is not synomous with having drm_file->master == drm_file->minor->master. This is because drm_file->master is the same for all drm_files of the same generation and so when there is a master, every drm_file believes itself to be the master. Confusion ensues and things go pear shaped when one file is closed and there is no master anymore." Conflicts: drivers/gpu/drm/drm_drv.c drivers/gpu/drm/drm_stub.c --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_drv.c | 10 +++++++--- drivers/gpu/drm/drm_fops.c | 4 +++- drivers/gpu/drm/drm_ioctl.c | 2 +- drivers/gpu/drm/drm_lock.c | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/staging/imx-drm/imx-drm-core.c | 2 +- include/drm/drmP.h | 19 +++---------------- 9 files changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index ca8bb1bc92a0..fa2be249999c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3244,7 +3244,7 @@ int drm_mode_getfb(struct drm_device *dev, r->bpp = fb->bits_per_pixel; r->pitch = fb->pitches[0]; if (fb->funcs->create_handle) { - if (drm_is_master(file_priv) || capable(CAP_SYS_ADMIN) || + if (file_priv->is_master || capable(CAP_SYS_ADMIN) || drm_is_control_client(file_priv)) { ret = fb->funcs->create_handle(fb, file_priv, &r->handle); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 92bc6b1d9646..3242e208c0d0 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -179,7 +179,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, int ret = 0; mutex_lock(&dev->master_mutex); - if (drm_is_master(file_priv)) + if (file_priv->is_master) goto out_unlock; if (file_priv->minor->master) { @@ -193,10 +193,13 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, } file_priv->minor->master = drm_master_get(file_priv->master); + file_priv->is_master = 1; if (dev->driver->master_set) { ret = dev->driver->master_set(dev, file_priv, false); - if (unlikely(ret != 0)) + if (unlikely(ret != 0)) { + file_priv->is_master = 0; drm_master_put(&file_priv->minor->master); + } } out_unlock: @@ -210,7 +213,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, int ret = -EINVAL; mutex_lock(&dev->master_mutex); - if (!drm_is_master(file_priv)) + if (!file_priv->is_master) goto out_unlock; if (!file_priv->minor->master) @@ -220,6 +223,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, if (dev->driver->master_drop) dev->driver->master_drop(dev, file_priv, false); drm_master_put(&file_priv->minor->master); + file_priv->is_master = 0; out_unlock: mutex_unlock(&dev->master_mutex); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 4b060942cb3c..79d5221c6e41 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -194,6 +194,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) goto out_close; } + priv->is_master = 1; /* take another reference for the copy in the local file priv */ priv->master = drm_master_get(priv->minor->master); priv->authenticated = 1; @@ -425,7 +426,7 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&dev->master_mutex); - if (drm_is_master(file_priv)) { + if (file_priv->is_master) { struct drm_master *master = file_priv->master; /** @@ -453,6 +454,7 @@ int drm_release(struct inode *inode, struct file *filp) /* drop the master reference held by the file priv */ if (file_priv->master) drm_master_put(&file_priv->master); + file_priv->is_master = 0; mutex_unlock(&dev->master_mutex); if (dev->driver->postclose) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index d3d1a8c72e98..40be746b7e68 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -607,7 +607,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) return -EACCES; /* MASTER is only for master or control clients */ - if (unlikely((flags & DRM_MASTER) && !drm_is_master(file_priv) && + if (unlikely((flags & DRM_MASTER) && !file_priv->is_master && !drm_is_control_client(file_priv))) return -EACCES; diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index ea1572596578..e26b59e385ff 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -112,7 +112,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) /* don't set the block all signals on the master process for now * really probably not the correct answer but lets us debug xkb * xserver for now */ - if (!drm_is_master(file_priv)) { + if (!file_priv->is_master) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGTSTP); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2dd19da6b4b3..60998fc4e5b2 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1260,7 +1260,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, flags = 0; if (args->flags & I915_EXEC_SECURE) { - if (!drm_is_master(file) || !capable(CAP_SYS_ADMIN)) + if (!file->is_master || !capable(CAP_SYS_ADMIN)) return -EPERM; flags |= I915_DISPATCH_SECURE; @@ -1369,7 +1369,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ret = i915_parse_cmds(ring, batch_obj, args->batch_start_offset, - drm_is_master(file)); + file->is_master); if (ret) goto err; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 63c4d6f0281e..18b54acacfbb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -990,7 +990,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev, if (unlikely(ret != 0)) return ERR_PTR(-ERESTARTSYS); - if (drm_is_master(file_priv)) { + if (file_priv->is_master) { mutex_unlock(&dev->master_mutex); return NULL; } diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 72913b299047..6f54ff4f9372 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -182,7 +182,7 @@ static void imx_drm_driver_preclose(struct drm_device *drm, { int i; - if (!drm_is_master(file)) + if (!file->is_master) return; for (i = 0; i < MAX_CRTC; i++) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index a57646382086..a12fbbac373c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -384,6 +384,8 @@ struct drm_prime_file_private { /** File private data */ struct drm_file { unsigned authenticated :1; + /* Whether we're master for a minor. Protected by master_mutex */ + unsigned is_master :1; /* true when the client has asked us to expose stereo 3D mode flags */ unsigned stereo_allowed :1; /* @@ -1020,7 +1022,7 @@ struct drm_device { /** \name Locks */ /*@{ */ struct mutex struct_mutex; /**< For others */ - struct mutex master_mutex; /**< For drm_minor::master */ + struct mutex master_mutex; /**< For drm_minor::master and drm_file::is_master */ /*@} */ /** \name Usage Counters */ @@ -1158,21 +1160,6 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv) return file_priv->minor->type == DRM_MINOR_LEGACY; } -/** - * drm_is_master() - Check whether a DRM open-file is DRM-Master - * @file: DRM open-file context - * - * This checks whether a DRM open-file context is owner of the master context - * attached to it. If a file owns a master context, it's called DRM-Master. - * Per DRM device, only one such file can be DRM-Master at a time. - * - * Returns: True if the file is DRM-Master, otherwise false. - */ -static inline bool drm_is_master(const struct drm_file *file) -{ - return file->master && file->master == file->minor->master; -} - /******************************************************************/ /** \name Internal function definitions */ /*@{*/ -- cgit v1.2.3 From 00e7208997d7a42b6f7b22f582523755f43a2f9b Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 24 Aug 2014 19:23:26 +0200 Subject: drm: fix division-by-zero on dumb_create() Kinda unexpected, but DIV_ROUND_UP() can overflow if passed an argument bigger than UINT_MAX - DIVISOR. Fix this by testing for "!cpp" before using it in the following division. Note that DIV_ROUND_UP() is defined as: #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) ..this will obviously overflow if (n + d - 1) is bigger than UINT_MAX. Reported-by: Tommi Rantala Signed-off-by: David Herrmann Reviewed-by: Rob Clark Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/drm_crtc.c') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fa2be249999c..90e773019eac 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4696,8 +4696,9 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, return -EINVAL; /* overflow checks for 32bit size calculations */ + /* NOTE: DIV_ROUND_UP() can overflow */ cpp = DIV_ROUND_UP(args->bpp, 8); - if (cpp > 0xffffffffU / args->width) + if (!cpp || cpp > 0xffffffffU / args->width) return -EINVAL; stride = cpp * args->width; if (args->height > 0xffffffffU / stride) -- cgit v1.2.3