From 6cbe5c466d73360506a24d98a2e71e47ae02e3ef Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 2 Feb 2017 16:56:29 -0500 Subject: drm/atomic: Save flip flags in drm_crtc_state Allows using atomic flip helpers for drivers using ASYNC flip. Remove ASYNC_FLIP restriction in helpers and caches the page flip flags in drm_crtc_state to be used in the low level drivers. v2: Resending the patch since the original was broken. v3: Save flag in crtc_state instead of plane_state v4: Reset the flag before using again. v5: Fix type in header. Rename the field to pageflip_flags. Remove unrelated hunk. Reviewed-by: Alex Deucher Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1486072591-3893-2-git-send-email-Andrey.Grodzovsky@amd.com --- include/drm/drm_crtc.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8f0b195e4a59..c38a572c16aa 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -155,9 +155,16 @@ struct drm_crtc_state { * Target vertical blank period when a page flip * should take effect. */ - u32 target_vblank; + /** + * @pageflip_flags: + * + * DRM_MODE_PAGE_FLIP_* flags, as passed to the page flip ioctl. + * Zero in any other case. + */ + u32 pageflip_flags; + /** * @event: * -- cgit v1.2.3 From bbba96931762bcad8a691dfbf8d1520b71831c3a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 4 Feb 2017 11:19:13 +0000 Subject: drm: Micro-optimise drm_mm_for_each_node_in_range() As we require valid start/end parameters, we can replace the initial potential NULL with a pointer to the drm_mm.head_node and so reduce the test on every iteration from a NULL + address comparison to just an address comparison. add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-26 (-26) function old new delta i915_gem_evict_for_node 719 693 -26 (No other users outside of the test harness.) Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170204111913.12416-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_mm.c | 2 +- drivers/gpu/drm/selftests/test-drm_mm.c | 10 ++++++---- include/drm/drm_mm.h | 5 ++++- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 8bfb0b327267..f794089d30ac 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -170,7 +170,7 @@ struct drm_mm_node * __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last) { return drm_mm_interval_tree_iter_first((struct rb_root *)&mm->interval_tree, - start, last); + start, last) ?: (struct drm_mm_node *)&mm->head_node; } EXPORT_SYMBOL(__drm_mm_interval_first); diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c index 1e71bc182ca9..2958f596081e 100644 --- a/drivers/gpu/drm/selftests/test-drm_mm.c +++ b/drivers/gpu/drm/selftests/test-drm_mm.c @@ -839,16 +839,18 @@ static bool assert_contiguous_in_range(struct drm_mm *mm, n++; } - drm_mm_for_each_node_in_range(node, mm, 0, start) { - if (node) { + if (start > 0) { + node = __drm_mm_interval_first(mm, 0, start - 1); + if (node->allocated) { pr_err("node before start: node=%llx+%llu, start=%llx\n", node->start, node->size, start); return false; } } - drm_mm_for_each_node_in_range(node, mm, end, U64_MAX) { - if (node) { + if (end < U64_MAX) { + node = __drm_mm_interval_first(mm, end, U64_MAX); + if (node->allocated) { pr_err("node after end: node=%llx+%llu, end=%llx\n", node->start, node->size, end); return false; diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index d81b0ba9921f..f262da180117 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -459,10 +459,13 @@ __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last); * but using the internal interval tree to accelerate the search for the * starting node, and so not safe against removal of elements. It assumes * that @end is within (or is the upper limit of) the drm_mm allocator. + * If [@start, @end] are beyond the range of the drm_mm, the iterator may walk + * over the special _unallocated_ &drm_mm.head_node, and may even continue + * indefinitely. */ #define drm_mm_for_each_node_in_range(node__, mm__, start__, end__) \ for (node__ = __drm_mm_interval_first((mm__), (start__), (end__)-1); \ - node__ && node__->start < (end__); \ + node__->start < (end__); \ node__ = list_next_entry(node__, node_list)) void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, -- cgit v1.2.3 From da7bdda2afdf1ae58546218b50771c2c646bb079 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 7 Feb 2017 17:16:03 +0100 Subject: drm/fb-helper: Automatically clean up fb_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed that everyone duplicates the same logic here and we could safe a few lines per driver. Yay for lots of drivers to make such tiny refactors worth-while! v2: Forgot to git add everything :( v3: Actually remove release_fbi (Sean, Emil, Chris) ... Cc: Chris Wilson Cc: Sean Paul Cc: Noralf Trønnes Cc: Emil Velikov Reviewed-by: Sean Paul Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170207161603.17611-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 11 +++---- drivers/gpu/drm/armada/armada_fbdev.c | 2 -- drivers/gpu/drm/ast/ast_fb.c | 9 ++---- drivers/gpu/drm/bochs/bochs_fbdev.c | 5 +-- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 1 - drivers/gpu/drm/drm_fb_cma_helper.c | 3 +- drivers/gpu/drm/drm_fb_helper.c | 39 ++++++++--------------- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 2 -- drivers/gpu/drm/gma500/framebuffer.c | 9 ++---- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 2 -- drivers/gpu/drm/i915/intel_fbdev.c | 5 +-- drivers/gpu/drm/mgag200/mgag200_fb.c | 5 +-- drivers/gpu/drm/msm/msm_fbdev.c | 1 - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 - drivers/gpu/drm/omapdrm/omap_fbdev.c | 4 --- drivers/gpu/drm/qxl/qxl_fb.c | 5 +-- drivers/gpu/drm/radeon/radeon_fb.c | 11 +++---- drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c | 9 ++---- drivers/gpu/drm/tegra/fb.c | 5 +-- drivers/gpu/drm/udl/udl_fb.c | 5 +-- drivers/gpu/drm/virtio/virtgpu_fb.c | 5 +-- include/drm/drm_fb_helper.h | 4 --- 22 files changed, 39 insertions(+), 104 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 36ce3cac81ba..72505b15dd13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -224,7 +224,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); - goto out_unref; + goto out; } info->par = rfbdev; @@ -233,7 +233,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); - goto out_destroy_fbi; + goto out; } fb = &rfbdev->rfb.base; @@ -266,7 +266,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, if (info->screen_base == NULL) { ret = -ENOSPC; - goto out_destroy_fbi; + goto out; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); @@ -278,9 +278,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, vga_switcheroo_client_fb_set(adev->ddev->pdev, info); return 0; -out_destroy_fbi: - drm_fb_helper_release_fbi(helper); -out_unref: +out: if (abo) { } @@ -304,7 +302,6 @@ static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfb struct amdgpu_framebuffer *rfb = &rfbdev->rfb; drm_fb_helper_unregister_fbi(&rfbdev->helper); - drm_fb_helper_release_fbi(&rfbdev->helper); if (rfb->obj) { amdgpufb_destroy_pinned_object(rfb->obj); diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 0233e1dc33e1..602dfead8eef 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -157,7 +157,6 @@ int armada_fbdev_init(struct drm_device *dev) return 0; err_fb_setup: - drm_fb_helper_release_fbi(fbh); drm_fb_helper_fini(fbh); err_fb_helper: priv->fbdev = NULL; @@ -179,7 +178,6 @@ void armada_fbdev_fini(struct drm_device *dev) if (fbh) { drm_fb_helper_unregister_fbi(fbh); - drm_fb_helper_release_fbi(fbh); drm_fb_helper_fini(fbh); diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 5d0ffab411a8..4ad4acd0ccab 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -215,13 +215,13 @@ static int astfb_create(struct drm_fb_helper *helper, info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); - goto err_free_vram; + goto out; } info->par = afbdev; ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj); if (ret) - goto err_release_fbi; + goto out; afbdev->sysram = sysram; afbdev->size = size; @@ -250,9 +250,7 @@ static int astfb_create(struct drm_fb_helper *helper, return 0; -err_release_fbi: - drm_fb_helper_release_fbi(helper); -err_free_vram: +out: vfree(sysram); return ret; } @@ -287,7 +285,6 @@ static void ast_fbdev_destroy(struct drm_device *dev, struct ast_framebuffer *afb = &afbdev->afb; drm_fb_helper_unregister_fbi(&afbdev->helper); - drm_fb_helper_release_fbi(&afbdev->helper); if (afb->obj) { drm_gem_object_unreference_unlocked(afb->obj); diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 932a769637ef..a11debaad626 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -107,10 +107,8 @@ static int bochsfb_create(struct drm_fb_helper *helper, info->par = &bochs->fb.helper; ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj); - if (ret) { - drm_fb_helper_release_fbi(helper); + if (ret) return ret; - } bochs->fb.size = size; @@ -144,7 +142,6 @@ static int bochs_fbdev_destroy(struct bochs_device *bochs) DRM_DEBUG_DRIVER("\n"); drm_fb_helper_unregister_fbi(&bochs->fb.helper); - drm_fb_helper_release_fbi(&bochs->fb.helper); if (gfb->obj) { drm_gem_object_unreference_unlocked(gfb->obj); diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 4cc679278182..7fa58eeadc9d 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -250,7 +250,6 @@ static int cirrus_fbdev_destroy(struct drm_device *dev, struct cirrus_framebuffer *gfb = &gfbdev->gfb; drm_fb_helper_unregister_fbi(&gfbdev->helper); - drm_fb_helper_release_fbi(&gfbdev->helper); if (gfb->obj) { drm_gem_object_unreference_unlocked(gfb->obj); diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 596fabf18c3e..920bb5764cd6 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -475,7 +475,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper, err_cma_destroy: drm_framebuffer_remove(&fbdev_cma->fb->fb); err_fb_info_destroy: - drm_fb_helper_release_fbi(helper); + drm_fb_helper_fini(helper); err_gem_free_object: drm_gem_object_unreference_unlocked(&obj->base); return ret; @@ -570,7 +570,6 @@ void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper); if (fbdev_cma->fb_helper.fbdev) drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev); - drm_fb_helper_release_fbi(&fbdev_cma->fb_helper); if (fbdev_cma->fb) drm_framebuffer_remove(&fbdev_cma->fb->fb); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d207ea376c0a..c91240598471 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -781,7 +781,9 @@ EXPORT_SYMBOL(drm_fb_helper_init); * @fb_helper: driver-allocated fbdev helper * * A helper to alloc fb_info and the members cmap and apertures. Called - * by the driver within the fb_probe fb_helper callback function. + * by the driver within the fb_probe fb_helper callback function. Drivers do not + * need to release the allocated fb_info structure themselves, this is + * automatically done when calling drm_fb_helper_fini(). * * RETURNS: * fb_info pointer if things went okay, pointer containing error code @@ -834,29 +836,6 @@ void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper) } EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); -/** - * drm_fb_helper_release_fbi - dealloc fb_info and its members - * @fb_helper: driver-allocated fbdev helper - * - * A helper to free memory taken by fb_info and the members cmap and - * apertures - */ -void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper) -{ - if (fb_helper) { - struct fb_info *info = fb_helper->fbdev; - - if (info) { - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - - fb_helper->fbdev = NULL; - } -} -EXPORT_SYMBOL(drm_fb_helper_release_fbi); - /** * drm_fb_helper_fini - finialize a &struct drm_fb_helper * @fb_helper: driver-allocated fbdev helper @@ -866,9 +845,19 @@ EXPORT_SYMBOL(drm_fb_helper_release_fbi); */ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { - if (!drm_fbdev_emulation) + struct fb_info *info; + + if (!drm_fbdev_emulation || !fb_helper) return; + info = fb_helper->fbdev; + if (info) { + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } + fb_helper->fbdev = NULL; + mutex_lock(&kernel_fb_helper_lock); if (!list_empty(&fb_helper->kernel_fb_list)) { list_del(&fb_helper->kernel_fb_list); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index bcdb2720b68e..40aa5056d4ae 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -99,7 +99,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); if (!exynos_gem->kvaddr) { DRM_ERROR("failed to map pages to kernel space.\n"); - drm_fb_helper_release_fbi(helper); return -EIO; } @@ -272,7 +271,6 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, } drm_fb_helper_unregister_fbi(fb_helper); - drm_fb_helper_release_fbi(fb_helper); drm_fb_helper_fini(fb_helper); } diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index da42d2e1d397..9b556b2c7e24 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -392,7 +392,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper); if (IS_ERR(info)) { ret = PTR_ERR(info); - goto err_free_range; + goto out; } info->par = fbdev; @@ -400,7 +400,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); if (ret) - goto err_release; + goto out; fb = &psbfb->base; psbfb->fbdev = info; @@ -445,9 +445,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, psbfb->base.width, psbfb->base.height); return 0; -err_release: - drm_fb_helper_release_fbi(&fbdev->psb_fb_helper); -err_free_range: +out: psb_gtt_free_range(dev, backing); return ret; } @@ -536,7 +534,6 @@ static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) struct psb_framebuffer *psbfb = &fbdev->pfb; drm_fb_helper_unregister_fbi(&fbdev->psb_fb_helper); - drm_fb_helper_release_fbi(&fbdev->psb_fb_helper); drm_fb_helper_fini(&fbdev->psb_fb_helper); drm_framebuffer_unregister_private(&psbfb->base); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c index d7a4d9095b33..f5ac80daeef2 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c @@ -147,7 +147,6 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, return 0; out_release_fbi: - drm_fb_helper_release_fbi(helper); ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL); if (ret1) { DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1); @@ -170,7 +169,6 @@ static void hibmc_fbdev_destroy(struct hibmc_fbdev *fbdev) struct drm_fb_helper *fbh = &fbdev->helper; drm_fb_helper_unregister_fbi(fbh); - drm_fb_helper_release_fbi(fbh); drm_fb_helper_fini(fbh); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 1b8ba2e77539..281c5c48a84d 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -253,7 +253,7 @@ static int intelfb_create(struct drm_fb_helper *helper, if (IS_ERR(vaddr)) { DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); ret = PTR_ERR(vaddr); - goto out_destroy_fbi; + goto out_unpin; } info->screen_base = vaddr; info->screen_size = vma->node.size; @@ -281,8 +281,6 @@ static int intelfb_create(struct drm_fb_helper *helper, vga_switcheroo_client_fb_set(pdev, info); return 0; -out_destroy_fbi: - drm_fb_helper_release_fbi(helper); out_unpin: intel_unpin_fb_vma(vma); out_unlock: @@ -543,7 +541,6 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) */ drm_fb_helper_unregister_fbi(&ifbdev->helper); - drm_fb_helper_release_fbi(&ifbdev->helper); drm_fb_helper_fini(&ifbdev->helper); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index a449bb91213a..5d3b1fac906f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -198,7 +198,7 @@ static int mgag200fb_create(struct drm_fb_helper *helper, ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj); if (ret) - goto err_framebuffer_init; + goto err_alloc_fbi; mfbdev->sysram = sysram; mfbdev->size = size; @@ -230,8 +230,6 @@ static int mgag200fb_create(struct drm_fb_helper *helper, return 0; -err_framebuffer_init: - drm_fb_helper_release_fbi(helper); err_alloc_fbi: vfree(sysram); err_sysram: @@ -246,7 +244,6 @@ static int mga_fbdev_destroy(struct drm_device *dev, struct mga_framebuffer *mfb = &mfbdev->mfb; drm_fb_helper_unregister_fbi(&mfbdev->helper); - drm_fb_helper_release_fbi(&mfbdev->helper); if (mfb->obj) { drm_gem_object_unreference_unlocked(mfb->obj); diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 6b1b375653f7..951e40faf6e8 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -235,7 +235,6 @@ void msm_fbdev_free(struct drm_device *dev) DBG(); drm_fb_helper_unregister_fbi(helper); - drm_fb_helper_release_fbi(helper); drm_fb_helper_fini(helper); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 971c147a3984..a9d48100e74f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -444,7 +444,6 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fbcon->helper.fb); drm_fb_helper_unregister_fbi(&fbcon->helper); - drm_fb_helper_release_fbi(&fbcon->helper); drm_fb_helper_fini(&fbcon->helper); if (nouveau_fb->nvbo) { diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 942c4d483008..4e89dd537862 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -222,9 +222,6 @@ fail_unlock: fail: if (ret) { - - drm_fb_helper_release_fbi(helper); - if (fb) drm_framebuffer_remove(fb); } @@ -301,7 +298,6 @@ void omap_fbdev_free(struct drm_device *dev) DBG(); drm_fb_helper_unregister_fbi(helper); - drm_fb_helper_release_fbi(helper); drm_fb_helper_fini(helper); diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index d479b7a7abe4..44e0619083fc 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -305,7 +305,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, if (info->screen_base == NULL) { ret = -ENOSPC; - goto out_destroy_fbi; + goto out_unref; } #ifdef CONFIG_DRM_FBDEV_EMULATION @@ -320,8 +320,6 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, fb->format->depth, fb->pitches[0], fb->width, fb->height); return 0; -out_destroy_fbi: - drm_fb_helper_release_fbi(&qfbdev->helper); out_unref: if (qbo) { ret = qxl_bo_reserve(qbo, false); @@ -363,7 +361,6 @@ static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev) struct qxl_framebuffer *qfb = &qfbdev->qfb; drm_fb_helper_unregister_fbi(&qfbdev->helper); - drm_fb_helper_release_fbi(&qfbdev->helper); if (qfb->obj) { qxlfb_destroy_pinned_object(qfb->obj); diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 2be4fe9c7217..8d28fe6a280a 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -242,7 +242,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); - goto out_unref; + goto out; } info->par = rfbdev; @@ -251,7 +251,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); - goto out_destroy_fbi; + goto out; } fb = &rfbdev->rfb.base; @@ -284,7 +284,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, if (info->screen_base == NULL) { ret = -ENOSPC; - goto out_destroy_fbi; + goto out; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); @@ -296,9 +296,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); return 0; -out_destroy_fbi: - drm_fb_helper_release_fbi(helper); -out_unref: +out: if (rbo) { } @@ -322,7 +320,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb struct radeon_framebuffer *rfb = &rfbdev->rfb; drm_fb_helper_unregister_fbi(&rfbdev->helper); - drm_fb_helper_release_fbi(&rfbdev->helper); if (rfb->obj) { radeonfb_destroy_pinned_object(rfb->obj); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index 70ad50dd594d..ce946b9c57a9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -78,7 +78,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, if (IS_ERR(fbi)) { dev_err(dev->dev, "Failed to create framebuffer info.\n"); ret = PTR_ERR(fbi); - goto err_rockchip_gem_free_object; + goto out; } helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd, @@ -86,7 +86,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, if (IS_ERR(helper->fb)) { dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); ret = PTR_ERR(helper->fb); - goto err_release_fbi; + goto out; } fbi->par = helper; @@ -114,9 +114,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, return 0; -err_release_fbi: - drm_fb_helper_release_fbi(helper); -err_rockchip_gem_free_object: +out: rockchip_gem_free_object(&rk_obj->base); return ret; } @@ -173,7 +171,6 @@ void rockchip_drm_fbdev_fini(struct drm_device *dev) helper = &private->fbdev_helper; drm_fb_helper_unregister_fbi(helper); - drm_fb_helper_release_fbi(helper); if (helper->fb) drm_framebuffer_unreference(helper->fb); diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index f142f6a4db25..c61d67d16ce3 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -235,7 +235,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", err); drm_gem_object_unreference_unlocked(&bo->gem); - goto release; + return PTR_ERR(fbdev->fb); } fb = &fbdev->fb->base; @@ -272,8 +272,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, destroy: drm_framebuffer_remove(fb); -release: - drm_fb_helper_release_fbi(helper); return err; } @@ -339,7 +337,6 @@ fini: static void tegra_fbdev_exit(struct tegra_fbdev *fbdev) { drm_fb_helper_unregister_fbi(&fbdev->base); - drm_fb_helper_release_fbi(&fbdev->base); if (fbdev->fb) drm_framebuffer_remove(&fbdev->fb->base); diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 8e8d60e9a1a2..d05abc69e305 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -381,7 +381,7 @@ static int udlfb_create(struct drm_fb_helper *helper, ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj); if (ret) - goto out_destroy_fbi; + goto out_gfree; fb = &ufbdev->ufb.base; @@ -403,8 +403,6 @@ static int udlfb_create(struct drm_fb_helper *helper, ufbdev->ufb.obj->vmapping); return ret; -out_destroy_fbi: - drm_fb_helper_release_fbi(helper); out_gfree: drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); out: @@ -419,7 +417,6 @@ static void udl_fbdev_destroy(struct drm_device *dev, struct udl_fbdev *ufbdev) { drm_fb_helper_unregister_fbi(&ufbdev->helper); - drm_fb_helper_release_fbi(&ufbdev->helper); drm_fb_helper_fini(&ufbdev->helper); drm_framebuffer_unregister_private(&ufbdev->ufb.base); drm_framebuffer_cleanup(&ufbdev->ufb.base); diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index 163a67db8cf1..9bfaef379469 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c @@ -320,7 +320,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper, ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, &mode_cmd, &obj->gem_base); if (ret) - goto err_fb_init; + goto err_fb_alloc; fb = &vfbdev->vgfb.base; @@ -341,8 +341,6 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper, info->fix.mmio_len = 0; return 0; -err_fb_init: - drm_fb_helper_release_fbi(helper); err_fb_alloc: virtio_gpu_cmd_resource_inval_backing(vgdev, resid); err_obj_attach: @@ -357,7 +355,6 @@ static int virtio_gpu_fbdev_destroy(struct drm_device *dev, struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb; drm_fb_helper_unregister_fbi(&vgfbdev->helper); - drm_fb_helper_release_fbi(&vgfbdev->helper); if (vgfb->obj) vgfb->obj = NULL; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 6f5acebb266a..339226d074f5 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -249,7 +249,6 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper); void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper); -void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper); void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, uint32_t fb_width, uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, @@ -354,9 +353,6 @@ drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper) static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper) { } -static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper) -{ -} static inline void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, -- cgit v1.2.3 From 84e354839b158d87318eb7fa9828d52baceb23c3 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 7 Feb 2017 17:16:13 +0800 Subject: drm: add vblank hooks to struct drm_crtc_funcs The vblank is mostly CRTC specific and implemented as part of CRTC driver. Let's keep the vblank hooks struct drm_driver for legacy drivers, and add corresponding hooks in struct drm_crtc_funcs. These hooks take struct drm_crtc pointer as argument, and will be called by core vblank handling code for DRIVER_MODESET drivers. The new hooks get plugged into core by adding wrapper functions for vblank handling code. The .get_vblank_counter hook is effectively optional, as we provide drm_vblank_no_hw_counter() as the default fallback in the wrapper function. Signed-off-by: Shawn Guo Reviewed-by: Andrzej Hajda Acked-by: Thierry Reding Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1486458995-31018-2-git-send-email-shawnguo@kernel.org --- drivers/gpu/drm/drm_irq.c | 53 +++++++++++++++++++++++++++++++++++++++++------ include/drm/drm_crtc.h | 44 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_drv.h | 9 ++++++++ 3 files changed, 100 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index e06cf11ebb4a..646b3e57b9ad 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -89,6 +89,21 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, write_sequnlock(&vblank->seqlock); } +static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + + if (crtc->funcs->get_vblank_counter) + return crtc->funcs->get_vblank_counter(crtc); + } + + if (dev->driver->get_vblank_counter) + return dev->driver->get_vblank_counter(dev, pipe); + + return drm_vblank_no_hw_counter(dev, pipe); +} + /* * Reset the stored timestamp for the current vblank count to correspond * to the last vblank occurred. @@ -112,9 +127,9 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe * when drm_vblank_enable() applies the diff */ do { - cur_vblank = dev->driver->get_vblank_counter(dev, pipe); + cur_vblank = __get_vblank_counter(dev, pipe); rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); - } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); /* * Only reinitialize corresponding vblank timestamp if high-precision query @@ -168,9 +183,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, * corresponding vblank timestamp. */ do { - cur_vblank = dev->driver->get_vblank_counter(dev, pipe); + cur_vblank = __get_vblank_counter(dev, pipe); rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); - } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); if (dev->max_vblank_count != 0) { /* trust the hw counter when it's around */ @@ -275,6 +290,20 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_accurate_vblank_count); +static void __disable_vblank(struct drm_device *dev, unsigned int pipe) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + + if (crtc->funcs->disable_vblank) { + crtc->funcs->disable_vblank(crtc); + return; + } + } + + dev->driver->disable_vblank(dev, pipe); +} + /* * Disable vblank irq's on crtc, make sure that last vblank count * of hardware and corresponding consistent software vblank counter @@ -298,7 +327,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) * hardware potentially runtime suspended. */ if (vblank->enabled) { - dev->driver->disable_vblank(dev, pipe); + __disable_vblank(dev, pipe); vblank->enabled = false; } @@ -1027,6 +1056,18 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_crtc_send_vblank_event); +static int __enable_vblank(struct drm_device *dev, unsigned int pipe) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + + if (crtc->funcs->enable_vblank) + return crtc->funcs->enable_vblank(crtc); + } + + return dev->driver->enable_vblank(dev, pipe); +} + /** * drm_vblank_enable - enable the vblank interrupt on a CRTC * @dev: DRM device @@ -1052,7 +1093,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) * timestamps. Filtercode in drm_handle_vblank() will * prevent double-accounting of same vblank interval. */ - ret = dev->driver->enable_vblank(dev, pipe); + ret = __enable_vblank(dev, pipe); DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); if (ret) atomic_dec(&vblank->refcount); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c38a572c16aa..bda9347554a1 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -608,6 +608,50 @@ struct drm_crtc_funcs { */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_crtc_state *state); + + /** + * @get_vblank_counter: + * + * Driver callback for fetching a raw hardware vblank counter for the + * CRTC. It's meant to be used by new drivers as the replacement of + * &drm_driver.get_vblank_counter hook. + * + * This callback is optional. If a device doesn't have a hardware + * counter, the driver can simply leave the hook as NULL. The DRM core + * will account for missed vblank events while interrupts where disabled + * based on system timestamps. + * + * Wraparound handling and loss of events due to modesetting is dealt + * with in the DRM core code, as long as drivers call + * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or + * enabling a CRTC. + * + * Returns: + * + * Raw vblank counter value. + */ + u32 (*get_vblank_counter)(struct drm_crtc *crtc); + + /** + * @enable_vblank: + * + * Enable vblank interrupts for the CRTC. It's meant to be used by + * new drivers as the replacement of &drm_driver.enable_vblank hook. + * + * Returns: + * + * Zero on success, appropriate errno if the vblank interrupt cannot + * be enabled. + */ + int (*enable_vblank)(struct drm_crtc *crtc); + + /** + * @disable_vblank: + * + * Disable vblank interrupts for the CRTC. It's meant to be used by + * new drivers as the replacement of &drm_driver.disable_vblank hook. + */ + void (*disable_vblank)(struct drm_crtc *crtc); }; /** diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 5699f42195fe..8f8b9a1e55e6 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -130,6 +130,9 @@ struct drm_driver { * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or * enabling a CRTC. * + * This is deprecated and should not be used by new drivers. + * Use &drm_crtc_funcs.get_vblank_counter instead. + * * Returns: * * Raw vblank counter value. @@ -142,6 +145,9 @@ struct drm_driver { * Enable vblank interrupts for the CRTC specified with the pipe * argument. * + * This is deprecated and should not be used by new drivers. + * Use &drm_crtc_funcs.enable_vblank instead. + * * Returns: * * Zero on success, appropriate errno if the given @crtc's vblank @@ -154,6 +160,9 @@ struct drm_driver { * * Disable vblank interrupts for the CRTC specified with the pipe * argument. + * + * This is deprecated and should not be used by new drivers. + * Use &drm_crtc_funcs.disable_vblank instead. */ void (*disable_vblank) (struct drm_device *dev, unsigned int pipe); -- cgit v1.2.3 From 5ac74757eef78d69cd3aabe503b29aff471fdd56 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 7 Feb 2017 17:16:15 +0800 Subject: drm: unexport function drm_vblank_no_hw_counter() The function drm_vblank_no_hw_counter() is now only used in core vblank wrapper code. Let's unexport it by making it a static function. Signed-off-by: Shawn Guo Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1486458995-31018-4-git-send-email-shawnguo@kernel.org --- drivers/gpu/drm/drm_irq.c | 28 ++++++++++------------------ include/drm/drm_drv.h | 7 +++---- include/drm/drm_irq.h | 1 - 3 files changed, 13 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 646b3e57b9ad..1906723af389 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -89,6 +89,16 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, write_sequnlock(&vblank->seqlock); } +/* + * "No hw counter" fallback implementation of .get_vblank_counter() hook, + * if there is no useable hardware frame counter available. + */ +static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe) +{ + WARN_ON_ONCE(dev->max_vblank_count != 0); + return 0; +} + static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe) { if (drm_core_check_feature(dev, DRIVER_MODESET)) { @@ -1748,21 +1758,3 @@ bool drm_crtc_handle_vblank(struct drm_crtc *crtc) return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); } EXPORT_SYMBOL(drm_crtc_handle_vblank); - -/** - * drm_vblank_no_hw_counter - "No hw counter" implementation of .get_vblank_counter() - * @dev: DRM device - * @pipe: CRTC for which to read the counter - * - * Drivers can plug this into the .get_vblank_counter() function if - * there is no useable hardware frame counter available. - * - * Returns: - * 0 - */ -u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe) -{ - WARN_ON_ONCE(dev->max_vblank_count != 0); - return 0; -} -EXPORT_SYMBOL(drm_vblank_no_hw_counter); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 8f8b9a1e55e6..4e66fbb56773 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -120,10 +120,9 @@ struct drm_driver { * * Driver callback for fetching a raw hardware vblank counter for the * CRTC specified with the pipe argument. If a device doesn't have a - * hardware counter, the driver can simply use - * drm_vblank_no_hw_counter() function. The DRM core will account for - * missed vblank events while interrupts where disabled based on system - * timestamps. + * hardware counter, the driver can simply leave the hook as NULL. + * The DRM core will account for missed vblank events while interrupts + * where disabled based on system timestamps. * * Wraparound handling and loss of events due to modesetting is dealt * with in the DRM core code, as long as drivers call diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h index 2fb880462a57..cf0be6594c8c 100644 --- a/include/drm/drm_irq.h +++ b/include/drm/drm_irq.h @@ -152,7 +152,6 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); void drm_vblank_cleanup(struct drm_device *dev); u32 drm_accurate_vblank_count(struct drm_crtc *crtc); -u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe); int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- cgit v1.2.3 From a4b10ccead4de0cf46bffb32fcb9e134b202676b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 2 Jan 2017 11:16:13 +0200 Subject: drm: Constify drm_mode_config atomic helper private pointer The drm_mode_config helper private field points to a structure of function pointers that don't need to be modified at runtime. Make it const. Signed-off-by: Laurent Pinchart Reviewed-by: Gabriel Krisman Bertazi Acked-by: Brian Starkey Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170102091613.6310-1-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/arm/malidp_drv.c | 2 +- drivers/gpu/drm/drm_atomic_helper.c | 2 +- drivers/gpu/drm/imx/imx-drm-core.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +- drivers/gpu/drm/virtio/virtgpu_display.c | 2 +- include/drm/drm_mode_config.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 5dfcdb05c96e..a9608a2e5a29 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -100,7 +100,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_cleanup_planes(drm, state); } -static struct drm_mode_config_helper_funcs malidp_mode_config_helpers = { +static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = { .atomic_commit_tail = malidp_atomic_commit_tail, }; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ace4485a27f7..cceb551c1a21 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1170,7 +1170,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail); static void commit_tail(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; - struct drm_mode_config_helper_funcs *funcs; + const struct drm_mode_config_helper_funcs *funcs; funcs = dev->mode_config.helper_private; diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 65bd8b8a2494..45dceb672e20 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -138,7 +138,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_cleanup_planes(dev, state); } -static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { +static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { .atomic_commit_tail = imx_drm_atomic_commit_tail, }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index d5e1f8627d38..200b35b6b389 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -193,7 +193,7 @@ rockchip_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_cleanup_planes(dev, state); } -static struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { +static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { .atomic_commit_tail = rockchip_atomic_commit_tail, }; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index fad5a1cc5903..d51bd4521f17 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -347,7 +347,7 @@ static void vgdev_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_cleanup_planes(dev, state); } -static struct drm_mode_config_helper_funcs virtio_mode_config_helpers = { +static const struct drm_mode_config_helper_funcs virtio_mode_config_helpers = { .atomic_commit_tail = vgdev_atomic_commit_tail, }; diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 5a29978062d3..6cd541d69c2e 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -661,7 +661,7 @@ struct drm_mode_config { /* cursor size */ uint32_t cursor_width, cursor_height; - struct drm_mode_config_helper_funcs *helper_private; + const struct drm_mode_config_helper_funcs *helper_private; }; void drm_mode_config_init(struct drm_device *dev); -- cgit v1.2.3 From 581e49fe6b411f407102a7f2377648849e0fa37f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 16 Jan 2017 10:37:38 +0100 Subject: drm/atomic: Add new iterators over all state, v3. Add for_each_(old)(new)_(plane,connector,crtc)_in_state iterators to replace the old for_each_xxx_in_state ones. This is useful for >1 flip depth and getting rid of all xxx->state dereferences. This requires extra fixups done when committing a state after duplicating, which in general isn't valid but is used by suspend/resume. To handle these, introduce drm_atomic_helper_commit_duplicated_state which performs those fixups before checking & committing the state. Changes since v1: - Remove nonblock parameter for commit_duplicated_state. Changes since v2: - Use commit_duplicated_state for i915 load detection. - Add WARN_ON(old_state != obj->state) before swapping. Signed-off-by: Maarten Lankhorst Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1484559464-27107-2-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic.c | 6 +++ drivers/gpu/drm/drm_atomic_helper.c | 65 +++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_display.c | 13 +++--- include/drm/drm_atomic.h | 81 ++++++++++++++++++++++++++++++++++-- include/drm/drm_atomic_helper.h | 2 + 5 files changed, 149 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index c97588a28216..28f192a0eb8e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -275,6 +275,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, return ERR_PTR(-ENOMEM); state->crtcs[index].state = crtc_state; + state->crtcs[index].old_state = crtc->state; + state->crtcs[index].new_state = crtc_state; state->crtcs[index].ptr = crtc; crtc_state->state = state; @@ -689,6 +691,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, state->planes[index].state = plane_state; state->planes[index].ptr = plane; + state->planes[index].old_state = plane->state; + state->planes[index].new_state = plane_state; plane_state->state = state; DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n", @@ -1028,6 +1032,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, drm_connector_reference(connector); state->connectors[index].state = connector_state; + state->connectors[index].old_state = connector->state; + state->connectors[index].new_state = connector_state; state->connectors[index].ptr = connector; connector_state->state = state; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index cceb551c1a21..cbd1332c20d1 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1977,11 +1977,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, int i; long ret; struct drm_connector *connector; - struct drm_connector_state *conn_state; + struct drm_connector_state *conn_state, *old_conn_state; struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *crtc_state, *old_crtc_state; struct drm_plane *plane; - struct drm_plane_state *plane_state; + struct drm_plane_state *plane_state, *old_plane_state; struct drm_crtc_commit *commit; if (stall) { @@ -2005,13 +2005,17 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, } } - for_each_connector_in_state(state, connector, conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) { + WARN_ON(connector->state != old_conn_state); + connector->state->state = state; swap(state->connectors[i].state, connector->state); connector->state->state = NULL; } - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { + WARN_ON(crtc->state != old_crtc_state); + crtc->state->state = state; swap(state->crtcs[i].state, crtc->state); crtc->state->state = NULL; @@ -2026,7 +2030,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, } } - for_each_plane_in_state(state, plane, plane_state, i) { + for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) { + WARN_ON(plane->state != old_plane_state); + plane->state->state = state; swap(state->planes[i].state, plane->state); plane->state->state = NULL; @@ -2477,7 +2483,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_all); * * See also: * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(), - * drm_atomic_helper_resume() + * drm_atomic_helper_resume(), drm_atomic_helper_commit_duplicated_state() */ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) { @@ -2517,6 +2523,47 @@ unlock: } EXPORT_SYMBOL(drm_atomic_helper_suspend); +/** + * drm_atomic_helper_commit_duplicated_state - commit duplicated state + * @state: duplicated atomic state to commit + * @ctx: pointer to acquire_ctx to use for commit. + * + * The state returned by drm_atomic_helper_duplicate_state() and + * drm_atomic_helper_suspend() is partially invalid, and needs to + * be fixed up before commit. + * + * Returns: + * 0 on success or a negative error code on failure. + * + * See also: + * drm_atomic_helper_suspend() + */ +int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx) +{ + int i; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + + state->acquire_ctx = ctx; + + for_each_new_plane_in_state(state, plane, plane_state, i) + state->planes[i].old_state = plane->state; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) + state->crtcs[i].old_state = crtc->state; + + for_each_new_connector_in_state(state, connector, conn_state, i) + state->connectors[i].old_state = connector->state; + + return drm_atomic_commit(state); +} +EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state); + /** * drm_atomic_helper_resume - subsystem-level resume helper * @dev: DRM device @@ -2540,9 +2587,9 @@ int drm_atomic_helper_resume(struct drm_device *dev, int err; drm_mode_config_reset(dev); + drm_modeset_lock_all(dev); - state->acquire_ctx = config->acquire_ctx; - err = drm_atomic_commit(state); + err = drm_atomic_helper_commit_duplicated_state(state, config->acquire_ctx); drm_modeset_unlock_all(dev); return err; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b3e773c9f872..36ecc864e711 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3481,7 +3481,8 @@ static void intel_update_primary_planes(struct drm_device *dev) static int __intel_display_resume(struct drm_device *dev, - struct drm_atomic_state *state) + struct drm_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx) { struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; @@ -3505,7 +3506,7 @@ __intel_display_resume(struct drm_device *dev, /* ignore any reset values/BIOS leftovers in the WM registers */ to_intel_atomic_state(state)->skip_intermediate_wm = true; - ret = drm_atomic_commit(state); + ret = drm_atomic_helper_commit_duplicated_state(state, ctx); WARN_ON(ret == -EDEADLK); return ret; @@ -3595,7 +3596,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) */ intel_update_primary_planes(dev); } else { - ret = __intel_display_resume(dev, state); + ret = __intel_display_resume(dev, state, ctx); if (ret) DRM_ERROR("Restoring old state failed with %i\n", ret); } @@ -3615,7 +3616,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) dev_priv->display.hpd_irq_setup(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); - ret = __intel_display_resume(dev, state); + ret = __intel_display_resume(dev, state, ctx); if (ret) DRM_ERROR("Restoring old state failed with %i\n", ret); @@ -11316,7 +11317,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, if (!state) return; - ret = drm_atomic_commit(state); + ret = drm_atomic_helper_commit_duplicated_state(state, ctx); if (ret) DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret); drm_atomic_state_put(state); @@ -17212,7 +17213,7 @@ void intel_display_resume(struct drm_device *dev) } if (!ret) - ret = __intel_display_resume(dev, state); + ret = __intel_display_resume(dev, state, &ctx); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 2e28fdca9c3d..3fa6e8dcb9d8 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -138,12 +138,12 @@ struct drm_crtc_commit { struct __drm_planes_state { struct drm_plane *ptr; - struct drm_plane_state *state; + struct drm_plane_state *state, *old_state, *new_state; }; struct __drm_crtcs_state { struct drm_crtc *ptr; - struct drm_crtc_state *state; + struct drm_crtc_state *state, *old_state, *new_state; struct drm_crtc_commit *commit; s64 __user *out_fence_ptr; unsigned last_vblank_count; @@ -151,7 +151,7 @@ struct __drm_crtcs_state { struct __drm_connnectors_state { struct drm_connector *ptr; - struct drm_connector_state *state; + struct drm_connector_state *state, *old_state, *new_state; }; /** @@ -398,6 +398,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if (connector) +#define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_connector && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (old_connector_state) = (__state)->connectors[__i].old_state, \ + (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ + (__i)++) \ + for_each_if (connector) + +#define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_connector && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (old_connector_state) = (__state)->connectors[__i].old_state, 1); \ + (__i)++) \ + for_each_if (connector) + +#define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_connector && \ + ((connector) = (__state)->connectors[__i].ptr, \ + (new_connector_state) = (__state)->connectors[__i].new_state, 1); \ + (__i)++) \ + for_each_if (connector) + #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->dev->mode_config.num_crtc && \ @@ -406,6 +431,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if (crtc_state) +#define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_crtc && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (old_crtc_state) = (__state)->crtcs[__i].old_state, \ + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ + (__i)++) \ + for_each_if (crtc) + +#define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_crtc && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (old_crtc_state) = (__state)->crtcs[__i].old_state, 1); \ + (__i)++) \ + for_each_if (crtc) + +#define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_crtc && \ + ((crtc) = (__state)->crtcs[__i].ptr, \ + (new_crtc_state) = (__state)->crtcs[__i].new_state, 1); \ + (__i)++) \ + for_each_if (crtc) + #define for_each_plane_in_state(__state, plane, plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->dev->mode_config.num_total_plane && \ @@ -414,6 +464,31 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); (__i)++) \ for_each_if (plane_state) +#define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_total_plane && \ + ((plane) = (__state)->planes[__i].ptr, \ + (old_plane_state) = (__state)->planes[__i].old_state, \ + (new_plane_state) = (__state)->planes[__i].new_state, 1); \ + (__i)++) \ + for_each_if (plane) + +#define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_total_plane && \ + ((plane) = (__state)->planes[__i].ptr, \ + (old_plane_state) = (__state)->planes[__i].old_state, 1); \ + (__i)++) \ + for_each_if (plane) + +#define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->dev->mode_config.num_total_plane && \ + ((plane) = (__state)->planes[__i].ptr, \ + (new_plane_state) = (__state)->planes[__i].new_state, 1); \ + (__i)++) \ + for_each_if (plane) + /** * drm_atomic_crtc_needs_modeset - compute combined modeset need * @state: &drm_crtc_state for the CRTC diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index d066e9491ae3..9ceda379ce58 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -105,6 +105,8 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, int drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev); +int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx); int drm_atomic_helper_resume(struct drm_device *dev, struct drm_atomic_state *state); -- cgit v1.2.3 From 07c2b84b9956dd5d0871d47f5f0bbf9388d2d83f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 17 Feb 2017 17:20:51 +0200 Subject: drm: move edid property update and add modes out of edid firmware loader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the firmware loader more generic and generally useful. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1487344854-18777-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/drm_edid_load.c | 17 ++++------------- drivers/gpu/drm/drm_probe_helper.c | 8 +++++++- include/drm/drm_edid.h | 7 ++++--- 3 files changed, 15 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 622f788bff46..1c0495acf341 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -256,15 +256,14 @@ out: return edid; } -int drm_load_edid_firmware(struct drm_connector *connector) +struct edid *drm_load_edid_firmware(struct drm_connector *connector) { const char *connector_name = connector->name; char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL; - int ret; struct edid *edid; if (edid_firmware[0] == '\0') - return 0; + return ERR_PTR(-ENOENT); /* * If there are multiple edid files specified and separated @@ -293,7 +292,7 @@ int drm_load_edid_firmware(struct drm_connector *connector) if (!edidname) { if (!fallback) { kfree(fwstr); - return 0; + return ERR_PTR(-ENOENT); } edidname = fallback; } @@ -305,13 +304,5 @@ int drm_load_edid_firmware(struct drm_connector *connector) edid = edid_load(connector, edidname, connector_name); kfree(fwstr); - if (IS_ERR_OR_NULL(edid)) - return 0; - - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - kfree(edid); - - return ret; + return edid; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 93381454bdf7..358957118ca9 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -311,7 +311,13 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, count = drm_add_edid_modes(connector, edid); drm_edid_to_eld(connector, edid); } else { - count = drm_load_edid_firmware(connector); + struct edid *edid = drm_load_edid_firmware(connector); + if (!IS_ERR_OR_NULL(edid)) { + drm_mode_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + kfree(edid); + } if (count == 0) count = (*connector_funcs->get_modes)(connector); } diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 43fb0ac5eb9c..a55eea4afb61 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -331,11 +331,12 @@ int drm_av_sync_delay(struct drm_connector *connector, const struct drm_display_mode *mode); #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE -int drm_load_edid_firmware(struct drm_connector *connector); +struct edid *drm_load_edid_firmware(struct drm_connector *connector); #else -static inline int drm_load_edid_firmware(struct drm_connector *connector) +static inline struct edid * +drm_load_edid_firmware(struct drm_connector *connector) { - return 0; + return ERR_PTR(-ENOENT); } #endif -- cgit v1.2.3 From 3c6d6e0fbf5eb6367dfc8a97f72bd625e78b1aae Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 15 Feb 2017 15:33:18 -0800 Subject: drm: drm_printer: add __printf validation drm_printf does not currently use the compiler to verify format and arguments. Make it do so. Miscellanea: o Add appropriate #include files for __printf and struct va_format o Convert dev_printk to dev_info Signed-off-by: Joe Perches Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/133858f214e9b90f92bb8eb44c6b1dc04429933d.1487201526.git.joe@perches.com --- drivers/gpu/drm/drm_print.c | 2 +- include/drm/drm_print.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 02a107d50706..74c466aca622 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -36,7 +36,7 @@ EXPORT_SYMBOL(__drm_printfn_seq_file); void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf) { - dev_printk(KERN_INFO, p->arg, "[" DRM_NAME "] %pV", vaf); + dev_info(p->arg, "[" DRM_NAME "] %pV", vaf); } EXPORT_SYMBOL(__drm_printfn_info); diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 7d98763c0444..ca4d7c6321f2 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -26,6 +26,8 @@ #ifndef DRM_PRINT_H_ #define DRM_PRINT_H_ +#include +#include #include #include @@ -75,6 +77,7 @@ void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf); +__printf(2, 3) void drm_printf(struct drm_printer *p, const char *f, ...); -- cgit v1.2.3 From 2955b73def6712b693fc7ad82b34b3831faaa146 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 21 Feb 2017 09:30:00 +0000 Subject: dma-buf/reservation: Wrap ww_mutex_trylock In a similar fashion to reservation_object_lock() and reservation_object_unlock(), ww_mutex_trylock is also useful and so is worth wrapping for consistency. Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Joonas Lahtinen Cc: Daniel Vetter [danvet: Add __must_check Joonas wants.] Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20170221093000.22802-1-chris@chris-wilson.co.uk --- include/linux/reservation.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include') diff --git a/include/linux/reservation.h b/include/linux/reservation.h index 2b5a4679daea..156cfd330b66 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h @@ -166,6 +166,26 @@ reservation_object_lock(struct reservation_object *obj, return ww_mutex_lock(&obj->lock, ctx); } +/** + * reservation_object_trylock - trylock the reservation object + * @obj: the reservation object + * + * Tries to lock the reservation object for exclusive access and modification. + * Note, that the lock is only against other writers, readers will run + * concurrently with a writer under RCU. The seqlock is used to notify readers + * if they overlap with a writer. + * + * Also note that since no context is provided, no deadlock protection is + * possible. + * + * Returns true if the lock was acquired, false otherwise. + */ +static inline bool __must_check +reservation_object_trylock(struct reservation_object *obj) +{ + return ww_mutex_trylock(&obj->lock); +} + /** * reservation_object_unlock - unlock the reservation object * @obj: the reservation object -- cgit v1.2.3 From 7adbd209ce5a1b17754e2b73ec43aed392ee950c Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 22 Feb 2017 14:17:41 +0530 Subject: drm/doc: Fix up some kms function names A couple of the kms functions didn't have the correct/newest names. This prevented them to be identified as refs in the html doc. Reviewed-by: Eric Engestrom Tested-by: Eric Engestrom Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/20170222084741.8485-1-architt@codeaurora.org --- include/drm/drm_mode_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 29f734a542c8..f220ee909bdb 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -267,7 +267,7 @@ struct drm_mode_config_funcs { * passed-in &drm_atomic_state. This hook is called when the caller * encountered a &drm_modeset_lock deadlock and needs to drop all * already acquired locks as part of the deadlock avoidance dance - * implemented in drm_modeset_lock_backoff(). + * implemented in drm_modeset_backoff(). * * Any duplicated state must be invalidated since a concurrent atomic * update might change it, and the drm atomic interfaces always apply @@ -285,8 +285,8 @@ struct drm_mode_config_funcs { * itself. Note that the core first calls drm_atomic_state_clear() to * avoid code duplicate between the clear and free hooks. * - * Drivers that implement this must call drm_atomic_state_default_free() - * to release common resources. + * Drivers that implement this must call + * drm_atomic_state_default_release() to release common resources. */ void (*atomic_state_free)(struct drm_atomic_state *state); }; -- cgit v1.2.3 From 40ee6fbef75fe6452dc9e69e6f9f1a2c7808ed67 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Fri, 16 Dec 2016 12:29:06 +0200 Subject: drm: Add a new connector atomic property for link status At the time userspace does setcrtc, we've already promised the mode would work. The promise is based on the theoretical capabilities of the link, but it's possible we can't reach this in practice. The DP spec describes how the link should be reduced, but we can't reduce the link below the requirements of the mode. Black screen follows. One idea would be to have setcrtc return a failure. However, it already should not fail as the atomic checks have passed. It would also conflict with the idea of making setcrtc asynchronous in the future, returning before the actual mode setting and link training. Another idea is to train the link "upfront" at hotplug time, before pruning the mode list, so that we can do the pruning based on practical not theoretical capabilities. However, the changes for link training are pretty drastic, all for the sake of error handling and DP compliance, when the most common happy day scenario is the current approach of link training at mode setting time, using the optimal parameters for the mode. It is also not certain all hardware could do this without the pipe on; not even all our hardware can do this. Some of this can be solved, but not trivially. Both of the above ideas also fail to address link degradation *during* operation. The solution is to add a new "link-status" connector property in order to address link training failure in a way that: a) changes the current happy day scenario as little as possible, to avoid regressions, b) can be implemented the same way by all drm drivers, c) is still opt-in for the drivers and userspace, and opting out doesn't regress the user experience, d) doesn't prevent drivers from implementing better or alternate approaches, possibly without userspace involvement. And, of course, handles all the issues presented. In the usual happy day scenario, this is always "good". If something fails during or after a mode set, the kernel driver can set the link status to "bad" and issue a hotplug uevent for userspace to have it re-check the valid modes through GET_CONNECTOR IOCTL, and try modeset again. If the theoretical capabilities of the link can't be reached, the mode list is trimmed based on that. v7 by Jani: * Rebase, simplify set property while at it, checkpatch fix v6: * Fix a typo in kernel doc (Sean Paul) v5: * Clarify doc for silent rejection of atomic properties by driver (Daniel Vetter) v4: * Add comments in kernel-doc format (Daniel Vetter) * Update the kernel-doc for link-status (Sean Paul) v3: * Fixed a build error (Jani Saarinen) v2: * Removed connector->link_status (Daniel Vetter) * Set connector->state->link_status in drm_mode_connector_set_link_status_property (Daniel Vetter) * Set the connector_changed flag to true if connector->state->link_status changed. * Reset link_status to GOOD in update_output_state (Daniel Vetter) * Never allow userspace to set link status from Good To Bad (Daniel Vetter) Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Reviewed-by: Jani Nikula Acked-by: Tony Cheng Acked-by: Harry Wentland Cc: Jani Nikula Cc: Daniel Vetter Cc: Ville Syrjala Cc: Chris Wilson Cc: Sean Paul Signed-off-by: Manasi Navare Signed-off-by: Jani Nikula Acked-by: Eric Anholt (for the -modesetting patch) Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/0182487051aa9f1594820e35a4853de2f8747b4e.1481883920.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_atomic.c | 16 ++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 15 +++++++++++ drivers/gpu/drm/drm_connector.c | 52 +++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 19 ++++++++++++++ include/drm/drm_mode_config.h | 5 ++++ include/uapi/drm/drm_mode.h | 4 +++ 6 files changed, 111 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index afec53832145..3b6e6e924e3c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1109,6 +1109,20 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, state->tv.saturation = val; } else if (property == config->tv_hue_property) { state->tv.hue = val; + } else if (property == config->link_status_property) { + /* Never downgrade from GOOD to BAD on userspace's request here, + * only hw issues can do that. + * + * For an atomic property the userspace doesn't need to be able + * to understand all the properties, but needs to be able to + * restore the state it wants on VT switch. So if the userspace + * tries to change the link_status from GOOD to BAD, driver + * silently rejects it and returns a 0. This prevents userspace + * from accidently breaking the display when it restores the + * state. + */ + if (state->link_status != DRM_LINK_STATUS_GOOD) + state->link_status = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -1183,6 +1197,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->tv.saturation; } else if (property == config->tv_hue_property) { *val = state->tv.hue; + } else if (property == config->link_status_property) { + *val = state->link_status; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9203f3e933f7..2e62b332ae8b 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -530,6 +530,13 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, connector_state); if (ret) return ret; + if (connector->state->crtc) { + crtc_state = drm_atomic_get_existing_crtc_state(state, + connector->state->crtc); + if (connector->state->link_status != + connector_state->link_status) + crtc_state->connectors_changed = true; + } } /* @@ -2241,6 +2248,8 @@ static int update_output_state(struct drm_atomic_state *state, NULL); if (ret) return ret; + /* Make sure legacy setCrtc always re-trains */ + conn_state->link_status = DRM_LINK_STATUS_GOOD; } } @@ -2284,6 +2293,12 @@ static int update_output_state(struct drm_atomic_state *state, * * Provides a default crtc set_config handler using the atomic driver interface. * + * NOTE: For backwards compatibility with old userspace this automatically + * resets the "link-status" property to GOOD, to force any link + * re-training. The SETCRTC ioctl does not define whether an update does + * need a full modeset or just a plane update, hence we're allowed to do + * that. See also drm_mode_connector_set_link_status_property(). + * * Returns: * Returns 0 on success, negative errno numbers on failure. */ diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 45464c8b797d..ab73e86ffdf1 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -244,6 +244,10 @@ int drm_connector_init(struct drm_device *dev, drm_object_attach_property(&connector->base, config->dpms_property, 0); + drm_object_attach_property(&connector->base, + config->link_status_property, + 0); + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); } @@ -599,6 +603,12 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = { }; DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) +static const struct drm_prop_enum_list drm_link_status_enum_list[] = { + { DRM_MODE_LINK_STATUS_GOOD, "Good" }, + { DRM_MODE_LINK_STATUS_BAD, "Bad" }, +}; +DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list) + /** * drm_display_info_set_bus_formats - set the supported bus formats * @info: display info to store bus formats in @@ -718,6 +728,11 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, * tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers * should update this value using drm_mode_connector_set_tile_property(). * Userspace cannot change this property. + * link-status: + * Connector link-status property to indicate the status of link. The default + * value of link-status is "GOOD". If something fails during or after modeset, + * the kernel driver may set this to "BAD" and issue a hotplug uevent. Drivers + * should update this value using drm_mode_connector_set_link_status_property(). * * Connectors also have one standardized atomic property: * @@ -759,6 +774,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.tile_property = prop; + prop = drm_property_create_enum(dev, 0, "link-status", + drm_link_status_enum_list, + ARRAY_SIZE(drm_link_status_enum_list)); + if (!prop) + return -ENOMEM; + dev->mode_config.link_status_property = prop; + return 0; } @@ -1088,6 +1110,36 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_mode_connector_update_edid_property); +/** + * drm_mode_connector_set_link_status_property - Set link status property of a connector + * @connector: drm connector + * @link_status: new value of link status property (0: Good, 1: Bad) + * + * In usual working scenario, this link status property will always be set to + * "GOOD". If something fails during or after a mode set, the kernel driver + * may set this link status property to "BAD". The caller then needs to send a + * hotplug uevent for userspace to re-check the valid modes through + * GET_CONNECTOR_IOCTL and retry modeset. + * + * Note: Drivers cannot rely on userspace to support this property and + * issue a modeset. As such, they may choose to handle issues (like + * re-training a link) without userspace's intervention. + * + * The reason for adding this property is to handle link training failures, but + * it is not limited to DP or link training. For example, if we implement + * asynchronous setcrtc, this property can be used to report any failures in that. + */ +void drm_mode_connector_set_link_status_property(struct drm_connector *connector, + uint64_t link_status) +{ + struct drm_device *dev = connector->dev; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + connector->state->link_status = link_status; + drm_modeset_unlock(&dev->mode_config.connection_mutex); +} +EXPORT_SYMBOL(drm_mode_connector_set_link_status_property); + int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, struct drm_property *property, uint64_t value) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index e5e1eddd19fb..f08aa5dfc9d7 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -89,6 +89,17 @@ enum subpixel_order { SubPixelNone, }; +/** + * enum drm_link_status - connector's link_status property value + * + * This enum is used as the connector's link status property value. + * It is set to the values defined in uapi. + */ +enum drm_link_status { + DRM_LINK_STATUS_GOOD = DRM_MODE_LINK_STATUS_GOOD, + DRM_LINK_STATUS_BAD = DRM_MODE_LINK_STATUS_BAD, +}; + /** * struct drm_display_info - runtime data about the connected sink * @@ -243,6 +254,12 @@ struct drm_connector_state { struct drm_encoder *best_encoder; + /** + * @link_status: Connector link_status to keep track of whether link is + * GOOD or BAD to notify userspace if retraining is necessary. + */ + enum drm_link_status link_status; + struct drm_atomic_state *state; struct drm_tv_connector_state tv; @@ -837,6 +854,8 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector, int drm_mode_connector_set_tile_property(struct drm_connector *connector); int drm_mode_connector_update_edid_property(struct drm_connector *connector, const struct edid *edid); +void drm_mode_connector_set_link_status_property(struct drm_connector *connector, + uint64_t link_status); /** * struct drm_tile_group - Tile group metadata diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index f220ee909bdb..ea169a90b3c4 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -438,6 +438,11 @@ struct drm_mode_config { * multiple CRTCs. */ struct drm_property *tile_property; + /** + * @link_status_property: Default connector property for link status + * of a connector + */ + struct drm_property *link_status_property; /** * @plane_type_property: Default plane property to differentiate * CURSOR, PRIMARY and OVERLAY legacy uses of planes. diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index ce7efe2e8a5e..8c67fc03d53d 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -123,6 +123,10 @@ extern "C" { #define DRM_MODE_DIRTY_ON 1 #define DRM_MODE_DIRTY_ANNOTATE 2 +/* Link Status options */ +#define DRM_MODE_LINK_STATUS_GOOD 0 +#define DRM_MODE_LINK_STATUS_BAD 1 + struct drm_mode_modeinfo { __u32 clock; __u16 hdisplay; -- cgit v1.2.3 From 38b0b219fbe89d824213beabf03bfb00b5d2c8fa Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 24 Feb 2017 17:14:33 +0100 Subject: of: add devm_ functions for populate and depopulate Lots of calls to of_platform_populate() are not unbalanced by a call to of_platform_depopulate(). This create issues while drivers are bind/unbind. In way to solve those issues is to add devm_of_platform_populate() which will call of_platform_depopulate() when the device is unbound from the bus. Signed-off-by: Benjamin Gaignard Acked-by: Rob Herring Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1487952874-23635-2-git-send-email-benjamin.gaignard@linaro.org --- drivers/of/platform.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_platform.h | 11 +++++++ 2 files changed, 82 insertions(+) (limited to 'include') diff --git a/drivers/of/platform.c b/drivers/of/platform.c index b8064bc2b6eb..f5bbb500ab80 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -571,6 +571,77 @@ void of_platform_depopulate(struct device *parent) } EXPORT_SYMBOL_GPL(of_platform_depopulate); +static void devm_of_platform_populate_release(struct device *dev, void *res) +{ + of_platform_depopulate(*(struct device **)res); +} + +/** + * devm_of_platform_populate() - Populate platform_devices from device tree data + * @dev: device that requested to populate from device tree data + * + * Similar to of_platform_populate(), but will automatically call + * of_platform_depopulate() when the device is unbound from the bus. + * + * Returns 0 on success, < 0 on failure. + */ +int devm_of_platform_populate(struct device *dev) +{ + struct device **ptr; + int ret; + + if (!dev) + return -EINVAL; + + ptr = devres_alloc(devm_of_platform_populate_release, + sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) { + devres_free(ptr); + } else { + *ptr = dev; + devres_add(dev, ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_platform_populate); + +static int devm_of_platform_match(struct device *dev, void *res, void *data) +{ + struct device **ptr = res; + + if (!ptr) { + WARN_ON(!ptr); + return 0; + } + + return *ptr == data; +} + +/** + * devm_of_platform_depopulate() - Remove devices populated from device tree + * @dev: device that requested to depopulate from device tree data + * + * Complementary to devm_of_platform_populate(), this function removes children + * of the given device (and, recurrently, their children) that have been + * created from their respective device tree nodes (and only those, + * leaving others - eg. manually created - unharmed). + */ +void devm_of_platform_depopulate(struct device *dev) +{ + int ret; + + ret = devres_release(dev, devm_of_platform_populate_release, + devm_of_platform_match, dev); + + WARN_ON(ret); +} +EXPORT_SYMBOL_GPL(devm_of_platform_depopulate); + #ifdef CONFIG_OF_DYNAMIC static int of_platform_notify(struct notifier_block *nb, unsigned long action, void *arg) diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 956a1006aefc..dc8224ae28d5 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -76,6 +76,10 @@ extern int of_platform_default_populate(struct device_node *root, const struct of_dev_auxdata *lookup, struct device *parent); extern void of_platform_depopulate(struct device *parent); + +extern int devm_of_platform_populate(struct device *dev); + +extern void devm_of_platform_depopulate(struct device *dev); #else static inline int of_platform_populate(struct device_node *root, const struct of_device_id *matches, @@ -91,6 +95,13 @@ static inline int of_platform_default_populate(struct device_node *root, return -ENODEV; } static inline void of_platform_depopulate(struct device *parent) { } + +static inline int devm_of_platform_populate(struct device *dev) +{ + return -ENODEV; +} + +static inline void devm_of_platform_depopulate(struct device *dev) { } #endif #if defined(CONFIG_OF_DYNAMIC) && defined(CONFIG_OF_ADDRESS) -- cgit v1.2.3 From 020a218f95bd3ceff7dd1022ff7ebc0497bc7bf9 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:38 +0100 Subject: drm: Introduce drm_mode_object_{get,put}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with other reference counting APIs in the kernel, add drm_mode_object_get() and drm_mode_object_put() to reference count DRM mode objects. Compatibility aliases are added to keep existing code working. To help speed up the transition, all the instances of the old functions in the DRM core are already replaced in this commit. A semantic patch is provided that can be used to convert all drivers to the new helpers. Reviewed-by: Sean Paul Acked-by: Christian König Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-3-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 14 +++++------ drivers/gpu/drm/drm_mode_object.c | 26 ++++++++++---------- drivers/gpu/drm/drm_property.c | 6 ++--- include/drm/drm_mode_object.h | 36 ++++++++++++++++++++++----- scripts/coccinelle/api/drm-get-put.cocci | 42 ++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 scripts/coccinelle/api/drm-get-put.cocci (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 08d03d4594ee..39e470eb8aea 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -2238,13 +2238,13 @@ retry: } if (!obj->properties) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); ret = -ENOENT; goto out; } if (get_user(count_props, count_props_ptr + copied_objs)) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); ret = -EFAULT; goto out; } @@ -2257,14 +2257,14 @@ retry: struct drm_property *prop; if (get_user(prop_id, props_ptr + copied_props)) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); ret = -EFAULT; goto out; } prop = drm_mode_obj_find_prop_id(obj, prop_id); if (!prop) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); ret = -ENOENT; goto out; } @@ -2272,14 +2272,14 @@ retry: if (copy_from_user(&prop_value, prop_values_ptr + copied_props, sizeof(prop_value))) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); ret = -EFAULT; goto out; } ret = atomic_set_prop(state, obj, prop, prop_value); if (ret) { - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); goto out; } @@ -2292,7 +2292,7 @@ retry: plane_mask |= (1 << drm_plane_index(plane)); plane->old_fb = plane->fb; } - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); } ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state, diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 2ab8ccf2ca98..2eb0792dfaf3 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -133,7 +133,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, * * This function is used to look up a modeset object. It will acquire a * reference for reference counted objects. This reference must be dropped again - * by callind drm_mode_object_unreference(). + * by callind drm_mode_object_put(). */ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) @@ -146,38 +146,38 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, EXPORT_SYMBOL(drm_mode_object_find); /** - * drm_mode_object_unreference - decr the object refcnt - * @obj: mode_object + * drm_mode_object_put - release a mode object reference + * @obj: DRM mode object * * This function decrements the object's refcount if it is a refcounted modeset * object. It is a no-op on any other object. This is used to drop references - * acquired with drm_mode_object_reference(). + * acquired with drm_mode_object_get(). */ -void drm_mode_object_unreference(struct drm_mode_object *obj) +void drm_mode_object_put(struct drm_mode_object *obj) { if (obj->free_cb) { DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount)); kref_put(&obj->refcount, obj->free_cb); } } -EXPORT_SYMBOL(drm_mode_object_unreference); +EXPORT_SYMBOL(drm_mode_object_put); /** - * drm_mode_object_reference - incr the object refcnt - * @obj: mode_object + * drm_mode_object_get - acquire a mode object reference + * @obj: DRM mode object * * This function increments the object's refcount if it is a refcounted modeset * object. It is a no-op on any other object. References should be dropped again - * by calling drm_mode_object_unreference(). + * by calling drm_mode_object_put(). */ -void drm_mode_object_reference(struct drm_mode_object *obj) +void drm_mode_object_get(struct drm_mode_object *obj) { if (obj->free_cb) { DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount)); kref_get(&obj->refcount); } } -EXPORT_SYMBOL(drm_mode_object_reference); +EXPORT_SYMBOL(drm_mode_object_get); /** * drm_object_attach_property - attach a property to a modeset object @@ -363,7 +363,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, &arg->count_props); out_unref: - drm_mode_object_unreference(obj); + drm_mode_object_put(obj); out: drm_modeset_unlock_all(dev); return ret; @@ -428,7 +428,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, drm_property_change_valid_put(property, ref); out_unref: - drm_mode_object_unreference(arg_obj); + drm_mode_object_put(arg_obj); out: drm_modeset_unlock_all(dev); return ret; diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 411e470369c0..15af0d42e8be 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -597,7 +597,7 @@ void drm_property_unreference_blob(struct drm_property_blob *blob) if (!blob) return; - drm_mode_object_unreference(&blob->base); + drm_mode_object_put(&blob->base); } EXPORT_SYMBOL(drm_property_unreference_blob); @@ -625,7 +625,7 @@ void drm_property_destroy_user_blobs(struct drm_device *dev, */ struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob) { - drm_mode_object_reference(&blob->base); + drm_mode_object_get(&blob->base); return blob; } EXPORT_SYMBOL(drm_property_reference_blob); @@ -906,7 +906,7 @@ void drm_property_change_valid_put(struct drm_property *property, return; if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { - drm_mode_object_unreference(ref); + drm_mode_object_put(ref); } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) drm_property_unreference_blob(obj_to_blob(ref)); } diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h index 2c017adf6d74..a767b4a30a6d 100644 --- a/include/drm/drm_mode_object.h +++ b/include/drm/drm_mode_object.h @@ -45,10 +45,10 @@ struct drm_device; * drm_object_attach_property() before the object is visible to userspace. * * - For objects with dynamic lifetimes (as indicated by a non-NULL @free_cb) it - * provides reference counting through drm_mode_object_reference() and - * drm_mode_object_unreference(). This is used by &drm_framebuffer, - * &drm_connector and &drm_property_blob. These objects provide specialized - * reference counting wrappers. + * provides reference counting through drm_mode_object_get() and + * drm_mode_object_put(). This is used by &drm_framebuffer, &drm_connector + * and &drm_property_blob. These objects provide specialized reference + * counting wrappers. */ struct drm_mode_object { uint32_t id; @@ -114,8 +114,32 @@ struct drm_object_properties { struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type); -void drm_mode_object_reference(struct drm_mode_object *obj); -void drm_mode_object_unreference(struct drm_mode_object *obj); +void drm_mode_object_get(struct drm_mode_object *obj); +void drm_mode_object_put(struct drm_mode_object *obj); + +/** + * drm_mode_object_reference - acquire a mode object reference + * @obj: DRM mode object + * + * This is a compatibility alias for drm_mode_object_get() and should not be + * used by new code. + */ +static inline void drm_mode_object_reference(struct drm_mode_object *obj) +{ + drm_mode_object_get(obj); +} + +/** + * drm_mode_object_unreference - release a mode object reference + * @obj: DRM mode object + * + * This is a compatibility alias for drm_mode_object_put() and should not be + * used by new code. + */ +static inline void drm_mode_object_unreference(struct drm_mode_object *obj) +{ + drm_mode_object_put(obj); +} int drm_object_property_set_value(struct drm_mode_object *obj, struct drm_property *property, diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci new file mode 100644 index 000000000000..a3742447c981 --- /dev/null +++ b/scripts/coccinelle/api/drm-get-put.cocci @@ -0,0 +1,42 @@ +/// +/// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and +/// drm_*_unreference() helpers. +/// +// Confidence: High +// Copyright: (C) 2017 NVIDIA Corporation +// Options: --no-includes --include-headers +// + +virtual patch +virtual report + +@depends on patch@ +expression object; +@@ + +( +- drm_mode_object_reference(object) ++ drm_mode_object_get(object) +| +- drm_mode_object_unreference(object) ++ drm_mode_object_put(object) +) + +@r depends on report@ +expression object; +position p; +@@ + +( +drm_mode_object_unreference@p(object) +| +drm_mode_object_reference@p(object) +) + +@script:python depends on report@ +object << r.object; +p << r.p; +@@ + +msg="WARNING: use get/put helpers to reference and dereference %s" % (object) +coccilib.report.print_report(p[0], msg) -- cgit v1.2.3 From ad09360750afa18a0a0ce0253d6ea6033abc22e7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:39 +0100 Subject: drm: Introduce drm_connector_{get,put}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with other reference counting APIs in the kernel, add drm_connector_get() and drm_connector_put() functions to reference count connectors. Compatibility aliases are added to keep existing code working. To help speed up the transition, all the instances of the old functions in the DRM core are already replaced in this commit. The existing semantic patch for mode object reference count conversion is extended for these new helpers. Reviewed-by: Sean Paul Acked-by: Christian König Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-4-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 8 +++---- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- drivers/gpu/drm/drm_connector.c | 10 ++++---- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_crtc_helper.c | 6 ++--- drivers/gpu/drm/drm_fb_helper.c | 12 +++++----- drivers/gpu/drm/drm_mode_config.c | 2 +- include/drm/drm_connector.h | 41 +++++++++++++++++++++++++------- scripts/coccinelle/api/drm-get-put.cocci | 10 ++++++++ 9 files changed, 65 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 39e470eb8aea..c5cb56db99f6 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -150,7 +150,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) state->connectors[i].state); state->connectors[i].ptr = NULL; state->connectors[i].state = NULL; - drm_connector_unreference(connector); + drm_connector_put(connector); } for (i = 0; i < config->num_crtc; i++) { @@ -1030,7 +1030,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, if (!connector_state) return ERR_PTR(-ENOMEM); - drm_connector_reference(connector); + drm_connector_get(connector); state->connectors[index].state = connector_state; state->connectors[index].old_state = connector->state; state->connectors[index].new_state = connector_state; @@ -1380,7 +1380,7 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, crtc_state->connector_mask &= ~(1 << drm_connector_index(conn_state->connector)); - drm_connector_unreference(conn_state->connector); + drm_connector_put(conn_state->connector); conn_state->crtc = NULL; } @@ -1392,7 +1392,7 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, crtc_state->connector_mask |= 1 << drm_connector_index(conn_state->connector); - drm_connector_reference(conn_state->connector); + drm_connector_get(conn_state->connector); conn_state->crtc = crtc; DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n", diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bdfddfa87316..6e7d9dfce342 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3351,7 +3351,7 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, { memcpy(state, connector->state, sizeof(*state)); if (state->crtc) - drm_connector_reference(connector); + drm_connector_get(connector); } EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); @@ -3477,7 +3477,7 @@ void __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) { if (state->crtc) - drm_connector_unreference(state->connector); + drm_connector_put(state->connector); } EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index a48e9a65046d..5a4be752a85e 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -35,8 +35,8 @@ * als fixed panels or anything else that can display pixels in some form. As * opposed to all other KMS objects representing hardware (like CRTC, encoder or * plane abstractions) connectors can be hotplugged and unplugged at runtime. - * Hence they are reference-counted using drm_connector_reference() and - * drm_connector_unreference(). + * Hence they are reference-counted using drm_connector_get() and + * drm_connector_put(). * * KMS driver must create, initialize, register and attach at a &struct * drm_connector for each such sink. The instance is created as other KMS @@ -557,7 +557,7 @@ drm_connector_list_iter_next(struct drm_connector_list_iter *iter) spin_unlock_irqrestore(&config->connector_list_lock, flags); if (old_conn) - drm_connector_unreference(old_conn); + drm_connector_put(old_conn); return iter->conn; } @@ -576,7 +576,7 @@ void drm_connector_list_iter_put(struct drm_connector_list_iter *iter) { iter->dev = NULL; if (iter->conn) - drm_connector_unreference(iter->conn); + drm_connector_put(iter->conn); lock_release(&connector_list_iter_dep_map, 0, _RET_IP_); } EXPORT_SYMBOL(drm_connector_list_iter_put); @@ -1309,7 +1309,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out: mutex_unlock(&dev->mode_config.mutex); out_unref: - drm_connector_unreference(connector); + drm_connector_put(connector); return ret; } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e2284539f82c..9594c623799b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -685,7 +685,7 @@ out: if (connector_set) { for (i = 0; i < crtc_req->count_connectors; i++) { if (connector_set[i]) - drm_connector_unreference(connector_set[i]); + drm_connector_put(connector_set[i]); } } kfree(connector_set); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 44ba0e990d6c..536051c627d8 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -465,7 +465,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) connector->dpms = DRM_MODE_DPMS_OFF; /* we keep a reference while the encoder is bound */ - drm_connector_unreference(connector); + drm_connector_put(connector); } drm_connector_list_iter_put(&conn_iter); } @@ -623,7 +623,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro]->encoder) continue; - drm_connector_reference(set->connectors[ro]); + drm_connector_get(set->connectors[ro]); } /* a) traverse passed in connector list and get encoders for them */ @@ -772,7 +772,7 @@ fail: for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro]->encoder) continue; - drm_connector_unreference(set->connectors[ro]); + drm_connector_put(set->connectors[ro]); } /* Try to restore the config */ diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1b068e6264d5..b243fdbdbb08 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -148,7 +148,7 @@ fail: struct drm_fb_helper_connector *fb_helper_connector = fb_helper->connector_info[i]; - drm_connector_unreference(fb_helper_connector->connector); + drm_connector_put(fb_helper_connector->connector); kfree(fb_helper_connector); fb_helper->connector_info[i] = NULL; @@ -185,7 +185,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ if (!fb_helper_connector) return -ENOMEM; - drm_connector_reference(connector); + drm_connector_get(connector); fb_helper_connector->connector = connector; fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; return 0; @@ -211,7 +211,7 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, if (i == fb_helper->connector_count) return -EINVAL; fb_helper_connector = fb_helper->connector_info[i]; - drm_connector_unreference(fb_helper_connector->connector); + drm_connector_put(fb_helper_connector->connector); for (j = i + 1; j < fb_helper->connector_count; j++) { fb_helper->connector_info[j - 1] = fb_helper->connector_info[j]; @@ -633,7 +633,7 @@ static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper, int i; for (i = 0; i < modeset->num_connectors; i++) { - drm_connector_unreference(modeset->connectors[i]); + drm_connector_put(modeset->connectors[i]); modeset->connectors[i] = NULL; } modeset->num_connectors = 0; @@ -650,7 +650,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) int i; for (i = 0; i < helper->connector_count; i++) { - drm_connector_unreference(helper->connector_info[i]->connector); + drm_connector_put(helper->connector_info[i]->connector); kfree(helper->connector_info[i]); } kfree(helper->connector_info); @@ -2192,7 +2192,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, fb_crtc->y = offset->y; modeset->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); - drm_connector_reference(connector); + drm_connector_get(connector); modeset->connectors[modeset->num_connectors++] = connector; modeset->fb = fb_helper->fb; modeset->x = offset->x; diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 884cc4d26fb5..20aec165abd7 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -418,7 +418,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) * current connector itself, which means it is inherently safe * against unreferencing the current connector - but not against * deleting it right away. */ - drm_connector_unreference(connector); + drm_connector_put(connector); } drm_connector_list_iter_put(&conn_iter); if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) { diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index f08aa5dfc9d7..e0acdb674d85 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -812,25 +812,50 @@ static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev, } /** - * drm_connector_reference - incr the connector refcnt - * @connector: connector + * drm_connector_get - acquire a connector reference + * @connector: DRM connector * * This function increments the connector's refcount. */ +static inline void drm_connector_get(struct drm_connector *connector) +{ + drm_mode_object_get(&connector->base); +} + +/** + * drm_connector_put - release a connector reference + * @connector: DRM connector + * + * This function decrements the connector's reference count and frees the + * object if the reference count drops to zero. + */ +static inline void drm_connector_put(struct drm_connector *connector) +{ + drm_mode_object_put(&connector->base); +} + +/** + * drm_connector_reference - acquire a connector reference + * @connector: DRM connector + * + * This is a compatibility alias for drm_connector_get() and should not be + * used by new code. + */ static inline void drm_connector_reference(struct drm_connector *connector) { - drm_mode_object_reference(&connector->base); + drm_connector_get(connector); } /** - * drm_connector_unreference - unref a connector - * @connector: connector to unref + * drm_connector_unreference - release a connector reference + * @connector: DRM connector * - * This function decrements the connector's refcount and frees it if it drops to zero. + * This is a compatibility alias for drm_connector_put() and should not be + * used by new code. */ static inline void drm_connector_unreference(struct drm_connector *connector) { - drm_mode_object_unreference(&connector->base); + drm_connector_put(connector); } const char *drm_get_connector_status_name(enum drm_connector_status status); @@ -924,7 +949,7 @@ void drm_connector_list_iter_put(struct drm_connector_list_iter *iter); * * Note that @connector is only valid within the list body, if you want to use * @connector after calling drm_connector_list_iter_put() then you need to grab - * your own reference first using drm_connector_reference(). + * your own reference first using drm_connector_get(). */ #define drm_for_each_connector_iter(connector, iter) \ while ((connector = drm_connector_list_iter_next(iter))) diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci index a3742447c981..8a4c2cb7889e 100644 --- a/scripts/coccinelle/api/drm-get-put.cocci +++ b/scripts/coccinelle/api/drm-get-put.cocci @@ -20,6 +20,12 @@ expression object; | - drm_mode_object_unreference(object) + drm_mode_object_put(object) +| +- drm_connector_reference(object) ++ drm_connector_get(object) +| +- drm_connector_unreference(object) ++ drm_connector_put(object) ) @r depends on report@ @@ -31,6 +37,10 @@ position p; drm_mode_object_unreference@p(object) | drm_mode_object_reference@p(object) +| +drm_connector_unreference@p(object) +| +drm_connector_reference@p(object) ) @script:python depends on report@ -- cgit v1.2.3 From a4a69da06bc11a937a6e417938b1bb698ee1fa46 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:40 +0100 Subject: drm: Introduce drm_framebuffer_{get,put}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with other reference counting APIs in the kernel, add drm_framebuffer_get() and drm_framebuffer_put() to reference count DRM framebuffers. Compatibility aliases are added to keep existing code working. To help speed up the transition, all the instances of the old functions in the DRM core are already replaced in this commit. The existing semantic patch for the DRM subsystem-wide conversion is extended to account for these new helpers. Reviewed-by: Sean Paul Acked-by: Christian König Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-5-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 6 ++-- drivers/gpu/drm/drm_atomic_helper.c | 4 +-- drivers/gpu/drm/drm_crtc.c | 8 +++--- drivers/gpu/drm/drm_framebuffer.c | 34 +++++++++++----------- drivers/gpu/drm/drm_plane.c | 12 ++++---- include/drm/drm_framebuffer.h | 49 ++++++++++++++++++++++++-------- scripts/coccinelle/api/drm-get-put.cocci | 10 +++++++ 7 files changed, 79 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index c5cb56db99f6..38cf374e7552 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -737,7 +737,7 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val); drm_atomic_set_fb_for_plane(state, fb); if (fb) - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); } else if (property == config->prop_in_fence_fd) { if (state->fence) return -EINVAL; @@ -1865,12 +1865,12 @@ void drm_atomic_clean_old_fb(struct drm_device *dev, if (ret == 0) { struct drm_framebuffer *new_fb = plane->state->fb; if (new_fb) - drm_framebuffer_reference(new_fb); + drm_framebuffer_get(new_fb); plane->fb = new_fb; plane->crtc = plane->state->crtc; if (plane->old_fb) - drm_framebuffer_unreference(plane->old_fb); + drm_framebuffer_put(plane->old_fb); } plane->old_fb = NULL; } diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 6e7d9dfce342..01b2dddbd431 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3230,7 +3230,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, memcpy(state, plane->state, sizeof(*state)); if (state->fb) - drm_framebuffer_reference(state->fb); + drm_framebuffer_get(state->fb); state->fence = NULL; } @@ -3270,7 +3270,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state) { if (state->fb) - drm_framebuffer_unreference(state->fb); + drm_framebuffer_put(state->fb); if (state->fence) dma_fence_put(state->fence); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9594c623799b..e2974d3c92e7 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -471,9 +471,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) drm_for_each_crtc(tmp, crtc->dev) { if (tmp->primary->fb) - drm_framebuffer_reference(tmp->primary->fb); + drm_framebuffer_get(tmp->primary->fb); if (tmp->primary->old_fb) - drm_framebuffer_unreference(tmp->primary->old_fb); + drm_framebuffer_put(tmp->primary->old_fb); tmp->primary->old_fb = NULL; } @@ -567,7 +567,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } fb = crtc->primary->fb; /* Make refcounting symmetric with the lookup path. */ - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); } else { fb = drm_framebuffer_lookup(dev, crtc_req->fb_id); if (!fb) { @@ -680,7 +680,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, out: if (fb) - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); if (connector_set) { for (i = 0; i < crtc_req->count_connectors; i++) { diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index dfc433450b81..e4909aef75d7 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -52,13 +52,13 @@ * metadata fields. * * The lifetime of a drm framebuffer is controlled with a reference count, - * drivers can grab additional references with drm_framebuffer_reference() and - * drop them again with drm_framebuffer_unreference(). For driver-private - * framebuffers for which the last reference is never dropped (e.g. for the - * fbdev framebuffer when the struct &struct drm_framebuffer is embedded into - * the fbdev helper struct) drivers can manually clean up a framebuffer at - * module unload time with drm_framebuffer_unregister_private(). But doing this - * is not recommended, and it's better to have a normal free-standing &struct + * drivers can grab additional references with drm_framebuffer_get() and drop + * them again with drm_framebuffer_put(). For driver-private framebuffers for + * which the last reference is never dropped (e.g. for the fbdev framebuffer + * when the struct &struct drm_framebuffer is embedded into the fbdev helper + * struct) drivers can manually clean up a framebuffer at module unload time + * with drm_framebuffer_unregister_private(). But doing this is not + * recommended, and it's better to have a normal free-standing &struct * drm_framebuffer. */ @@ -374,7 +374,7 @@ int drm_mode_rmfb(struct drm_device *dev, mutex_unlock(&file_priv->fbs_lock); /* drop the reference we picked up in framebuffer lookup */ - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); /* * we now own the reference that was stored in the fbs list @@ -394,12 +394,12 @@ int drm_mode_rmfb(struct drm_device *dev, flush_work(&arg.work); destroy_work_on_stack(&arg.work); } else - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); return 0; fail_unref: - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); return -ENOENT; } @@ -453,7 +453,7 @@ int drm_mode_getfb(struct drm_device *dev, ret = -ENODEV; } - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); return ret; } @@ -540,7 +540,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, out_err2: kfree(clips); out_err1: - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); return ret; } @@ -580,7 +580,7 @@ void drm_fb_release(struct drm_file *priv) list_del_init(&fb->filp_head); /* This drops the fpriv->fbs reference. */ - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); } } @@ -661,7 +661,7 @@ EXPORT_SYMBOL(drm_framebuffer_init); * * If successful, this grabs an additional reference to the framebuffer - * callers need to make sure to eventually unreference the returned framebuffer - * again, using @drm_framebuffer_unreference. + * again, using drm_framebuffer_put(). */ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, uint32_t id) @@ -687,8 +687,8 @@ EXPORT_SYMBOL(drm_framebuffer_lookup); * * NOTE: This function is deprecated. For driver-private framebuffers it is not * recommended to embed a framebuffer struct info fbdev struct, instead, a - * framebuffer pointer is preferred and drm_framebuffer_unreference() should be - * called when the framebuffer is to be cleaned up. + * framebuffer pointer is preferred and drm_framebuffer_put() should be called + * when the framebuffer is to be cleaned up. */ void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) { @@ -797,7 +797,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) } out: - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); } EXPORT_SYMBOL(drm_framebuffer_remove); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index f42590049a3a..a22e76837065 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -293,7 +293,7 @@ void drm_plane_force_disable(struct drm_plane *plane) return; } /* disconnect the plane from the fb and crtc: */ - drm_framebuffer_unreference(plane->old_fb); + drm_framebuffer_put(plane->old_fb); plane->old_fb = NULL; plane->fb = NULL; plane->crtc = NULL; @@ -520,9 +520,9 @@ static int __setplane_internal(struct drm_plane *plane, out: if (fb) - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); if (plane->old_fb) - drm_framebuffer_unreference(plane->old_fb); + drm_framebuffer_put(plane->old_fb); plane->old_fb = NULL; return ret; @@ -638,7 +638,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, } else { fb = crtc->cursor->fb; if (fb) - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); } if (req->flags & DRM_MODE_CURSOR_MOVE) { @@ -902,9 +902,9 @@ out: if (ret && crtc->funcs->page_flip_target) drm_crtc_vblank_put(crtc); if (fb) - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); if (crtc->primary->old_fb) - drm_framebuffer_unreference(crtc->primary->old_fb); + drm_framebuffer_put(crtc->primary->old_fb); crtc->primary->old_fb = NULL; drm_modeset_unlock_crtc(crtc); diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 04c77eee9c20..45410ba0d4f7 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -101,8 +101,8 @@ struct drm_framebuffer_funcs { * cleanup (like releasing the reference(s) on the backing GEM bo(s)) * should be deferred. In cases like this, the driver would like to * hold a ref to the fb even though it has already been removed from - * userspace perspective. See drm_framebuffer_reference() and - * drm_framebuffer_unreference(). + * userspace perspective. See drm_framebuffer_get() and + * drm_framebuffer_put(). * * The refcount is stored inside the mode object @base. */ @@ -204,25 +204,50 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb); void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); /** - * drm_framebuffer_reference - incr the fb refcnt - * @fb: framebuffer + * drm_framebuffer_get - acquire a framebuffer reference + * @fb: DRM framebuffer + * + * This function increments the framebuffer's reference count. + */ +static inline void drm_framebuffer_get(struct drm_framebuffer *fb) +{ + drm_mode_object_get(&fb->base); +} + +/** + * drm_framebuffer_put - release a framebuffer reference + * @fb: DRM framebuffer + * + * This function decrements the framebuffer's reference count and frees the + * framebuffer if the reference count drops to zero. + */ +static inline void drm_framebuffer_put(struct drm_framebuffer *fb) +{ + drm_mode_object_put(&fb->base); +} + +/** + * drm_framebuffer_reference - acquire a framebuffer reference + * @fb: DRM framebuffer * - * This functions increments the fb's refcount. + * This is a compatibility alias for drm_framebuffer_get() and should not be + * used by new code. */ static inline void drm_framebuffer_reference(struct drm_framebuffer *fb) { - drm_mode_object_reference(&fb->base); + drm_framebuffer_get(fb); } /** - * drm_framebuffer_unreference - unref a framebuffer - * @fb: framebuffer to unref + * drm_framebuffer_unreference - release a framebuffer reference + * @fb: DRM framebuffer * - * This functions decrements the fb's refcount and frees it if it drops to zero. + * This is a compatibility alias for drm_framebuffer_put() and should not be + * used by new code. */ static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb) { - drm_mode_object_unreference(&fb->base); + drm_framebuffer_put(fb); } /** @@ -248,9 +273,9 @@ static inline void drm_framebuffer_assign(struct drm_framebuffer **p, struct drm_framebuffer *fb) { if (fb) - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); if (*p) - drm_framebuffer_unreference(*p); + drm_framebuffer_put(*p); *p = fb; } diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci index 8a4c2cb7889e..fd298c24a465 100644 --- a/scripts/coccinelle/api/drm-get-put.cocci +++ b/scripts/coccinelle/api/drm-get-put.cocci @@ -26,6 +26,12 @@ expression object; | - drm_connector_unreference(object) + drm_connector_put(object) +| +- drm_framebuffer_reference(object) ++ drm_framebuffer_get(object) +| +- drm_framebuffer_unreference(object) ++ drm_framebuffer_put(object) ) @r depends on report@ @@ -41,6 +47,10 @@ drm_mode_object_reference@p(object) drm_connector_unreference@p(object) | drm_connector_reference@p(object) +| +drm_framebuffer_unreference@p(object) +| +drm_framebuffer_reference@p(object) ) @script:python depends on report@ -- cgit v1.2.3 From e6b62714e87c8811d5564b6a0738dcde63a51774 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:41 +0100 Subject: drm: Introduce drm_gem_object_{get,put}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with other reference counting APIs in the kernel, add drm_gem_object_get() and drm_gem_object_put(), as well as an unlocked variant of the latter, to reference count GEM buffer objects. Compatibility aliases are added to keep existing code working. To help speed up the transition, all the instances of the old functions in the DRM core are already replaced in this commit. The existing semantic patch for the DRM subsystem-wide conversion is extended to account for these new helpers. Reviewed-by: Sean Paul Acked-by: Christian König Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-6-thierry.reding@gmail.com --- Documentation/gpu/drm-mm.rst | 14 +++--- drivers/gpu/drm/drm_fb_cma_helper.c | 16 +++---- drivers/gpu/drm/drm_gem.c | 44 +++++++++--------- drivers/gpu/drm/drm_gem_cma_helper.c | 10 ++-- drivers/gpu/drm/drm_prime.c | 10 ++-- include/drm/drm_gem.h | 80 +++++++++++++++++++++++++------- scripts/coccinelle/api/drm-get-put.cocci | 20 ++++++++ 7 files changed, 130 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index f5760b140f13..fd35998acefc 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -183,14 +183,12 @@ GEM Objects Lifetime -------------------- All GEM objects are reference-counted by the GEM core. References can be -acquired and release by :c:func:`calling -drm_gem_object_reference()` and -:c:func:`drm_gem_object_unreference()` respectively. The caller -must hold the :c:type:`struct drm_device ` -struct_mutex lock when calling -:c:func:`drm_gem_object_reference()`. As a convenience, GEM -provides :c:func:`drm_gem_object_unreference_unlocked()` -functions that can be called without holding the lock. +acquired and release by :c:func:`calling drm_gem_object_get()` and +:c:func:`drm_gem_object_put()` respectively. The caller must hold the +:c:type:`struct drm_device ` struct_mutex lock when calling +:c:func:`drm_gem_object_get()`. As a convenience, GEM provides +:c:func:`drm_gem_object_put_unlocked()` functions that can be called without +holding the lock. When the last reference to a GEM object is released the GEM core calls the :c:type:`struct drm_driver ` gem_free_object diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 920bb5764cd6..be6d90664e50 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -102,7 +102,7 @@ void drm_fb_cma_destroy(struct drm_framebuffer *fb) for (i = 0; i < 4; i++) { if (fb_cma->obj[i]) - drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base); + drm_gem_object_put_unlocked(&fb_cma->obj[i]->base); } drm_framebuffer_cleanup(fb); @@ -190,7 +190,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, if (!obj) { dev_err(dev->dev, "Failed to lookup GEM object\n"); ret = -ENXIO; - goto err_gem_object_unreference; + goto err_gem_object_put; } min_size = (height - 1) * mode_cmd->pitches[i] @@ -198,9 +198,9 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, + mode_cmd->offsets[i]; if (obj->size < min_size) { - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); ret = -EINVAL; - goto err_gem_object_unreference; + goto err_gem_object_put; } objs[i] = to_drm_gem_cma_obj(obj); } @@ -208,14 +208,14 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i, funcs); if (IS_ERR(fb_cma)) { ret = PTR_ERR(fb_cma); - goto err_gem_object_unreference; + goto err_gem_object_put; } return &fb_cma->fb; -err_gem_object_unreference: +err_gem_object_put: for (i--; i >= 0; i--) - drm_gem_object_unreference_unlocked(&objs[i]->base); + drm_gem_object_put_unlocked(&objs[i]->base); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs); @@ -477,7 +477,7 @@ err_cma_destroy: err_fb_info_destroy: drm_fb_helper_fini(helper); err_gem_free_object: - drm_gem_object_unreference_unlocked(&obj->base); + drm_gem_object_put_unlocked(&obj->base); return ret; } diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index bc93de308673..b1e28c944637 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -218,7 +218,7 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj) } static void -drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) +drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; bool final = false; @@ -241,7 +241,7 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) mutex_unlock(&dev->object_name_lock); if (final) - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); } /* @@ -262,7 +262,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); - drm_gem_object_handle_unreference_unlocked(obj); + drm_gem_object_handle_put_unlocked(obj); return 0; } @@ -352,7 +352,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv, WARN_ON(!mutex_is_locked(&dev->object_name_lock)); if (obj->handle_count++ == 0) - drm_gem_object_reference(obj); + drm_gem_object_get(obj); /* * Get the user-visible handle using idr. Preload and perform @@ -392,7 +392,7 @@ err_remove: idr_remove(&file_priv->object_idr, handle); spin_unlock(&file_priv->table_lock); err_unref: - drm_gem_object_handle_unreference_unlocked(obj); + drm_gem_object_handle_put_unlocked(obj); return ret; } @@ -606,7 +606,7 @@ drm_gem_object_lookup(struct drm_file *filp, u32 handle) /* Check if we currently have a reference on the object */ obj = idr_find(&filp->object_idr, handle); if (obj) - drm_gem_object_reference(obj); + drm_gem_object_get(obj); spin_unlock(&filp->table_lock); @@ -683,7 +683,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, err: mutex_unlock(&dev->object_name_lock); - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return ret; } @@ -713,7 +713,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->object_name_lock); obj = idr_find(&dev->object_name_idr, (int) args->name); if (obj) { - drm_gem_object_reference(obj); + drm_gem_object_get(obj); } else { mutex_unlock(&dev->object_name_lock); return -ENOENT; @@ -721,7 +721,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ ret = drm_gem_handle_create_tail(file_priv, obj, &handle); - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); if (ret) return ret; @@ -809,16 +809,16 @@ drm_gem_object_free(struct kref *kref) EXPORT_SYMBOL(drm_gem_object_free); /** - * drm_gem_object_unreference_unlocked - release a GEM BO reference + * drm_gem_object_put_unlocked - drop a GEM buffer object reference * @obj: GEM buffer object * * This releases a reference to @obj. Callers must not hold the * &drm_device.struct_mutex lock when calling this function. * - * See also __drm_gem_object_unreference(). + * See also __drm_gem_object_put(). */ void -drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) +drm_gem_object_put_unlocked(struct drm_gem_object *obj) { struct drm_device *dev; @@ -834,10 +834,10 @@ drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) &dev->struct_mutex)) mutex_unlock(&dev->struct_mutex); } -EXPORT_SYMBOL(drm_gem_object_unreference_unlocked); +EXPORT_SYMBOL(drm_gem_object_put_unlocked); /** - * drm_gem_object_unreference - release a GEM BO reference + * drm_gem_object_put - release a GEM buffer object reference * @obj: GEM buffer object * * This releases a reference to @obj. Callers must hold the @@ -845,10 +845,10 @@ EXPORT_SYMBOL(drm_gem_object_unreference_unlocked); * driver doesn't use &drm_device.struct_mutex for anything. * * For drivers not encumbered with legacy locking use - * drm_gem_object_unreference_unlocked() instead. + * drm_gem_object_put_unlocked() instead. */ void -drm_gem_object_unreference(struct drm_gem_object *obj) +drm_gem_object_put(struct drm_gem_object *obj) { if (obj) { WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); @@ -856,7 +856,7 @@ drm_gem_object_unreference(struct drm_gem_object *obj) kref_put(&obj->refcount, drm_gem_object_free); } } -EXPORT_SYMBOL(drm_gem_object_unreference); +EXPORT_SYMBOL(drm_gem_object_put); /** * drm_gem_vm_open - vma->ops->open implementation for GEM @@ -869,7 +869,7 @@ void drm_gem_vm_open(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - drm_gem_object_reference(obj); + drm_gem_object_get(obj); } EXPORT_SYMBOL(drm_gem_vm_open); @@ -884,7 +884,7 @@ void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); } EXPORT_SYMBOL(drm_gem_vm_close); @@ -935,7 +935,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, * (which should happen whether the vma was created by this call, or * by a vm_open due to mremap or partial unmap or whatever). */ - drm_gem_object_reference(obj); + drm_gem_object_get(obj); return 0; } @@ -992,14 +992,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) return -EINVAL; if (!drm_vma_node_is_allowed(node, priv)) { - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return -EACCES; } ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, vma); - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return ret; } diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index 5cf38a474845..906984d4bec2 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, return cma_obj; error: - drm_gem_object_unreference_unlocked(&cma_obj->base); + drm_gem_object_put_unlocked(&cma_obj->base); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(drm_gem_cma_create); @@ -163,7 +163,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, */ ret = drm_gem_handle_create(file_priv, gem_obj, handle); /* drop reference from allocate - handle holds it now. */ - drm_gem_object_unreference_unlocked(gem_obj); + drm_gem_object_put_unlocked(gem_obj); if (ret) return ERR_PTR(ret); @@ -293,7 +293,7 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv, *offset = drm_vma_node_offset_addr(&gem_obj->vma_node); - drm_gem_object_unreference_unlocked(gem_obj); + drm_gem_object_put_unlocked(gem_obj); return 0; } @@ -416,13 +416,13 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, return -EINVAL; if (!drm_vma_node_is_allowed(node, priv)) { - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return -EACCES; } cma_obj = to_drm_gem_cma_obj(obj); - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL; } diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 25aa4558f1b5..866b294e7c61 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -318,7 +318,7 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, return dma_buf; drm_dev_ref(dev); - drm_gem_object_reference(exp_info->priv); + drm_gem_object_get(exp_info->priv); return dma_buf; } @@ -339,7 +339,7 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf) struct drm_device *dev = obj->dev; /* drop the reference on the export fd holds */ - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); drm_dev_unref(dev); } @@ -585,7 +585,7 @@ out_have_handle: fail_put_dmabuf: dma_buf_put(dmabuf); out: - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); out_unlock: mutex_unlock(&file_priv->prime.lock); @@ -616,7 +616,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, * Importing dmabuf exported from out own gem increases * refcount on gem itself instead of f_count of dmabuf. */ - drm_gem_object_reference(obj); + drm_gem_object_get(obj); return obj; } } @@ -704,7 +704,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev, /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */ ret = drm_gem_handle_create_tail(file_priv, obj, handle); - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); if (ret) goto out_put; diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 449a41b56ffc..3b2a28f7f49f 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -48,9 +48,9 @@ struct drm_gem_object { * * Reference count of this object * - * Please use drm_gem_object_reference() to acquire and - * drm_gem_object_unreference() or drm_gem_object_unreference_unlocked() - * to release a reference to a GEM buffer object. + * Please use drm_gem_object_get() to acquire and drm_gem_object_put() + * or drm_gem_object_put_unlocked() to release a reference to a GEM + * buffer object. */ struct kref refcount; @@ -187,42 +187,90 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); /** - * drm_gem_object_reference - acquire a GEM BO reference + * drm_gem_object_get - acquire a GEM buffer object reference * @obj: GEM buffer object * - * This acquires additional reference to @obj. It is illegal to call this - * without already holding a reference. No locks required. + * This function acquires an additional reference to @obj. It is illegal to + * call this without already holding a reference. No locks required. */ -static inline void -drm_gem_object_reference(struct drm_gem_object *obj) +static inline void drm_gem_object_get(struct drm_gem_object *obj) { kref_get(&obj->refcount); } /** - * __drm_gem_object_unreference - raw function to release a GEM BO reference + * __drm_gem_object_put - raw function to release a GEM buffer object reference * @obj: GEM buffer object * * This function is meant to be used by drivers which are not encumbered with * &drm_device.struct_mutex legacy locking and which are using the * gem_free_object_unlocked callback. It avoids all the locking checks and - * locking overhead of drm_gem_object_unreference() and - * drm_gem_object_unreference_unlocked(). + * locking overhead of drm_gem_object_put() and drm_gem_object_put_unlocked(). * * Drivers should never call this directly in their code. Instead they should - * wrap it up into a ``driver_gem_object_unreference(struct driver_gem_object - * *obj)`` wrapper function, and use that. Shared code should never call this, to + * wrap it up into a ``driver_gem_object_put(struct driver_gem_object *obj)`` + * wrapper function, and use that. Shared code should never call this, to * avoid breaking drivers by accident which still depend upon * &drm_device.struct_mutex locking. */ static inline void -__drm_gem_object_unreference(struct drm_gem_object *obj) +__drm_gem_object_put(struct drm_gem_object *obj) { kref_put(&obj->refcount, drm_gem_object_free); } -void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj); -void drm_gem_object_unreference(struct drm_gem_object *obj); +void drm_gem_object_put_unlocked(struct drm_gem_object *obj); +void drm_gem_object_put(struct drm_gem_object *obj); + +/** + * drm_gem_object_reference - acquire a GEM buffer object reference + * @obj: GEM buffer object + * + * This is a compatibility alias for drm_gem_object_get() and should not be + * used by new code. + */ +static inline void drm_gem_object_reference(struct drm_gem_object *obj) +{ + drm_gem_object_get(obj); +} + +/** + * __drm_gem_object_unreference - raw function to release a GEM buffer object + * reference + * @obj: GEM buffer object + * + * This is a compatibility alias for __drm_gem_object_put() and should not be + * used by new code. + */ +static inline void __drm_gem_object_unreference(struct drm_gem_object *obj) +{ + __drm_gem_object_put(obj); +} + +/** + * drm_gem_object_unreference_unlocked - release a GEM buffer object reference + * @obj: GEM buffer object + * + * This is a compatibility alias for drm_gem_object_put_unlocked() and should + * not be used by new code. + */ +static inline void +drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) +{ + drm_gem_object_put_unlocked(obj); +} + +/** + * drm_gem_object_unreference - release a GEM buffer object reference + * @obj: GEM buffer object + * + * This is a compatibility alias for drm_gem_object_put() and should not be + * used by new code. + */ +static inline void drm_gem_object_unreference(struct drm_gem_object *obj) +{ + drm_gem_object_put(obj); +} int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci index fd298c24a465..24882547b4d1 100644 --- a/scripts/coccinelle/api/drm-get-put.cocci +++ b/scripts/coccinelle/api/drm-get-put.cocci @@ -32,6 +32,18 @@ expression object; | - drm_framebuffer_unreference(object) + drm_framebuffer_put(object) +| +- drm_gem_object_reference(object) ++ drm_gem_object_get(object) +| +- drm_gem_object_unreference(object) ++ drm_gem_object_put(object) +| +- __drm_gem_object_unreference(object) ++ __drm_gem_object_put(object) +| +- drm_gem_object_unreference_unlocked(object) ++ drm_gem_object_put_unlocked(object) ) @r depends on report@ @@ -51,6 +63,14 @@ drm_connector_reference@p(object) drm_framebuffer_unreference@p(object) | drm_framebuffer_reference@p(object) +| +drm_gem_object_unreference@p(object) +| +drm_gem_object_reference@p(object) +| +__drm_gem_object_unreference(object) +| +drm_gem_object_unreference_unlocked(object) ) @script:python depends on report@ -- cgit v1.2.3 From 6472e5090be7c78749a3c279b4faae87ab835c40 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:42 +0100 Subject: drm: Introduce drm_property_blob_{get,put}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency with other reference counting APIs in the kernel, add drm_property_blob_get() and drm_property_blob_put() to reference count DRM blob properties. Compatibility aliases are added to keep existing code working. To help speed up the transition, all the instances of the old functions in the DRM core are already replaced in this commit. A semantic patch is provided that can be used to convert all drivers to the new helpers. Reviewed-by: Sean Paul Acked-by: Christian König Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-7-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 16 ++++++------- drivers/gpu/drm/drm_atomic_helper.c | 18 +++++++------- drivers/gpu/drm/drm_mode_config.c | 2 +- drivers/gpu/drm/drm_property.c | 40 ++++++++++++++++---------------- include/drm/drm_property.h | 35 ++++++++++++++++++++++++---- scripts/coccinelle/api/drm-get-put.cocci | 10 ++++++++ 6 files changed, 78 insertions(+), 43 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 38cf374e7552..aea8bbad1674 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -324,7 +324,7 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0) return 0; - drm_property_unreference_blob(state->mode_blob); + drm_property_blob_put(state->mode_blob); state->mode_blob = NULL; if (mode) { @@ -370,7 +370,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, if (blob == state->mode_blob) return 0; - drm_property_unreference_blob(state->mode_blob); + drm_property_blob_put(state->mode_blob); state->mode_blob = NULL; memset(&state->mode, 0, sizeof(state->mode)); @@ -382,7 +382,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, blob->data)) return -EINVAL; - state->mode_blob = drm_property_reference_blob(blob); + state->mode_blob = drm_property_blob_get(blob); state->enable = true; DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", state->mode.name, state); @@ -415,9 +415,9 @@ drm_atomic_replace_property_blob(struct drm_property_blob **blob, if (old_blob == new_blob) return; - drm_property_unreference_blob(old_blob); + drm_property_blob_put(old_blob); if (new_blob) - drm_property_reference_blob(new_blob); + drm_property_blob_get(new_blob); *blob = new_blob; *replaced = true; @@ -439,13 +439,13 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, return -EINVAL; if (expected_size > 0 && expected_size != new_blob->length) { - drm_property_unreference_blob(new_blob); + drm_property_blob_put(new_blob); return -EINVAL; } } drm_atomic_replace_property_blob(blob, new_blob, replaced); - drm_property_unreference_blob(new_blob); + drm_property_blob_put(new_blob); return 0; } @@ -480,7 +480,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_property_blob *mode = drm_property_lookup_blob(dev, val); ret = drm_atomic_set_mode_prop_for_crtc(state, mode); - drm_property_unreference_blob(mode); + drm_property_blob_put(mode); return ret; } else if (property == config->degamma_lut_property) { ret = drm_atomic_replace_property_blob_from_id(crtc, diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 01b2dddbd431..ffcae3fa94f9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3120,13 +3120,13 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, memcpy(state, crtc->state, sizeof(*state)); if (state->mode_blob) - drm_property_reference_blob(state->mode_blob); + drm_property_blob_get(state->mode_blob); if (state->degamma_lut) - drm_property_reference_blob(state->degamma_lut); + drm_property_blob_get(state->degamma_lut); if (state->ctm) - drm_property_reference_blob(state->ctm); + drm_property_blob_get(state->ctm); if (state->gamma_lut) - drm_property_reference_blob(state->gamma_lut); + drm_property_blob_get(state->gamma_lut); state->mode_changed = false; state->active_changed = false; state->planes_changed = false; @@ -3171,10 +3171,10 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); */ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) { - drm_property_unreference_blob(state->mode_blob); - drm_property_unreference_blob(state->degamma_lut); - drm_property_unreference_blob(state->ctm); - drm_property_unreference_blob(state->gamma_lut); + drm_property_blob_put(state->mode_blob); + drm_property_blob_put(state->degamma_lut); + drm_property_blob_put(state->ctm); + drm_property_blob_put(state->gamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); @@ -3572,7 +3572,7 @@ fail: goto backoff; drm_atomic_state_put(state); - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); return ret; backoff: diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 20aec165abd7..37779b9f0c1e 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -444,7 +444,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, head_global) { - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); } /* diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 15af0d42e8be..b17959c3e099 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -587,19 +587,19 @@ drm_property_create_blob(struct drm_device *dev, size_t length, EXPORT_SYMBOL(drm_property_create_blob); /** - * drm_property_unreference_blob - Unreference a blob property - * @blob: Pointer to blob property + * drm_property_blob_put - release a blob property reference + * @blob: DRM blob property * - * Drop a reference on a blob property. May free the object. + * Releases a reference to a blob property. May free the object. */ -void drm_property_unreference_blob(struct drm_property_blob *blob) +void drm_property_blob_put(struct drm_property_blob *blob) { if (!blob) return; drm_mode_object_put(&blob->base); } -EXPORT_SYMBOL(drm_property_unreference_blob); +EXPORT_SYMBOL(drm_property_blob_put); void drm_property_destroy_user_blobs(struct drm_device *dev, struct drm_file *file_priv) @@ -612,23 +612,23 @@ void drm_property_destroy_user_blobs(struct drm_device *dev, */ list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) { list_del_init(&blob->head_file); - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); } } /** - * drm_property_reference_blob - Take a reference on an existing property - * @blob: Pointer to blob property + * drm_property_blob_get - acquire blob property reference + * @blob: DRM blob property * - * Take a new reference on an existing blob property. Returns @blob, which + * Acquires a reference to an existing blob property. Returns @blob, which * allows this to be used as a shorthand in assignments. */ -struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob) +struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob) { drm_mode_object_get(&blob->base); return blob; } -EXPORT_SYMBOL(drm_property_reference_blob); +EXPORT_SYMBOL(drm_property_blob_get); /** * drm_property_lookup_blob - look up a blob property and take a reference @@ -637,7 +637,7 @@ EXPORT_SYMBOL(drm_property_reference_blob); * * If successful, this takes an additional reference to the blob property. * callers need to make sure to eventually unreference the returned property - * again, using @drm_property_unreference_blob. + * again, using drm_property_blob_put(). * * Return: * NULL on failure, pointer to the blob on success. @@ -712,13 +712,13 @@ int drm_property_replace_global_blob(struct drm_device *dev, goto err_created; } - drm_property_unreference_blob(old_blob); + drm_property_blob_put(old_blob); *replace = new_blob; return 0; err_created: - drm_property_unreference_blob(new_blob); + drm_property_blob_put(new_blob); return ret; } EXPORT_SYMBOL(drm_property_replace_global_blob); @@ -747,7 +747,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, } out_resp->length = blob->length; unref: - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); return ret; } @@ -784,7 +784,7 @@ int drm_mode_createblob_ioctl(struct drm_device *dev, return 0; out_blob: - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); return ret; } @@ -823,14 +823,14 @@ int drm_mode_destroyblob_ioctl(struct drm_device *dev, mutex_unlock(&dev->mode_config.blob_lock); /* One reference from lookup, and one from the filp. */ - drm_property_unreference_blob(blob); - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); + drm_property_blob_put(blob); return 0; err: mutex_unlock(&dev->mode_config.blob_lock); - drm_property_unreference_blob(blob); + drm_property_blob_put(blob); return ret; } @@ -908,5 +908,5 @@ void drm_property_change_valid_put(struct drm_property *property, if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { drm_mode_object_put(ref); } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) - drm_property_unreference_blob(obj_to_blob(ref)); + drm_property_blob_put(obj_to_blob(ref)); } diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index f66fdb47551c..13e8c17d1c79 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h @@ -200,9 +200,8 @@ struct drm_property { * Blobs are used to store bigger values than what fits directly into the 64 * bits available for a &drm_property. * - * Blobs are reference counted using drm_property_reference_blob() and - * drm_property_unreference_blob(). They are created using - * drm_property_create_blob(). + * Blobs are reference counted using drm_property_blob_get() and + * drm_property_blob_put(). They are created using drm_property_create_blob(). */ struct drm_property_blob { struct drm_mode_object base; @@ -274,8 +273,34 @@ int drm_property_replace_global_blob(struct drm_device *dev, const void *data, struct drm_mode_object *obj_holds_id, struct drm_property *prop_holds_id); -struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob); -void drm_property_unreference_blob(struct drm_property_blob *blob); +struct drm_property_blob *drm_property_blob_get(struct drm_property_blob *blob); +void drm_property_blob_put(struct drm_property_blob *blob); + +/** + * drm_property_reference_blob - acquire a blob property reference + * @blob: DRM blob property + * + * This is a compatibility alias for drm_property_blob_get() and should not be + * used by new code. + */ +static inline struct drm_property_blob * +drm_property_reference_blob(struct drm_property_blob *blob) +{ + return drm_property_blob_get(blob); +} + +/** + * drm_property_unreference_blob - release a blob property reference + * @blob: DRM blob property + * + * This is a compatibility alias for drm_property_blob_put() and should not be + * used by new code. + */ +static inline void +drm_property_unreference_blob(struct drm_property_blob *blob) +{ + drm_property_blob_put(blob); +} /** * drm_connector_find - find property object diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci index 24882547b4d1..0c7a9265c07e 100644 --- a/scripts/coccinelle/api/drm-get-put.cocci +++ b/scripts/coccinelle/api/drm-get-put.cocci @@ -44,6 +44,12 @@ expression object; | - drm_gem_object_unreference_unlocked(object) + drm_gem_object_put_unlocked(object) +| +- drm_property_reference_blob(object) ++ drm_property_blob_get(object) +| +- drm_property_unreference_blob(object) ++ drm_property_blob_put(object) ) @r depends on report@ @@ -71,6 +77,10 @@ drm_gem_object_reference@p(object) __drm_gem_object_unreference(object) | drm_gem_object_unreference_unlocked(object) +| +drm_property_unreference_blob@p(object) +| +drm_property_reference_blob@p(object) ) @script:python depends on report@ -- cgit v1.2.3 From b982dab1e66d2b998e80a97acb6eaf56518988d3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 28 Feb 2017 15:46:43 +0100 Subject: drm: Rename connector list iterator API Currently the functions that initialize and tear down a connector iterator use the _get() and _put() suffixes. However, these suffixes are typically used by reference counting functions. Make these function names a little more consistent by changing the suffixes to _begin() and _end(), which is a fairly common pattern in the rest of the Linux kernel. Suggested-by: Jani Nikula Signed-off-by: Thierry Reding Link: http://patchwork.freedesktop.org/patch/msgid/20170228144643.5668-8-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 10 +++++----- drivers/gpu/drm/drm_atomic_helper.c | 14 +++++++------- drivers/gpu/drm/drm_connector.c | 24 ++++++++++++------------ drivers/gpu/drm/drm_crtc_helper.c | 36 ++++++++++++++++++------------------ drivers/gpu/drm/drm_encoder.c | 6 +++--- drivers/gpu/drm/drm_fb_helper.c | 4 ++-- drivers/gpu/drm/drm_mode_config.c | 18 +++++++++--------- drivers/gpu/drm/drm_plane_helper.c | 4 ++-- drivers/gpu/drm/drm_probe_helper.c | 12 ++++++------ include/drm/drm_connector.h | 12 ++++++------ 10 files changed, 70 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index aea8bbad1674..236d947011f9 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1449,18 +1449,18 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state, * Changed connectors are already in @state, so only need to look * at the connector_mask in crtc_state. */ - drm_connector_list_iter_get(state->dev, &conn_iter); + drm_connector_list_iter_begin(state->dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (!(crtc_state->connector_mask & (1 << drm_connector_index(connector)))) continue; conn_state = drm_atomic_get_connector_state(state, connector); if (IS_ERR(conn_state)) { - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return PTR_ERR(conn_state); } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return 0; } @@ -1722,10 +1722,10 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p) list_for_each_entry(crtc, &config->crtc_list, head) drm_atomic_crtc_print_state(p, crtc->state); - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) drm_atomic_connector_print_state(p, connector->state); - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); } EXPORT_SYMBOL(drm_state_dump); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ffcae3fa94f9..6b12396f718b 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -145,7 +145,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, * and the crtc is disabled if no encoder is left. This preserves * compatibility with the legacy set_config behavior. */ - drm_connector_list_iter_get(state->dev, &conn_iter); + drm_connector_list_iter_begin(state->dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { struct drm_crtc_state *crtc_state; @@ -193,7 +193,7 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, } } out: - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return ret; } @@ -3018,7 +3018,7 @@ retry: WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - drm_connector_list_iter_get(connector->dev, &conn_iter); + drm_connector_list_iter_begin(connector->dev, &conn_iter); drm_for_each_connector_iter(tmp_connector, &conn_iter) { if (tmp_connector->state->crtc != crtc) continue; @@ -3028,7 +3028,7 @@ retry: break; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); crtc_state->active = active; ret = drm_atomic_commit(state); @@ -3439,18 +3439,18 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, } } - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(conn, &conn_iter) { struct drm_connector_state *conn_state; conn_state = drm_atomic_get_connector_state(state, conn); if (IS_ERR(conn_state)) { err = PTR_ERR(conn_state); - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); goto free; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); /* clear the acquire context so that it isn't accidentally reused */ state->acquire_ctx = NULL; diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 5a4be752a85e..9f847615ac74 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -435,10 +435,10 @@ void drm_connector_unregister_all(struct drm_device *dev) struct drm_connector *connector; struct drm_connector_list_iter conn_iter; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) drm_connector_unregister(connector); - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); } int drm_connector_register_all(struct drm_device *dev) @@ -447,13 +447,13 @@ int drm_connector_register_all(struct drm_device *dev) struct drm_connector_list_iter conn_iter; int ret = 0; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { ret = drm_connector_register(connector); if (ret) break; } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); if (ret) drm_connector_unregister_all(dev); @@ -507,23 +507,23 @@ static struct lockdep_map connector_list_iter_dep_map = { #endif /** - * drm_connector_list_iter_get - initialize a connector_list iterator + * drm_connector_list_iter_begin - initialize a connector_list iterator * @dev: DRM device * @iter: connector_list iterator * * Sets @iter up to walk the &drm_mode_config.connector_list of @dev. @iter - * must always be cleaned up again by calling drm_connector_list_iter_put(). + * must always be cleaned up again by calling drm_connector_list_iter_end(). * Iteration itself happens using drm_connector_list_iter_next() or * drm_for_each_connector_iter(). */ -void drm_connector_list_iter_get(struct drm_device *dev, - struct drm_connector_list_iter *iter) +void drm_connector_list_iter_begin(struct drm_device *dev, + struct drm_connector_list_iter *iter) { iter->dev = dev; iter->conn = NULL; lock_acquire_shared_recursive(&connector_list_iter_dep_map, 0, 1, NULL, _RET_IP_); } -EXPORT_SYMBOL(drm_connector_list_iter_get); +EXPORT_SYMBOL(drm_connector_list_iter_begin); /** * drm_connector_list_iter_next - return next connector @@ -564,7 +564,7 @@ drm_connector_list_iter_next(struct drm_connector_list_iter *iter) EXPORT_SYMBOL(drm_connector_list_iter_next); /** - * drm_connector_list_iter_put - tear down a connector_list iterator + * drm_connector_list_iter_end - tear down a connector_list iterator * @iter: connector_list iterator * * Tears down @iter and releases any resources (like &drm_connector references) @@ -572,14 +572,14 @@ EXPORT_SYMBOL(drm_connector_list_iter_next); * iteration completes fully or when it was aborted without walking the entire * list. */ -void drm_connector_list_iter_put(struct drm_connector_list_iter *iter) +void drm_connector_list_iter_end(struct drm_connector_list_iter *iter) { iter->dev = NULL; if (iter->conn) drm_connector_put(iter->conn); lock_release(&connector_list_iter_dep_map, 0, _RET_IP_); } -EXPORT_SYMBOL(drm_connector_list_iter_put); +EXPORT_SYMBOL(drm_connector_list_iter_end); static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { { SubPixelUnknown, "Unknown" }, diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 536051c627d8..8aa8c1084121 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -102,14 +102,14 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder) } - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder == encoder) { - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return true; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return false; } EXPORT_SYMBOL(drm_helper_encoder_in_use); @@ -449,7 +449,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) if (encoder->crtc != crtc) continue; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder != encoder) continue; @@ -467,7 +467,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) /* we keep a reference while the encoder is bound */ drm_connector_put(connector); } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); } __drm_helper_disable_unused_functions(dev); @@ -583,10 +583,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } count = 0; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) save_connector_encoders[count++] = connector->encoder; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); save_set.crtc = set->crtc; save_set.mode = &set->crtc->mode; @@ -628,7 +628,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) /* a) traverse passed in connector list and get encoders for them */ count = 0; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; @@ -662,7 +662,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) connector->encoder = new_encoder; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); if (fail) { ret = -EINVAL; @@ -670,7 +670,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } count = 0; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (!connector->encoder) continue; @@ -689,7 +689,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (new_crtc && !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { ret = -EINVAL; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); goto fail; } if (new_crtc != connector->encoder->crtc) { @@ -706,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) connector->base.id, connector->name); } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); /* mode_set_base is not a required function */ if (fb_changed && !crtc_funcs->mode_set_base) @@ -761,10 +761,10 @@ fail: } count = 0; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) connector->encoder = save_connector_encoders[count++]; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); /* after fail drop reference on all unbound connectors in set, let * bound connectors keep their reference @@ -794,12 +794,12 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) struct drm_connector_list_iter conn_iter; struct drm_device *dev = encoder->dev; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) if (connector->encoder == encoder) if (connector->dpms < dpms) dpms = connector->dpms; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return dpms; } @@ -835,12 +835,12 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) struct drm_connector_list_iter conn_iter; struct drm_device *dev = crtc->dev; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) if (connector->encoder && connector->encoder->crtc == crtc) if (connector->dpms < dpms) dpms = connector->dpms; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return dpms; } diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c index 634ae0244ea9..0708779840d2 100644 --- a/drivers/gpu/drm/drm_encoder.c +++ b/drivers/gpu/drm/drm_encoder.c @@ -188,7 +188,7 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) /* For atomic drivers only state objects are synchronously updated and * protected by modeset locks, so check those first. */ - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (!connector->state) continue; @@ -198,10 +198,10 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) if (connector->state->best_encoder != encoder) continue; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return connector->state->crtc; } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); /* Don't return stale data (e.g. pending async disable). */ if (uses_atomic) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index b243fdbdbb08..2c92ccf5266a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -134,7 +134,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&dev->mode_config.mutex); - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { ret = drm_fb_helper_add_one_connector(fb_helper, connector); @@ -155,7 +155,7 @@ fail: } fb_helper->connector_count = 0; out: - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev->mode_config.mutex); return ret; diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 37779b9f0c1e..d9862259a2a7 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -139,19 +139,19 @@ int drm_mode_getresources(struct drm_device *dev, void *data, } card_res->count_encoders = count; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); count = 0; connector_id = u64_to_user_ptr(card_res->connector_id_ptr); drm_for_each_connector_iter(connector, &conn_iter) { if (count < card_res->count_connectors && put_user(connector->base.id, connector_id + count)) { - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return -EFAULT; } count++; } card_res->count_connectors = count; - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return ret; } @@ -184,11 +184,11 @@ void drm_mode_config_reset(struct drm_device *dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder); - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) if (connector->funcs->reset) connector->funcs->reset(connector); - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); } EXPORT_SYMBOL(drm_mode_config_reset); @@ -412,7 +412,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) encoder->funcs->destroy(encoder); } - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { /* drm_connector_list_iter holds an full reference to the * current connector itself, which means it is inherently safe @@ -420,12 +420,12 @@ void drm_mode_config_cleanup(struct drm_device *dev) * deleting it right away. */ drm_connector_put(connector); } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) { - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) DRM_ERROR("connector %s leaked!\n", connector->name); - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); } list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index d8639e46bd2b..244cf2619294 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -85,7 +85,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, */ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder && connector->encoder->crtc == crtc) { if (connector_list != NULL && count < num_connectors) @@ -94,7 +94,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, count++; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); return count; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 358957118ca9..03d376f91c23 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -140,13 +140,13 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) return; - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) poll = true; } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); if (dev->mode_config.delayed_event) { /* @@ -420,7 +420,7 @@ static void output_poll_execute(struct work_struct *work) goto out; } - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { /* Ignore forced connectors. */ if (connector->force) @@ -474,7 +474,7 @@ static void output_poll_execute(struct work_struct *work) changed = true; } } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev->mode_config.mutex); @@ -580,7 +580,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) return false; mutex_lock(&dev->mode_config.mutex); - drm_connector_list_iter_get(dev, &conn_iter); + drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { /* Only handle HPD capable connectors. */ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) @@ -597,7 +597,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) if (old_status != connector->status) changed = true; } - drm_connector_list_iter_put(&conn_iter); + drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev->mode_config.mutex); if (changed) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index e0acdb674d85..ccc0770b2de0 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -926,7 +926,7 @@ void drm_mode_put_tile_group(struct drm_device *dev, * * This iterator tracks state needed to be able to walk the connector_list * within struct drm_mode_config. Only use together with - * drm_connector_list_iter_get(), drm_connector_list_iter_put() and + * drm_connector_list_iter_begin(), drm_connector_list_iter_end() and * drm_connector_list_iter_next() respectively the convenience macro * drm_for_each_connector_iter(). */ @@ -936,11 +936,11 @@ struct drm_connector_list_iter { struct drm_connector *conn; }; -void drm_connector_list_iter_get(struct drm_device *dev, - struct drm_connector_list_iter *iter); +void drm_connector_list_iter_begin(struct drm_device *dev, + struct drm_connector_list_iter *iter); struct drm_connector * drm_connector_list_iter_next(struct drm_connector_list_iter *iter); -void drm_connector_list_iter_put(struct drm_connector_list_iter *iter); +void drm_connector_list_iter_end(struct drm_connector_list_iter *iter); /** * drm_for_each_connector_iter - connector_list iterator macro @@ -948,8 +948,8 @@ void drm_connector_list_iter_put(struct drm_connector_list_iter *iter); * @iter: &struct drm_connector_list_iter * * Note that @connector is only valid within the list body, if you want to use - * @connector after calling drm_connector_list_iter_put() then you need to grab - * your own reference first using drm_connector_get(). + * @connector after calling drm_connector_list_iter_end() then you need to grab + * your own reference first using drm_connector_begin(). */ #define drm_for_each_connector_iter(connector, iter) \ while ((connector = drm_connector_list_iter_next(iter))) -- cgit v1.2.3 From 41232c1b7405666e74cfab74168864bb86ef21ae Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Wed, 1 Mar 2017 06:45:10 -0800 Subject: drm: Fix the kernel doc warning for drm_link_status This fixes the kernel doc warning that was introduced in the 'commit 40ee6fbef75fe6 ("drm: Add a new connector atomic property for link status")'. Description has been added for the enum values. Signed-off-by: Manasi Navare Cc: Jani Nikula Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1488379510-15059-1-git-send-email-manasi.d.navare@intel.com --- include/drm/drm_connector.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ccc0770b2de0..fabb35aba5f6 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -94,6 +94,11 @@ enum subpixel_order { * * This enum is used as the connector's link status property value. * It is set to the values defined in uapi. + * + * @DRM_LINK_STATUS_GOOD: DP Link is Good as a result of successful + * link training + * @DRM_LINK_STATUS_BAD: DP Link is BAD as a result of link training + * failure */ enum drm_link_status { DRM_LINK_STATUS_GOOD = DRM_MODE_LINK_STATUS_GOOD, -- cgit v1.2.3 From 0f3bbe074dd179dfbdaabcc601086bc4f6ab885b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 28 Feb 2017 16:36:51 +0100 Subject: drm/fb-helper: implement ioctl FBIO_WAITFORVSYNC Implement legacy framebuffer ioctl FBIO_WAITFORVSYNC in the generic framebuffer emulation driver. Legacy framebuffer users like non kms/drm based OpenGL(ES)/EGL implementations may require the ioctl to synchronize drawing or buffer flip for double buffering. It is tested on the i.MX6. Signed-off-by: Maxime Ripard Tested-by: Neil Armstrong Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 68 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 12 +++++++- 2 files changed, 79 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 2c92ccf5266a..45fde2ffef2a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1244,6 +1244,74 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_setcmap); +/** + * drm_fb_helper_ioctl - legacy ioctl implementation + * @info: fbdev registered by the helper + * @cmd: ioctl command + * @arg: ioctl argument + * + * A helper to implement the standard fbdev ioctl. Only + * FBIO_WAITFORVSYNC is implemented for now. + */ +int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct drm_fb_helper *fb_helper = info->par; + struct drm_device *dev = fb_helper->dev; + struct drm_mode_set *mode_set; + struct drm_crtc *crtc; + int ret = 0; + + mutex_lock(&dev->mode_config.mutex); + if (!drm_fb_helper_is_bound(fb_helper)) { + ret = -EBUSY; + goto unlock; + } + + switch (cmd) { + case FBIO_WAITFORVSYNC: + /* + * Only consider the first CRTC. + * + * This ioctl is supposed to take the CRTC number as + * an argument, but in fbdev times, what that number + * was supposed to be was quite unclear, different + * drivers were passing that argument differently + * (some by reference, some by value), and most of the + * userspace applications were just hardcoding 0 as an + * argument. + * + * The first CRTC should be the integrated panel on + * most drivers, so this is the best choice we can + * make. If we're not smart enough here, one should + * just consider switch the userspace to KMS. + */ + mode_set = &fb_helper->crtc_info[0].mode_set; + crtc = mode_set->crtc; + + /* + * Only wait for a vblank event if the CRTC is + * enabled, otherwise just don't do anythintg, + * not even report an error. + */ + ret = drm_crtc_vblank_get(crtc); + if (!ret) { + drm_crtc_wait_one_vblank(crtc); + drm_crtc_vblank_put(crtc); + } + + ret = 0; + goto unlock; + default: + ret = -ENOTTY; + } + +unlock: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} +EXPORT_SYMBOL(drm_fb_helper_ioctl); + /** * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var * @var: screeninfo to check diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 339226d074f5..119e5e4609c7 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -230,7 +230,8 @@ struct drm_fb_helper { .fb_blank = drm_fb_helper_blank, \ .fb_pan_display = drm_fb_helper_pan_display, \ .fb_debug_enter = drm_fb_helper_debug_enter, \ - .fb_debug_leave = drm_fb_helper_debug_leave + .fb_debug_leave = drm_fb_helper_debug_leave, \ + .fb_ioctl = drm_fb_helper_ioctl #ifdef CONFIG_DRM_FBDEV_EMULATION void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, @@ -284,6 +285,9 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); +int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); + int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); @@ -371,6 +375,12 @@ static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap, return 0; } +static inline int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + return 0; +} + static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) { } -- cgit v1.2.3