Re: [PATCH] drm/amdgpu/dc: Stop dma_resv_lock inversion in commit_tail
Am 27.07.20 um 23:30 schrieb Daniel Vetter: Trying to grab dma_resv_lock while in commit_tail before we've done all the code that leads to the eventual signalling of the vblank event (which can be a dma_fence) is deadlock-y. Don't do that. Here the solution is easy because just grabbing locks to read something races anyway. We don't need to bother, READ_ONCE is equivalent. And avoids the locking issue. v2: Also take into account tmz_surface boolean, plus just delete the old code. Cc: linux-me...@vger.kernel.org Cc: linaro-mm-...@lists.linaro.org Cc: linux-r...@vger.kernel.org Cc: amd-...@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: Chris Wilson Cc: Maarten Lankhorst Cc: Christian König Signed-off-by: Daniel Vetter --- DC-folks, I think this split out patch from my series here https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fdri-devel%2F20200707201229.472834-1-daniel.vetter%40ffwll.ch%2F&data=02%7C01%7Cchristian.koenig%40amd.com%7C8a4f5736682a4b5c943e08d832747ab1%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637314823145521840&sdata=qd7Nrox62Lr%2FXWbJJFVskg9RYL4%2FoRVCFjR6rUDMA5E%3D&reserved=0 should be ready for review/merging. I fixed it up a bit so that it's not just a gross hack :-) Cheers, Daniel --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 21ec64fe5527..a20b62b1f2ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6959,20 +6959,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("Waiting for fences timed out!"); /* -* TODO This might fail and hence better not used, wait -* explicitly on fences instead -* and in general should be called for -* blocking commit to as per framework helpers +* We cannot reserve buffers here, which means the normal flag +* access functions don't work. Paper over this with READ_ONCE, +* but maybe the flags are invariant enough that not even that +* would be needed. */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) - DRM_ERROR("failed to reserve buffer before flip\n"); - - amdgpu_bo_get_tiling_flags(abo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(abo); - - amdgpu_bo_unreserve(abo); + tiling_flags = READ_ONCE(abo->tiling_flags); + tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; Yeah, the abo->flags are mostly fixed after creation, especially the encrypted flag can't change or we corrupt page table tables. So that should work fine. Anybody who picks this up feel free to add an Reviewed-by: Christian König . Regards, Christian. fill_dc_plane_info_and_addr( dm->adev, new_plane_state, tiling_flags, ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm/nouveau: consolidate slowpath reserve
From: Dave Airlie The WARN_ON in the non-underscore path is off questionable value (can we drop it from the non-slowpath?). At least for nouveau where it's just looked up the gem object we know the ttm object has a reference always so we can skip the check. It's probably nouveau could use execbut utils here at some point but for now align the code between them to always call the __ versions, and remove the non underscored version. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_gem.c | 6 ++--- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 10 + include/drm/ttm/ttm_bo_driver.h| 31 +++--- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 81f111ad3f4f..d2d535d2ece1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -422,15 +422,15 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, break; } - ret = ttm_bo_reserve(&nvbo->bo, true, false, &op->ticket); + ret = __ttm_bo_reserve(&nvbo->bo, true, false, &op->ticket); if (ret) { list_splice_tail_init(&vram_list, &op->list); list_splice_tail_init(&gart_list, &op->list); list_splice_tail_init(&both_list, &op->list); validate_fini_no_ticket(op, chan, NULL, NULL); if (unlikely(ret == -EDEADLK)) { - ret = ttm_bo_reserve_slowpath(&nvbo->bo, true, - &op->ticket); + ret = __ttm_bo_reserve_slowpath(&nvbo->bo, true, + &op->ticket); if (!ret) res_bo = nvbo; } diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index 1797f04c0534..a24f13bc90fb 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -119,13 +119,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, ttm_eu_backoff_reservation_reverse(list, entry); if (ret == -EDEADLK) { - if (intr) { - ret = dma_resv_lock_slow_interruptible(bo->base.resv, - ticket); - } else { - dma_resv_lock_slow(bo->base.resv, ticket); - ret = 0; - } + ret = __ttm_bo_reserve_slowpath(bo, intr, ticket); } if (!ret && entry->num_shared) @@ -133,8 +127,6 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, entry->num_shared); if (unlikely(ret != 0)) { - if (ret == -EINTR) - ret = -ERESTARTSYS; if (ticket) { ww_acquire_done(ticket); ww_acquire_fini(ticket); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 5a37f1cc057e..563b970949a1 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -695,7 +695,7 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, } /** - * ttm_bo_reserve_slowpath: + * __ttm_bo_reserve_slowpath: * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @sequence: Set (@bo)->sequence to this value after lock @@ -704,24 +704,19 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, * from all our other reservations. Because there are no other reservations * held by us, this function cannot deadlock any more. */ -static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, - bool interruptible, - struct ww_acquire_ctx *ticket) +static inline int __ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, + bool interruptible, + struct ww_acquire_ctx *ticket) { - int ret = 0; - - WARN_ON(!kref_read(&bo->kref)); - - if (interruptible) - ret = dma_resv_lock_slow_interruptible(bo->base.resv, -ticket); - else - dma_resv_lock_slow(bo->base.resv, ticket); - - if (ret == -EINTR) - ret = -ERESTARTSYS; - - return ret; + if (interruptible) {
[PATCH] drm/ttm: drop unusued function declaration
From: Dave Airlie This was removed in f5a9a9383f279de9da63296cb623a6418a66196b drm/ttm: remove TTM_MEMTYPE_FLAG_CMA but the the declaration was left dangling. Signed-off-by: Dave Airlie --- include/drm/ttm/ttm_bo_driver.h | 11 --- 1 file changed, 11 deletions(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 71b195e78c7c..5a37f1cc057e 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -525,17 +525,6 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) * ttm_bo.c */ -/** - * ttm_mem_reg_is_pci - * - * @bdev: Pointer to a struct ttm_bo_device. - * @mem: A valid struct ttm_mem_reg. - * - * Returns true if the memory described by @mem is PCI memory, - * false otherwise. - */ -bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); - /** * ttm_bo_mem_space * -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm/nouveau: don't call tt destroy callback on alloc failure.
From: Dave Airlie This is confusing, and from my reading of all the drivers only nouveau got this right. Just make the API act under driver control of it's own allocation failing, and don't call destroy, if the page table fails to create there is nothing to cleanup here. (I'm willing to believe I've missed something here, so please review deeply). Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 9 +++-- drivers/gpu/drm/ttm/ttm_tt.c| 3 --- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 20b6d0b3de5c..c3ccf661b7a6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -95,12 +95,9 @@ nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags) else nvbe->ttm.ttm.func = &nv50_sgdma_backend; - if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) - /* -* A failing ttm_dma_tt_init() will call ttm_tt_destroy() -* and thus our nouveau_sgdma_destroy() hook, so we don't need -* to free nvbe here. -*/ + if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) { + kfree(nvbe); return NULL; + } return &nvbe->ttm.ttm; } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index bab67873cfd4..9d1c7177384c 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -244,7 +244,6 @@ int ttm_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo, ttm_tt_init_fields(ttm, bo, page_flags); if (ttm_tt_alloc_page_directory(ttm)) { - ttm_tt_destroy(ttm); pr_err("Failed allocating page table\n"); return -ENOMEM; } @@ -268,7 +267,6 @@ int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, INIT_LIST_HEAD(&ttm_dma->pages_list); if (ttm_dma_tt_alloc_page_directory(ttm_dma)) { - ttm_tt_destroy(ttm); pr_err("Failed allocating page table\n"); return -ENOMEM; } @@ -290,7 +288,6 @@ int ttm_sg_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, else ret = ttm_dma_tt_alloc_page_directory(ttm_dma); if (ret) { - ttm_tt_destroy(ttm); pr_err("Failed allocating page table\n"); return -ENOMEM; } -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/ttm: make ttm_tt unbind function return void.
From: Dave Airlie The return value just led to BUG_ON, I think if a driver wants to BUG_ON here it can do it itself. (don't BUG_ON). Signed-off-by: Dave Airlie --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c| 5 ++--- drivers/gpu/drm/nouveau/nouveau_sgdma.c| 3 +-- drivers/gpu/drm/qxl/qxl_ttm.c | 3 +-- drivers/gpu/drm/radeon/radeon_ttm.c| 4 +--- drivers/gpu/drm/ttm/ttm_agp_backend.c | 9 + drivers/gpu/drm/ttm/ttm_tt.c | 5 + drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 4 +--- include/drm/ttm/ttm_tt.h | 2 +- 8 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fcff5671f6f8..e11c5d69843d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1292,7 +1292,7 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) * Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and * ttm_tt_destroy(). */ -static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) +static void amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) { struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; @@ -1303,14 +1303,13 @@ static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) amdgpu_ttm_tt_unpin_userptr(ttm); if (gtt->offset == AMDGPU_BO_INVALID_OFFSET) - return 0; + return; /* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */ r = amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages); if (r) DRM_ERROR("failed to unbind %lu pages at 0x%08llX\n", gtt->ttm.ttm.num_pages, gtt->offset); - return r; } static void amdgpu_ttm_backend_destroy(struct ttm_tt *ttm) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index feaac908efed..20b6d0b3de5c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -46,12 +46,11 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) return 0; } -static int +static void nv04_sgdma_unbind(struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; nouveau_mem_fini(nvbe->mem); - return 0; } static struct ttm_backend_func nv04_sgdma_backend = { diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1d8e07b8b19e..bf9dc451583a 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -149,10 +149,9 @@ static int qxl_ttm_backend_bind(struct ttm_tt *ttm, return -1; } -static int qxl_ttm_backend_unbind(struct ttm_tt *ttm) +static void qxl_ttm_backend_unbind(struct ttm_tt *ttm) { /* Not implemented */ - return -1; } static void qxl_ttm_backend_destroy(struct ttm_tt *ttm) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 54af06df865b..004344dce140 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -591,7 +591,7 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm, return 0; } -static int radeon_ttm_backend_unbind(struct ttm_tt *ttm) +static void radeon_ttm_backend_unbind(struct ttm_tt *ttm) { struct radeon_ttm_tt *gtt = (void *)ttm; @@ -599,8 +599,6 @@ static int radeon_ttm_backend_unbind(struct ttm_tt *ttm) if (gtt->userptr) radeon_ttm_tt_unpin_userptr(ttm); - - return 0; } static void radeon_ttm_backend_destroy(struct ttm_tt *ttm) diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 6050dc846894..38f1351140e2 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -82,17 +82,18 @@ static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) return ret; } -static int ttm_agp_unbind(struct ttm_tt *ttm) +static void ttm_agp_unbind(struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); if (agp_be->mem) { - if (agp_be->mem->is_bound) - return agp_unbind_memory(agp_be->mem); + if (agp_be->mem->is_bound) { + agp_unbind_memory(agp_be->mem); + return; + } agp_free_memory(agp_be->mem); agp_be->mem = NULL; } - return 0; } static void ttm_agp_destroy(struct ttm_tt *ttm) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index e25d4097aa16..bab67873cfd4 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -313,11 +313,8 @@ EXPORT_SYMBOL(ttm_dma_tt_fini); void ttm_tt_unbind(struct ttm_tt *ttm) { - int ret; - if (tt
[PATCH] ttm: ttm_bo_swapout_all doesn't use it's argument.
From: Dave Airlie Just drop the argument from this. This does ask the question if this is the function vmwgfx should be using or should it be doing an evict all like the other drivers. Signed-off-by: Dave Airlie --- drivers/gpu/drm/ttm/ttm_bo.c| 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- include/drm/ttm/ttm_bo_api.h| 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b03747717ec7..f297fd5e02d4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1838,7 +1838,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) } EXPORT_SYMBOL(ttm_bo_swapout); -void ttm_bo_swapout_all(struct ttm_bo_device *bdev) +void ttm_bo_swapout_all(void) { struct ttm_operation_ctx ctx = { .interruptible = false, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 470428387878..fb39826f72c1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1352,7 +1352,7 @@ static int vmw_pm_freeze(struct device *kdev) vmw_execbuf_release_pinned_bo(dev_priv); vmw_resource_evict_all(dev_priv); vmw_release_device_early(dev_priv); - ttm_bo_swapout_all(&dev_priv->bdev); + ttm_bo_swapout_all(); if (dev_priv->enable_fb) vmw_fifo_resource_dec(dev_priv); if (atomic_read(&dev_priv->num_fifo_resources) != 0) { diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index b1c705a93517..a9e13b252820 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -692,7 +692,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx); -void ttm_bo_swapout_all(struct ttm_bo_device *bdev); +void ttm_bo_swapout_all(void); /** * ttm_bo_uses_embedded_gem_object - check if the given bo uses the -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
linux-next: manual merge of the drm tree with the drm-misc-fixes tree
Hi all, Today's linux-next merge of the drm tree got a conflict in: drivers/gpu/drm/drm_gem.c between commit: 8490d6a7e0a0 ("drm: hold gem reference until object is no longer accessed") from the drm-misc-fixes tree and commit: be6ee102341b ("drm: remove _unlocked suffix in drm_gem_object_put_unlocked") from the drm tree. I fixed it up (see below) and can carry the fix as necessary. This is now fixed as far as linux-next is concerned, but any non trivial conflicts should be mentioned to your upstream maintainer when your tree is submitted for merging. You may also want to consider cooperating with the maintainer of the conflicting tree to minimise any particularly complex conflicts. -- Cheers, Stephen Rothwell diff --cc drivers/gpu/drm/drm_gem.c index ee2058ad482c,a57f5379fc08.. --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@@ -901,9 -913,7 +909,9 @@@ drm_gem_open_ioctl(struct drm_device *d args->handle = handle; args->size = obj->size; - return 0; +err: - drm_gem_object_put_unlocked(obj); ++ drm_gem_object_put(obj); + return ret; } /** pgpng9x56_UUo.pgp Description: OpenPGP digital signature ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207383] [Regression] 5.7 amdgpu/polaris11 gpf: amdgpu_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=207383 --- Comment #104 from mn...@protonmail.com --- (In reply to mnrzk from comment #103) > (In reply to Nicholas Kazlauskas from comment #95) > > Created attachment 290583 [details] > > 0001-drm-amd-display-Force-add-all-CRTCs-to-state-when-us.patch > > > > So the sequence looks like the following: > > > > 1. Non-blocking commit #1 requested, checked, swaps state and deferred to > > work queue. > > > > 2. Non-blocking commit #2 requested, checked, swaps state and deferred to > > work queue. > > > > Commits #1 and #2 don't touch any of the same core DRM objects (CRTCs, > > Planes, Connectors) so Commit #2 does not stall for Commit #1. DRM Private > > Objects have always been avoided in stall checks, so we have no safety from > > DRM core in this regard. > > > > 3. Due to system load commit #2 executes first and finishes its commit tail > > work. At the end of commit tail, as part of DRM core, it calls > > drm_atomic_state_put(). > > > > Since this was the pageflip IOCTL we likely already dropped the reference > on > > the state held by the IOCTL itself. So it's going to actually free at this > > point. > > > > This eventually calls drm_atomic_state_clear() which does the following: > > > > obj->funcs->atomic_destroy_state(obj, state->private_objs[i].state); > > > > Note that it clears "state" here. Commit sets "state" to the following: > > > > state->private_objs[i].state = old_obj_state; > > obj->state = new_obj_state; > > > > Since Commit #1 swapped first this means Commit #2 actually does free > Commit > > #1's private object. > > > > 4. Commit #1 then executes and we get a use after free. > > > > Same bug, it's just this was never corrupted before by the slab changes. > > It's been sitting dormant for 5.0~5.8. > > > > Attached is a patch that might help resolve this. > > So I just got around to testing this patch and so far, not very promising. > > Right now I can't comment on if the bug in question was resolved but this > just introduced some new critical bugs for me. > > I first tried this on my bare metal system w/ my RX 480 and it boots into > lightdm just fine. As soon as I log in and start up XFCE however, one of my > two monitors goes black (monitor reports being asleep) but my cursor seems > to drift into the other monitor just fine. So after that, I check the > display settings and both monitors are detected. So I tried re-enabling the > off monitor and then both monitors work fine. > > After that, another bug: I now have two cursors, one only works on my right > monitor and the other only stays in one position. > > At this point, I recompiled and remade the initramfs, and sure enough, same > issues. This time, however, changing the display settings didn't "fix" the > issue with one monitor being blank; the off monitor activated, but the > previously working one just froze. > > I also tried this on my VM passing through my GPU w/ vfio-pci; similar > issues. Lightdm worked fine but when I started KDE Plasma, it started > flashing white and one of my monitors just became blank. This time, I > couldn't enable the blank display from the settings, it just didn't show > up. Xrandr only showed one output as well; switching HDMI outputs still > only lets me use the monitor on the "working" HDMI port. > > I don't exactly know how I would go about debugging this since there's just > too many bugs to count. I also don't know if it would be worth it at all. > > Do you have any idea why this would occur? This patch only seems to force > synchronisation, I don't quite know why it would break my system so much. This just gets even weirder the more I test it out. Swapping the two monitors (i.e. swapping the HDMI ports used for each monitor) seems to fix the issue completely on my VM (at least from 1 minute of testing), but on the host it fixes some of the issues (my cursor still disappears on one of my monitors). -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Monday, July 27, 2020 9:26 AM, Kazlauskas, Nicholas wrote: > On 2020-07-27 1:40 a.m., Mazin Rezk wrote: > > This patch fixes a race condition that causes a use-after-free during > > amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits > > are requested and the second one finishes before the first. Essentially, > > this bug occurs when the following sequence of events happens: > > > > 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > > deferred to the workqueue. > > > > 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > > deferred to the workqueue. > > > > 3. Commit #2 starts before commit #1, dm_state #1 is used in the > > commit_tail and commit #2 completes, freeing dm_state #1. > > > > 4. Commit #1 starts after commit #2 completes, uses the freed dm_state > > 1 and dereferences a freelist pointer while setting the context. > > > > Since this bug has only been spotted with fast commits, this patch fixes > > the bug by clearing the dm_state instead of using the old dc_state for > > fast updates. In addition, since dm_state is only used for its dc_state > > and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, > > removing the dm_state should not have any consequences in fast updates. > > > > This use-after-free bug has existed for a while now, but only caused a > > noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate > > freelist pointer to middle of object") moving the freelist pointer from > > dm_state->base (which was unused) to dm_state->context (which is > > dereferenced). > > > > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 > > Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast > > updates") > > Reported-by: Duncan <1i5t5.dun...@cox.net> > > Signed-off-by: Mazin Rezk > > --- > > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++- > > 1 file changed, 27 insertions(+), 9 deletions(-) > > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > > index 86ffa0c2880f..710edc70e37e 100644 > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > > @@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device > > *dev, > > * the same resource. If we have a new DC context as part of > > * the DM atomic state from validation we need to free it and > > * retain the existing one instead. > > +* > > +* Furthermore, since the DM atomic state only contains the DC > > +* context and can safely be annulled, we can free the state > > +* and clear the associated private object now to free > > +* some memory and avoid a possible use-after-free later. > > */ > > - struct dm_atomic_state *new_dm_state, *old_dm_state; > > > > - new_dm_state = dm_atomic_get_new_state(state); > > - old_dm_state = dm_atomic_get_old_state(state); > > + for (i = 0; i < state->num_private_objs; i++) { > > + struct drm_private_obj *obj = > > state->private_objs[i].ptr; > > > > - if (new_dm_state && old_dm_state) { > > - if (new_dm_state->context) > > - dc_release_state(new_dm_state->context); > > + if (obj->funcs == adev->dm.atomic_obj.funcs) { > > + int j = state->num_private_objs-1; > > > > - new_dm_state->context = old_dm_state->context; > > + dm_atomic_destroy_state(obj, > > + state->private_objs[i].state); > > + > > + /* If i is not at the end of the array then the > > +* last element needs to be moved to where i was > > +* before the array can safely be truncated. > > +*/ > > + if (i != j) > > + state->private_objs[i] = > > + state->private_objs[j]; > > > > - if (old_dm_state->context) > > - dc_retain_state(old_dm_state->context); > > + state->private_objs[j].ptr = NULL; > > + state->private_objs[j].state = NULL; > > + state->private_objs[j].old_state = NULL; > > + state->private_objs[j].new_state = NULL; > > + > > + state->num_private_objs = j; > > + break; > > + } > > In the bug report itself I mentioned that I don't really like hacking > around the DRM core for resolving this patch but to go into more > specifics, it's really two issues of code maintenanc
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Monday, July 27, 2020 4:29 PM, Daniel Vetter wrote: > On Mon, Jul 27, 2020 at 9:28 PM Christian König > wrote: > > > > Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: > > > On 2020-07-27 9:39 a.m., Christian König wrote: > > >> Am 27.07.20 um 07:40 schrieb Mazin Rezk: > > >>> This patch fixes a race condition that causes a use-after-free during > > >>> amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking > > >>> commits > > >>> are requested and the second one finishes before the first. > > >>> Essentially, > > >>> this bug occurs when the following sequence of events happens: > > >>> > > >>> 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > > >>> deferred to the workqueue. > > >>> > > >>> 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > > >>> deferred to the workqueue. > > >>> > > >>> 3. Commit #2 starts before commit #1, dm_state #1 is used in the > > >>> commit_tail and commit #2 completes, freeing dm_state #1. > > >>> > > >>> 4. Commit #1 starts after commit #2 completes, uses the freed dm_state > > >>> 1 and dereferences a freelist pointer while setting the context. > > >> > > >> Well I only have a one mile high view on this, but why don't you let > > >> the work items execute in order? > > >> > > >> That would be better anyway cause this way we don't trigger a cache > > >> line ping pong between CPUs. > > >> > > >> Christian. > > > > > > We use the DRM helpers for managing drm_atomic_commit_state and those > > > helpers internally push non-blocking commit work into the system > > > unbound work queue. > > > > Mhm, well if you send those helper atomic commits in the order A,B and > > they execute it in the order B,A I would call that a bug :) > > The way it works is it pushes all commits into unbound work queue, but > then forces serialization as needed. We do _not_ want e.g. updates on > different CRTC to be serialized, that would result in lots of judder. > And hw is funny enough that there's all kinds of dependencies. > > The way you force synchronization is by adding other CRTC state > objects. So if DC is busted and can only handle a single update per > work item, then I guess you always need all CRTC states and everything > will be run in order. But that also totally kills modern multi-screen > compositors. Xorg isn't modern, just in case that's not clear :-) > > Lucking at the code it seems like you indeed have only a single dm > state, so yeah global sync is what you'll need as immediate fix, and > then maybe fix up DM to not be quite so silly ... or at least only do > the dm state stuff when really needed. > > We could also sprinkle the drm_crtc_commit structure around a bit > (it's the glue that provides the synchronization across commits), but > since your dm state is global just grabbing all crtc states > unconditionally as part of that is probably best. > > > > While we could duplicate a copy of that code with nothing but the > > > workqueue changed that isn't something I'd really like to maintain > > > going forward. > > > > I'm not talking about duplicating the code, I'm talking about fixing the > > helpers. I don't know that code well, but from the outside it sounds > > like a bug there. > > > > And executing work items in the order they are submitted is trivial. > > > > Had anybody pinged Daniel or other people familiar with the helper code > > about it? > > Yeah something is wrong here, and the fix looks horrible :-) > > Aside, I've also seen some recent discussion flare up about > drm_atomic_state_get/put used to paper over some other use-after-free, > but this time related to interrupt handlers. Maybe a few rules about > that: > - dont > - especially not when it's interrupt handlers, because you can't call > drm_atomic_state_put from interrupt handlers. > > Instead have an spin_lock_irq to protect the shared date with your > interrupt handler, and _copy_ the date over. This is e.g. what > drm_crtc_arm_vblank_event does. Nicholas wrote a patch that attempted to resolve the issue by adding every CRTC into the commit to use use the stall checks. [1] While this forces synchronisation on commits, it's kind of a hacky method that may take a toll on performance. Is it possible to have a DRM helper that forces synchronisation on some commits without having to add every CRTC into the commit? Also, is synchronisation really necessary for fast updates in amdgpu? I'll admit, the idea of eliminating the use-after-free bug by eliminating the use entirely doesn't seem ideal; but is forcing synchronisation on these updates that much better? [1] https://bugzilla.kernel.org/show_bug.cgi?id=207383#c96 Thanks, Mazin Rezk > > Cheers, Daniel > > > > > Regards, > > Christian. > > > > > > > > Regards, > > > Nicholas Kazlauskas > > > > > >> > > >>> > > >>> Since this bug has only been spotted with fast commits, this patch > > >>> fixes > > >>> the bug by clearing the dm_state instead of using the old dc_state for > > >>> fast updates. In add
[PATCH] nouveau: use ttm populate mapping functions. (v2)
From: Dave Airlie Instead of rolling driver copies of them. v2: cleanup return handling (Ben) Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_bo.c | 38 ++-- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7806278dce57..6ef5085c9a91 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1231,8 +1231,6 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; - int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (ttm->state != tt_unpopulated) @@ -1260,31 +1258,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) return ttm_dma_populate((void *)ttm, dev, ctx); } #endif - - r = ttm_pool_populate(ttm, ctx); - if (r) { - return r; - } - - for (i = 0; i < ttm->num_pages; i++) { - dma_addr_t addr; - - addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE, - DMA_BIDIRECTIONAL); - - if (dma_mapping_error(dev, addr)) { - while (i--) { - dma_unmap_page(dev, ttm_dma->dma_address[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); - ttm_dma->dma_address[i] = 0; - } - ttm_pool_unpopulate(ttm); - return -EFAULT; - } - - ttm_dma->dma_address[i] = addr; - } - return 0; + return ttm_populate_and_map_pages(dev, ttm_dma, ctx); } static void @@ -1293,7 +1267,6 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (slave) @@ -1316,14 +1289,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) } #endif - for (i = 0; i < ttm->num_pages; i++) { - if (ttm_dma->dma_address[i]) { - dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE, - DMA_BIDIRECTIONAL); - } - } - - ttm_pool_unpopulate(ttm); + ttm_unmap_and_unpopulate_pages(dev, ttm_dma); } void -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
ttm_tt_set_placement_caching on vram->ram transfers
Hi Christian + Ben, Just been reviewing around driver TTM code, and found an inconsistency, amdgpu + radeon both call the above before binding the ttm and going gpu vram->ram copies, but I don't see nouveau doing it Not sure if it could cause any issues, but it does look inconsistent. Dave. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207383] [Regression] 5.7 amdgpu/polaris11 gpf: amdgpu_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=207383 --- Comment #103 from mn...@protonmail.com --- (In reply to Nicholas Kazlauskas from comment #95) > Created attachment 290583 [details] > 0001-drm-amd-display-Force-add-all-CRTCs-to-state-when-us.patch > > So the sequence looks like the following: > > 1. Non-blocking commit #1 requested, checked, swaps state and deferred to > work queue. > > 2. Non-blocking commit #2 requested, checked, swaps state and deferred to > work queue. > > Commits #1 and #2 don't touch any of the same core DRM objects (CRTCs, > Planes, Connectors) so Commit #2 does not stall for Commit #1. DRM Private > Objects have always been avoided in stall checks, so we have no safety from > DRM core in this regard. > > 3. Due to system load commit #2 executes first and finishes its commit tail > work. At the end of commit tail, as part of DRM core, it calls > drm_atomic_state_put(). > > Since this was the pageflip IOCTL we likely already dropped the reference on > the state held by the IOCTL itself. So it's going to actually free at this > point. > > This eventually calls drm_atomic_state_clear() which does the following: > > obj->funcs->atomic_destroy_state(obj, state->private_objs[i].state); > > Note that it clears "state" here. Commit sets "state" to the following: > > state->private_objs[i].state = old_obj_state; > obj->state = new_obj_state; > > Since Commit #1 swapped first this means Commit #2 actually does free Commit > #1's private object. > > 4. Commit #1 then executes and we get a use after free. > > Same bug, it's just this was never corrupted before by the slab changes. > It's been sitting dormant for 5.0~5.8. > > Attached is a patch that might help resolve this. So I just got around to testing this patch and so far, not very promising. Right now I can't comment on if the bug in question was resolved but this just introduced some new critical bugs for me. I first tried this on my bare metal system w/ my RX 480 and it boots into lightdm just fine. As soon as I log in and start up XFCE however, one of my two monitors goes black (monitor reports being asleep) but my cursor seems to drift into the other monitor just fine. So after that, I check the display settings and both monitors are detected. So I tried re-enabling the off monitor and then both monitors work fine. After that, another bug: I now have two cursors, one only works on my right monitor and the other only stays in one position. At this point, I recompiled and remade the initramfs, and sure enough, same issues. This time, however, changing the display settings didn't "fix" the issue with one monitor being blank; the off monitor activated, but the previously working one just froze. I also tried this on my VM passing through my GPU w/ vfio-pci; similar issues. Lightdm worked fine but when I started KDE Plasma, it started flashing white and one of my monitors just became blank. This time, I couldn't enable the blank display from the settings, it just didn't show up. Xrandr only showed one output as well; switching HDMI outputs still only lets me use the monitor on the "working" HDMI port. I don't exactly know how I would go about debugging this since there's just too many bugs to count. I also don't know if it would be worth it at all. Do you have any idea why this would occur? This patch only seems to force synchronisation, I don't quite know why it would break my system so much. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/vmwgfx: drop bo map/unmap dma functions.
From: Dave Airlie The map one was used once, just inline it, and drop them both. Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h| 2 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 46 +++--- 2 files changed, 6 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index b7c763713b4c..65c414f119c0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1019,8 +1019,6 @@ extern struct ttm_placement vmw_mob_placement; extern struct ttm_placement vmw_mob_ne_placement; extern struct ttm_placement vmw_nonfixed_placement; extern struct ttm_bo_driver vmw_bo_driver; -extern int vmw_bo_map_dma(struct ttm_buffer_object *bo); -extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo); extern const struct vmw_sg_table * vmw_bo_sg_table(struct ttm_buffer_object *bo); extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index d051b84aaeb5..0f0f9600ea46 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -519,43 +519,6 @@ static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt) vmw_tt->mapped = false; } - -/** - * vmw_bo_map_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - * Note that the buffer object must be either pinned or reserved before - * calling this function. - */ -int vmw_bo_map_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - return vmw_ttm_map_dma(vmw_tt); -} - - -/** - * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - */ -void vmw_bo_unmap_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - vmw_ttm_unmap_dma(vmw_tt); -} - - /** * vmw_bo_sg_table - Return a struct vmw_sg_table object for a * TTM buffer object @@ -876,9 +839,12 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, ret = ttm_bo_reserve(bo, false, true, NULL); BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(bo->ttm, &ctx); - if (likely(ret == 0)) - ret = vmw_bo_map_dma(bo); + ret = vmw_ttm_populate(bo->ttm, &ctx); + if (likely(ret == 0)) { + struct vmw_ttm_tt *vmw_tt = + container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); + ret = vmw_ttm_map_dma(vmw_tt); + } ttm_bo_unreserve(bo); -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/vmwgfx: consolidate ttm object creation and populate
From: Dave Airlie These two functions has the same code in them, create a common helper function instead. Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h| 4 ++ drivers/gpu/drm/vmwgfx/vmwgfx_mob.c| 60 ++ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 32 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 3596f3923ea3..b7c763713b4c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1023,6 +1023,10 @@ extern int vmw_bo_map_dma(struct ttm_buffer_object *bo); extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo); extern const struct vmw_sg_table * vmw_bo_sg_table(struct ttm_buffer_object *bo); +extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, + unsigned long bo_size, + struct ttm_buffer_object **bo_p); + extern void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt, unsigned long p_offs); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index e8eb42933ca2..7f95ed6aa224 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -238,10 +238,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, unsigned long offset; unsigned long bo_size; struct vmw_otable *otables = batch->otables; - struct ttm_operation_ctx ctx = { - .interruptible = false, - .no_wait_gpu = false - }; SVGAOTableType i; int ret; @@ -255,24 +251,9 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, bo_size += otables[i].size; } - ret = ttm_bo_create(&dev_priv->bdev, bo_size, - ttm_bo_type_device, - &vmw_sys_ne_placement, - 0, false, &batch->otable_bo); - - if (unlikely(ret != 0)) - goto out_no_bo; - - ret = ttm_bo_reserve(batch->otable_bo, false, true, NULL); - BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(batch->otable_bo->ttm, &ctx); - if (unlikely(ret != 0)) - goto out_unreserve; - ret = vmw_bo_map_dma(batch->otable_bo); + ret = vmw_bo_create_and_populate(dev_priv, bo_size, &batch->otable_bo); if (unlikely(ret != 0)) - goto out_unreserve; - - ttm_bo_unreserve(batch->otable_bo); + return ret; offset = 0; for (i = 0; i < batch->num_otables; ++i) { @@ -289,8 +270,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, return 0; -out_unreserve: - ttm_bo_unreserve(batch->otable_bo); out_no_setup: for (i = 0; i < batch->num_otables; ++i) { if (batch->otables[i].enabled) @@ -300,7 +279,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; -out_no_bo: return ret; } @@ -432,41 +410,9 @@ struct vmw_mob *vmw_mob_create(unsigned long data_pages) static int vmw_mob_pt_populate(struct vmw_private *dev_priv, struct vmw_mob *mob) { - int ret; - struct ttm_operation_ctx ctx = { - .interruptible = false, - .no_wait_gpu = false - }; - BUG_ON(mob->pt_bo != NULL); - ret = ttm_bo_create(&dev_priv->bdev, mob->num_pages * PAGE_SIZE, - ttm_bo_type_device, - &vmw_sys_ne_placement, - 0, false, &mob->pt_bo); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_bo_reserve(mob->pt_bo, false, true, NULL); - - BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(mob->pt_bo->ttm, &ctx); - if (unlikely(ret != 0)) - goto out_unreserve; - ret = vmw_bo_map_dma(mob->pt_bo); - if (unlikely(ret != 0)) - goto out_unreserve; - - ttm_bo_unreserve(mob->pt_bo); - - return 0; - -out_unreserve: - ttm_bo_unreserve(mob->pt_bo); - ttm_bo_put(mob->pt_bo); - mob->pt_bo = NULL; - - return ret; + return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE, &mob->pt_bo); } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 1d78187eaba6..d051b84aaeb5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -854,3 +854,35 @@ struct ttm_bo_driver vmw_bo_driver = { .swap_notify = vmw_swap_notify, .io_mem_reserve = &vmw_ttm_io_mem_reserve, }; + +int vmw_bo_create_and_populate(struct vmw_private
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On 2020-07-27 5:32 p.m., Daniel Vetter wrote: On Mon, Jul 27, 2020 at 11:11 PM Mazin Rezk wrote: On Monday, July 27, 2020 4:29 PM, Daniel Vetter wrote: On Mon, Jul 27, 2020 at 9:28 PM Christian König wrote: Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: On 2020-07-27 9:39 a.m., Christian König wrote: Am 27.07.20 um 07:40 schrieb Mazin Rezk: This patch fixes a race condition that causes a use-after-free during amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits are requested and the second one finishes before the first. Essentially, this bug occurs when the following sequence of events happens: 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is deferred to the workqueue. 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is deferred to the workqueue. 3. Commit #2 starts before commit #1, dm_state #1 is used in the commit_tail and commit #2 completes, freeing dm_state #1. 4. Commit #1 starts after commit #2 completes, uses the freed dm_state 1 and dereferences a freelist pointer while setting the context. Well I only have a one mile high view on this, but why don't you let the work items execute in order? That would be better anyway cause this way we don't trigger a cache line ping pong between CPUs. Christian. We use the DRM helpers for managing drm_atomic_commit_state and those helpers internally push non-blocking commit work into the system unbound work queue. Mhm, well if you send those helper atomic commits in the order A,B and they execute it in the order B,A I would call that a bug :) The way it works is it pushes all commits into unbound work queue, but then forces serialization as needed. We do _not_ want e.g. updates on different CRTC to be serialized, that would result in lots of judder. And hw is funny enough that there's all kinds of dependencies. The way you force synchronization is by adding other CRTC state objects. So if DC is busted and can only handle a single update per work item, then I guess you always need all CRTC states and everything will be run in order. But that also totally kills modern multi-screen compositors. Xorg isn't modern, just in case that's not clear :-) Lucking at the code it seems like you indeed have only a single dm state, so yeah global sync is what you'll need as immediate fix, and then maybe fix up DM to not be quite so silly ... or at least only do the dm state stuff when really needed. We could also sprinkle the drm_crtc_commit structure around a bit (it's the glue that provides the synchronization across commits), but since your dm state is global just grabbing all crtc states unconditionally as part of that is probably best. While we could duplicate a copy of that code with nothing but the workqueue changed that isn't something I'd really like to maintain going forward. I'm not talking about duplicating the code, I'm talking about fixing the helpers. I don't know that code well, but from the outside it sounds like a bug there. And executing work items in the order they are submitted is trivial. Had anybody pinged Daniel or other people familiar with the helper code about it? Yeah something is wrong here, and the fix looks horrible :-) Aside, I've also seen some recent discussion flare up about drm_atomic_state_get/put used to paper over some other use-after-free, but this time related to interrupt handlers. Maybe a few rules about that: - dont - especially not when it's interrupt handlers, because you can't call drm_atomic_state_put from interrupt handlers. Instead have an spin_lock_irq to protect the shared date with your interrupt handler, and _copy_ the date over. This is e.g. what drm_crtc_arm_vblank_event does. Nicholas wrote a patch that attempted to resolve the issue by adding every CRTC into the commit to use use the stall checks. [1] While this forces synchronisation on commits, it's kind of a hacky method that may take a toll on performance. Is it possible to have a DRM helper that forces synchronisation on some commits without having to add every CRTC into the commit? Also, is synchronisation really necessary for fast updates in amdgpu? I'll admit, the idea of eliminating the use-after-free bug by eliminating the use entirely doesn't seem ideal; but is forcing synchronisation on these updates that much better? Well clearing the dc_state pointer here and then allocating another one in atomic_commit_tail also looks fishy. The proper fix is probably a lot more involved, but yeah interim fix is to grab all crtc states iff you also grabbed the dm_atomic_state structure. Real fix is to only do this when necessary, which pretty much means the dc_state needs to be somehow split up, or there needs to be some guarantees about when it's necessary and when not. Otherwise parallel commits on different CRTC are not possible with the current dc backend code. Thanks for spending some time to help take a look at this as well. The DRM documentation (at least at th
[PATCH] nouveau: use ttm populate mapping functions.
From: Dave Airlie Instead of rolling driver copies of them. Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_bo.c | 32 ++-- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7806278dce57..fe773737b662 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1231,7 +1231,6 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1261,29 +1260,10 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) } #endif - r = ttm_pool_populate(ttm, ctx); + r = ttm_populate_and_map_pages(dev, ttm_dma, ctx); if (r) { return r; } - - for (i = 0; i < ttm->num_pages; i++) { - dma_addr_t addr; - - addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE, - DMA_BIDIRECTIONAL); - - if (dma_mapping_error(dev, addr)) { - while (i--) { - dma_unmap_page(dev, ttm_dma->dma_address[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); - ttm_dma->dma_address[i] = 0; - } - ttm_pool_unpopulate(ttm); - return -EFAULT; - } - - ttm_dma->dma_address[i] = addr; - } return 0; } @@ -1293,7 +1273,6 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (slave) @@ -1316,14 +1295,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) } #endif - for (i = 0; i < ttm->num_pages; i++) { - if (ttm_dma->dma_address[i]) { - dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE, - DMA_BIDIRECTIONAL); - } - } - - ttm_pool_unpopulate(ttm); + ttm_unmap_and_unpopulate_pages(dev, ttm_dma); } void -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207383] [Regression] 5.7 amdgpu/polaris11 gpf: amdgpu_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=207383 --- Comment #102 from Duncan (1i5t5.dun...@cox.net) --- (In reply to Duncan from comment #101) > (In reply to Nicholas Kazlauskas from comment #95) > > 0001-drm-amd-display-Force-add-all-CRTCs-to-state-when-us.patch > > Just booted to 5.8-rc7 with this patched in locally (and the g320+ reverts > /not/ patched in). So testing, but noting again that the bug can take a > couple days to trigger on my hardware, so while verifying bug-still-there > /might/ be fast, verifying that it's /not/ there will take awhile. So far building system updates so heavy cpu load while playing only moderate FHD video. No freezes but I have seen a bit of the predicted judder. I suspect the synchronization is preventing the freezes, and the judder hasn't been /bad/. But with different-refresh monitors (mine are both 60 Hz 4k bigscreen TVs so same refresh), or trying 4k video, particularly 4k60 which my system already struggles with, or possibly even both say 120 Hz monitors, the judder would be noticeably worse. The 4k30 and 4k60 youtube tests will probably have to wait for tomorrow, tho, as I've been up near 24 now... -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/6] i915: fail atomic commit when muxed away
Attempting to commit a modeset while mux-switched away can cause problems due to DisplayPort links being unavailable while they are physically disconnected. In order to avoid this, bail out of atomic commit early if attempted while a display mux is switched away. Signed-off-by: Daniel Dadap --- drivers/gpu/drm/i915/display/intel_display.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 346846609f45..4ad799e4b024 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -15736,6 +15737,12 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_i915_private *dev_priv = to_i915(dev); int ret = 0; + if (!vga_switcheroo_is_client_active(to_pci_dev(dev->dev))) { + drm_dbg_atomic(&dev_priv->drm, + "Atomic commit attempted while muxed away.\n"); + return -EINVAL; + } + state->wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); drm_atomic_state_get(&state->base); -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/6] drm/panel: Add panel driver for NewVision NV3052C based LCDs
This driver supports the NewVision NV3052C based LCDs. Right now, it only supports the LeadTek LTK035C5444T 2.4" 640x480 TFT LCD panel, which can be found in the Anbernic RG-350M handheld console. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile| 1 + .../gpu/drm/panel/panel-newvision-nv3052c.c | 523 ++ 3 files changed, 533 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-newvision-nv3052c.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index de2f2a452be5..6a8a51a702d8 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -198,6 +198,15 @@ config DRM_PANEL_NEC_NL8048HL11 panel (found on the Zoom2/3/3630 SDP boards). To compile this driver as a module, choose M here. +config DRM_PANEL_NEWVISION_NV3052C + tristate "NewVision NV3052C DSI/SPI RGB panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the panels built + around the NewVision NV3052C display controller. + config DRM_PANEL_NOVATEK_NT35510 tristate "Novatek NT35510 RGB panel driver" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index e45ceac6286f..a0516ced87db 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o +obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c new file mode 100644 index ..2feabef6dc3c --- /dev/null +++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NevVision NV3052C IPS LCD panel driver + * + * Copyright (C) 2020, Paul Cercueil + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +struct nv3052c_panel_info { + const struct drm_display_mode *display_modes; + unsigned int num_modes; + unsigned int bus_type; + u16 width_mm, height_mm; + u32 bus_format, bus_flags; +}; + +struct nv3052c_reg { + u8 cmd; + u8 value; +}; + +struct nv3052c { + struct drm_panel drm_panel; + struct mipi_dsi_device *dsi; + struct device *dev; + + struct regulator *supply; + const struct nv3052c_panel_info *panel_info; + + struct gpio_desc *reset_gpio; + + struct backlight_device *backlight; +}; + +static const struct nv3052c_reg nv3052c_regs[] = { + { 0xff, 0x30 }, + { 0xff, 0x52 }, + { 0xff, 0x01 }, + { 0xe3, 0x00 }, + { 0x40, 0x00 }, + { 0x03, 0x40 }, + { 0x04, 0x00 }, + { 0x05, 0x03 }, + { 0x08, 0x00 }, + { 0x09, 0x07 }, + { 0x0a, 0x01 }, + { 0x0b, 0x32 }, + { 0x0c, 0x32 }, + { 0x0d, 0x0b }, + { 0x0e, 0x00 }, + { 0x23, 0xa0 }, + + { 0x24, 0x0c }, + { 0x25, 0x06 }, + { 0x26, 0x14 }, + { 0x27, 0x14 }, + + { 0x38, 0xcc }, + { 0x39, 0xd7 }, + { 0x3a, 0x4a }, + + { 0x28, 0x40 }, + { 0x29, 0x01 }, + { 0x2a, 0xdf }, + { 0x49, 0x3c }, + { 0x91, 0x77 }, + { 0x92, 0x77 }, + { 0xa0, 0x55 }, + { 0xa1, 0x50 }, + { 0xa4, 0x9c }, + { 0xa7, 0x02 }, + { 0xa8, 0x01 }, + { 0xa9, 0x01 }, + { 0xaa, 0xfc }, + { 0xab, 0x28 }, + { 0xac, 0x06 }, + { 0xad, 0x06 }, + { 0xae, 0x06 }, + { 0xaf, 0x03 }, + { 0xb0, 0x08 }, + { 0xb1, 0x26 }, + { 0xb2, 0x28 }, + { 0xb3, 0x28 }, + { 0xb4, 0x33 }, + { 0xb5, 0x08 }, + { 0xb6, 0x26 }, + { 0xb7, 0x08 }, + { 0xb8, 0x26 }, + { 0xf0, 0x00 }, + { 0xf6, 0xc0 }, + + { 0xff, 0x30 }, + { 0xff, 0x52 }, + { 0xff, 0x02 }, + { 0xb0, 0x0b }, + { 0xb1, 0x16 }, + { 0xb2, 0x17 }, + { 0xb3, 0x2c }, + { 0xb4, 0x32 }, + { 0xb5, 0x3b }, + { 0xb6, 0x29 }, + { 0xb7, 0x40 }, + { 0xb8, 0x0d }, + { 0xb9, 0x05 }, + { 0xba, 0x12 }, + { 0xbb, 0x10 }, + { 0xbc, 0x12 }, + { 0xbd, 0x15 }, + { 0xbe, 0x19 }, + { 0xbf, 0x0e }, + { 0xc0, 0x16 }, + { 0xc1, 0x0a }, +
[PATCH 3/6] vga-switcheroo: notify clients of pending/completed switch events
Add a new vga-switcheroo client callback to allow clients to register for receiving notifications when a mux switch is pending, completed, or failed. This allows individual client drivers to prepare for or respond to mux switches to and from the registered client device. Signed-off-by: Daniel Dadap --- drivers/gpu/vga/vga_switcheroo.c | 29 - include/linux/vga_switcheroo.h | 18 ++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index a4fc78c4bf4f..6392dc92696b 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -756,14 +756,41 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client, if (new_client->fb_info) fbcon_remap_all(new_client->fb_info); + if (active->ops->notify) + active->ops->notify(active->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_AWAY, + VGA_SWITCHEROO_NOTIFY_SWITCH_PENDING); + if (new_client->ops->notify) + new_client->ops->notify(new_client->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_TO, + VGA_SWITCHEROO_NOTIFY_SWITCH_PENDING); + active->switched = false; mutex_lock(&vgasr_priv.mux_hw_lock); ret = vgasr_priv.handler->switchto(new_client->id); mutex_unlock(&vgasr_priv.mux_hw_lock); - if (ret) + if (ret) { + if (active->ops->notify) + active->ops->notify(active->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_AWAY, + VGA_SWITCHEROO_NOTIFY_SWITCH_FAILED); + if (new_client->ops->notify) + new_client->ops->notify(new_client->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_TO, + VGA_SWITCHEROO_NOTIFY_SWITCH_FAILED); return ret; + } new_client->switched = true; + if (active->ops->notify) + active->ops->notify(active->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_AWAY, + VGA_SWITCHEROO_NOTIFY_SWITCH_COMPLETE); + if (new_client->ops->notify) + new_client->ops->notify(new_client->pdev, + VGA_SWITCHEROO_NOTIFY_SWITCH_TO, + VGA_SWITCHEROO_NOTIFY_SWITCH_COMPLETE); + if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 63e6d6e5786e..2dc8ebc84fd4 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -90,6 +90,17 @@ enum vga_switcheroo_client_id { VGA_SWITCHEROO_MAX_CLIENTS, }; +enum vga_switcheroo_notify_direction { + VGA_SWITCHEROO_NOTIFY_SWITCH_TO, + VGA_SWITCHEROO_NOTIFY_SWITCH_AWAY, +}; + +enum vga_switcheroo_notify_action { + VGA_SWITCHEROO_NOTIFY_SWITCH_PENDING, + VGA_SWITCHEROO_NOTIFY_SWITCH_COMPLETE, + VGA_SWITCHEROO_NOTIFY_SWITCH_FAILED, +}; + /** * struct vga_switcheroo_handler - handler callbacks * @init: initialize handler. @@ -134,6 +145,10 @@ struct vga_switcheroo_handler { * Mandatory. The client should return false if a user space process * has one of its device files open * @gpu_bound: notify the client id to audio client when the GPU is bound. + * @notify: notify clients of pending and completed switches + * Optional. This gets called for both active and inactive clients, + * before a switch begins, and after a switch successfully completes + * or fails. * * Client callbacks. A client can be either a GPU or an audio device on a GPU. * The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be @@ -145,6 +160,9 @@ struct vga_switcheroo_client_ops { void (*reprobe)(struct pci_dev *dev); bool (*can_switch)(struct pci_dev *dev); void (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id); + void (*notify)(struct pci_dev *dev, + enum vga_switcheroo_notify_direction, + enum vga_switcheroo_notify_action); }; #if defined(CONFIG_VGA_SWITCHEROO) -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [v7, PATCH 7/7] drm/mediatek: add support for mediatek SOC MT8183
On Sat, 2020-07-25 at 07:24 +0800, Chun-Kuang Hu wrote: > Hi Yongqiang: > > Yongqiang Niu 於 2020年7月23日 週四 上午10:15寫道: > > > > This patch add support for mediatek SOC MT8183 > > 1.ovl_2l share driver with ovl > > I think this is done in [1], [2], [3], this patch just add the support > of mt8183-ovl and mt8183-ovl-2l. > > [1] > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/gpu/drm/mediatek?h=v5.8-rc6&id=132c6e250ed745443973cada8db17cdbaebdf551 > [2] > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/gpu/drm/mediatek?h=v5.8-rc6&id=318462d1a568634ba09263cc730cb0fb1d56c2b3 > [3] > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/gpu/drm/mediatek?h=v5.8-rc6&id=57148baac8b78461e394953cfd5317bde8f795ab > > > 2.rdma1 share drive with rdma0, but fifo size is different > > I think this is done in [4], this patch just add the support of mt8183-rdma. > > [4] https://patchwork.kernel.org/patch/11679549/ > > > 3.add mt8183 mutex private data, and mmsys private data > > 4.add mt8183 main and external path module for crtc create > > The fourth item is the mmsys private data in third item, so you need > not to repeat it. > > > > > Signed-off-by: Yongqiang Niu > > --- > > drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 18 > > drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 6 > > drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 47 > > > > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 43 + > > 4 files changed, 114 insertions(+) > > > > [snip] > > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c > > b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c > > index 014c1bb..60788c1 100644 > > --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c > > +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c > > @@ -15,6 +15,8 @@ > > > > #define MT2701_DISP_MUTEX0_MOD00x2c > > #define MT2701_DISP_MUTEX0_SOF00x30 > > +#define MT8183_DISP_MUTEX0_MOD00x30 > > +#define MT8183_DISP_MUTEX0_SOF00x2c > > > > #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) > > #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) > > @@ -25,6 +27,18 @@ > > > > #define INT_MUTEX BIT(1) > > > > +#define MT8183_MUTEX_MOD_DISP_RDMA00 > > +#define MT8183_MUTEX_MOD_DISP_RDMA11 > > +#define MT8183_MUTEX_MOD_DISP_OVL0 9 > > +#define MT8183_MUTEX_MOD_DISP_OVL0_2L 10 > > +#define MT8183_MUTEX_MOD_DISP_OVL1_2L 11 > > +#define MT8183_MUTEX_MOD_DISP_WDMA012 > > +#define MT8183_MUTEX_MOD_DISP_COLOR0 13 > > +#define MT8183_MUTEX_MOD_DISP_CCORR0 14 > > +#define MT8183_MUTEX_MOD_DISP_AAL0 15 > > +#define MT8183_MUTEX_MOD_DISP_GAMMA0 16 > > +#define MT8183_MUTEX_MOD_DISP_DITHER0 17 > > + > > #define MT8173_MUTEX_MOD_DISP_OVL0 11 > > #define MT8173_MUTEX_MOD_DISP_OVL1 12 > > #define MT8173_MUTEX_MOD_DISP_RDMA013 > > @@ -74,6 +88,10 @@ > > #define MUTEX_SOF_DSI2 5 > > #define MUTEX_SOF_DSI3 6 > > > > +#define MT8183_MUTEX_SOF_DPI0 2 > > +#define MT8183_MUTEX_EOF_DSI0 (MUTEX_SOF_DSI0 << 6) > > +#define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6) > > + > > > > struct mtk_disp_mutex { > > int id; > > @@ -153,6 +171,20 @@ struct mtk_ddp { > > [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, > > }; > > > > +static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = { > > + [DDP_COMPONENT_AAL0] = MT8183_MUTEX_MOD_DISP_AAL0, > > + [DDP_COMPONENT_CCORR] = MT8183_MUTEX_MOD_DISP_CCORR0, > > + [DDP_COMPONENT_COLOR0] = MT8183_MUTEX_MOD_DISP_COLOR0, > > + [DDP_COMPONENT_DITHER] = MT8183_MUTEX_MOD_DISP_DITHER0, > > + [DDP_COMPONENT_GAMMA] = MT8183_MUTEX_MOD_DISP_GAMMA0, > > + [DDP_COMPONENT_OVL0] = MT8183_MUTEX_MOD_DISP_OVL0, > > + [DDP_COMPONENT_OVL_2L0] = MT8183_MUTEX_MOD_DISP_OVL0_2L, > > + [DDP_COMPONENT_OVL_2L1] = MT8183_MUTEX_MOD_DISP_OVL1_2L, > > + [DDP_COMPONENT_RDMA0] = MT8183_MUTEX_MOD_DISP_RDMA0, > > + [DDP_COMPONENT_RDMA1] = MT8183_MUTEX_MOD_DISP_RDMA1, > > + [DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0, > > +}; > > + > > static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = { > > [DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, > > [DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, > > @@ -163,6 +195,12 @@ struct mtk_ddp { > > [DDP_MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3, > > }; > > > > +static const unsigned int mt8183_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = { > > + [DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, > > + [DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0 | MT8183_MUTEX_EOF_DSI0, >
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Mon, 27 Jul 2020 10:05:01 -0400 "Kazlauskas, Nicholas" wrote: > On 2020-07-27 9:39 a.m., Christian König wrote: > > Am 27.07.20 um 07:40 schrieb Mazin Rezk: > >> This patch fixes a race condition that causes a use-after-free > >> during amdgpu_dm_atomic_commit_tail. This can occur when 2 > >> non-blocking commits are requested and the second one finishes > >> before the first. Essentially, this bug occurs when the following > >> sequence of events happens: > >> > >> 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > >> deferred to the workqueue. > >> > >> 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > >> deferred to the workqueue. > >> > >> 3. Commit #2 starts before commit #1, dm_state #1 is used in the > >> commit_tail and commit #2 completes, freeing dm_state #1. > >> > >> 4. Commit #1 starts after commit #2 completes, uses the freed > >> dm_state 1 and dereferences a freelist pointer while setting the > >> context. > > > > Well I only have a one mile high view on this, but why don't you > > let the work items execute in order? > > > > That would be better anyway cause this way we don't trigger a cache > > line ping pong between CPUs. > > > > Christian. > > We use the DRM helpers for managing drm_atomic_commit_state and those > helpers internally push non-blocking commit work into the system > unbound work queue. > > While we could duplicate a copy of that code with nothing but the > workqueue changed that isn't something I'd really like to maintain > going forward. > > Regards, > Nicholas Kazlauskas Additionally, I don't see mentioned on-thread (it's on the bug and now in the details below) that we're talking multi-monitor, not single-monitor. Presumably that goes some way toward answering the "why not force order?" question, considering the outputs may be running at different refresh frequencies, etc... All the reports on the bug seem to be multi-monitor (after seeing multi-monitor/output in several reports I asked if anyone was seeing it with only one monitor and no answers), and as you commented on the bug for your proposed patch but seems missing from this one here (different author/proposal) ... Commits #1 and #2 don't touch any of the same core DRM objects (CRTCs, Planes, Connectors) so Commit #2 does not stall for Commit #1. DRM Private Objects have always been avoided in stall checks, so we have no safety from DRM core in this regard. > >> > >> Since this bug has only been spotted with fast commits, this patch > >> fixes the bug by clearing the dm_state instead of using the old > >> dc_state for fast updates. In addition, since dm_state is only > >> used for its dc_state and amdgpu_dm_atomic_commit_tail will retain > >> the dc_state if none is found, > >> removing the dm_state should not have any consequences in fast > >> updates. > >> > >> This use-after-free bug has existed for a while now, but only > >> caused a noticeable issue starting from 5.7-rc1 due to 3202fa62f > >> ("slub: relocate freelist pointer to middle of object") moving the > >> freelist pointer from dm_state->base (which was unused) to > >> dm_state->context (which is dereferenced). > >> > >> Bugzilla: > >> https://bugzilla.kernel.org/show_bug.cgi?id=207383 > >> > >> Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state > >> for fast updates") > >> Reported-by: Duncan <1i5t5.dun...@cox.net> > >> Signed-off-by: Mazin Rezk > >> --- > >> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 > >> ++- 1 file changed, 27 insertions(+), 9 > >> deletions(-) > >> > >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > >> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > >> index 86ffa0c2880f..710edc70e37e 100644 > >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > >> @@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct > >> drm_device *dev, > >> * the same resource. If we have a new DC context as > >> part of > >> * the DM atomic state from validation we need to free > >> it and > >> * retain the existing one instead. > >> + * > >> + * Furthermore, since the DM atomic state only contains > >> the DC > >> + * context and can safely be annulled, we can free the > >> state > >> + * and clear the associated private object now to free > >> + * some memory and avoid a possible use-after-free later. > >> */ > >> - struct dm_atomic_state *new_dm_state, *old_dm_state; > >> > >> - new_dm_state = dm_atomic_get_new_state(state); > >> - old_dm_state = dm_atomic_get_old_state(state); > >> + for (i = 0; i < state->num_private_objs; i++) { > >> + struct drm_private_obj *obj = > >> state->private_objs[i].ptr; > >> > >> - if (new_dm_state && old_dm_state) { > >> - if (new_dm_state->context) > >> - dc_release_state
[PATCH 1/2] drm/radeon: switch from 'pci_' to 'dma_' API
The wrappers in include/linux/pci-dma-compat.h should go away. The patch has been generated with the coccinelle script below and has been hand modified to replace GFP_ with a correct flag. It has been compile tested. When memory is allocated in 'radeon_gart_table_ram_alloc()' GFP_KERNEL can be used because its callers already use this flag. Both 'r100_pci_gart_init()' (r100.c) and 'rs400_gart_init()' (rs400.c) call 'radeon_gart_init()'. This function uses 'vmalloc'. @@ @@ -PCI_DMA_BIDIRECTIONAL +DMA_BIDIRECTIONAL @@ @@ -PCI_DMA_TODEVICE +DMA_TO_DEVICE @@ @@ -PCI_DMA_FROMDEVICE +DMA_FROM_DEVICE @@ @@ -PCI_DMA_NONE +DMA_NONE @@ expression e1, e2, e3; @@ -pci_alloc_consistent(e1, e2, e3) +dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3; @@ -pci_zalloc_consistent(e1, e2, e3) +dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3, e4; @@ -pci_free_consistent(e1, e2, e3, e4) +dma_free_coherent(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_map_single(e1, e2, e3, e4) +dma_map_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_unmap_single(e1, e2, e3, e4) +dma_unmap_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4, e5; @@ -pci_map_page(e1, e2, e3, e4, e5) +dma_map_page(&e1->dev, e2, e3, e4, e5) @@ expression e1, e2, e3, e4; @@ -pci_unmap_page(e1, e2, e3, e4) +dma_unmap_page(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_map_sg(e1, e2, e3, e4) +dma_map_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_unmap_sg(e1, e2, e3, e4) +dma_unmap_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_dma_sync_single_for_cpu(e1, e2, e3, e4) +dma_sync_single_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_dma_sync_single_for_device(e1, e2, e3, e4) +dma_sync_single_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_dma_sync_sg_for_cpu(e1, e2, e3, e4) +dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ -pci_dma_sync_sg_for_device(e1, e2, e3, e4) +dma_sync_sg_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2; @@ -pci_dma_mapping_error(e1, e2) +dma_mapping_error(&e1->dev, e2) @@ expression e1, e2; @@ -pci_set_dma_mask(e1, e2) +dma_set_mask(&e1->dev, e2) @@ expression e1, e2; @@ -pci_set_consistent_dma_mask(e1, e2) +dma_set_coherent_mask(&e1->dev, e2) Signed-off-by: Christophe JAILLET --- If needed, see post from Christoph Hellwig on the kernel-janitors ML: https://marc.info/?l=kernel-janitors&m=158745678307186&w=4 --- drivers/gpu/drm/radeon/radeon_gart.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index f178ba321715..b7ce254e5663 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -72,8 +72,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) { void *ptr; - ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, - &rdev->gart.table_addr); + ptr = dma_alloc_coherent(&rdev->pdev->dev, rdev->gart.table_size, +&rdev->gart.table_addr, GFP_KERNEL); if (ptr == NULL) { return -ENOMEM; } @@ -110,9 +110,8 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) rdev->gart.table_size >> PAGE_SHIFT); } #endif - pci_free_consistent(rdev->pdev, rdev->gart.table_size, - (void *)rdev->gart.ptr, - rdev->gart.table_addr); + dma_free_coherent(&rdev->pdev->dev, rdev->gart.table_size, + (void *)rdev->gart.ptr, rdev->gart.table_addr); rdev->gart.ptr = NULL; rdev->gart.table_addr = 0; } -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/6] i915: implement vga-switcheroo reprobe() callback
Add a vga-switcheroo callback for reprobing displays. Use this new callback to retrain the link on all DP encoders after a mux switch. Signed-off-by: Daniel Dadap --- drivers/gpu/drm/i915/i915_switcheroo.c | 27 +- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c index ed69b5d4a375..fa388de03cf6 100644 --- a/drivers/gpu/drm/i915/i915_switcheroo.c +++ b/drivers/gpu/drm/i915/i915_switcheroo.c @@ -7,6 +7,8 @@ #include "i915_drv.h" #include "i915_switcheroo.h" +#include "display/intel_display_types.h" +#include "display/intel_dp.h" static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) @@ -46,9 +48,32 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) return i915 && atomic_read(&i915->drm.open_count) == 0; } +static void i915_switcheroo_reprobe(struct pci_dev *pdev) +{ + struct drm_i915_private *i915 = pdev_to_i915(pdev); + struct intel_encoder *encoder; + + for_each_intel_dp(&i915->drm, encoder) { + int ret = -EDEADLK; + struct drm_modeset_acquire_ctx ctx; + + drm_modeset_acquire_init(&ctx, 0); + + while (ret == -EDEADLK) { + ret = intel_dp_retrain_link(encoder, &ctx); + + if (ret == -EDEADLK) + drm_modeset_backoff(&ctx); + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + } +} + static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { .set_gpu_state = i915_switcheroo_set_state, - .reprobe = NULL, + .reprobe = i915_switcheroo_reprobe, .can_switch = i915_switcheroo_can_switch, }; -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/6] drm/bridge: Add SPI DBI host driver
This driver will register a DBI host driver for panels connected over SPI. DBI types c1 and c3 are supported. C1 is a SPI protocol with 9 bits per word, with the data/command information in the 9th (MSB) bit. C3 is a SPI protocol with 8 bits per word, with the data/command information carried by a separate GPIO. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/dbi-spi.c | 261 +++ 3 files changed, 270 insertions(+) create mode 100644 drivers/gpu/drm/bridge/dbi-spi.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c7f0dacfb57a..ed38366847c1 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -219,6 +219,14 @@ config DRM_TI_TPD12S015 Texas Instruments TPD12S015 HDMI level shifter and ESD protection driver. +config DRM_MIPI_DBI_SPI + tristate "SPI host support for MIPI DBI" + depends on OF && SPI + select DRM_MIPI_DSI + select DRM_MIPI_DBI + help + Driver to support DBI over SPI. + source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 7d7c123a95e4..c2c522c2774f 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o +obj-$(CONFIG_DRM_MIPI_DBI_SPI) += dbi-spi.o obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o obj-y += analogix/ diff --git a/drivers/gpu/drm/bridge/dbi-spi.c b/drivers/gpu/drm/bridge/dbi-spi.c new file mode 100644 index ..1060b8f95fba --- /dev/null +++ b/drivers/gpu/drm/bridge/dbi-spi.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MIPI Display Bus Interface (DBI) SPI support + * + * Copyright 2016 Noralf Trønnes + * Copyright 2020 Paul Cercueil + */ + +#include +#include +#include + +#include +#include + +#include + +struct dbi_spi { + struct mipi_dsi_host host; + struct mipi_dsi_host_ops host_ops; + + struct spi_device *spi; + struct gpio_desc *dc; + struct mutex cmdlock; + + unsigned int current_bus_type; + + /** +* @tx_buf9: Buffer used for Option 1 9-bit conversion +*/ + void *tx_buf9; + + /** +* @tx_buf9_len: Size of tx_buf9. +*/ + size_t tx_buf9_len; +}; + +static inline struct dbi_spi *host_to_dbi_spi(struct mipi_dsi_host *host) +{ + return container_of(host, struct dbi_spi, host); +} + +static ssize_t dbi_spi1_transfer(struct mipi_dsi_host *host, +const struct mipi_dsi_msg *msg) +{ + struct dbi_spi *dbi = host_to_dbi_spi(host); + struct spi_device *spi = dbi->spi; + struct spi_transfer tr = { + .bits_per_word = 9, + }; + const u8 *src8 = msg->tx_buf; + struct spi_message m; + size_t max_chunk, chunk; + size_t len = msg->tx_len; + bool cmd_byte = true; + unsigned int i; + u16 *dst16; + int ret; + + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); + dst16 = dbi->tx_buf9; + + max_chunk = min(dbi->tx_buf9_len / 2, len); + + spi_message_init_with_transfers(&m, &tr, 1); + tr.tx_buf = dst16; + + while (len) { + chunk = min(len, max_chunk); + + for (i = 0; i < chunk; i++) { + dst16[i] = *src8++; + + /* Bit 9: 0 means command, 1 means data */ + if (!cmd_byte) + dst16[i] |= BIT(9); + + cmd_byte = false; + } + + tr.len = chunk * 2; + len -= chunk; + + ret = spi_sync(spi, &m); + if (ret) + return ret; + } + + return 0; +} + +static ssize_t dbi_spi3_transfer(struct mipi_dsi_host *host, +const struct mipi_dsi_msg *msg) +{ + struct dbi_spi *dbi = host_to_dbi_spi(host); + struct spi_device *spi = dbi->spi; + const u8 *buf = msg->tx_buf; + unsigned int bpw = 8; + u32 speed_hz; + ssize_t ret; + + /* for now we only support sending messages, not receiving */ + if (msg->rx_len) + return -EINVAL; + + gpiod_set_value_cansleep(dbi->dc, 0); + + speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); + ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, buf, 1); + if (ret || msg->tx_len == 1) + return ret; + + if (buf[0] == MIPI_DCS_WRITE_MEMORY_START) + bpw = 16; + + gpiod_set_value_cansleep(dbi->dc, 1); + speed_hz = mipi_d
[PATCH 2/6] vga-switcheroo: Add a way to test for the active client
vga-switcheroo clients may wish to know whether they are currently active, i.e., whether the mux is currently switched to the client in question. Add an in-kernel API to test whether a vga-switcheroo client, as identified by PCI device, is actively switched. Signed-off-by: Daniel Dadap --- drivers/gpu/vga/vga_switcheroo.c | 38 +++- include/linux/vga_switcheroo.h | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index cf3c7024dafa..a4fc78c4bf4f 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -99,7 +99,13 @@ * @id: client identifier. Determining the id requires the handler, * so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID * and later given their true id in vga_switcheroo_enable() - * @active: whether the outputs are currently switched to this client + * @active: whether the client is currently active: this is unset for the + * currently active client before preparing for a mux switch, and set + * for the newly active client after completing all post-switch actions. + * @switched: whether the outputs are physically switched to the client: + * this is unset for the currently switched client immediately before + * switching the mux, and set for the newly switched client immediately + * after switching the mux. * @driver_power_control: whether power state is controlled by the driver's * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs * interface is a no-op so as not to interfere with runtime pm @@ -117,6 +123,7 @@ struct vga_switcheroo_client { const struct vga_switcheroo_client_ops *ops; enum vga_switcheroo_client_id id; bool active; + bool switched; bool driver_power_control; struct list_head list; struct pci_dev *vga_dev; @@ -306,6 +313,7 @@ static int register_client(struct pci_dev *pdev, client->ops = ops; client->id = id; client->active = active; + client->switched = active; client->driver_power_control = driver_power_control; client->vga_dev = vga_dev; @@ -748,11 +756,13 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client, if (new_client->fb_info) fbcon_remap_all(new_client->fb_info); + active->switched = false; mutex_lock(&vgasr_priv.mux_hw_lock); ret = vgasr_priv.handler->switchto(new_client->id); mutex_unlock(&vgasr_priv.mux_hw_lock); if (ret) return ret; + new_client->switched = true; if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); @@ -,3 +1121,29 @@ void vga_switcheroo_fini_domain_pm_ops(struct device *dev) dev_pm_domain_set(dev, NULL); } EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); + +/** + * vga_switcheroo_is_client_active() - test if a device is the active client + * @pdev: vga client device + * + * Check whether the mux is switched to the switcheroo client associated with + * the given PCI device. Assumes that mux is always switched to the device in + * question when switcheroo is inactive, and that the mux is switched away if + * no matching client is registered. + */ +bool vga_switcheroo_is_client_active(struct pci_dev *pdev) +{ + if (vgasr_priv.active) { + struct vga_switcheroo_client *client; + + client = find_client_from_pci(&vgasr_priv.clients, pdev); + + if (client) + return client->switched; + else + return false; + } else { + return true; + } +} +EXPORT_SYMBOL(vga_switcheroo_is_client_active); diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 7e6ac0114d55..63e6d6e5786e 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -173,6 +173,7 @@ enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev); int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain); void vga_switcheroo_fini_domain_pm_ops(struct device *dev); +bool vga_switcheroo_is_client_active(struct pci_dev *pdev); #else static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} @@ -194,6 +195,7 @@ static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct p static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {} +static inline bool vga_switcheroo_is_client_active(struct pci_dev *pdev) { return true; } #endif #endif /* _LINUX_VGA_SWITCHEROO_H_ */ -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.f
[PATCH 2/6] drm: dsi: Let host and device specify supported bus
The current MIPI DSI framework can very well be used to support MIPI DBI panels. In order to add support for the various bus types supported by DBI, the DRM panel drivers should specify the bus type they will use, and the DSI host drivers should specify the bus types they are compatible with. The DSI host driver can then use the information provided by the DBI/DSI device driver, such as the bus type and the number of lanes, to configure its hardware properly. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/drm_mipi_dsi.c | 9 + include/drm/drm_mipi_dsi.h | 12 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 5dd475e82995..11ef885de765 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -281,6 +281,9 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) { struct device_node *node; + if (WARN_ON_ONCE(!host->bus_types)) + host->bus_types = MIPI_DEVICE_TYPE_DSI; + for_each_available_child_of_node(host->dev->of_node, node) { /* skip nodes without reg property */ if (!of_find_property(node, "reg", NULL)) @@ -323,6 +326,12 @@ int mipi_dsi_attach(struct mipi_dsi_device *dsi) { const struct mipi_dsi_host_ops *ops = dsi->host->ops; + if (WARN_ON_ONCE(!dsi->bus_type)) + dsi->bus_type = MIPI_DEVICE_TYPE_DSI; + + if (!(dsi->bus_type & dsi->host->bus_types)) + return -EINVAL; + if (!ops || !ops->attach) return -ENOSYS; diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 360e6377e84b..65d2961fc054 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -63,6 +63,14 @@ struct mipi_dsi_packet { int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, const struct mipi_dsi_msg *msg); +/* MIPI bus types */ +#define MIPI_DEVICE_TYPE_DSI BIT(0) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1 BIT(1) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2 BIT(2) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3 BIT(3) +#define MIPI_DEVICE_TYPE_DBI_M6800 BIT(4) +#define MIPI_DEVICE_TYPE_DBI_I8080 BIT(5) + /** * struct mipi_dsi_host_ops - DSI bus operations * @attach: attach DSI device to DSI host @@ -94,11 +102,13 @@ struct mipi_dsi_host_ops { * struct mipi_dsi_host - DSI host device * @dev: driver model device node for this DSI host * @ops: DSI host operations + * @bus_types: Bitmask of supported MIPI bus types * @list: list management */ struct mipi_dsi_host { struct device *dev; const struct mipi_dsi_host_ops *ops; + unsigned int bus_types; struct list_head list; }; @@ -162,6 +172,7 @@ struct mipi_dsi_device_info { * @host: DSI host for this peripheral * @dev: driver model device node for this peripheral * @name: DSI peripheral chip type + * @bus_type: MIPI bus type (MIPI_DEVICE_TYPE_DSI/...) * @channel: virtual channel assigned to the peripheral * @format: pixel format for video mode * @lanes: number of active data lanes @@ -178,6 +189,7 @@ struct mipi_dsi_device { struct device dev; char name[DSI_DEV_NAME_SIZE]; + unsigned int bus_type; unsigned int channel; unsigned int lanes; enum mipi_dsi_pixel_format format; -- 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/6] i915: bail out of eDP link training while mux-switched away
It is not possible to train a Displayport link while the lanes are physically disconnected by a display mux. In order to prevent problems associated with attempting to train a disconnected link, abort eDP link training if the i915 GPU is not an active vga-switcheroo client. This short circuit is eDP-specific, as normal DP (e.g. for external displays) should be able to detect that the link is not physically connected, while eDP is usually assumed to be always connected. Signed-off-by: Daniel Dadap --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index a7defb37ab00..a1c61db8a228 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -24,6 +24,7 @@ #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_link_training.h" +#include "linux/vga_switcheroo.h" static void intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE]) @@ -371,6 +372,14 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp) { struct intel_connector *intel_connector = intel_dp->attached_connector; + struct device *dev = dp_to_dig_port(intel_dp)->base.base.dev->dev; + + if (intel_dp_is_edp(intel_dp) && + !vga_switcheroo_is_client_active(to_pci_dev(dev))) { + drm_dbg_kms(&dp_to_i915(intel_dp)->drm, + "eDP link training not allowed when muxed away."); + return; + } if (!intel_dp_link_training_clock_recovery(intel_dp)) goto failure_handling; -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/6] drm/panel: Add Ilitek ILI9341 DBI panel driver
This driver is for the Ilitek ILI9341 based YX240QV29-T 2.4" 240x320 TFT LCD panel from Adafruit. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/panel/Kconfig| 9 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 345 +++ 3 files changed, 355 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 6a8a51a702d8..132a42a81895 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -105,6 +105,15 @@ config DRM_PANEL_ILITEK_IL9322 Say Y here if you want to enable support for Ilitek IL9322 QVGA (320x240) RGB, YUV and ITU-T BT.656 panels. +config DRM_PANEL_ILITEK_ILI9341 + tristate "Ilitek ILI9341 320x240 QVGA panels" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Ilitek IL9341 + QVGA (320x240) RGB, YUV and ITU-T BT.656 panels. + config DRM_PANEL_ILITEK_ILI9881C tristate "Ilitek ILI9881C-based panels" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index a0516ced87db..ad5e6089c3ef 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o +obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c new file mode 100644 index ..3af6628639d6 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DRM driver for Ilitek ILI9341 panels + * + * Copyright 2018 David Lechner + * Copyright 2020 Paul Cercueil + * + * Based on mi0283qt.c: + * Copyright 2016 Noralf Trønnes + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ILI9341_FRMCTR10xb1 +#define ILI9341_DISCTRL0xb6 +#define ILI9341_ETMOD 0xb7 + +#define ILI9341_PWCTRL10xc0 +#define ILI9341_PWCTRL20xc1 +#define ILI9341_VMCTRL10xc5 +#define ILI9341_VMCTRL20xc7 +#define ILI9341_PWCTRLA0xcb +#define ILI9341_PWCTRLB0xcf + +#define ILI9341_PGAMCTRL 0xe0 +#define ILI9341_NGAMCTRL 0xe1 +#define ILI9341_DTCTRLA0xe8 +#define ILI9341_DTCTRLB0xea +#define ILI9341_PWRSEQ 0xed + +#define ILI9341_EN3GAM 0xf2 +#define ILI9341_PUMPCTRL 0xf7 + +#define ILI9341_MADCTL_BGR BIT(3) +#define ILI9341_MADCTL_MV BIT(5) +#define ILI9341_MADCTL_MX BIT(6) +#define ILI9341_MADCTL_MY BIT(7) + +struct ili9341_pdata { + struct drm_display_mode mode; + unsigned int width_mm; + unsigned int height_mm; + unsigned int bus_type; + unsigned int lanes; +}; + +struct ili9341 { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + const struct ili9341_pdata *pdata; + + struct gpio_desc*reset_gpiod; + struct backlight_device *backlight; + u32 rotation; +}; + +#define mipi_dcs_command(dsi, cmd, seq...) \ +({ \ + u8 d[] = { seq }; \ + mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \ +}) + +static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel) +{ + return container_of(panel, struct ili9341, panel); +} + +static int ili9341_prepare(struct drm_panel *panel) +{ + struct ili9341 *priv = panel_to_ili9341(panel); + struct mipi_dsi_device *dsi = priv->dsi; + u8 addr_mode; + int ret; + + gpiod_set_value_cansleep(priv->reset_gpiod, 0); + usleep_range(20, 1000); + gpiod_set_value_cansleep(priv->reset_gpiod, 1); + msleep(120); + + ret = mipi_dcs_command(dsi, MIPI_DCS_SOFT_RESET); + if (ret) { + dev_err(panel->dev, "Failed to send reset command: %d\n", ret); + return ret; + } + + /* Wait 5ms after soft reset per MIPI DCS spec */ + usleep_range(5000, 2); + + mipi_dcs_command(dsi, MIPI_DCS_SET_DISPLAY_OFF); + + mipi_dcs_command(dsi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30); + mipi_dcs_command(dsi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12,
[PATCH 1/6] vga-switcheroo: add new "immediate" switch event type
vga-switcheroo supports the following types of mux switch events: * standard: checks the clients' can_switch() callbacks and switches the mux if the client drivers report that they are prepared for a switch. Also uses client and handler callbacks to manage power on the GPUs and reprobe display outputs. * deferred: registers the intent to perform a mux switch and defers it until the client drivers no longer have any active modesetting clients. Performs the equivalent of a standard switch when clients are ready. * mux-only: switches the mux immediately without testing can_switch first and without calling any of the client or handler callbacks for power management and reprobing. In order to support additional use cases involving dynamic switching of display muxes, add a new type of "immediate" switch event which skips the can_switch test and power management hooks, but still calls the reprobe hook. This switch event type uses 'I' as a prefix for its commands, similar to the existing 'D' pefix for the deferred commands and 'M' for the mux-only commands. Signed-off-by: Daniel Dadap --- drivers/gpu/vga/vga_switcheroo.c | 86 +--- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 087304b1a5d7..cf3c7024dafa 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -631,16 +631,23 @@ EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); * * DDIS: Delayed switch to the discrete graphics device. * * MIGD: Mux-only switch to the integrated graphics device. * Does not remap console or change the power state of either gpu. + * Does not call into any client-supplied callbacks, e.g. reprobe. * If the integrated GPU is currently off, the screen will turn black. * If it is on, the screen will show whatever happens to be in VRAM. * Either way, the user has to blindly enter the command to switch back. * * MDIS: Mux-only switch to the discrete graphics device. + * * IIGD: Immediate switch to the integrated graphics device. + * Does not test for active user space processes utilizing the device + * files of the GPU or audio device. Does not change the power state of + * either gpu. The console is remapped and client-provided callbacks + * such as reprobe are called. + * * IDIS: Immediate switch to the discrete graphics device. * * For GPUs whose power state is controlled by the driver's runtime pm, * the ON and OFF commands are a no-op (see next section). * - * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands - * should not be used. + * For muxless machines, the IGD/DIS, DIGD/DDIS, MIGD/MDIS and IIGD/IDIS + * commands should not be used. */ static int vga_switcheroo_show(struct seq_file *m, void *v) @@ -704,7 +711,8 @@ static void set_audio_state(enum vga_switcheroo_client_id id, } /* stage one happens before delay */ -static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) +static int vga_switchto_stage1(struct vga_switcheroo_client *new_client, + bool power_control) { struct vga_switcheroo_client *active; @@ -712,7 +720,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) if (!active) return 0; - if (vga_switcheroo_pwr_state(new_client) == VGA_SWITCHEROO_OFF) + if (power_control && + vga_switcheroo_pwr_state(new_client) == VGA_SWITCHEROO_OFF) vga_switchon(new_client); vga_set_default_device(new_client->pdev); @@ -720,7 +729,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) } /* post delay */ -static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) +static int vga_switchto_stage2(struct vga_switcheroo_client *new_client, + bool power_control) { int ret; struct vga_switcheroo_client *active; @@ -747,7 +757,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); - if (vga_switcheroo_pwr_state(active) == VGA_SWITCHEROO_ON) + if (power_control && + vga_switcheroo_pwr_state(active) == VGA_SWITCHEROO_ON) vga_switchoff(active); /* let HDA controller autoresume if GPU uses driver power control */ @@ -779,6 +790,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, int ret; bool delay = false, can_switch; bool just_mux = false; + bool immediate_switch = false; enum vga_switcheroo_client_id client_id = VGA_SWITCHEROO_UNKNOWN_ID; struct vga_switcheroo_client *client = NULL; @@ -822,30 +834,48 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, goto out; } - /* request a dela
Re: [PATCH 1/6] dt-bindings: display: Document NewVision NV3052C DT node
On Monday, 27 July 2020 21:10:52 CEST Sam Ravnborg wrote: > > +description: | > > + This is a driver for 320x240 TFT panels, > > The binding describes the HW, not the driver. So please re-phrase this > part. > > This datasheet: > https://www.phoenixdisplay.com/wp-content/uploads/2019/05/NV3052C-Dat > asheet-V0.2.pdf tells that the driver supports additional resoltions. > I guess the 320x240 resolution is limited to the leadtek panel. The word "driver" is overloaded ;) I guess "driver IC" would make it clearer. Bye, Maarten ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] clk: qcom: gcc-sdm660: Add missing modem reset
Fixes: f2a76a2955c0 (clk: qcom: Add Global Clock controller (GCC) driver for SDM660) ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/6] drm/bridge: Add SPI DBI host driver
Hi Laurent, Le lun. 27 juil. 2020 à 20:06, Laurent Pinchart a écrit : Hi Paul, Thank you for the patch. On Mon, Jul 27, 2020 at 06:46:10PM +0200, Paul Cercueil wrote: This driver will register a DBI host driver for panels connected over SPI. DBI types c1 and c3 are supported. C1 is a SPI protocol with 9 bits per word, with the data/command information in the 9th (MSB) bit. C3 is a SPI protocol with 8 bits per word, with the data/command information carried by a separate GPIO. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/dbi-spi.c | 261 +++ 3 files changed, 270 insertions(+) create mode 100644 drivers/gpu/drm/bridge/dbi-spi.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c7f0dacfb57a..ed38366847c1 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -219,6 +219,14 @@ config DRM_TI_TPD12S015 Texas Instruments TPD12S015 HDMI level shifter and ESD protection driver. +config DRM_MIPI_DBI_SPI + tristate "SPI host support for MIPI DBI" + depends on OF && SPI + select DRM_MIPI_DSI + select DRM_MIPI_DBI + help +Driver to support DBI over SPI. + source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 7d7c123a95e4..c2c522c2774f 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o +obj-$(CONFIG_DRM_MIPI_DBI_SPI) += dbi-spi.o obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o obj-y += analogix/ diff --git a/drivers/gpu/drm/bridge/dbi-spi.c b/drivers/gpu/drm/bridge/dbi-spi.c new file mode 100644 index ..1060b8f95fba --- /dev/null +++ b/drivers/gpu/drm/bridge/dbi-spi.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MIPI Display Bus Interface (DBI) SPI support + * + * Copyright 2016 Noralf Trønnes + * Copyright 2020 Paul Cercueil + */ + +#include +#include +#include + +#include +#include + +#include + +struct dbi_spi { + struct mipi_dsi_host host; + struct mipi_dsi_host_ops host_ops; + + struct spi_device *spi; + struct gpio_desc *dc; + struct mutex cmdlock; + + unsigned int current_bus_type; + + /** + * @tx_buf9: Buffer used for Option 1 9-bit conversion + */ + void *tx_buf9; + + /** + * @tx_buf9_len: Size of tx_buf9. + */ + size_t tx_buf9_len; +}; + +static inline struct dbi_spi *host_to_dbi_spi(struct mipi_dsi_host *host) +{ + return container_of(host, struct dbi_spi, host); +} + +static ssize_t dbi_spi1_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct dbi_spi *dbi = host_to_dbi_spi(host); + struct spi_device *spi = dbi->spi; + struct spi_transfer tr = { + .bits_per_word = 9, + }; + const u8 *src8 = msg->tx_buf; + struct spi_message m; + size_t max_chunk, chunk; + size_t len = msg->tx_len; + bool cmd_byte = true; + unsigned int i; + u16 *dst16; + int ret; + + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); + dst16 = dbi->tx_buf9; + + max_chunk = min(dbi->tx_buf9_len / 2, len); + + spi_message_init_with_transfers(&m, &tr, 1); + tr.tx_buf = dst16; + + while (len) { + chunk = min(len, max_chunk); + + for (i = 0; i < chunk; i++) { + dst16[i] = *src8++; + + /* Bit 9: 0 means command, 1 means data */ + if (!cmd_byte) + dst16[i] |= BIT(9); + + cmd_byte = false; + } + + tr.len = chunk * 2; + len -= chunk; + + ret = spi_sync(spi, &m); + if (ret) + return ret; + } + + return 0; +} + +static ssize_t dbi_spi3_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct dbi_spi *dbi = host_to_dbi_spi(host); + struct spi_device *spi = dbi->spi; + const u8 *buf = msg->tx_buf; + unsigned int bpw = 8; + u32 speed_hz; + ssize_t ret; + + /* for now we only support sending messages, not receiving */ + if (msg->rx_len) + return -EINVAL; + + gpiod_set_value_cansleep(dbi->dc, 0); + + speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); + ret
Re: [Freedreno] [PATCH V2] drm: hold gem reference until object is no longer accessed
On 2020-07-27 16:11, dan...@ffwll.ch wrote: On Mon, Jul 27, 2020 at 09:55:07PM +0200, Greg KH wrote: On Mon, Jul 20, 2020 at 06:30:50PM -0400, Steve Cohen wrote: > A use-after-free in drm_gem_open_ioctl can happen if the > GEM object handle is closed between the idr lookup and > retrieving the size from said object since a local reference > is not being held at that point. Hold the local reference > while the object can still be accessed to fix this and > plug the potential security hole. > > Signed-off-by: Steve Cohen > --- > drivers/gpu/drm/drm_gem.c | 10 -- > 1 file changed, 4 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > index 7bf628e..ee2058a 100644 > --- a/drivers/gpu/drm/drm_gem.c > +++ b/drivers/gpu/drm/drm_gem.c > @@ -871,9 +871,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, > * @file_priv: drm file-private structure > * > * Open an object using the global name, returning a handle and the size. > - * > - * This handle (of course) holds a reference to the object, so the object > - * will not go away until the handle is deleted. > */ > int > drm_gem_open_ioctl(struct drm_device *dev, void *data, > @@ -898,14 +895,15 @@ 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_put_unlocked(obj); >if (ret) > - return ret; > + goto err; > >args->handle = handle; >args->size = obj->size; > > - return 0; > +err: > + drm_gem_object_put_unlocked(obj); > + return ret; > } > > /** As this seems to fix an important issue, any reason it wasn't cc: stable on it so that it gets backported properly? How about a "Fixes:" tag so that we know what commit id it fixes so we know how far back to backport things? And a hint to the maintainers that "this is an issue that needs to get into 5.8-final, it shouldn't wait around longer please" would have also been nice to see :) And what chagned from v1, aren't you supposed to list that somewhere in the changelog or below the --- line (never remember what DRM drivers want here...) Care to send a v3? Don't worry, I'm pushing this to drm-misc-fixes now, should still make it to 5.8. Plus cc: stable. I didn't bother with Fixes: since I think the bug is rather old. Also, worst case you leak 32bit of some kernel memory that got reused already (but yeah I know that's often enough to get the foot in somewhere nasty and crack the door open). I think it fell through cracks because Sam said he'll apply, guess that didn't happen. Sam added his Reviewed-By on V1 with a comment to rename the goto label, but in V2 I also updated the API documentation and the commit text for a more complete change and thought he would re-add the tag. Also yes a changelog, somewhere, for next time around. Apologies, it won't happen again. Should I still submit a V3? It looks like you've got Greg's concerns covered. -Steve -Daniel thanks, greg k-h ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/sun4i: mixer: Enable register value caching
Hi, On Fri, Jul 24, 2020 at 10:35:49PM +0200, Jernej Skrabec wrote: > It was discovered in the past by Ondrej Jirman that mixer register read > may occasionally return wrong value, most likely zero. It turns out > that all mixer units are affected by this issue. This becomes especially > obvious with applications like video player. After a few minutes of a > playback visual glitches appeared but not always in the same way. After > register inspection it was clear that some bits are not set even when > they should be. There was a similar issue on the earlier backend stuff, and it turned out to be because we were accessing registers while the registers "commit" wasn't completed yet. It looks that in the DE2, it's the register GLB_DBUFFER that controls it (offset 0x08). It would be worth looking into whether it happens only when the bit 0 is still high. I ended up writing a small program using devmem back then to write a known value in known to be faulty register and checking it in a tight loop (and then with a poll on that bit) to see if that fixed it or not. > Best solution would be to shuffle the code a bit to avoid > read-modify-write operations and use only register writes. However, > quicker solution is to enable caching support in regmap which is also > used here. Such fix is also easier to backport in stable kernels. It only partially fixes the issue though. None of the volatile registers would be covered, and this includes GLB_CTL too at least. Maxime signature.asc Description: PGP signature ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/6] DBI/DSI, panel drivers, and tinyDRM compat
Hi, Here's a follow-up on the previous discussion about the current state of DSI/DBI panel drivers, TinyDRM, and the need of a cleanup. For the record, here is a small sum-up of the current situation: - the current MIPI DBI code (drivers/gpu/drm/drm_mipi_dbi.c) is lagging way behind the MIPI DSI code (drivers/gpu/drm/drm_mipi_dsi.c). While the DSI code adds a proper bus support, with support for host drivers and client devices, there is no such thing with the DBI code. As such, it is currently impossible to write a standard DRM panel driver for a DBI panel. - Even if the MIPI DBI code was updated with a proper bus, many panels and MIPI controllers support both DSI and DBI, so it would be a pain to support them without resolving to duplicating each driver. - The panel drivers written against the DBI code are all "tinyDRM" drivers, which means that they will register a full yet simple DRM driver, and cannot be used as regular DRM panels for a different DRM driver. - These "tinyDRM" drivers all use SPI directly, even though the panels they're driving can work on other interfaces (e.g. i8080 bus). Which means that one driver written for e.g. a ILI9341 would not work if the control interface is not SPI. - The "tinyDRM" common code is entangled with DBI and there is no clear separation between the two. It could very well be moved to a single "tinyDRM" driver that works with a DRM panel obtained from devicetree, because the only requirement is that the panel supports a few given DCS commands. This patchset introduces the following: * Patch [2/6] slightly tweaks the MIPI DSI code so that it now also supports MIPI DBI over various hardware buses. Because if you think about it, DSI is just the same as DBI just on a different hardware bus. The DSI host drivers, now DSI/DBI host drivers, set compatibility bits for the hardware buses they support (DSI, DBI/i8080, DBI/SPI9, DBI/SPI+GPIO), which is matched against the hardware bus that panel drivers request. * For the DBI panels connected over SPI, a new DSI/DBI host driver is added in patch [3/6]. It allows MIPI DBI panel drivers to be written with the DSI/DBI framework, even if they are connected over SPI, instead of registering as SPI device drivers. Since most of these panels can be connected over various buses, it permits to reuse the same driver independently of the bus used. * Patch [4/6] adds a panel driver for NewVision NV3052C based panels. This has been successfully tested on the Anbernic RG350M handheld console, along with the dbi-spi bridge and the ingenic-drm driver. * A TinyDRM driver for DSI/DBI panels, once again independent of the bus used; the only dependency (currently) being that the panel must understand DCS commands. * A DRM panel driver to test the stack. This driver controls Ilitek ILI9341 based DBI panels, like the Adafruit YX240QV29-T 320x240 2.4" TFT LCD panel. This panel was converted from drivers/gpu/drm/tiny/ili9341.c. Patches [1-4] were successfully tested on hardware. Patches [5-6] were compile-tested and runtime-tested but without hardware connected, so I'd want a Tested-by on these two. Another thing to note, is that it does not break Device Tree ABI. The display node stays the same: spi { ... display@0 { compatible = "adafruit,yx240qv29", "ilitek,ili9341"; reg = <0>; spi-max-frequency = <3200>; dc-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; rotation = <270>; backlight = <&backlight>; }; }; The reason it works, is that the "adafruit,yx240qv29" device is probed on the SPI bus, so it will match with the SPI/DBI host driver. This will in turn register the very same node with the DSI bus, and the ILI9341 DRM panel driver will probe. The driver will detect that no controller is linked to the panel, and eventually register the DBI/DSI TinyDRM driver. One drawback of this approach, is that the "adafruit,yx240qv29" must be added to the dbi-spi bridge driver (unless a custom rule is added for a "dbi-spi" fallback compatible string). I still think that it's a small price to pay to avoid breaking the Device Tree bindings. Feedback welcome. Cheers, -Paul Paul Cercueil (6): dt-bindings: display: Document NewVision NV3052C DT node drm: dsi: Let host and device specify supported bus drm/bridge: Add SPI DBI host driver drm/panel: Add panel driver for NewVision NV3052C based LCDs drm/tiny: Add TinyDRM for DSI/DBI panels drm/panel: Add Ilitek ILI9341 DBI panel driver .../display/panel/newvision,nv3052c.yaml | 69 +++ drivers/gpu/drm/bridge/Kconfig| 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/dbi-spi.c | 262 + drivers/gpu/drm/drm_mipi_dsi.c| 9 + drivers/gpu/drm/panel/Kconfig
[PATCH 5/6] drm/tiny: Add TinyDRM for DSI/DBI panels
The new API function mipi_dsi_maybe_register_tiny_driver() is supposed to be called by DSI/DBI panel drivers at the end of their probe. If it is detected that the panel is not connected to any controller, because it has no port #0 node in Device Tree that points back to it, then a TinyDRM driver is registered with it. This TinyDRM driver expects that a DCS-compliant protocol is used by the DSI/DBI panel and can only be used with these. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/tiny/Kconfig| 8 + drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/tiny/tiny-dsi.c | 266 include/drm/drm_mipi_dsi.h | 19 +++ 4 files changed, 294 insertions(+) create mode 100644 drivers/gpu/drm/tiny/tiny-dsi.c diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 2b6414f0fa75..b62427b88dfe 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -28,6 +28,14 @@ config DRM_GM12U320 This is a KMS driver for projectors which use the GM12U320 chipset for video transfer over USB2/3, such as the Acer C120 mini projector. +config TINYDRM_DSI + tristate "DRM support for generic DBI/DSI display panels" + depends on DRM && DRM_MIPI_DSI + select DRM_MIPI_DBI + select DRM_KMS_CMA_HELPER + help + DRM driver for generic DBI/DSI display panels + config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" depends on DRM && SPI diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index 6ae4e9e5a35f..2bfee13347a5 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o obj-$(CONFIG_DRM_GM12U320) += gm12u320.o +obj-$(CONFIG_TINYDRM_DSI) += tiny-dsi.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o diff --git a/drivers/gpu/drm/tiny/tiny-dsi.c b/drivers/gpu/drm/tiny/tiny-dsi.c new file mode 100644 index ..b24d49836125 --- /dev/null +++ b/drivers/gpu/drm/tiny/tiny-dsi.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * TinyDRM driver for standard DSI/DBI panels + * + * Copyright 2020 Paul Cercueil + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct tiny_dsi { + struct drm_device drm; + struct drm_connector connector; + struct drm_simple_display_pipe pipe; + + struct mipi_dsi_device *dsi; + struct drm_panel *panel; +}; + +#define mipi_dcs_command(dsi, cmd, seq...) \ +({ \ + u8 d[] = { seq }; \ + mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \ +}) + +static inline struct tiny_dsi *drm_to_tiny_dsi(struct drm_device *drm) +{ + return container_of(drm, struct tiny_dsi, drm); +} + +static void tiny_dsi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) +{ + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem); + struct tiny_dsi *priv = drm_to_tiny_dsi(fb->dev); + unsigned int height = rect->y2 - rect->y1; + unsigned int width = rect->x2 - rect->x1; + bool fb_convert; + int idx, ret; + void *tr; + + if (!drm_dev_enter(fb->dev, &idx)) + return; + + DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); + + fb_convert = width != fb->width || height != fb->height + || fb->format->format == DRM_FORMAT_XRGB; + if (fb_convert) { + tr = kzalloc(width * height * 2, GFP_KERNEL); + + /* TODO: swap pixels if needed */ + ret = mipi_dbi_buf_copy(tr, fb, rect, false); + if (ret) + goto err_msg; + } else { + tr = cma_obj->vaddr; + } + + mipi_dcs_command(priv->dsi, MIPI_DCS_SET_COLUMN_ADDRESS, +(rect->x1 >> 8) & 0xff, rect->x1 & 0xff, +(rect->x2 >> 8) & 0xff, rect->x2 & 0xff); + mipi_dcs_command(priv->dsi, MIPI_DCS_SET_PAGE_ADDRESS, +(rect->y1 >> 8) & 0xff, rect->y1 & 0xff, +(rect->y2 >> 8) & 0xff, rect->y2 & 0xff); + + ret = mipi_dsi_dcs_write(priv->dsi, MIPI_DCS_WRITE_MEMORY_START, +tr, width * height * 2); +err_msg: + if (ret) + dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); + + if (fb_convert) + kfree(tr); + drm_dev_exit(idx); +} + +static void tiny_dsi_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + stru
Re: [PATCH 3/6] drm/bridge: Add SPI DBI host driver
Hi Sam, Le lun. 27 juil. 2020 à 22:31, Sam Ravnborg a écrit : Hi Paul. On Mon, Jul 27, 2020 at 06:46:10PM +0200, Paul Cercueil wrote: This driver will register a DBI host driver for panels connected over SPI. So this is actually a MIPI DBI host driver. I personally would love to have added mipi_ in the names - to make it all more explicit. But maybe that just because I get confused on all the acronyms. I can rename the driver and move it out of drm/bridge/, no problem. Some details in the following. Will try to find some more time so I can grasp the full picture. The following was just my low-level notes for now. Sam DBI types c1 and c3 are supported. C1 is a SPI protocol with 9 bits per word, with the data/command information in the 9th (MSB) bit. C3 is a SPI protocol with 8 bits per word, with the data/command information carried by a separate GPIO. We did not have any define to distingush between DBI_C1 and DBI_c3: +/* MIPI bus types */ +#define MIPI_DEVICE_TYPE_DSI BIT(0) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1 BIT(1) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2 BIT(2) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3 BIT(3) +#define MIPI_DEVICE_TYPE_DBI_M6800 BIT(4) +#define MIPI_DEVICE_TYPE_DBI_I8080 BIT(5) Is this on purpose? I understand the confusion. Here SPI_MODE1/3 actually mean SPI_C1/3. I will rename them. I had assumed the host should tell what it supports and the device should tell what it wanted. So if the host did not support DBI_C3 and device wants it - then we could give up early. Well that's exactly what's done here - just with badly named macros :) Signed-off-by: Paul Cercueil --- drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/dbi-spi.c | 261 +++ This is no bridge driver - so does not belong in the bridge directory. gpu/drm/drm_mipi_dbi_spi.c? 3 files changed, 270 insertions(+) create mode 100644 drivers/gpu/drm/bridge/dbi-spi.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c7f0dacfb57a..ed38366847c1 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -219,6 +219,14 @@ config DRM_TI_TPD12S015 Texas Instruments TPD12S015 HDMI level shifter and ESD protection driver. +config DRM_MIPI_DBI_SPI + tristate "SPI host support for MIPI DBI" + depends on OF && SPI + select DRM_MIPI_DSI + select DRM_MIPI_DBI + help +Driver to support DBI over SPI. + source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 7d7c123a95e4..c2c522c2774f 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o +obj-$(CONFIG_DRM_MIPI_DBI_SPI) += dbi-spi.o mipi_dbi_spi.o would be nice... obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o obj-y += analogix/ diff --git a/drivers/gpu/drm/bridge/dbi-spi.c b/drivers/gpu/drm/bridge/dbi-spi.c new file mode 100644 index ..1060b8f95fba --- /dev/null +++ b/drivers/gpu/drm/bridge/dbi-spi.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MIPI Display Bus Interface (DBI) SPI support + * + * Copyright 2016 Noralf Trønnes + * Copyright 2020 Paul Cercueil + */ + +#include +#include +#include + +#include +#include + +#include + +struct dbi_spi { + struct mipi_dsi_host host; It is very confusing that the mipi_dbi_spi driver uses a dsi_host. It clashes in my head - and then reviewing it not easy. From now on read all "mipi_dsi_*" as a MIPI DSI/DBI API. Renaming the API means a treewide patchset that touches many many files... + struct mipi_dsi_host_ops host_ops; const? + + struct spi_device *spi; + struct gpio_desc *dc; + struct mutex cmdlock; + + unsigned int current_bus_type; + + /** + * @tx_buf9: Buffer used for Option 1 9-bit conversion + */ + void *tx_buf9; + + /** + * @tx_buf9_len: Size of tx_buf9. + */ + size_t tx_buf9_len; +}; + +static inline struct dbi_spi *host_to_dbi_spi(struct mipi_dsi_host *host) +{ + return container_of(host, struct dbi_spi, host); +} + +static ssize_t dbi_spi1_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct dbi_spi *dbi = host_to_dbi_spi(host); + struct spi_device *spi = dbi->spi; + struct spi_transfer tr = { + .bits_per_word = 9, + }; + const u8 *src8 = msg->tx_buf; + struct spi_message m; + size_t m
[PATCH 2/2] drm/radeon: avoid a useless memset
Avoid a memset after a call to 'dma_alloc_coherent()'. This is useless since commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*") Signed-off-by: Christophe JAILLET --- drivers/gpu/drm/radeon/radeon_gart.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index b7ce254e5663..3808a753127b 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -85,7 +85,6 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) } #endif rdev->gart.ptr = ptr; - memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); return 0; } -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 4/4] xen: add helpers to allocate unpopulated memory
On Fri, Jul 24, 2020 at 12:36:33PM -0400, Boris Ostrovsky wrote: > On 7/24/20 10:34 AM, David Hildenbrand wrote: > > CCing Dan > > > > On 24.07.20 14:42, Roger Pau Monne wrote: > >> + > >> +#include > >> +#include > >> +#include > >> +#include > >> +#include > >> +#include > >> + > >> +#include > >> + > >> +#include > >> +#include > >> + > >> +static DEFINE_MUTEX(lock); > >> +static LIST_HEAD(list); > >> +static unsigned int count; > >> + > >> +static int fill(unsigned int nr_pages) > > > Less generic names? How about list_lock, pg_list, pg_count, > fill_pglist()? (But these are bad too, so maybe you can come up with > something better) OK, I have to admit I like using such short names when the code allows to, for example this code is so simple that it didn't seem to warrant using longer names. Will rename on next version. > >> +{ > >> + struct dev_pagemap *pgmap; > >> + void *vaddr; > >> + unsigned int i, alloc_pages = round_up(nr_pages, PAGES_PER_SECTION); > >> + int nid, ret; > >> + > >> + pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL); > >> + if (!pgmap) > >> + return -ENOMEM; > >> + > >> + pgmap->type = MEMORY_DEVICE_DEVDAX; > >> + pgmap->res.name = "XEN SCRATCH"; > > > Typically iomem resources only capitalize first letters. > > > >> + pgmap->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; > >> + > >> + ret = allocate_resource(&iomem_resource, &pgmap->res, > >> + alloc_pages * PAGE_SIZE, 0, -1, > >> + PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); > > > Are we not going to end up with a whole bunch of "Xen scratch" resource > ranges for each miss in the page list? Or do we expect them to get merged? PAGES_PER_SECTION is IMO big enough to prevent ending up with a lot of separated ranges. I think the value is 32 or 64MiB on x86, so while we are likely to end up with more than one resource added, I don't think it's going to be massive. > > >> + if (ret < 0) { > >> + pr_err("Cannot allocate new IOMEM resource\n"); > >> + kfree(pgmap); > >> + return ret; > >> + } > >> + > >> + nid = memory_add_physaddr_to_nid(pgmap->res.start); > > > Should we consider page range crossing node boundaries? I'm not sure whether this is possible (I would think allocate_resource should return a range from a single node), but then it would greatly complicate the code to perform the memremap_pages, as we would have to split the region into multiple dev_pagemap structs. FWIW the current code in the balloon driver does exactly the same (which doesn't mean it's correct, but that's where I got the logic from). > >> + > >> +#ifdef CONFIG_XEN_HAVE_PVMMU > >> + /* > >> + * We don't support PV MMU when Linux and Xen is using > >> + * different page granularity. > >> + */ > >> + BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE); > >> + > >> +/* > >> + * memremap will build page tables for the new memory so > >> + * the p2m must contain invalid entries so the correct > >> + * non-present PTEs will be written. > >> + * > >> + * If a failure occurs, the original (identity) p2m entries > >> + * are not restored since this region is now known not to > >> + * conflict with any devices. > >> + */ > >> + if (!xen_feature(XENFEAT_auto_translated_physmap)) { > >> + xen_pfn_t pfn = PFN_DOWN(pgmap->res.start); > >> + > >> + for (i = 0; i < alloc_pages; i++) { > >> + if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) { > >> + pr_warn("set_phys_to_machine() failed, no > >> memory added\n"); > >> + release_resource(&pgmap->res); > >> + kfree(pgmap); > >> + return -ENOMEM; > >> + } > >> +} > >> + } > >> +#endif > >> + > >> + vaddr = memremap_pages(pgmap, nid); > >> + if (IS_ERR(vaddr)) { > >> + pr_err("Cannot remap memory range\n"); > >> + release_resource(&pgmap->res); > >> + kfree(pgmap); > >> + return PTR_ERR(vaddr); > >> + } > >> + > >> + for (i = 0; i < alloc_pages; i++) { > >> + struct page *pg = virt_to_page(vaddr + PAGE_SIZE * i); > >> + > >> + BUG_ON(!virt_addr_valid(vaddr + PAGE_SIZE * i)); > >> + list_add(&pg->lru, &list); > >> + count++; > >> + } > >> + > >> + return 0; > >> +} > >> + > >> +/** > >> + * xen_alloc_unpopulated_pages - alloc unpopulated pages > >> + * @nr_pages: Number of pages > >> + * @pages: pages returned > >> + * @return 0 on success, error otherwise > >> + */ > >> +int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page > >> **pages) > >> +{ > >> + unsigned int i; > >> + int ret = 0; > >> + > >> + mutex_lock(&lock); > >> + if (count < nr_pages) { > >> + ret = fill(nr_pages); > > > (nr_pages - count) ? Yup, already fixed as Juergen also pointed it out. > >> +
Re: [PATCH 2/6] drm: dsi: Let host and device specify supported bus
Hi Laurent, Le lun. 27 juil. 2020 à 20:02, Laurent Pinchart a écrit : Hi Paul, Thank you for the patch. On Mon, Jul 27, 2020 at 06:46:09PM +0200, Paul Cercueil wrote: The current MIPI DSI framework can very well be used to support MIPI DBI panels. In order to add support for the various bus types supported by DBI, the DRM panel drivers should specify the bus type they will use, and the DSI host drivers should specify the bus types they are compatible with. The DSI host driver can then use the information provided by the DBI/DSI device driver, such as the bus type and the number of lanes, to configure its hardware properly. Signed-off-by: Paul Cercueil --- drivers/gpu/drm/drm_mipi_dsi.c | 9 + include/drm/drm_mipi_dsi.h | 12 Use the mipi_dsi_* API for DBI panels will be very confusing to say the least. Can we consider a global name refactoring to clarify all this ? I was thinking that this could be done when the code is cleaned up and drivers/gpu/drm/drm_mipi_dbi.c is removed. I'm scared of tree-wide patchsets. -Paul 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 5dd475e82995..11ef885de765 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -281,6 +281,9 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) { struct device_node *node; + if (WARN_ON_ONCE(!host->bus_types)) + host->bus_types = MIPI_DEVICE_TYPE_DSI; + for_each_available_child_of_node(host->dev->of_node, node) { /* skip nodes without reg property */ if (!of_find_property(node, "reg", NULL)) @@ -323,6 +326,12 @@ int mipi_dsi_attach(struct mipi_dsi_device *dsi) { const struct mipi_dsi_host_ops *ops = dsi->host->ops; + if (WARN_ON_ONCE(!dsi->bus_type)) + dsi->bus_type = MIPI_DEVICE_TYPE_DSI; + + if (!(dsi->bus_type & dsi->host->bus_types)) + return -EINVAL; + if (!ops || !ops->attach) return -ENOSYS; diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 360e6377e84b..65d2961fc054 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -63,6 +63,14 @@ struct mipi_dsi_packet { int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, const struct mipi_dsi_msg *msg); +/* MIPI bus types */ +#define MIPI_DEVICE_TYPE_DSI BIT(0) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1BIT(1) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2BIT(2) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3BIT(3) +#define MIPI_DEVICE_TYPE_DBI_M6800BIT(4) +#define MIPI_DEVICE_TYPE_DBI_I8080BIT(5) + /** * struct mipi_dsi_host_ops - DSI bus operations * @attach: attach DSI device to DSI host @@ -94,11 +102,13 @@ struct mipi_dsi_host_ops { * struct mipi_dsi_host - DSI host device * @dev: driver model device node for this DSI host * @ops: DSI host operations + * @bus_types: Bitmask of supported MIPI bus types * @list: list management */ struct mipi_dsi_host { struct device *dev; const struct mipi_dsi_host_ops *ops; + unsigned int bus_types; struct list_head list; }; @@ -162,6 +172,7 @@ struct mipi_dsi_device_info { * @host: DSI host for this peripheral * @dev: driver model device node for this peripheral * @name: DSI peripheral chip type + * @bus_type: MIPI bus type (MIPI_DEVICE_TYPE_DSI/...) * @channel: virtual channel assigned to the peripheral * @format: pixel format for video mode * @lanes: number of active data lanes @@ -178,6 +189,7 @@ struct mipi_dsi_device { struct device dev; char name[DSI_DEV_NAME_SIZE]; + unsigned int bus_type; unsigned int channel; unsigned int lanes; enum mipi_dsi_pixel_format format; -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 8/9] clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
>Fixes tag? Can I add it here? I supose I can. Fixes: f2a76a2955c0 (clk: qcom: Add Global Clock controller (GCC) driver for SDM660) ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/6] vga-switcheroo: initial dynamic mux switch support
Changes to allow vga-switcheroo to switch the mux while modesetting clients remain active. There is existing support for switching the mux without checking can_switch; however, this support also does not reprobe after the mux switch is complete. This patch series adds a new type of switch event which switches immediately while still calling client driver callbacks, and updates the i915 DRM-KMS driver to reprobe eDP outputs after switching the mux to an i915-driven GPU, and to avoid using eDP links (which i915 always assumes to be connected) while the mux is switched away. Daniel Dadap (6): vga-switcheroo: add new "immediate" switch event type vga-switcheroo: Add a way to test for the active client vga-switcheroo: notify clients of pending/completed switch events i915: implement vga-switcheroo reprobe() callback i915: fail atomic commit when muxed away i915: bail out of eDP link training while mux-switched away drivers/gpu/drm/i915/display/intel_display.c | 7 + .../drm/i915/display/intel_dp_link_training.c | 9 ++ drivers/gpu/drm/i915/i915_switcheroo.c| 27 +++- drivers/gpu/vga/vga_switcheroo.c | 153 ++ include/linux/vga_switcheroo.h| 20 +++ 5 files changed, 185 insertions(+), 31 deletions(-) -- 2.18.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 4/4] xen: add helpers to allocate unpopulated memory
To be used in order to create foreign mappings. This is based on the ZONE_DEVICE facility which is used by persistent memory devices in order to create struct pages and kernel virtual mappings for the IOMEM areas of such devices. Note that on kernels without support for ZONE_DEVICE Xen will fallback to use ballooned pages in order to create foreign mappings. The newly added helpers use the same parameters as the existing {alloc/free}_xenballooned_pages functions, which allows for in-place replacement of the callers. Once a memory region has been added to be used as scratch mapping space it will no longer be released, and pages returned are kept in a linked list. This allows to have a buffer of pages and prevents resorting to frequent additions and removals of regions. If enabled (because ZONE_DEVICE is supported) the usage of the new functionality untangles Xen balloon and RAM hotplug from the usage of unpopulated physical memory ranges to map foreign pages, which is the correct thing to do in order to avoid mappings of foreign pages depend on memory hotplug. Signed-off-by: Roger Pau Monné --- I've not added a new memory_type type and just used MEMORY_DEVICE_DEVDAX which seems to be what we want for such memory regions. I'm unsure whether abusing this type is fine, or if I should instead add a specific type, maybe MEMORY_DEVICE_GENERIC? I don't think we should be using a specific Xen type at all. --- Cc: Oleksandr Andrushchenko Cc: David Airlie Cc: Daniel Vetter Cc: Boris Ostrovsky Cc: Juergen Gross Cc: Stefano Stabellini Cc: Dan Carpenter Cc: Roger Pau Monne Cc: Wei Liu Cc: Yan Yankovskyi Cc: dri-devel@lists.freedesktop.org Cc: xen-de...@lists.xenproject.org Cc: linux...@kvack.org Cc: David Hildenbrand Cc: Michal Hocko Cc: Dan Williams --- Changes since v2: - Drop BUILD_BUG_ON regarding PVMMU page sizes. - Use a SPDX license identifier. - Call fill with only the minimum required number of pages. - Include xen.h header in xen_drm_front_gem.c. - Use less generic function names. - Exit early from the init function if not a PV guest. - Don't use all caps for region name. --- drivers/gpu/drm/xen/xen_drm_front_gem.c | 9 +- drivers/xen/Makefile| 1 + drivers/xen/balloon.c | 4 +- drivers/xen/grant-table.c | 4 +- drivers/xen/privcmd.c | 4 +- drivers/xen/unpopulated-alloc.c | 185 drivers/xen/xenbus/xenbus_client.c | 6 +- drivers/xen/xlate_mmu.c | 4 +- include/xen/xen.h | 9 ++ 9 files changed, 211 insertions(+), 15 deletions(-) create mode 100644 drivers/xen/unpopulated-alloc.c diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index f0b85e094111..270e1bd3e4da 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -18,6 +18,7 @@ #include #include +#include #include "xen_drm_front.h" #include "xen_drm_front_gem.h" @@ -99,8 +100,8 @@ static struct xen_gem_object *gem_create(struct drm_device *dev, size_t size) * allocate ballooned pages which will be used to map * grant references provided by the backend */ - ret = alloc_xenballooned_pages(xen_obj->num_pages, - xen_obj->pages); + ret = xen_alloc_unpopulated_pages(xen_obj->num_pages, + xen_obj->pages); if (ret < 0) { DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", xen_obj->num_pages, ret); @@ -152,8 +153,8 @@ void xen_drm_front_gem_free_object_unlocked(struct drm_gem_object *gem_obj) } else { if (xen_obj->pages) { if (xen_obj->be_alloc) { - free_xenballooned_pages(xen_obj->num_pages, - xen_obj->pages); + xen_free_unpopulated_pages(xen_obj->num_pages, + xen_obj->pages); gem_free_pages_array(xen_obj); } else { drm_gem_put_pages(&xen_obj->base, diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0d322f3d90cd..788a5d9c8ef0 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -42,3 +42,4 @@ xen-gntdev-$(CONFIG_XEN_GNTDEV_DMABUF)+= gntdev-dmabuf.o xen-gntalloc-y := gntalloc.o xen-privcmd-y := privcmd.o privcmd-buf.o obj-$(CONFIG_XEN_FRONT_PGDIR_SHBUF)+= xen-front-pgdir-shbuf.o +obj-$(CONFIG_ZONE_DEVICE) += unpopulated-alloc.o diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b1d8b028bf80..815ef10eb2ff 100644 --- a/dr
Re: divide error in fbcon_switch
syzbot suspects this issue was fixed by commit: commit ce684552a266cb1c7cc2f7e623f38567adec6653 Author: Tetsuo Handa Date: Sun Jul 12 11:10:12 2020 + vt: Reject zero-sized screen buffer size. bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=155549c490 start commit: 76bb8b05 Merge tag 'kbuild-v5.5' of git://git.kernel.org/p.. git tree: upstream kernel config: https://syzkaller.appspot.com/x/.config?x=dd226651cb0f364b dashboard link: https://syzkaller.appspot.com/bug?extid=13013adc4a234406c29e syz repro: https://syzkaller.appspot.com/x/repro.syz?x=17d69aeae0 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13fdcc2ae0 If the result looks correct, please mark the issue as fixed by replying with: #syz fix: vt: Reject zero-sized screen buffer size. For information about bisection process see: https://goo.gl/tpsmEJ#bisection ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/6] dt-bindings: display: Document NewVision NV3052C DT node
Add documentation for the Device Tree node for LCD panels based on the NewVision NV3052C controller. Signed-off-by: Paul Cercueil --- .../display/panel/newvision,nv3052c.yaml | 69 +++ 1 file changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml diff --git a/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml b/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml new file mode 100644 index ..751a28800fc2 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/newvision,nv3052c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NewVision NV3052C TFT LCD panel driver with SPI control bus + +maintainers: + - Paul Cercueil + +description: | + This is a driver for 320x240 TFT panels, accepting a variety of input + streams that get adapted and scaled to the panel. The panel output has + 960 TFT source driver pins and 240 TFT gate driver pins, VCOM, VCOML and + VCOMH outputs. + + The panel must obey the rules for a SPI slave device as specified in + spi/spi-controller.yaml + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: +items: + - enum: +- leadtek,ltk035c5444t-spi + + - const: newvision,nv3052c + + reg: +maxItems: 1 + + reset-gpios: true + port: true + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | +#include +spi { + #address-cells = <1>; + #size-cells = <0>; + + display@0 { +compatible = "leadtek,ltk035c5444t-spi", "newvision,nv3052c"; +reg = <0>; + +spi-max-frequency = <1500>; +spi-3wire; +reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>; +backlight = <&backlight>; +power-supply = <&vcc>; + +port { + panel_input: endpoint { + remote-endpoint = <&panel_output>; + }; +}; + }; +}; + +... -- 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 8/9] clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
Quoting Konrad Dybcio (2020-07-26 04:12:05) > Add missing halt_check, hwcg_reg and hwcg_bit properties. > These were likely omitted when porting the driver upstream. > > Signed-off-by: Konrad Dybcio > --- Applied to clk-next ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] clk: qcom: gcc-sdm660: Add missing modem reset
Quoting Konrad Dybcio (2020-07-26 04:11:58) > This will be required in order to support the > modem upstream. > > Signed-off-by: Konrad Dybcio > --- Applied to clk-next ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v5 1/5] drm/i915: Add enable/disable flip done and flip done handler
On Mon, Jul 27, 2020 at 2:27 PM Michel Dänzer wrote: > > On 2020-07-25 1:26 a.m., Paulo Zanoni wrote: > > Em seg, 2020-07-20 às 17:01 +0530, Karthik B S escreveu: > >> > >> diff --git a/drivers/gpu/drm/i915/i915_irq.c > >> b/drivers/gpu/drm/i915/i915_irq.c > >> index 1fa67700d8f4..95953b393941 100644 > >> --- a/drivers/gpu/drm/i915/i915_irq.c > >> +++ b/drivers/gpu/drm/i915/i915_irq.c > >> @@ -697,14 +697,24 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) > >> return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xff; > >> } > >> > >> +static u32 g4x_get_flip_counter(struct drm_crtc *crtc) > >> +{ > >> +struct drm_i915_private *dev_priv = to_i915(crtc->dev); > >> +enum pipe pipe = to_intel_crtc(crtc)->pipe; > >> + > >> +return I915_READ(PIPE_FLIPCOUNT_G4X(pipe)); > >> +} > >> + > >> u32 g4x_get_vblank_counter(struct drm_crtc *crtc) > >> { > >> struct drm_i915_private *dev_priv = to_i915(crtc->dev); > >> enum pipe pipe = to_intel_crtc(crtc)->pipe; > >> > >> +if (crtc->state->async_flip) > >> +return g4x_get_flip_counter(crtc); > >> + > >> return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); > > > > I don't understand the intention behind this, can you please clarify? > > This goes back to my reply of the cover letter. It seems that here > > we're going to alternate between two different counters in our vblank > > count. So if user space alternates between sometimes using async flips > > and sometimes using normal flip it's going to get some very weird > > deltas, isn't it? At least this is what I remember from when I played > > with these registers: FLIPCOUNT drifts away from FRMCOUNT when we start > > using async flips. > > This definitely looks wrong. The counter value returned by the > get_vblank_counter hook is supposed to increment when a vertical blank > period occurs; page flips are not supposed to affect this in any way. Also you just flat out can't access crtc->state from interrupt context. Anything you need in there needs to be protected by the right irq-type spin_lock, updates correctly synchronized against both the interrupt handler and atomic updates, and data copied over, not pointers. Otherwise just crash&burn. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Mon, Jul 27, 2020 at 11:11 PM Mazin Rezk wrote: > > On Monday, July 27, 2020 4:29 PM, Daniel Vetter wrote: > > > On Mon, Jul 27, 2020 at 9:28 PM Christian König > > wrote: > > > > > > Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: > > > > On 2020-07-27 9:39 a.m., Christian König wrote: > > > >> Am 27.07.20 um 07:40 schrieb Mazin Rezk: > > > >>> This patch fixes a race condition that causes a use-after-free during > > > >>> amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking > > > >>> commits > > > >>> are requested and the second one finishes before the first. > > > >>> Essentially, > > > >>> this bug occurs when the following sequence of events happens: > > > >>> > > > >>> 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > > > >>> deferred to the workqueue. > > > >>> > > > >>> 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > > > >>> deferred to the workqueue. > > > >>> > > > >>> 3. Commit #2 starts before commit #1, dm_state #1 is used in the > > > >>> commit_tail and commit #2 completes, freeing dm_state #1. > > > >>> > > > >>> 4. Commit #1 starts after commit #2 completes, uses the freed dm_state > > > >>> 1 and dereferences a freelist pointer while setting the context. > > > >> > > > >> Well I only have a one mile high view on this, but why don't you let > > > >> the work items execute in order? > > > >> > > > >> That would be better anyway cause this way we don't trigger a cache > > > >> line ping pong between CPUs. > > > >> > > > >> Christian. > > > > > > > > We use the DRM helpers for managing drm_atomic_commit_state and those > > > > helpers internally push non-blocking commit work into the system > > > > unbound work queue. > > > > > > Mhm, well if you send those helper atomic commits in the order A,B and > > > they execute it in the order B,A I would call that a bug :) > > > > The way it works is it pushes all commits into unbound work queue, but > > then forces serialization as needed. We do _not_ want e.g. updates on > > different CRTC to be serialized, that would result in lots of judder. > > And hw is funny enough that there's all kinds of dependencies. > > > > The way you force synchronization is by adding other CRTC state > > objects. So if DC is busted and can only handle a single update per > > work item, then I guess you always need all CRTC states and everything > > will be run in order. But that also totally kills modern multi-screen > > compositors. Xorg isn't modern, just in case that's not clear :-) > > > > Lucking at the code it seems like you indeed have only a single dm > > state, so yeah global sync is what you'll need as immediate fix, and > > then maybe fix up DM to not be quite so silly ... or at least only do > > the dm state stuff when really needed. > > > > We could also sprinkle the drm_crtc_commit structure around a bit > > (it's the glue that provides the synchronization across commits), but > > since your dm state is global just grabbing all crtc states > > unconditionally as part of that is probably best. > > > > > > While we could duplicate a copy of that code with nothing but the > > > > workqueue changed that isn't something I'd really like to maintain > > > > going forward. > > > > > > I'm not talking about duplicating the code, I'm talking about fixing the > > > helpers. I don't know that code well, but from the outside it sounds > > > like a bug there. > > > > > > And executing work items in the order they are submitted is trivial. > > > > > > Had anybody pinged Daniel or other people familiar with the helper code > > > about it? > > > > Yeah something is wrong here, and the fix looks horrible :-) > > > > Aside, I've also seen some recent discussion flare up about > > drm_atomic_state_get/put used to paper over some other use-after-free, > > but this time related to interrupt handlers. Maybe a few rules about > > that: > > - dont > > - especially not when it's interrupt handlers, because you can't call > > drm_atomic_state_put from interrupt handlers. > > > > Instead have an spin_lock_irq to protect the shared date with your > > interrupt handler, and _copy_ the date over. This is e.g. what > > drm_crtc_arm_vblank_event does. > > Nicholas wrote a patch that attempted to resolve the issue by adding every > CRTC into the commit to use use the stall checks. [1] While this forces > synchronisation on commits, it's kind of a hacky method that may take a > toll on performance. > > Is it possible to have a DRM helper that forces synchronisation on some > commits without having to add every CRTC into the commit? > > Also, is synchronisation really necessary for fast updates in amdgpu? > I'll admit, the idea of eliminating the use-after-free bug by eliminating > the use entirely doesn't seem ideal; but is forcing synchronisation on > these updates that much better? Well clearing the dc_state pointer here and then allocating another one in atomic_commit_tail also looks fishy. The proper fix is probably a lot mo
[PATCH] drm/amdgpu/dc: Stop dma_resv_lock inversion in commit_tail
Trying to grab dma_resv_lock while in commit_tail before we've done all the code that leads to the eventual signalling of the vblank event (which can be a dma_fence) is deadlock-y. Don't do that. Here the solution is easy because just grabbing locks to read something races anyway. We don't need to bother, READ_ONCE is equivalent. And avoids the locking issue. v2: Also take into account tmz_surface boolean, plus just delete the old code. Cc: linux-me...@vger.kernel.org Cc: linaro-mm-...@lists.linaro.org Cc: linux-r...@vger.kernel.org Cc: amd-...@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Cc: Chris Wilson Cc: Maarten Lankhorst Cc: Christian König Signed-off-by: Daniel Vetter --- DC-folks, I think this split out patch from my series here https://lore.kernel.org/dri-devel/20200707201229.472834-1-daniel.vet...@ffwll.ch/ should be ready for review/merging. I fixed it up a bit so that it's not just a gross hack :-) Cheers, Daniel --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 21ec64fe5527..a20b62b1f2ef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6959,20 +6959,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("Waiting for fences timed out!"); /* -* TODO This might fail and hence better not used, wait -* explicitly on fences instead -* and in general should be called for -* blocking commit to as per framework helpers +* We cannot reserve buffers here, which means the normal flag +* access functions don't work. Paper over this with READ_ONCE, +* but maybe the flags are invariant enough that not even that +* would be needed. */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) - DRM_ERROR("failed to reserve buffer before flip\n"); - - amdgpu_bo_get_tiling_flags(abo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(abo); - - amdgpu_bo_unreserve(abo); + tiling_flags = READ_ONCE(abo->tiling_flags); + tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; fill_dc_plane_info_and_addr( dm->adev, new_plane_state, tiling_flags, -- 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/3] drm: Restore driver.preclose() for all to use
Hi [This is an automated email] This commit has been processed because it contains a -stable tag. The stable tag indicates that it's relevant for the following trees: 4.12+ The bot has tested the following trees: v5.7.10, v5.4.53, v4.19.134, v4.14.189. v5.7.10: Build OK! v5.4.53: Build OK! v4.19.134: Build OK! v4.14.189: Failed to apply! Possible dependencies: 112ed2d31a46 ("drm/i915: Move GraphicsTechnology files under gt/") 1572042a4ab2 ("drm: provide management functions for drm_file") 7a2c65dd32b1 ("drm: Release filp before global lock") 7e13ad896484 ("drm: Avoid drm_global_mutex for simple inc/dec of dev->open_count") b46a33e271ed ("drm/i915/pmu: Expose a PMU interface for perf queries") c2400ec3b6d1 ("drm/i915: add Makefile magic for testing headers are self-contained") cc662126b413 ("drm/i915: Introduce DRM_I915_GEM_MMAP_OFFSET") e7af3116836f ("drm/i915: Introduce a preempt context") f0e4a0639752 ("drm/i915: Move GEM domain management to its own file") NOTE: The patch will not be queued to stable trees until it is upstream. How should we proceed with this patch? -- Thanks Sasha ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/3] drm/i915/gem: Serialise debugfs i915_gem_objects with ctx->mutex
Hi [This is an automated email] This commit has been processed because it contains a -stable tag. The stable tag indicates that it's relevant for the following trees: all The bot has tested the following trees: v5.7.10, v5.4.53, v4.19.134, v4.14.189, v4.9.231, v4.4.231. v5.7.10: Build OK! v5.4.53: Failed to apply! Possible dependencies: 061489c65ff5 ("drm/i915/dsb: single register write function for DSB.") 11988e393813 ("drm/i915/execlists: Try rearranging breadcrumb flush") 2850748ef876 ("drm/i915: Pull i915_vma_pin under the vm->mutex") 5a90606df7cb ("drm/i915: Replace obj->pin_global with obj->frontbuffer") 67f3b58f3bac ("drm/i915/dsb: DSB context creation.") 8a9a982767b7 ("drm/i915: use a separate context for gpu relocs") a4e7ccdac38e ("drm/i915: Move context management under GEM") b27a96ad72fd ("drm/i915/dsb: Indexed register write function for DSB.") bb120e1171a9 ("drm/i915: Show the logical context ring state on dumping") c210e85b8f33 ("drm/i915/tgl: Extend MI_SEMAPHORE_WAIT") d19d71fc2b15 ("drm/i915: Mark i915_request.timeline as a volatile, rcu pointer") e8f6b4952ec5 ("drm/i915/execlists: Flush the post-sync breadcrumb write harder") v4.19.134: Failed to apply! Possible dependencies: 0258404f9d38 ("drm/i915: start moving runtime device info to a separate struct") 026844460743 ("drm/i915: Remove intel_context.active_link") 07d805721938 ("drm/i915: Introduce intel_runtime_pm_disable to pair intel_runtime_pm_enable") 13f1bfd3b332 ("drm/i915: Make object/vma allocation caches global") 1c71bc565cdb ("drm/i915/perf: simplify configure all context function") 2cc8376fd350 ("drm/i915: rename dev_priv info to __info to avoid usage") 2cd9a689e97b ("drm/i915: Refactor intel_display_set_init_power() logic") 37d7c9cc2eb6 ("drm/i915: Check engine->default_state mapping on module load") 55ac5a1614f9 ("drm/i915: Attach the pci match data to the device upon creation") 666424abfb86 ("drm/i915/execlists: Use coherent writes into the context image") 6dfc4a8f134f ("drm/i915: Verify power domains after enabling them") 722f3de39e03 ("i915/oa: Simplify updating contexts") 900ccf30f9e1 ("drm/i915: Only force GGTT coherency w/a on required chipsets") c4d52feb2c46 ("drm/i915: Move over to intel_context_lookup()") f6e8aa387171 ("drm/i915: Report the number of closed vma held by each context in debugfs") fa9f668141f4 ("drm/i915: Export intel_context_instance()") v4.14.189: Failed to apply! Possible dependencies: 3bd4073524fa ("drm/i915: Consolidate get_fence with pin_fence") 465c403cb508 ("drm/i915: introduce simple gemfs") 66df1014efba ("drm/i915: Keep a small stash of preallocated WC pages") 67b48040255b ("drm/i915: Assert that the handle->vma lut is empty on object close") 73ebd503034c ("drm/i915: make mappable struct resource centric") 7789422665f5 ("drm/i915: make dsm struct resource centric") 82ad6443a55e ("drm/i915/gtt: Rename i915_hw_ppgtt base member") 969b0950a188 ("drm/i915: Add interface to reserve fence registers for vGPU") a65adaf8a834 ("drm/i915: Track user GTT faulting per-vma") b4563f595ed4 ("drm/i915: Pin fence for iomap") e91ef99b9543 ("drm/i915/selftests: Remember to create the fake preempt context") f6e8aa387171 ("drm/i915: Report the number of closed vma held by each context in debugfs") f773568b6ff8 ("drm/i915: nuke the duplicated stolen discovery") v4.9.231: Failed to apply! Possible dependencies: 0e70447605f4 ("drm/i915: Move common code out of i915_gpu_error.c") 1b36595ffb35 ("drm/i915: Show RING registers through debugfs") 28a60dee2ce6 ("drm/i915/gvt: vGPU HW resource management") 3b3f1650b1ca ("drm/i915: Allocate intel_engine_cs structure only for the enabled engines") 82ad6443a55e ("drm/i915/gtt: Rename i915_hw_ppgtt base member") 85fd4f58d7ef ("drm/i915: Mark all non-vma being inserted into the address spaces") 9c870d03674f ("drm/i915: Use RPM as the barrier for controlling user mmap access") bb6dc8d96b68 ("drm/i915: Implement pread without struct-mutex") d636951ec01b ("drm/i915: Cleanup instdone collection") e007b19d7ba7 ("drm/i915: Use the MRU stack search after evicting") f6e8aa387171 ("drm/i915: Report the number of closed vma held by each context in debugfs") f9e613728090 ("drm/i915: Try to print INSTDONE bits for all slice/subslice") v4.4.231: Failed to apply! Possible dependencies: 1b683729e7ac ("drm/i915: Remove redundant check in i915_gem_obj_to_vma") 1c7f4bca5a6f ("drm/i915: Rename vma->*_list to *_link for consistency") 3272db53136f ("drm/i915: Combine all i915_vma bitfields into a single set of flags") 596c5923197b ("drm/i915: Reduce the pointer dance of i915_is_ggtt()") c1a415e261aa ("drm/i915: Disable shrinker for non-swapped backed objects") d0710abbcd88 ("drm/i915: Set the map-and-fenceable flag for preallocated objects")
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Mon, Jul 27, 2020 at 10:29 PM Daniel Vetter wrote: > > On Mon, Jul 27, 2020 at 9:28 PM Christian König > wrote: > > > > Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: > > > On 2020-07-27 9:39 a.m., Christian König wrote: > > >> Am 27.07.20 um 07:40 schrieb Mazin Rezk: > > >>> This patch fixes a race condition that causes a use-after-free during > > >>> amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking > > >>> commits > > >>> are requested and the second one finishes before the first. > > >>> Essentially, > > >>> this bug occurs when the following sequence of events happens: > > >>> > > >>> 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > > >>> deferred to the workqueue. > > >>> > > >>> 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > > >>> deferred to the workqueue. > > >>> > > >>> 3. Commit #2 starts before commit #1, dm_state #1 is used in the > > >>> commit_tail and commit #2 completes, freeing dm_state #1. > > >>> > > >>> 4. Commit #1 starts after commit #2 completes, uses the freed dm_state > > >>> 1 and dereferences a freelist pointer while setting the context. > > >> > > >> Well I only have a one mile high view on this, but why don't you let > > >> the work items execute in order? > > >> > > >> That would be better anyway cause this way we don't trigger a cache > > >> line ping pong between CPUs. > > >> > > >> Christian. > > > > > > We use the DRM helpers for managing drm_atomic_commit_state and those > > > helpers internally push non-blocking commit work into the system > > > unbound work queue. > > > > Mhm, well if you send those helper atomic commits in the order A,B and > > they execute it in the order B,A I would call that a bug :) > > The way it works is it pushes all commits into unbound work queue, but > then forces serialization as needed. We do _not_ want e.g. updates on > different CRTC to be serialized, that would result in lots of judder. > And hw is funny enough that there's all kinds of dependencies. > > The way you force synchronization is by adding other CRTC state > objects. So if DC is busted and can only handle a single update per > work item, then I guess you always need all CRTC states and everything > will be run in order. But that also totally kills modern multi-screen > compositors. Xorg isn't modern, just in case that's not clear :-) > > Lucking at the code it seems like you indeed have only a single dm > state, so yeah global sync is what you'll need as immediate fix, and > then maybe fix up DM to not be quite so silly ... or at least only do > the dm state stuff when really needed. Just looked a bit more at this struct dc_state, and that looks a lot like an atomic side-wagon. I don't think that works as a private state, this should probably be embedded into a subclass of drm_atomic_state. And probably a lot of these pointers moved to other places I think, or I'm not entirely clear on what exactly this stuff is needed for ... dc_state is also refcounted, which is definitely rather funny for a state structure. Feels like this entire thing (how the overall dc state machinery is glued into atomic) isn't quite thought thru just yet :-/ -Daniel > We could also sprinkle the drm_crtc_commit structure around a bit > (it's the glue that provides the synchronization across commits), but > since your dm state is global just grabbing all crtc states > unconditionally as part of that is probably best. > > > > While we could duplicate a copy of that code with nothing but the > > > workqueue changed that isn't something I'd really like to maintain > > > going forward. > > > > I'm not talking about duplicating the code, I'm talking about fixing the > > helpers. I don't know that code well, but from the outside it sounds > > like a bug there. > > > > And executing work items in the order they are submitted is trivial. > > > > Had anybody pinged Daniel or other people familiar with the helper code > > about it? > > Yeah something is wrong here, and the fix looks horrible :-) > > Aside, I've also seen some recent discussion flare up about > drm_atomic_state_get/put used to paper over some other use-after-free, > but this time related to interrupt handlers. Maybe a few rules about > that: > - dont > - especially not when it's interrupt handlers, because you can't call > drm_atomic_state_put from interrupt handlers. > > Instead have an spin_lock_irq to protect the shared date with your > interrupt handler, and _copy_ the date over. This is e.g. what > drm_crtc_arm_vblank_event does. > > Cheers, Daniel > > > > > Regards, > > Christian. > > > > > > > > Regards, > > > Nicholas Kazlauskas > > > > > >> > > >>> > > >>> Since this bug has only been spotted with fast commits, this patch > > >>> fixes > > >>> the bug by clearing the dm_state instead of using the old dc_state for > > >>> fast updates. In addition, since dm_state is only used for its dc_state > > >>> and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is >
Re: [PATCH v3 1/2] dt-bindings: display: panel: Add bindings for Tianma nt36672a panel
On Mon, 27 Jul 2020 13:13:47 +0530, Sumit Semwal wrote: > The nt36672a panel from Tianma is a FHD+ panel with a resolution of > 1080x2246 and 6.18 inches size. It is found in some of the Poco F1 > phones. > > Signed-off-by: Sumit Semwal > > --- > v2: remove ports node, making port@0 directly under panel@0 node. > v3: updated to replace port@0 to just 'port'. > --- > .../display/panel/tianma,nt36672a.yaml| 95 +++ > 1 file changed, 95 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/tianma,nt36672a.yaml > Reviewed-by: Rob Herring ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/6] drm/bridge: Add SPI DBI host driver
Hi Paul. On Mon, Jul 27, 2020 at 06:46:10PM +0200, Paul Cercueil wrote: > This driver will register a DBI host driver for panels connected over > SPI. So this is actually a MIPI DBI host driver. I personally would love to have added mipi_ in the names - to make it all more explicit. But maybe that just because I get confused on all the acronyms. Some details in the following. Will try to find some more time so I can grasp the full picture. The following was just my low-level notes for now. Sam > > DBI types c1 and c3 are supported. C1 is a SPI protocol with 9 bits per > word, with the data/command information in the 9th (MSB) bit. C3 is a > SPI protocol with 8 bits per word, with the data/command information > carried by a separate GPIO. We did not have any define to distingush between DBI_C1 and DBI_c3: +/* MIPI bus types */ +#define MIPI_DEVICE_TYPE_DSI BIT(0) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1 BIT(1) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2 BIT(2) +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3 BIT(3) +#define MIPI_DEVICE_TYPE_DBI_M6800 BIT(4) +#define MIPI_DEVICE_TYPE_DBI_I8080 BIT(5) Is this on purpose? I had assumed the host should tell what it supports and the device should tell what it wanted. So if the host did not support DBI_C3 and device wants it - then we could give up early. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/bridge/Kconfig | 8 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/dbi-spi.c | 261 +++ This is no bridge driver - so does not belong in the bridge directory. gpu/drm/drm_mipi_dbi_spi.c? > 3 files changed, 270 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/dbi-spi.c > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index c7f0dacfb57a..ed38366847c1 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -219,6 +219,14 @@ config DRM_TI_TPD12S015 > Texas Instruments TPD12S015 HDMI level shifter and ESD protection > driver. > > +config DRM_MIPI_DBI_SPI > + tristate "SPI host support for MIPI DBI" > + depends on OF && SPI > + select DRM_MIPI_DSI > + select DRM_MIPI_DBI > + help > + Driver to support DBI over SPI. > + > source "drivers/gpu/drm/bridge/analogix/Kconfig" > > source "drivers/gpu/drm/bridge/adv7511/Kconfig" > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index 7d7c123a95e4..c2c522c2774f 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ > obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o > obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o > obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o > +obj-$(CONFIG_DRM_MIPI_DBI_SPI) += dbi-spi.o mipi_dbi_spi.o would be nice... > obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o > > obj-y += analogix/ > diff --git a/drivers/gpu/drm/bridge/dbi-spi.c > b/drivers/gpu/drm/bridge/dbi-spi.c > new file mode 100644 > index ..1060b8f95fba > --- /dev/null > +++ b/drivers/gpu/drm/bridge/dbi-spi.c > @@ -0,0 +1,261 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * MIPI Display Bus Interface (DBI) SPI support > + * > + * Copyright 2016 Noralf Trønnes > + * Copyright 2020 Paul Cercueil > + */ > + > +#include > +#include > +#include > + > +#include > +#include > + > +#include > + > +struct dbi_spi { > + struct mipi_dsi_host host; It is very confusing that the mipi_dbi_spi driver uses a dsi_host. It clashes in my head - and then reviewing it not easy. > + struct mipi_dsi_host_ops host_ops; const? > + > + struct spi_device *spi; > + struct gpio_desc *dc; > + struct mutex cmdlock; > + > + unsigned int current_bus_type; > + > + /** > + * @tx_buf9: Buffer used for Option 1 9-bit conversion > + */ > + void *tx_buf9; > + > + /** > + * @tx_buf9_len: Size of tx_buf9. > + */ > + size_t tx_buf9_len; > +}; > + > +static inline struct dbi_spi *host_to_dbi_spi(struct mipi_dsi_host *host) > +{ > + return container_of(host, struct dbi_spi, host); > +} > + > +static ssize_t dbi_spi1_transfer(struct mipi_dsi_host *host, > + const struct mipi_dsi_msg *msg) > +{ > + struct dbi_spi *dbi = host_to_dbi_spi(host); > + struct spi_device *spi = dbi->spi; > + struct spi_transfer tr = { > + .bits_per_word = 9, > + }; > + const u8 *src8 = msg->tx_buf; > + struct spi_message m; > + size_t max_chunk, chunk; > + size_t len = msg->tx_len; > + bool cmd_byte = true; > + unsigned int i; > + u16 *dst16; > + int ret; > + > + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); > + dst16 = dbi->tx_buf9; > + > + max_chunk = min(dbi->tx_buf9_len / 2, len); Hmm, this looks not right. We limit the max_chunk to 8K here. We learned the other day th
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
On Mon, Jul 27, 2020 at 9:28 PM Christian König wrote: > > Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: > > On 2020-07-27 9:39 a.m., Christian König wrote: > >> Am 27.07.20 um 07:40 schrieb Mazin Rezk: > >>> This patch fixes a race condition that causes a use-after-free during > >>> amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking > >>> commits > >>> are requested and the second one finishes before the first. > >>> Essentially, > >>> this bug occurs when the following sequence of events happens: > >>> > >>> 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is > >>> deferred to the workqueue. > >>> > >>> 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is > >>> deferred to the workqueue. > >>> > >>> 3. Commit #2 starts before commit #1, dm_state #1 is used in the > >>> commit_tail and commit #2 completes, freeing dm_state #1. > >>> > >>> 4. Commit #1 starts after commit #2 completes, uses the freed dm_state > >>> 1 and dereferences a freelist pointer while setting the context. > >> > >> Well I only have a one mile high view on this, but why don't you let > >> the work items execute in order? > >> > >> That would be better anyway cause this way we don't trigger a cache > >> line ping pong between CPUs. > >> > >> Christian. > > > > We use the DRM helpers for managing drm_atomic_commit_state and those > > helpers internally push non-blocking commit work into the system > > unbound work queue. > > Mhm, well if you send those helper atomic commits in the order A,B and > they execute it in the order B,A I would call that a bug :) The way it works is it pushes all commits into unbound work queue, but then forces serialization as needed. We do _not_ want e.g. updates on different CRTC to be serialized, that would result in lots of judder. And hw is funny enough that there's all kinds of dependencies. The way you force synchronization is by adding other CRTC state objects. So if DC is busted and can only handle a single update per work item, then I guess you always need all CRTC states and everything will be run in order. But that also totally kills modern multi-screen compositors. Xorg isn't modern, just in case that's not clear :-) Lucking at the code it seems like you indeed have only a single dm state, so yeah global sync is what you'll need as immediate fix, and then maybe fix up DM to not be quite so silly ... or at least only do the dm state stuff when really needed. We could also sprinkle the drm_crtc_commit structure around a bit (it's the glue that provides the synchronization across commits), but since your dm state is global just grabbing all crtc states unconditionally as part of that is probably best. > > While we could duplicate a copy of that code with nothing but the > > workqueue changed that isn't something I'd really like to maintain > > going forward. > > I'm not talking about duplicating the code, I'm talking about fixing the > helpers. I don't know that code well, but from the outside it sounds > like a bug there. > > And executing work items in the order they are submitted is trivial. > > Had anybody pinged Daniel or other people familiar with the helper code > about it? Yeah something is wrong here, and the fix looks horrible :-) Aside, I've also seen some recent discussion flare up about drm_atomic_state_get/put used to paper over some other use-after-free, but this time related to interrupt handlers. Maybe a few rules about that: - dont - especially not when it's interrupt handlers, because you can't call drm_atomic_state_put from interrupt handlers. Instead have an spin_lock_irq to protect the shared date with your interrupt handler, and _copy_ the date over. This is e.g. what drm_crtc_arm_vblank_event does. Cheers, Daniel > > Regards, > Christian. > > > > > Regards, > > Nicholas Kazlauskas > > > >> > >>> > >>> Since this bug has only been spotted with fast commits, this patch > >>> fixes > >>> the bug by clearing the dm_state instead of using the old dc_state for > >>> fast updates. In addition, since dm_state is only used for its dc_state > >>> and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is > >>> found, > >>> removing the dm_state should not have any consequences in fast updates. > >>> > >>> This use-after-free bug has existed for a while now, but only caused a > >>> noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: > >>> relocate > >>> freelist pointer to middle of object") moving the freelist pointer from > >>> dm_state->base (which was unused) to dm_state->context (which is > >>> dereferenced). > >>> > >>> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 > >>> Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state > >>> for fast updates") > >>> Reported-by: Duncan <1i5t5.dun...@cox.net> > >>> Signed-off-by: Mazin Rezk > >>> --- > >>> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 > >>> ++- > >>> 1 file changed, 27 insertions(+), 9 deletions
Re: [PATCH V2] drm: hold gem reference until object is no longer accessed
On Mon, Jul 27, 2020 at 09:55:07PM +0200, Greg KH wrote: > On Mon, Jul 20, 2020 at 06:30:50PM -0400, Steve Cohen wrote: > > A use-after-free in drm_gem_open_ioctl can happen if the > > GEM object handle is closed between the idr lookup and > > retrieving the size from said object since a local reference > > is not being held at that point. Hold the local reference > > while the object can still be accessed to fix this and > > plug the potential security hole. > > > > Signed-off-by: Steve Cohen > > --- > > drivers/gpu/drm/drm_gem.c | 10 -- > > 1 file changed, 4 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > > index 7bf628e..ee2058a 100644 > > --- a/drivers/gpu/drm/drm_gem.c > > +++ b/drivers/gpu/drm/drm_gem.c > > @@ -871,9 +871,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, > > * @file_priv: drm file-private structure > > * > > * Open an object using the global name, returning a handle and the size. > > - * > > - * This handle (of course) holds a reference to the object, so the object > > - * will not go away until the handle is deleted. > > */ > > int > > drm_gem_open_ioctl(struct drm_device *dev, void *data, > > @@ -898,14 +895,15 @@ 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_put_unlocked(obj); > > if (ret) > > - return ret; > > + goto err; > > > > args->handle = handle; > > args->size = obj->size; > > > > - return 0; > > +err: > > + drm_gem_object_put_unlocked(obj); > > + return ret; > > } > > > > /** > > As this seems to fix an important issue, any reason it wasn't cc: stable > on it so that it gets backported properly? > > How about a "Fixes:" tag so that we know what commit id it fixes so we > know how far back to backport things? > > And a hint to the maintainers that "this is an issue that needs to get > into 5.8-final, it shouldn't wait around longer please" would have also > been nice to see :) > > And what chagned from v1, aren't you supposed to list that somewhere in > the changelog or below the --- line (never remember what DRM drivers > want here...) > > Care to send a v3? Don't worry, I'm pushing this to drm-misc-fixes now, should still make it to 5.8. Plus cc: stable. I didn't bother with Fixes: since I think the bug is rather old. Also, worst case you leak 32bit of some kernel memory that got reused already (but yeah I know that's often enough to get the foot in somewhere nasty and crack the door open). I think it fell through cracks because Sam said he'll apply, guess that didn't happen. Also yes a changelog, somewhere, for next time around. -Daniel > > thanks, > > greg k-h -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 1/3] drm: Restore driver.preclose() for all to use
> -Original Message- > From: Daniel Vetter > Sent: Monday, July 27, 2020 12:33 PM > To: Chris Wilson ; Dave Airlie > Cc: intel-gfx ; stable > ; Gustavo Padovan > ; Tang, CQ ; dri- > devel ; Vetter, Daniel > > Subject: Re: [PATCH 1/3] drm: Restore driver.preclose() for all to use > > On Thu, Jul 23, 2020 at 7:21 PM Chris Wilson > wrote: > > > > An unfortunate sequence of events, but it turns out there is a valid > > usecase for being able to free/decouple the driver objects before they > > are freed by the DRM core. In particular, if we have a pointer into a > > drm core object from inside a driver object, that pointer needs to be > > nerfed *before* it is freed so that concurrent access (e.g. debugfs) > > does not following the dangling pointer. > > > > The legacy marker was adding in the code movement from drp_fops.c to > > drm_file.c > > I might fumble a lot, but not this one: > > commit 45c3d213a400c952ab7119f394c5293bb6877e6b > Author: Daniel Vetter > Date: Mon May 8 10:26:33 2017 +0200 > > drm: Nerf the preclose callback for modern drivers > > Also looking at the debugfs hook that has some rather adventurous stuff > going on I think, feels a bit like a kitchensink with batteries included. If > that's > really all needed I'd say iterate the contexts by first going over files, > then the > ctx (which arent shared anyway) and the problem should also be gone. Debugfs code can jump in after drm_gem_release() (where file->object_idr is destroyed), but before postclose(). At this window, everything is fine for debugfs context accessing except the file->object_idr. --CQ > -Daniel > > > References: 9acdac68bcdc ("drm: rename drm_fops.c to drm_file.c") > > Signed-off-by: Chris Wilson > > Cc: Daniel Vetter > > Cc: Gustavo Padovan > > Cc: CQ Tang > > Cc: # v4.12+ > > --- > > drivers/gpu/drm/drm_file.c | 3 +-- > > 1 file changed, 1 insertion(+), 2 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c > > index 0ac4566ae3f4..7b4258d6f7cc 100644 > > --- a/drivers/gpu/drm/drm_file.c > > +++ b/drivers/gpu/drm/drm_file.c > > @@ -258,8 +258,7 @@ void drm_file_free(struct drm_file *file) > > (long)old_encode_dev(file->minor->kdev->devt), > > atomic_read(&dev->open_count)); > > > > - if (drm_core_check_feature(dev, DRIVER_LEGACY) && > > - dev->driver->preclose) > > + if (dev->driver->preclose) > > dev->driver->preclose(dev, file); > > > > if (drm_core_check_feature(dev, DRIVER_LEGACY)) > > -- > > 2.20.1 > > > > ___ > > dri-devel mailing list > > dri-devel@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/dri-devel > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/6] drm: dsi: Let host and device specify supported bus
Hi Paul. On Mon, Jul 27, 2020 at 06:46:09PM +0200, Paul Cercueil wrote: > The current MIPI DSI framework can very well be used to support MIPI DBI > panels. In order to add support for the various bus types supported by > DBI, the DRM panel drivers should specify the bus type they will use, > and the DSI host drivers should specify the bus types they are > compatible with. > > The DSI host driver can then use the information provided by the DBI/DSI > device driver, such as the bus type and the number of lanes, to > configure its hardware properly. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/drm_mipi_dsi.c | 9 + > include/drm/drm_mipi_dsi.h | 12 > 2 files changed, 21 insertions(+) > > diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c > index 5dd475e82995..11ef885de765 100644 > --- a/drivers/gpu/drm/drm_mipi_dsi.c > +++ b/drivers/gpu/drm/drm_mipi_dsi.c > @@ -281,6 +281,9 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) > { > struct device_node *node; > > + if (WARN_ON_ONCE(!host->bus_types)) > + host->bus_types = MIPI_DEVICE_TYPE_DSI; > + So all 14 users need to specify bus_types. Seems doable. > for_each_available_child_of_node(host->dev->of_node, node) { > /* skip nodes without reg property */ > if (!of_find_property(node, "reg", NULL)) > @@ -323,6 +326,12 @@ int mipi_dsi_attach(struct mipi_dsi_device *dsi) > { > const struct mipi_dsi_host_ops *ops = dsi->host->ops; > > + if (WARN_ON_ONCE(!dsi->bus_type)) > + dsi->bus_type = MIPI_DEVICE_TYPE_DSI; We have ~50 users of mipi_dsi_attach() - doable. But a bit more work. > + > + if (!(dsi->bus_type & dsi->host->bus_types)) > + return -EINVAL; > + > if (!ops || !ops->attach) > return -ENOSYS; > > diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h > index 360e6377e84b..65d2961fc054 100644 > --- a/include/drm/drm_mipi_dsi.h > +++ b/include/drm/drm_mipi_dsi.h > @@ -63,6 +63,14 @@ struct mipi_dsi_packet { > int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, > const struct mipi_dsi_msg *msg); > > +/* MIPI bus types */ If you define this as an enum then kernel-doc syntax will be picked up. See for example: enum drm_driver_feature > +#define MIPI_DEVICE_TYPE_DSI BIT(0) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1 BIT(1) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2 BIT(2) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3 BIT(3) > +#define MIPI_DEVICE_TYPE_DBI_M6800 BIT(4) > +#define MIPI_DEVICE_TYPE_DBI_I8080 BIT(5) > + > /** > * struct mipi_dsi_host_ops - DSI bus operations > * @attach: attach DSI device to DSI host > @@ -94,11 +102,13 @@ struct mipi_dsi_host_ops { > * struct mipi_dsi_host - DSI host device > * @dev: driver model device node for this DSI host > * @ops: DSI host operations > + * @bus_types: Bitmask of supported MIPI bus types Please add some kind of reference to MIPI_DEVICE_TYPE_* - so the reader knows for sure this is the bits used here. > * @list: list management > */ > struct mipi_dsi_host { > struct device *dev; > const struct mipi_dsi_host_ops *ops; > + unsigned int bus_types; Use u32. Shorter and we know this is 32 bits wide. > struct list_head list; > }; > > @@ -162,6 +172,7 @@ struct mipi_dsi_device_info { > * @host: DSI host for this peripheral > * @dev: driver model device node for this peripheral > * @name: DSI peripheral chip type > + * @bus_type: MIPI bus type (MIPI_DEVICE_TYPE_DSI/...) > * @channel: virtual channel assigned to the peripheral > * @format: pixel format for video mode > * @lanes: number of active data lanes > @@ -178,6 +189,7 @@ struct mipi_dsi_device { > struct device dev; > > char name[DSI_DEV_NAME_SIZE]; > + unsigned int bus_type; Use u32. > unsigned int channel; > unsigned int lanes; > enum mipi_dsi_pixel_format format; > -- > 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH V2] drm: hold gem reference until object is no longer accessed
On Mon, Jul 20, 2020 at 06:30:50PM -0400, Steve Cohen wrote: > A use-after-free in drm_gem_open_ioctl can happen if the > GEM object handle is closed between the idr lookup and > retrieving the size from said object since a local reference > is not being held at that point. Hold the local reference > while the object can still be accessed to fix this and > plug the potential security hole. > > Signed-off-by: Steve Cohen > --- > drivers/gpu/drm/drm_gem.c | 10 -- > 1 file changed, 4 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c > index 7bf628e..ee2058a 100644 > --- a/drivers/gpu/drm/drm_gem.c > +++ b/drivers/gpu/drm/drm_gem.c > @@ -871,9 +871,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, > * @file_priv: drm file-private structure > * > * Open an object using the global name, returning a handle and the size. > - * > - * This handle (of course) holds a reference to the object, so the object > - * will not go away until the handle is deleted. > */ > int > drm_gem_open_ioctl(struct drm_device *dev, void *data, > @@ -898,14 +895,15 @@ 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_put_unlocked(obj); > if (ret) > - return ret; > + goto err; > > args->handle = handle; > args->size = obj->size; > > - return 0; > +err: > + drm_gem_object_put_unlocked(obj); > + return ret; > } > > /** As this seems to fix an important issue, any reason it wasn't cc: stable on it so that it gets backported properly? How about a "Fixes:" tag so that we know what commit id it fixes so we know how far back to backport things? And a hint to the maintainers that "this is an issue that needs to get into 5.8-final, it shouldn't wait around longer please" would have also been nice to see :) And what chagned from v1, aren't you supposed to list that somewhere in the changelog or below the --- line (never remember what DRM drivers want here...) Care to send a v3? thanks, greg k-h ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] clk: qcom: gcc-sdm660: Add missing modem reset
Quoting Konrad Dybcio (2020-07-26 04:11:58) > This will be required in order to support the > modem upstream. > > Signed-off-by: Konrad Dybcio > --- Should have a fixes tag too. > drivers/clk/qcom/gcc-sdm660.c | 1 + > include/dt-bindings/clock/qcom,gcc-sdm660.h | 1 + > 2 files changed, 2 insertions(+) > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [v6] dt-bindings: msm: disp: add yaml schemas for DPU and DSI bindings
On Thu, Jul 16, 2020 at 08:15:28PM +0530, Krishna Manikandan wrote: > MSM Mobile Display Subsytem (MDSS) encapsulates sub-blocks > like DPU display controller, DSI etc. Add YAML schema > for the device tree bindings for the same. > > Signed-off-by: Krishna Manikandan > > Changes in v2: > - Changed dpu to DPU (Sam Ravnborg) > - Fixed indentation issues (Sam Ravnborg) > - Added empty line between different properties (Sam Ravnborg) > - Replaced reference txt files with their corresponding > yaml files (Sam Ravnborg) > - Modified the file to use "|" only when it is > necessary (Sam Ravnborg) > > Changes in v3: > - Corrected the license used (Rob Herring) > - Added maxItems for properties (Rob Herring) > - Dropped generic descriptions (Rob Herring) > - Added ranges property (Rob Herring) > - Corrected the indendation (Rob Herring) > - Added additionalProperties (Rob Herring) > - Split dsi file into two, one for dsi controller > and another one for dsi phy per target (Rob Herring) > - Corrected description for pinctrl-names (Rob Herring) > - Corrected the examples used in yaml file (Rob Herring) > - Delete dsi.txt and dpu.txt (Rob Herring) > > Changes in v4: > - Move schema up by one level (Rob Herring) > - Add patternProperties for mdp node (Rob Herring) > - Corrected description of some properties (Rob Herring) > > Changes in v5: > - Correct the indentation (Rob Herring) > - Remove unnecessary description from properties (Rob Herring) > - Correct the number of interconnect entries (Rob Herring) > - Add interconnect names for sc7180 (Rob Herring) > - Add description for ports (Rob Herring) > - Remove common properties (Rob Herring) > - Add unevalutatedProperties (Rob Herring) > - Reference existing dsi controller yaml in the common > dsi controller file (Rob Herring) > - Correct the description of clock names to include only the > clocks that are required (Rob Herring) > - Remove properties which are already covered under the common > binding (Rob Herring) > - Add dsi phy supply nodes which are required for sc7180 and > sdm845 targets (Rob Herring) > - Add type ref for syscon-sfpb (Rob Herring) > > Changes in v6: > - Fixed errors during dt_binding_check (Rob Herring) > - Add maxItems for phys and phys-names (Rob Herring) > - Use unevaluatedProperties wherever required (Rob Herring) > - Removed interrupt controller from required properties for > dsi controller (Rob Herring) > - Add constraints for dsi-phy reg-names based on the compatible > phy version (Rob Herring) > - Add constraints for dsi-phy supply nodes based on the > compatible phy version (Rob Herring) > --- > .../bindings/display/msm/dpu-sc7180.yaml | 236 > .../bindings/display/msm/dpu-sdm845.yaml | 216 ++ > .../devicetree/bindings/display/msm/dpu.txt| 141 > .../display/msm/dsi-common-controller.yaml | 180 +++ > .../display/msm/dsi-controller-sc7180.yaml | 120 ++ > .../display/msm/dsi-controller-sdm845.yaml | 120 ++ > .../bindings/display/msm/dsi-phy-sc7180.yaml | 80 +++ > .../bindings/display/msm/dsi-phy-sdm845.yaml | 82 +++ > .../devicetree/bindings/display/msm/dsi-phy.yaml | 126 +++ > .../devicetree/bindings/display/msm/dsi.txt| 246 > - > 10 files changed, 1160 insertions(+), 387 deletions(-) > create mode 100644 > Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml > delete mode 100644 Documentation/devicetree/bindings/display/msm/dpu.txt > create mode 100644 > Documentation/devicetree/bindings/display/msm/dsi-common-controller.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/dsi-controller-sc7180.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/dsi-controller-sdm845.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/dsi-phy-sc7180.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/dsi-phy-sdm845.yaml > create mode 100644 Documentation/devicetree/bindings/display/msm/dsi-phy.yaml > delete mode 100644 Documentation/devicetree/bindings/display/msm/dsi.txt > > diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml > b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml > new file mode 100644 > index 000..df70393 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml > @@ -0,0 +1,236 @@ > +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/msm/dpu-sc7180.yaml# > +$schema: http://devicetree.org/meta-schemas
Re: [PATCH 8/9] clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
Quoting Konrad Dybcio (2020-07-26 04:12:05) > Add missing halt_check, hwcg_reg and hwcg_bit properties. > These were likely omitted when porting the driver upstream. > > Signed-off-by: Konrad Dybcio > --- Fixes tag? ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/3] drm: Restore driver.preclose() for all to use
On Thu, Jul 23, 2020 at 7:21 PM Chris Wilson wrote: > > An unfortunate sequence of events, but it turns out there is a valid > usecase for being able to free/decouple the driver objects before they > are freed by the DRM core. In particular, if we have a pointer into a > drm core object from inside a driver object, that pointer needs to be > nerfed *before* it is freed so that concurrent access (e.g. debugfs) > does not following the dangling pointer. > > The legacy marker was adding in the code movement from drp_fops.c to > drm_file.c I might fumble a lot, but not this one: commit 45c3d213a400c952ab7119f394c5293bb6877e6b Author: Daniel Vetter Date: Mon May 8 10:26:33 2017 +0200 drm: Nerf the preclose callback for modern drivers Also looking at the debugfs hook that has some rather adventurous stuff going on I think, feels a bit like a kitchensink with batteries included. If that's really all needed I'd say iterate the contexts by first going over files, then the ctx (which arent shared anyway) and the problem should also be gone. -Daniel > References: 9acdac68bcdc ("drm: rename drm_fops.c to drm_file.c") > Signed-off-by: Chris Wilson > Cc: Daniel Vetter > Cc: Gustavo Padovan > Cc: CQ Tang > Cc: # v4.12+ > --- > drivers/gpu/drm/drm_file.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c > index 0ac4566ae3f4..7b4258d6f7cc 100644 > --- a/drivers/gpu/drm/drm_file.c > +++ b/drivers/gpu/drm/drm_file.c > @@ -258,8 +258,7 @@ void drm_file_free(struct drm_file *file) > (long)old_encode_dev(file->minor->kdev->devt), > atomic_read(&dev->open_count)); > > - if (drm_core_check_feature(dev, DRIVER_LEGACY) && > - dev->driver->preclose) > + if (dev->driver->preclose) > dev->driver->preclose(dev, file); > > if (drm_core_check_feature(dev, DRIVER_LEGACY)) > -- > 2.20.1 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/amd/display: Clear dm_state for fast updates
Am 27.07.20 um 16:05 schrieb Kazlauskas, Nicholas: On 2020-07-27 9:39 a.m., Christian König wrote: Am 27.07.20 um 07:40 schrieb Mazin Rezk: This patch fixes a race condition that causes a use-after-free during amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits are requested and the second one finishes before the first. Essentially, this bug occurs when the following sequence of events happens: 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is deferred to the workqueue. 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is deferred to the workqueue. 3. Commit #2 starts before commit #1, dm_state #1 is used in the commit_tail and commit #2 completes, freeing dm_state #1. 4. Commit #1 starts after commit #2 completes, uses the freed dm_state 1 and dereferences a freelist pointer while setting the context. Well I only have a one mile high view on this, but why don't you let the work items execute in order? That would be better anyway cause this way we don't trigger a cache line ping pong between CPUs. Christian. We use the DRM helpers for managing drm_atomic_commit_state and those helpers internally push non-blocking commit work into the system unbound work queue. Mhm, well if you send those helper atomic commits in the order A,B and they execute it in the order B,A I would call that a bug :) While we could duplicate a copy of that code with nothing but the workqueue changed that isn't something I'd really like to maintain going forward. I'm not talking about duplicating the code, I'm talking about fixing the helpers. I don't know that code well, but from the outside it sounds like a bug there. And executing work items in the order they are submitted is trivial. Had anybody pinged Daniel or other people familiar with the helper code about it? Regards, Christian. Regards, Nicholas Kazlauskas Since this bug has only been spotted with fast commits, this patch fixes the bug by clearing the dm_state instead of using the old dc_state for fast updates. In addition, since dm_state is only used for its dc_state and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, removing the dm_state should not have any consequences in fast updates. This use-after-free bug has existed for a while now, but only caused a noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate freelist pointer to middle of object") moving the freelist pointer from dm_state->base (which was unused) to dm_state->context (which is dereferenced). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates") Reported-by: Duncan <1i5t5.dun...@cox.net> Signed-off-by: Mazin Rezk --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 86ffa0c2880f..710edc70e37e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, * the same resource. If we have a new DC context as part of * the DM atomic state from validation we need to free it and * retain the existing one instead. + * + * Furthermore, since the DM atomic state only contains the DC + * context and can safely be annulled, we can free the state + * and clear the associated private object now to free + * some memory and avoid a possible use-after-free later. */ - struct dm_atomic_state *new_dm_state, *old_dm_state; - new_dm_state = dm_atomic_get_new_state(state); - old_dm_state = dm_atomic_get_old_state(state); + for (i = 0; i < state->num_private_objs; i++) { + struct drm_private_obj *obj = state->private_objs[i].ptr; - if (new_dm_state && old_dm_state) { - if (new_dm_state->context) - dc_release_state(new_dm_state->context); + if (obj->funcs == adev->dm.atomic_obj.funcs) { + int j = state->num_private_objs-1; - new_dm_state->context = old_dm_state->context; + dm_atomic_destroy_state(obj, + state->private_objs[i].state); + + /* If i is not at the end of the array then the + * last element needs to be moved to where i was + * before the array can safely be truncated. + */ + if (i != j) + state->private_objs[i] = + state->private_objs[j]; - if (old_dm_state->context) - dc_retain_state(old_dm_state->context); + state->private_objs[j].ptr = NULL; +
Re: [PATCH 1/6] dt-bindings: display: Document NewVision NV3052C DT node
Hi Paul. On Mon, Jul 27, 2020 at 06:46:08PM +0200, Paul Cercueil wrote: > Add documentation for the Device Tree node for LCD panels based on the > NewVision NV3052C controller. > > Signed-off-by: Paul Cercueil Very happy to see work on RG-350 :-) Some feedback below. Sam > --- > .../display/panel/newvision,nv3052c.yaml | 69 +++ > 1 file changed, 69 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml > > diff --git > a/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml > b/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml > new file mode 100644 > index ..751a28800fc2 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/newvision,nv3052c.yaml > @@ -0,0 +1,69 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/newvision,nv3052c.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: NewVision NV3052C TFT LCD panel driver with SPI control bus > + > +maintainers: > + - Paul Cercueil > + > +description: | > + This is a driver for 320x240 TFT panels, The binding describes the HW, not the driver. So please re-phrase this part. This datasheet: https://www.phoenixdisplay.com/wp-content/uploads/2019/05/NV3052C-Datasheet-V0.2.pdf tells that the driver supports additional resoltions. I guess the 320x240 resolution is limited to the leadtek panel. > + accepting a variety of input > + streams that get adapted and scaled to the panel. The panel output has > + 960 TFT source driver pins and 240 TFT gate driver pins, VCOM, VCOML and > + VCOMH outputs. > + > + The panel must obey the rules for a SPI slave device as specified in > + spi/spi-controller.yaml > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > +items: > + - enum: > +- leadtek,ltk035c5444t-spi > + > + - const: newvision,nv3052c > + > + reg: > +maxItems: 1 > + > + reset-gpios: true > + port: true > + > +required: > + - compatible > + - reg > + > +unevaluatedProperties: false > + Do the panel need any power? I had expected to see a power-supply node as mandatory. > +examples: > + - | > +#include > +spi { > + #address-cells = <1>; > + #size-cells = <0>; > + > + display@0 { > +compatible = "leadtek,ltk035c5444t-spi", "newvision,nv3052c"; > +reg = <0>; > + > +spi-max-frequency = <1500>; > +spi-3wire; > +reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>; > +backlight = <&backlight>; > +power-supply = <&vcc>; These would fail later due to "unevaluatedProperties: false". Add them above like backlight: true power-supply: true as done for reset-gpios for example. > + > +port { > + panel_input: endpoint { > + remote-endpoint = <&panel_output>; > + }; > +}; > + }; > +}; Personally I prefer 4 space indent. But there is no fixed rule (yet) what to use. > + > +... > -- > 2.27.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Nouveau] [PATCH v2] drm/nouveau: Accept 'legacy' format modifiers
On 7/23/20 9:06 PM, Ben Skeggs wrote: On Sat, 18 Jul 2020 at 13:34, James Jones wrote: Accept the DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK() family of modifiers to handle broken userspace Xorg modesetting and Mesa drivers. Existing Mesa drivers are still aware of only these older format modifiers which do not differentiate between different variations of the block linear layout. When the format modifier support flag was flipped in the nouveau kernel driver, the X.org modesetting driver began attempting to use its format modifier-enabled framebuffer path. Because the set of format modifiers advertised by the kernel prior to this change do not intersect with the set of format modifiers advertised by Mesa, allocating GBM buffers using format modifiers fails and the modesetting driver falls back to non-modifier allocation. However, it still later queries the modifier of the GBM buffer when creating its DRM-KMS framebuffer object, receives the old-format modifier from Mesa, and attempts to create a framebuffer with it. Since the kernel is still not aware of these formats, this fails. Userspace should not be attempting to query format modifiers of GBM buffers allocated with a non- format-modifier-aware allocation path, but to avoid breaking existing userspace behavior, this change accepts the old-style format modifiers when creating framebuffers and applying them to planes by translating them to the equivalent new-style modifier. To accomplish this, some layout parameters must be assumed to match properties of the device targeted by the relevant ioctls. To avoid perpetuating misuse of the old-style modifiers, this change does not advertise support for them. Doing so would imply compatibility between devices with incompatible memory layouts. Tested with Xorg 1.20 modesetting driver, weston@c46c70dac84a4b3030cd05b380f9f410536690fc, gnome & KDE wayland desktops from Ubuntu 18.04, and sway 1.5 Reported-by: Kirill A. Shutemov Fixes: fa4f4c213f5f ("drm/nouveau/kms: Support NVIDIA format modifiers") Link: https://lkml.org/lkml/2020/6/30/1251 Signed-off-by: James Jones --- drivers/gpu/drm/nouveau/nouveau_display.c | 26 +-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 496c4621cc78..31543086254b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -191,8 +191,14 @@ nouveau_decode_mod(struct nouveau_drm *drm, uint32_t *tile_mode, uint8_t *kind) { + struct nouveau_display *disp = nouveau_display(drm->dev); BUG_ON(!tile_mode || !kind); + if ((modifier & (0xffull << 12)) == 0ull) { + /* Legacy modifier. Translate to this device's 'kind.' */ + modifier |= disp->format_modifiers[0] & (0xffull << 12); + } I believe this should be moved into the != MOD_LINEAR case. Yes, of course, thanks. I need to re-evaluate my testing yet again to make sure I hit that case too. Preparing a v3... Thanks, -James + if (modifier == DRM_FORMAT_MOD_LINEAR) { /* tile_mode will not be used in this case */ *tile_mode = 0; @@ -227,6 +233,16 @@ nouveau_framebuffer_get_layout(struct drm_framebuffer *fb, } } +static const u64 legacy_modifiers[] = { + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0), + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1), + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2), + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3), + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4), + DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5), + DRM_FORMAT_MOD_INVALID +}; + static int nouveau_validate_decode_mod(struct nouveau_drm *drm, uint64_t modifier, @@ -247,8 +263,14 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm, (disp->format_modifiers[mod] != modifier); mod++); - if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) - return -EINVAL; + if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) { + for (mod = 0; +(legacy_modifiers[mod] != DRM_FORMAT_MOD_INVALID) && +(legacy_modifiers[mod] != modifier); +mod++); + if (legacy_modifiers[mod] == DRM_FORMAT_MOD_INVALID) + return -EINVAL; + } nouveau_decode_mod(drm, modifier, tile_mode, kind); -- 2.17.1 ___ Nouveau mailing list nouv...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/dbi: Fix SPI Type 1 (9-bit) transfer
Hi Paul. On Fri, Jul 03, 2020 at 04:23:57PM +0200, Sam Ravnborg wrote: > On Fri, Jul 03, 2020 at 04:13:41PM +0200, Paul Cercueil wrote: > > The function mipi_dbi_spi1_transfer() will transfer its payload as 9-bit > > data, the 9th (MSB) bit being the data/command bit. In order to do that, > > it unpacks the 8-bit values into 16-bit values, then sets the 9th bit if > > the byte corresponds to data, clears it otherwise. The 7 MSB are > > padding. The array of now 16-bit values is then passed to the SPI core > > for transfer. > > > > This function was broken since its introduction, as the length of the > > SPI transfer was set to the payload size before its conversion, but the > > payload doubled in size due to the 8-bit -> 16-bit conversion. > > > > Fixes: 02dd95fe3169 ("drm/tinydrm: Add MIPI DBI support") > > Cc: # 4.10 > > Signed-off-by: Paul Cercueil > > As discussed on irc this looks correct to me too. > > Reviewed-by: Sam Ravnborg > > > I will apply later, but let's wait and see if Noralf or others > have any feedback first. I finally went back to this patch, I missed it yesterday. Applied to drm-misc-fixes with a stable 5.4+ tag. Sam > > --- > > drivers/gpu/drm/drm_mipi_dbi.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c > > index bb27c82757f1..bf7888ad9ad4 100644 > > --- a/drivers/gpu/drm/drm_mipi_dbi.c > > +++ b/drivers/gpu/drm/drm_mipi_dbi.c > > @@ -923,7 +923,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, > > int dc, > > } > > } > > > > - tr.len = chunk; > > + tr.len = chunk * 2; > > len -= chunk; > > > > ret = spi_sync(spi, &m); > > -- > > 2.27.0 > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/3] drm/ast: Store image size in HW cursor info
On Mon, Jul 27, 2020 at 1:37 PM Thomas Zimmermann wrote: > > Hi > > Am 27.07.20 um 12:42 schrieb dan...@ffwll.ch: > > On Mon, Jul 27, 2020 at 09:37:06AM +0200, Thomas Zimmermann wrote: > >> Store the image size as part of the HW cursor info, so that the > >> cursor show function doesn't require the information from the > >> caller. No functional changes. > > > > Uh just pass the state structure and done? All these "store random stuff > > in private structures" (they're not even atomic state structures, it's the > > driver private thing even!) is very non-atomic. And I see zero reasons why > > you have to do this, the cursor stays around. > > It's not random stuff. Ast cannot use ARGB for cursors. Anything in > ast_private.cursor represents cursor hardware state (not DRM state); > duplicated for double buffering. > > * gbo: two perma-pinned GEM objects at the end of VRAM. It's the HW > cursor buffer in ARGB format. The userspace's cursor image is > converted to ARGB and copied into the current backbuffer. > > * vaddr: A mapping of the gbo's into kernel address space. We don't > want to map the gbo on each update, so they are mapped once and the > kernel address is stored in vaddr. > > * size: the size of each HW buffer. We could use the value in the fb, > but storing this as well makes the cursor code self-contained. Yeah, but this kind of stuff should be in the ast_plane_state. Not in ast_private, that latter option is very non-atomic and results in all kinds of coordination fun. -Daniel > > Best regards > Thomas > > > -Daniel > > > >> > >> Signed-off-by: Thomas Zimmermann > >> Fixes: 4961eb60f145 ("drm/ast: Enable atomic modesetting") > >> Cc: Thomas Zimmermann > >> Cc: Gerd Hoffmann > >> Cc: Dave Airlie > >> Cc: Daniel Vetter > >> Cc: Sam Ravnborg > >> Cc: Emil Velikov > >> Cc: "Y.C. Chen" > >> Cc: # v5.6+ > >> --- > >> drivers/gpu/drm/ast/ast_cursor.c | 13 +++-- > >> drivers/gpu/drm/ast/ast_drv.h| 7 +-- > >> drivers/gpu/drm/ast/ast_mode.c | 8 +--- > >> 3 files changed, 17 insertions(+), 11 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/ast/ast_cursor.c > >> b/drivers/gpu/drm/ast/ast_cursor.c > >> index acf0d23514e8..8642a0ce9da6 100644 > >> --- a/drivers/gpu/drm/ast/ast_cursor.c > >> +++ b/drivers/gpu/drm/ast/ast_cursor.c > >> @@ -87,6 +87,8 @@ int ast_cursor_init(struct ast_private *ast) > >> > >> ast->cursor.gbo[i] = gbo; > >> ast->cursor.vaddr[i] = vaddr; > >> +ast->cursor.size[i].width = 0; > >> +ast->cursor.size[i].height = 0; > >> } > >> > >> return drmm_add_action_or_reset(dev, ast_cursor_release, NULL); > >> @@ -194,6 +196,9 @@ int ast_cursor_blit(struct ast_private *ast, struct > >> drm_framebuffer *fb) > >> /* do data transfer to cursor BO */ > >> update_cursor_image(dst, src, fb->width, fb->height); > >> > >> +ast->cursor.size[ast->cursor.next_index].width = fb->width; > >> +ast->cursor.size[ast->cursor.next_index].height = fb->height; > >> + > >> drm_gem_vram_vunmap(gbo, src); > >> drm_gem_vram_unpin(gbo); > >> > >> @@ -249,14 +254,18 @@ static void ast_cursor_set_location(struct > >> ast_private *ast, u16 x, u16 y, > >> ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); > >> } > >> > >> -void ast_cursor_show(struct ast_private *ast, int x, int y, > >> - unsigned int offset_x, unsigned int offset_y) > >> +void ast_cursor_show(struct ast_private *ast, int x, int y) > >> { > >> +unsigned int offset_x, offset_y; > >> u8 x_offset, y_offset; > >> u8 __iomem *dst, __iomem *sig; > >> u8 jreg; > >> > >> dst = ast->cursor.vaddr[ast->cursor.next_index]; > >> +offset_x = AST_MAX_HWC_WIDTH - > >> + ast->cursor.size[ast->cursor.next_index].width; > >> +offset_y = AST_MAX_HWC_HEIGHT - > >> + ast->cursor.size[ast->cursor.next_index].height; > >> > >> sig = dst + AST_HWC_SIZE; > >> writel(x, sig + AST_HWC_SIGNATURE_X); > >> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h > >> index e3a264ac7ee2..57414b429db3 100644 > >> --- a/drivers/gpu/drm/ast/ast_drv.h > >> +++ b/drivers/gpu/drm/ast/ast_drv.h > >> @@ -116,6 +116,10 @@ struct ast_private { > >> struct { > >> struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM]; > >> void __iomem *vaddr[AST_DEFAULT_HWC_NUM]; > >> +struct { > >> +unsigned int width; > >> +unsigned int height; > >> +} size[AST_DEFAULT_HWC_NUM]; > >> unsigned int next_index; > >> } cursor; > >> > >> @@ -311,8 +315,7 @@ void ast_release_firmware(struct drm_device *dev); > >> int ast_cursor_init(struct ast_private *ast); > >> int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb); > >> void ast_cursor_page_flip(struct ast_private *ast); > >> -void ast_cursor_show(struct ast_private *ast, int x, i
Re: [PATCH 1/3] drm/ast: Do full modeset if the primary plane's format changes
On Mon, Jul 27, 2020 at 1:24 PM Thomas Zimmermann wrote: > > Hi > > Am 27.07.20 um 12:40 schrieb dan...@ffwll.ch: > > On Mon, Jul 27, 2020 at 09:37:05AM +0200, Thomas Zimmermann wrote: > >> The atomic modesetting code tried to distinguish format changes from > >> full modesetting operations. In practice, this was buggy and the format > >> registers were often updated even for simple pageflips. > > > > Nah it's not buggy, it's intentional. Most hw can update formats in a flip > > withouth having to shut down the hw to do so. > > Admittedly it was intentional when I write it, but it never really > worked. I think it might have even updated these color registers on each > frame. > > > > > > >> Instead do a full modeset if the primary plane changes formats. It's > >> just as rare as an actual mode change, so there will be no performance > >> penalty. > >> > >> The patch also replaces a reference to drm_crtc_state.allow_modeset with > >> the correct call to drm_atomic_crtc_needs_modeset(). > >> > >> Signed-off-by: Thomas Zimmermann > >> Fixes: 4961eb60f145 ("drm/ast: Enable atomic modesetting") > >> Cc: Thomas Zimmermann > >> Cc: Gerd Hoffmann > >> Cc: Dave Airlie > >> Cc: Daniel Vetter > >> Cc: Sam Ravnborg > >> Cc: Emil Velikov > >> Cc: "Y.C. Chen" > >> Cc: # v5.6+ > >> --- > >> drivers/gpu/drm/ast/ast_mode.c | 23 --- > >> 1 file changed, 16 insertions(+), 7 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/ast/ast_mode.c > >> b/drivers/gpu/drm/ast/ast_mode.c > >> index 154cd877d9d1..3680a000b812 100644 > >> --- a/drivers/gpu/drm/ast/ast_mode.c > >> +++ b/drivers/gpu/drm/ast/ast_mode.c > >> @@ -527,8 +527,8 @@ static const uint32_t ast_primary_plane_formats[] = { > >> static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane, > >> struct drm_plane_state > >> *state) > >> { > >> -struct drm_crtc_state *crtc_state; > >> -struct ast_crtc_state *ast_crtc_state; > >> +struct drm_crtc_state *crtc_state, *old_crtc_state; > >> +struct ast_crtc_state *ast_crtc_state, *old_ast_crtc_state; > >> int ret; > >> > >> if (!state->crtc) > >> @@ -550,6 +550,15 @@ static int > >> ast_primary_plane_helper_atomic_check(struct drm_plane *plane, > >> > >> ast_crtc_state->format = state->fb->format; > >> > >> +old_crtc_state = drm_atomic_get_old_crtc_state(state->state, > >> state->crtc); > >> +if (!old_crtc_state) > >> +return 0; > >> +old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); > >> +if (!old_ast_crtc_state) > > > > The above two if checks should never fail, I'd wrap them in a WARN_ON. > > Really? But what's the old state when the first mode is being programmed? Uh, atomic _always_ has a state. That's why you need to call drm_mode_config_reset, to get this entire machinery started. Also, the sw state is supposed to always match the hw state (at least once all the nonblocking commit workers have caught up). > > > >> +return 0; > >> +if (ast_crtc_state->format != old_ast_crtc_state->format) > >> +crtc_state->mode_changed = true; > >> + > >> return 0; > >> } > >> > >> @@ -775,18 +784,18 @@ static void ast_crtc_helper_atomic_flush(struct > >> drm_crtc *crtc, > >> > >> ast_state = to_ast_crtc_state(crtc->state); > >> > >> -format = ast_state->format; > >> -if (!format) > >> +if (!drm_atomic_crtc_needs_modeset(crtc->state)) > >> return; > >> > >> +format = ast_state->format; > >> +if (drm_WARN_ON_ONCE(dev, !format)) > >> +return; /* BUG: We didn't set format in primary check(). */ > > > > Hm that entire ast_state->format machinery looks kinda strange, can't you > > just look up the primary plane state everywhere and that's it? > > drm_framebuffer are fully invariant and refcounted to the state, so there > > really shouldn't be any need to copy format around. > > ast_state->format is the format that has to be programmed in > atomic_flush(). If it's NULL, the current format was used. Updating the > primary plane's format also requires the vbios info, which depends on > CRTC state. So it's collected in the CRTC's atomic_check(). > > It felt natural to use the various atomic_check() functions to collect > and store and store away these structures, and later use them in > atomic_flush(). > > I'd prefer to keep the current design. It's the one that worked best > while writing the atomic-modesetting support for ast. So if you have actual checks in atomic_check for validation, then this makes sense - it avoids computing stuff twice and getting in wrong in one case. But from reading ast code all you do is store the temporary lookup in there, and that's really just confusing. You can just look up the atomic state, at least in atomic_check (in the commit side it's mildly more annoying, we need to fix a few things). But it's also not totally horrible ofc, just would be nice to improve this. -
Re: [PATCH 1/2] drm/radeon: switch from 'pci_' to 'dma_' API
Applied. Thanks! Alex On Mon, Jul 27, 2020 at 9:42 AM Christian König wrote: > > Am 27.07.20 um 12:34 schrieb Christophe JAILLET: > > The wrappers in include/linux/pci-dma-compat.h should go away. > > > > The patch has been generated with the coccinelle script below and has been > > hand modified to replace GFP_ with a correct flag. > > It has been compile tested. > > > > When memory is allocated in 'radeon_gart_table_ram_alloc()' GFP_KERNEL > > can be used because its callers already use this flag. > > > > Both 'r100_pci_gart_init()' (r100.c) and 'rs400_gart_init()' (rs400.c) > > call 'radeon_gart_init()'. > > This function uses 'vmalloc'. > > > > > > @@ > > @@ > > -PCI_DMA_BIDIRECTIONAL > > +DMA_BIDIRECTIONAL > > > > @@ > > @@ > > -PCI_DMA_TODEVICE > > +DMA_TO_DEVICE > > > > @@ > > @@ > > -PCI_DMA_FROMDEVICE > > +DMA_FROM_DEVICE > > > > @@ > > @@ > > -PCI_DMA_NONE > > +DMA_NONE > > > > @@ > > expression e1, e2, e3; > > @@ > > -pci_alloc_consistent(e1, e2, e3) > > +dma_alloc_coherent(&e1->dev, e2, e3, GFP_) > > > > @@ > > expression e1, e2, e3; > > @@ > > -pci_zalloc_consistent(e1, e2, e3) > > +dma_alloc_coherent(&e1->dev, e2, e3, GFP_) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_free_consistent(e1, e2, e3, e4) > > +dma_free_coherent(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_map_single(e1, e2, e3, e4) > > +dma_map_single(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_unmap_single(e1, e2, e3, e4) > > +dma_unmap_single(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4, e5; > > @@ > > -pci_map_page(e1, e2, e3, e4, e5) > > +dma_map_page(&e1->dev, e2, e3, e4, e5) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_unmap_page(e1, e2, e3, e4) > > +dma_unmap_page(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_map_sg(e1, e2, e3, e4) > > +dma_map_sg(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_unmap_sg(e1, e2, e3, e4) > > +dma_unmap_sg(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_dma_sync_single_for_cpu(e1, e2, e3, e4) > > +dma_sync_single_for_cpu(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_dma_sync_single_for_device(e1, e2, e3, e4) > > +dma_sync_single_for_device(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_dma_sync_sg_for_cpu(e1, e2, e3, e4) > > +dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2, e3, e4; > > @@ > > -pci_dma_sync_sg_for_device(e1, e2, e3, e4) > > +dma_sync_sg_for_device(&e1->dev, e2, e3, e4) > > > > @@ > > expression e1, e2; > > @@ > > -pci_dma_mapping_error(e1, e2) > > +dma_mapping_error(&e1->dev, e2) > > > > @@ > > expression e1, e2; > > @@ > > -pci_set_dma_mask(e1, e2) > > +dma_set_mask(&e1->dev, e2) > > > > @@ > > expression e1, e2; > > @@ > > -pci_set_consistent_dma_mask(e1, e2) > > +dma_set_coherent_mask(&e1->dev, e2) > > > > Signed-off-by: Christophe JAILLET > > Reviewed-by: Christian König > > > --- > > If needed, see post from Christoph Hellwig on the kernel-janitors ML: > > https://marc.info/?l=kernel-janitors&m=158745678307186&w=4 > > --- > > drivers/gpu/drm/radeon/radeon_gart.c | 9 - > > 1 file changed, 4 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/gpu/drm/radeon/radeon_gart.c > > b/drivers/gpu/drm/radeon/radeon_gart.c > > index f178ba321715..b7ce254e5663 100644 > > --- a/drivers/gpu/drm/radeon/radeon_gart.c > > +++ b/drivers/gpu/drm/radeon/radeon_gart.c > > @@ -72,8 +72,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device > > *rdev) > > { > > void *ptr; > > > > - ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, > > -&rdev->gart.table_addr); > > + ptr = dma_alloc_coherent(&rdev->pdev->dev, rdev->gart.table_size, > > + &rdev->gart.table_addr, GFP_KERNEL); > > if (ptr == NULL) { > > return -ENOMEM; > > } > > @@ -110,9 +110,8 @@ void radeon_gart_table_ram_free(struct radeon_device > > *rdev) > > rdev->gart.table_size >> PAGE_SHIFT); > > } > > #endif > > - pci_free_consistent(rdev->pdev, rdev->gart.table_size, > > - (void *)rdev->gart.ptr, > > - rdev->gart.table_addr); > > + dma_free_coherent(&rdev->pdev->dev, rdev->gart.table_size, > > + (void *)rdev->gart.ptr, rdev->gart.table_addr); > > rdev->gart.ptr = NULL; > > rdev->gart.table_addr = 0; > > } > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel _
Re: [PATCH 9/9] soc/qcom: Add REVID driver
On Sun, Jul 26, 2020 at 01:12:06PM +0200, Konrad Dybcio wrote: > From: Xiaozhe Shi > > Add the REVID device driver. The REVID driver will print out the PMIC > revision at probe time. > > Signed-off-by: Xiaozhe Shi > [konradyb...@gmail.com: Fast-forward the driver from kernel 4.14 to 5.8, > convert binding to yaml] > Signed-off-by: Konrad Dybcio > --- > .../bindings/soc/qcom/qcom,qpnp-revid.yaml| 38 ++ Bindings should be a separate patch. checkpatch.pl will tell you this. > drivers/soc/qcom/Kconfig | 9 + > drivers/soc/qcom/Makefile | 1 + > drivers/soc/qcom/qpnp-revid.c | 288 ++ > include/linux/qpnp/qpnp-revid.h | 369 ++ > 5 files changed, 705 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml > create mode 100644 drivers/soc/qcom/qpnp-revid.c > create mode 100644 include/linux/qpnp/qpnp-revid.h ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 9/9] soc/qcom: Add REVID driver
On Sun, 26 Jul 2020 13:12:06 +0200, Konrad Dybcio wrote: > From: Xiaozhe Shi > > Add the REVID device driver. The REVID driver will print out the PMIC > revision at probe time. > > Signed-off-by: Xiaozhe Shi > [konradyb...@gmail.com: Fast-forward the driver from kernel 4.14 to 5.8, > convert binding to yaml] > Signed-off-by: Konrad Dybcio > --- > .../bindings/soc/qcom/qcom,qpnp-revid.yaml| 38 ++ > drivers/soc/qcom/Kconfig | 9 + > drivers/soc/qcom/Makefile | 1 + > drivers/soc/qcom/qpnp-revid.c | 288 ++ > include/linux/qpnp/qpnp-revid.h | 369 ++ > 5 files changed, 705 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml > create mode 100644 drivers/soc/qcom/qpnp-revid.c > create mode 100644 include/linux/qpnp/qpnp-revid.h > My bot found errors running 'make dt_binding_check' on your patch: Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml: while scanning a block scalar in "", line 22, column 18 found a tab character where an indentation space is expected in "", line 24, column 1 Documentation/devicetree/bindings/Makefile:20: recipe for target 'Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.example.dts' failed make[1]: *** [Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.example.dts] Error 1 make[1]: *** Waiting for unfinished jobs /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml: ignoring, error parsing file warning: no schema found in file: ./Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml: ignoring, error parsing file warning: no schema found in file: ./Documentation/devicetree/bindings/soc/qcom/qcom,qpnp-revid.yaml Makefile:1347: recipe for target 'dt_binding_check' failed make: *** [dt_binding_check] Error 2 See https://patchwork.ozlabs.org/patch/1336467 If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure dt-schema is up to date: pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade Please check and re-submit. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/2] drm/radeon: avoid a useless memset
Applied. Thanks! Alex On Mon, Jul 27, 2020 at 9:41 AM Christian König wrote: > > Am 27.07.20 um 12:34 schrieb Christophe JAILLET: > > Avoid a memset after a call to 'dma_alloc_coherent()'. > > This is useless since > > commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*") > > > > Signed-off-by: Christophe JAILLET > > Reviewed-by: Christian König > > > --- > > drivers/gpu/drm/radeon/radeon_gart.c | 1 - > > 1 file changed, 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/radeon/radeon_gart.c > > b/drivers/gpu/drm/radeon/radeon_gart.c > > index b7ce254e5663..3808a753127b 100644 > > --- a/drivers/gpu/drm/radeon/radeon_gart.c > > +++ b/drivers/gpu/drm/radeon/radeon_gart.c > > @@ -85,7 +85,6 @@ int radeon_gart_table_ram_alloc(struct radeon_device > > *rdev) > > } > > #endif > > rdev->gart.ptr = ptr; > > - memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); > > return 0; > > } > > > > ___ > amd-gfx mailing list > amd-...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/3] dt-bindings: Add DT bindings for Powertip PH800480T013
On Sat, 25 Jul 2020 23:13:34 +0200, Marek Vasut wrote: > Add DT bindings for Powertip PH800480T013 800x480 parallel LCD, > this one is used in the Raspberry Pi 7" touchscreen display unit. > > Signed-off-by: Marek Vasut > To: dri-devel@lists.freedesktop.org > Cc: Eric Anholt > Cc: Rob Herring > Cc: Sam Ravnborg > Cc: devicet...@vger.kernel.org > --- > .../panel/powertip,ph800480t013-idf02.yaml| 28 +++ > 1 file changed, 28 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml > My bot found errors running 'make dt_binding_check' on your patch: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml: $id: 'http://devicetree.org/schemas/display/panel/powertip,ph800480t013-idf02#' does not match 'http://devicetree.org/schemas/.*\\.yaml#' Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml: $id: relative path/filename doesn't match actual path or filename expected: http://devicetree.org/schemas/display/panel/powertip,ph800480t013-idf02.yaml# Documentation/devicetree/bindings/Makefile:20: recipe for target 'Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.example.dts' failed make[1]: *** [Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.example.dts] Error 1 make[1]: *** Waiting for unfinished jobs /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml: ignoring, error in schema: $id warning: no schema found in file: ./Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml: ignoring, error in schema: $id warning: no schema found in file: ./Documentation/devicetree/bindings/display/panel/powertip,ph800480t013-idf02.yaml Makefile:1347: recipe for target 'dt_binding_check' failed make: *** [dt_binding_check] Error 2 See https://patchwork.ozlabs.org/patch/1336335 If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure dt-schema is up to date: pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade Please check and re-submit. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/2] dt-bindings: Add DT bindings for Toshiba TC358762 DSI-to-DPI bridge
On Sat, 25 Jul 2020 23:14:56 +0200, Marek Vasut wrote: > Add DT bindings for Toshiba TC358762 DSI-to-DPI bridge, this > one is used in the Raspberry Pi 7" touchscreen display unit. > > Signed-off-by: Marek Vasut > To: dri-devel@lists.freedesktop.org > Cc: Eric Anholt > Cc: Rob Herring > Cc: Sam Ravnborg > Cc: devicet...@vger.kernel.org > --- > .../display/bridge/toshiba,tc358762.yaml | 116 ++ > 1 file changed, 116 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.yaml > My bot found errors running 'make dt_binding_check' on your patch: Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dts:20.13-23: Warning (reg_format): /example-0/bridge@0:reg: property has invalid length (4 bytes) (#address-cells == 1, #size-cells == 1) Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: Warning (pci_device_reg): Failed prerequisite 'reg_format' Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: Warning (pci_device_bus_num): Failed prerequisite 'reg_format' Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: Warning (simple_bus_reg): Failed prerequisite 'reg_format' Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: Warning (i2c_bus_reg): Failed prerequisite 'reg_format' Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: Warning (spi_bus_reg): Failed prerequisite 'reg_format' /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: example-0: bridge@0:reg:0: [0] is too short /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: bridge@0: '#address-cells', '#size-cells', 'port@0', 'port@1' do not match any of the regexes: 'pinctrl-[0-9]+' /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.example.dt.yaml: bridge@0: 'ports' is a required property See https://patchwork.ozlabs.org/patch/1336337 If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure dt-schema is up to date: pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade Please check and re-submit. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH -next] crc:Fix build errors
Hi, I actually already sent a patch for this: https://patchwork.freedesktop.org/patch/378202/ I'm guessing it hasn't gotten picked up upstream yet? On Mon, 2020-07-27 at 12:00 +0800, Peng Wu wrote: > If CONFIG_DRM_NOUVEAU=y,the following errors > are seen while building crc.h. > > In file included from > /scratch/linux/drivers/gpu/drm/nouveau/nouveau_display.c:47: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_head_crc_late_register’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:109:47: error: > parameter name omitted > static inline int nv50_head_crc_late_register(struct nv50_head *) {} >^~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:109:54: warning: no > return statement in function returning non-void [-Wreturn-type] > static inline int nv50_head_crc_late_register(struct nv50_head *) {} > ^ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_crc_handle_vblank’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:111:57: warning: > ‘return’ with a value, in function returning void > nv50_crc_handle_vblank(struct nv50_head *head) { return 0; } > ^ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:111:1: note: declared > here > nv50_crc_handle_vblank(struct nv50_head *head) { return 0; } > ^~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_crc_atomic_check_head’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:114:28: error: > parameter name omitted > nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *, > ^~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:114:48: error: > parameter name omitted > nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *, > ^~~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:115:7: error: > parameter name omitted >struct nv50_head_atom *) {} >^~~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:115:14: warning: no > return statement in function returning non-void [-Wreturn-type] >struct nv50_head_atom *) {} > ^~ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_crc_atomic_stop_reporting’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:118:32: error: > parameter name omitted > nv50_crc_atomic_stop_reporting(struct drm_atomic_state *) {} > ^ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_crc_atomic_init_notifier_contexts’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:120:40: error: > parameter name omitted > nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *) {} > ^ > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h: In function > ‘nv50_crc_atomic_release_notifier_contexts’: > /scratch/linux/drivers/gpu/drm/nouveau/dispnv50/crc.h:122:43: error: > parameter name omitted > > Signed-off-by: Peng Wu > --- > drivers/gpu/drm/nouveau/dispnv50/crc.h | 44 + > - > 1 file changed, 22 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.h > b/drivers/gpu/drm/nouveau/dispnv50/crc.h > index 4bc59e7..3da16cd 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/crc.h > +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.h > @@ -76,22 +76,22 @@ struct nv50_crc { > }; > > void nv50_crc_init(struct drm_device *dev); > -int nv50_head_crc_late_register(struct nv50_head *); > +int nv50_head_crc_late_register(struct nv50_head *head); > void nv50_crc_handle_vblank(struct nv50_head *head); > > -int nv50_crc_verify_source(struct drm_crtc *, const char *, size_t *); > -const char *const *nv50_crc_get_sources(struct drm_crtc *, size_t *); > -int nv50_crc_set_source(struct drm_crtc *, const char *); > +int nv50_crc_verify_source(struct drm_crtc *crtc, const char *source_name, > size_t *values_cnt); > +const char *const *nv50_crc_get_sources(struct drm_crtc *crtc, size_t > *count); > +int nv50_crc_set_source(struct drm_crtc *crtc, const char *source_str); > > -int nv50_crc_atomic_check_head(struct nv50_head *, struct nv50_head_atom *, > -struct nv50_head_atom *); > +int nv50_crc_atomic_check_head(struct nv50_head *head, struct > nv50_head_atom *asyh, > +struct nv50_head_atom *armh); > void nv50_crc_atomic_check_outp(struct nv50_atom *atom); > -void nv50_crc_atomic_stop_reporting(struct drm_atomic_state *); > -void nv50_crc_atomic_init_notifier_contexts(struct drm_atomic_state *); > -void nv50_crc_atomic_relea
Re: [PATCH v5 0/5] drm/bridge: Update tc358767 and nxp-ptn3460 to support chained bridges
Hi all. On Mon, Jul 27, 2020 at 07:03:15PM +0200, Sam Ravnborg wrote: > This patch-set aims to make connector creation optional > and prepare the bridge drivers for use in a chained setup. > > The objective is that all bridge drivers shall support a chained setup > connector creation is moved to the display drivers. > This is just one step on this path. > > The general approach for the bridge drivers: > - Introduce bridge operations > - Introduce use of panel bridge and make connector creation optional > > v5: > - Applied reviewed patches, so we went from 15 to 5 > - Fixed bug in connector creation in both drivers > > v4: > - Dropped patch for ti-sn65dsi86. Await full conversion > - Dropped patch for ti-tpd12s015. It was wrong (Laurent) > - Drop boe,hv070wsa-100 patch, it was applied > - Combined a few patches to fix connector created twice (Laurent) > - Fix memory leak in get_edid (Laurent) > - Added patch to validate panel descriptions in panel-simple > - Set bridge.type in relevant drivers > > v3: > - Rebase on top of drm-misc-next > - Address kbuild test robot feedback > > v2: > - Updated bus_flags for boe,hv070wsa-100 > - Collected r-b, but did not apply patches yet > - On the panel side the panel-simple driver gained a default > connector type for all the dumb panels that do not > include so in their description. > With this change panels always provide a connector type, > and we have the potential to drop most uses of > devm_drm_panel_bridge_add_typed(). > - Added conversion of a few more bridge drivers > > Patches can build but no run-time testing. > So both test and review feedback appreciated! > > Sam > > > Sam Ravnborg (5): > drm/bridge: tc358767: add detect bridge operation > drm/bridge: tc358767: add get_edid bridge operation > drm/bridge: tc358767: add drm_panel_bridge support > drm/bridge: nxp-ptn3460: add get_edid bridge operation > drm/bridge: nxp-ptn3460: add drm_panel_bridge support Fixed up per Laurent's suggestion and applied to drm-misc-next. Sam > > drivers/gpu/drm/bridge/nxp-ptn3460.c | 103 +--- > drivers/gpu/drm/bridge/tc358767.c| 126 > +++ > 2 files changed, 114 insertions(+), 115 deletions(-) > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v5 5/5] drm/bridge: nxp-ptn3460: add drm_panel_bridge support
Hi Sam, Thank you for the patch. On Mon, Jul 27, 2020 at 07:03:20PM +0200, Sam Ravnborg wrote: > Prepare the bridge driver for use in a chained setup. > > - Replacing direct use of drm_panel with drm_panel_bridge support. > - Make the connector creation optional > > Note: the bridge panel will use the connector type from the panel. > > v3: > - Fix wrong logic in connector creation (Laurent) > > v2: > - Use panel_bridge for local variable name to align with other drivers > - Fix that connector was created twice (Laurent) > - Set bridge.type to DRM_MODE_CONNECTOR_LVDS. > > Signed-off-by: Sam Ravnborg > Cc: Andrzej Hajda > Cc: Neil Armstrong > Cc: Laurent Pinchart > Cc: Jonas Karlman > Cc: Jernej Skrabec > --- > drivers/gpu/drm/bridge/nxp-ptn3460.c | 60 ++-- > 1 file changed, 20 insertions(+), 40 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c > b/drivers/gpu/drm/bridge/nxp-ptn3460.c > index 2805c8938f98..391c1f66f60f 100644 > --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c > +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c > @@ -29,7 +29,7 @@ struct ptn3460_bridge { > struct drm_connector connector; > struct i2c_client *client; > struct drm_bridge bridge; > - struct drm_panel *panel; > + struct drm_bridge *panel_bridge; > struct gpio_desc *gpio_pd_n; > struct gpio_desc *gpio_rst_n; > u32 edid_emulation; > @@ -126,11 +126,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) > usleep_range(10, 20); > gpiod_set_value(ptn_bridge->gpio_rst_n, 1); > > - if (drm_panel_prepare(ptn_bridge->panel)) { > - DRM_ERROR("failed to prepare panel\n"); > - return; > - } > - > /* >* There's a bug in the PTN chip where it falsely asserts hotplug before >* it is fully functional. We're forced to wait for the maximum start up > @@ -145,16 +140,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) > ptn_bridge->enabled = true; > } > > -static void ptn3460_enable(struct drm_bridge *bridge) > -{ > - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); > - > - if (drm_panel_enable(ptn_bridge->panel)) { > - DRM_ERROR("failed to enable panel\n"); > - return; > - } > -} > - > static void ptn3460_disable(struct drm_bridge *bridge) > { > struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); > @@ -164,24 +149,10 @@ static void ptn3460_disable(struct drm_bridge *bridge) > > ptn_bridge->enabled = false; > > - if (drm_panel_disable(ptn_bridge->panel)) { > - DRM_ERROR("failed to disable panel\n"); > - return; > - } > - > gpiod_set_value(ptn_bridge->gpio_rst_n, 1); > gpiod_set_value(ptn_bridge->gpio_pd_n, 0); > } > > -static void ptn3460_post_disable(struct drm_bridge *bridge) > -{ > - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); > - > - if (drm_panel_unprepare(ptn_bridge->panel)) { > - DRM_ERROR("failed to unprepare panel\n"); > - return; > - } > -} > > static struct edid *ptn3460_get_edid(struct drm_bridge *bridge, >struct drm_connector *connector) > @@ -245,12 +216,18 @@ static int ptn3460_bridge_attach(struct drm_bridge > *bridge, >enum drm_bridge_attach_flags flags) > { > struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); > + enum drm_bridge_attach_flags panel_flags; > int ret; > > - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { > - DRM_ERROR("Fix bridge driver to make connector optional!"); > - return -EINVAL; > - } > + /* Let this driver create connector if requested */ > + panel_flags = flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR; > + ret = drm_bridge_attach(bridge->encoder, ptn_bridge->panel_bridge, > + bridge, panel_flags); Same here, you could write flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR); Reviewed-by: Laurent Pinchart > + if (ret < 0) > + return ret; > + > + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) > + return 0; > > if (!bridge->encoder) { > DRM_ERROR("Parent encoder object not found"); > @@ -270,9 +247,6 @@ static int ptn3460_bridge_attach(struct drm_bridge > *bridge, > drm_connector_attach_encoder(&ptn_bridge->connector, > bridge->encoder); > > - if (ptn_bridge->panel) > - drm_panel_attach(ptn_bridge->panel, &ptn_bridge->connector); > - > drm_helper_hpd_irq_event(ptn_bridge->connector.dev); > > return ret; > @@ -280,9 +254,7 @@ static int ptn3460_bridge_attach(struct drm_bridge > *bridge, > > static const struct drm_bridge_funcs ptn3460_bridge_funcs = { > .pre_enable = ptn3460_pre_enable, > - .enable = p
Re: [PATCH v5 3/5] drm/bridge: tc358767: add drm_panel_bridge support
Hi Sam, Thank you for the patch. On Mon, Jul 27, 2020 at 07:03:18PM +0200, Sam Ravnborg wrote: > With the bridge operations implemented the last step to prepare > this driver for a chained setup is the use of the bridge panel driver. > > The bridge panel driver is only used when a port@2 is present in > the DT. So when the display driver requests a connector > support both situations: > - connector created by bridge panel driver > - connector created by this driver > > And on top, support that the display driver creates the connector, > which is the preferred setup. > > Note: the bridge panel will use the connector type from the panel. > > v3: > - Fix wrong logic in connector creation (Laurent) > > v2: > - Merge connector and drm_panel_bridge patches > and fix so we do not create two connectors (Laurent) > > Signed-off-by: Sam Ravnborg > Cc: Laurent Pinchart > Cc: Andrzej Hajda > Cc: Neil Armstrong > Cc: Jonas Karlman > Cc: Jernej Skrabec > --- > drivers/gpu/drm/bridge/tc358767.c | 70 +++ > 1 file changed, 35 insertions(+), 35 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/tc358767.c > b/drivers/gpu/drm/bridge/tc358767.c > index b26c669f3e91..cbad2607ab43 100644 > --- a/drivers/gpu/drm/bridge/tc358767.c > +++ b/drivers/gpu/drm/bridge/tc358767.c > @@ -244,8 +244,8 @@ struct tc_data { > struct drm_dp_aux aux; > > struct drm_bridge bridge; > + struct drm_bridge *panel_bridge; > struct drm_connectorconnector; > - struct drm_panel*panel; > > /* link settings */ > struct tc_edp_link link; > @@ -1234,13 +1234,6 @@ static int tc_stream_disable(struct tc_data *tc) > return 0; > } > > -static void tc_bridge_pre_enable(struct drm_bridge *bridge) > -{ > - struct tc_data *tc = bridge_to_tc(bridge); > - > - drm_panel_prepare(tc->panel); > -} > - > static void tc_bridge_enable(struct drm_bridge *bridge) > { > struct tc_data *tc = bridge_to_tc(bridge); > @@ -1264,8 +1257,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) > tc_main_link_disable(tc); > return; > } > - > - drm_panel_enable(tc->panel); > } > > static void tc_bridge_disable(struct drm_bridge *bridge) > @@ -1273,8 +1264,6 @@ static void tc_bridge_disable(struct drm_bridge *bridge) > struct tc_data *tc = bridge_to_tc(bridge); > int ret; > > - drm_panel_disable(tc->panel); > - > ret = tc_stream_disable(tc); > if (ret < 0) > dev_err(tc->dev, "main link stream stop error: %d\n", ret); > @@ -1284,13 +1273,6 @@ static void tc_bridge_disable(struct drm_bridge > *bridge) > dev_err(tc->dev, "main link disable error: %d\n", ret); > } > > -static void tc_bridge_post_disable(struct drm_bridge *bridge) > -{ > - struct tc_data *tc = bridge_to_tc(bridge); > - > - drm_panel_unprepare(tc->panel); > -} > - > static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, >const struct drm_display_mode *mode, >struct drm_display_mode *adj) > @@ -1354,9 +1336,11 @@ static int tc_connector_get_modes(struct drm_connector > *connector) > return 0; > } > > - num_modes = drm_panel_get_modes(tc->panel, connector); > - if (num_modes > 0) > - return num_modes; > + if (tc->panel_bridge) { > + num_modes = drm_bridge_get_modes(tc->panel_bridge, connector); > + if (num_modes > 0) > + return num_modes; > + } > > edid = tc_get_edid(&tc->bridge, connector); > num_modes = drm_add_edid_modes(connector, edid); > @@ -1396,7 +1380,7 @@ tc_connector_detect(struct drm_connector *connector, > bool force) > if (tc->hpd_pin >= 0) > return tc_bridge_detect(&tc->bridge); > > - if (tc->panel) > + if (tc->panel_bridge) > return connector_status_connected; > else > return connector_status_unknown; > @@ -1419,16 +1403,23 @@ static int tc_bridge_attach(struct drm_bridge *bridge, > struct drm_device *drm = bridge->dev; > int ret; > > - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { > - DRM_ERROR("Fix bridge driver to make connector optional!"); > - return -EINVAL; > + if (tc->panel_bridge) { > + enum drm_bridge_attach_flags panel_flags; > + > + /* If a connector is required then this driver shall create it > */ > + panel_flags = flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR; > + ret = drm_bridge_attach(tc->bridge.encoder, tc->panel_bridge, > + &tc->bridge, panel_flags); You could write this flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR); and drop the panel_flags variable. Reviewed-by: Laurent Pinchart > + if (ret) > +
Re: [PATCH 3/6] drm/bridge: Add SPI DBI host driver
Hi Paul, Thank you for the patch. On Mon, Jul 27, 2020 at 06:46:10PM +0200, Paul Cercueil wrote: > This driver will register a DBI host driver for panels connected over > SPI. > > DBI types c1 and c3 are supported. C1 is a SPI protocol with 9 bits per > word, with the data/command information in the 9th (MSB) bit. C3 is a > SPI protocol with 8 bits per word, with the data/command information > carried by a separate GPIO. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/bridge/Kconfig | 8 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/dbi-spi.c | 261 +++ > 3 files changed, 270 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/dbi-spi.c > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index c7f0dacfb57a..ed38366847c1 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -219,6 +219,14 @@ config DRM_TI_TPD12S015 > Texas Instruments TPD12S015 HDMI level shifter and ESD protection > driver. > > +config DRM_MIPI_DBI_SPI > + tristate "SPI host support for MIPI DBI" > + depends on OF && SPI > + select DRM_MIPI_DSI > + select DRM_MIPI_DBI > + help > + Driver to support DBI over SPI. > + > source "drivers/gpu/drm/bridge/analogix/Kconfig" > > source "drivers/gpu/drm/bridge/adv7511/Kconfig" > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index 7d7c123a95e4..c2c522c2774f 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ > obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o > obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o > obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o > +obj-$(CONFIG_DRM_MIPI_DBI_SPI) += dbi-spi.o > obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o > > obj-y += analogix/ > diff --git a/drivers/gpu/drm/bridge/dbi-spi.c > b/drivers/gpu/drm/bridge/dbi-spi.c > new file mode 100644 > index ..1060b8f95fba > --- /dev/null > +++ b/drivers/gpu/drm/bridge/dbi-spi.c > @@ -0,0 +1,261 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * MIPI Display Bus Interface (DBI) SPI support > + * > + * Copyright 2016 Noralf Trønnes > + * Copyright 2020 Paul Cercueil > + */ > + > +#include > +#include > +#include > + > +#include > +#include > + > +#include > + > +struct dbi_spi { > + struct mipi_dsi_host host; > + struct mipi_dsi_host_ops host_ops; > + > + struct spi_device *spi; > + struct gpio_desc *dc; > + struct mutex cmdlock; > + > + unsigned int current_bus_type; > + > + /** > + * @tx_buf9: Buffer used for Option 1 9-bit conversion > + */ > + void *tx_buf9; > + > + /** > + * @tx_buf9_len: Size of tx_buf9. > + */ > + size_t tx_buf9_len; > +}; > + > +static inline struct dbi_spi *host_to_dbi_spi(struct mipi_dsi_host *host) > +{ > + return container_of(host, struct dbi_spi, host); > +} > + > +static ssize_t dbi_spi1_transfer(struct mipi_dsi_host *host, > + const struct mipi_dsi_msg *msg) > +{ > + struct dbi_spi *dbi = host_to_dbi_spi(host); > + struct spi_device *spi = dbi->spi; > + struct spi_transfer tr = { > + .bits_per_word = 9, > + }; > + const u8 *src8 = msg->tx_buf; > + struct spi_message m; > + size_t max_chunk, chunk; > + size_t len = msg->tx_len; > + bool cmd_byte = true; > + unsigned int i; > + u16 *dst16; > + int ret; > + > + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); > + dst16 = dbi->tx_buf9; > + > + max_chunk = min(dbi->tx_buf9_len / 2, len); > + > + spi_message_init_with_transfers(&m, &tr, 1); > + tr.tx_buf = dst16; > + > + while (len) { > + chunk = min(len, max_chunk); > + > + for (i = 0; i < chunk; i++) { > + dst16[i] = *src8++; > + > + /* Bit 9: 0 means command, 1 means data */ > + if (!cmd_byte) > + dst16[i] |= BIT(9); > + > + cmd_byte = false; > + } > + > + tr.len = chunk * 2; > + len -= chunk; > + > + ret = spi_sync(spi, &m); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static ssize_t dbi_spi3_transfer(struct mipi_dsi_host *host, > + const struct mipi_dsi_msg *msg) > +{ > + struct dbi_spi *dbi = host_to_dbi_spi(host); > + struct spi_device *spi = dbi->spi; > + const u8 *buf = msg->tx_buf; > + unsigned int bpw = 8; > + u32 speed_hz; > + ssize_t ret; > + > + /* for now we only support sending messages, not receiving */ > + if (msg->rx_len) > + return -EINVAL; > + > + gpiod_set_value_cansleep(dbi->dc, 0); > + > + speed_hz = mipi_dbi_spi_cmd_max_speed(spi
[PATCH v5 2/5] drm/bridge: tc358767: add get_edid bridge operation
Prepare for chained bridge with the addition of get_edid support. v2: - Fixed handling of edid storage (Laurent) Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec --- drivers/gpu/drm/bridge/tc358767.c | 34 --- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index bde89e213882..b26c669f3e91 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -250,8 +250,6 @@ struct tc_data { /* link settings */ struct tc_edp_link link; - /* display edid */ - struct edid *edid; /* current mode */ struct drm_display_mode mode; @@ -1335,11 +1333,19 @@ static void tc_bridge_mode_set(struct drm_bridge *bridge, tc->mode = *mode; } +static struct edid *tc_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct tc_data *tc = bridge_to_tc(bridge); + + return drm_get_edid(connector, &tc->aux.ddc); +} + static int tc_connector_get_modes(struct drm_connector *connector) { struct tc_data *tc = connector_to_tc(connector); + int num_modes; struct edid *edid; - int count; int ret; ret = tc_get_display_props(tc); @@ -1348,21 +1354,15 @@ static int tc_connector_get_modes(struct drm_connector *connector) return 0; } - count = drm_panel_get_modes(tc->panel, connector); - if (count > 0) - return count; - - edid = drm_get_edid(connector, &tc->aux.ddc); - - kfree(tc->edid); - tc->edid = edid; - if (!edid) - return 0; + num_modes = drm_panel_get_modes(tc->panel, connector); + if (num_modes > 0) + return num_modes; - drm_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); + edid = tc_get_edid(&tc->bridge, connector); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); - return count; + return num_modes; } static const struct drm_connector_helper_funcs tc_connector_helper_funcs = { @@ -1465,6 +1465,7 @@ static const struct drm_bridge_funcs tc_bridge_funcs = { .post_disable = tc_bridge_post_disable, .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, + .get_edid = tc_get_edid, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) @@ -1689,6 +1690,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->bridge.funcs = &tc_bridge_funcs; if (tc->hpd_pin >= 0) tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; + tc->bridge.ops |= DRM_BRIDGE_OP_EDID; tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 0/5] drm/bridge: Update tc358767 and nxp-ptn3460 to support chained bridges
This patch-set aims to make connector creation optional and prepare the bridge drivers for use in a chained setup. The objective is that all bridge drivers shall support a chained setup connector creation is moved to the display drivers. This is just one step on this path. The general approach for the bridge drivers: - Introduce bridge operations - Introduce use of panel bridge and make connector creation optional v5: - Applied reviewed patches, so we went from 15 to 5 - Fixed bug in connector creation in both drivers v4: - Dropped patch for ti-sn65dsi86. Await full conversion - Dropped patch for ti-tpd12s015. It was wrong (Laurent) - Drop boe,hv070wsa-100 patch, it was applied - Combined a few patches to fix connector created twice (Laurent) - Fix memory leak in get_edid (Laurent) - Added patch to validate panel descriptions in panel-simple - Set bridge.type in relevant drivers v3: - Rebase on top of drm-misc-next - Address kbuild test robot feedback v2: - Updated bus_flags for boe,hv070wsa-100 - Collected r-b, but did not apply patches yet - On the panel side the panel-simple driver gained a default connector type for all the dumb panels that do not include so in their description. With this change panels always provide a connector type, and we have the potential to drop most uses of devm_drm_panel_bridge_add_typed(). - Added conversion of a few more bridge drivers Patches can build but no run-time testing. So both test and review feedback appreciated! Sam Sam Ravnborg (5): drm/bridge: tc358767: add detect bridge operation drm/bridge: tc358767: add get_edid bridge operation drm/bridge: tc358767: add drm_panel_bridge support drm/bridge: nxp-ptn3460: add get_edid bridge operation drm/bridge: nxp-ptn3460: add drm_panel_bridge support drivers/gpu/drm/bridge/nxp-ptn3460.c | 103 +--- drivers/gpu/drm/bridge/tc358767.c| 126 +++ 2 files changed, 114 insertions(+), 115 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 5/5] drm/bridge: nxp-ptn3460: add drm_panel_bridge support
Prepare the bridge driver for use in a chained setup. - Replacing direct use of drm_panel with drm_panel_bridge support. - Make the connector creation optional Note: the bridge panel will use the connector type from the panel. v3: - Fix wrong logic in connector creation (Laurent) v2: - Use panel_bridge for local variable name to align with other drivers - Fix that connector was created twice (Laurent) - Set bridge.type to DRM_MODE_CONNECTOR_LVDS. Signed-off-by: Sam Ravnborg Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 60 ++-- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 2805c8938f98..391c1f66f60f 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -29,7 +29,7 @@ struct ptn3460_bridge { struct drm_connector connector; struct i2c_client *client; struct drm_bridge bridge; - struct drm_panel *panel; + struct drm_bridge *panel_bridge; struct gpio_desc *gpio_pd_n; struct gpio_desc *gpio_rst_n; u32 edid_emulation; @@ -126,11 +126,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) usleep_range(10, 20); gpiod_set_value(ptn_bridge->gpio_rst_n, 1); - if (drm_panel_prepare(ptn_bridge->panel)) { - DRM_ERROR("failed to prepare panel\n"); - return; - } - /* * There's a bug in the PTN chip where it falsely asserts hotplug before * it is fully functional. We're forced to wait for the maximum start up @@ -145,16 +140,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) ptn_bridge->enabled = true; } -static void ptn3460_enable(struct drm_bridge *bridge) -{ - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); - - if (drm_panel_enable(ptn_bridge->panel)) { - DRM_ERROR("failed to enable panel\n"); - return; - } -} - static void ptn3460_disable(struct drm_bridge *bridge) { struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); @@ -164,24 +149,10 @@ static void ptn3460_disable(struct drm_bridge *bridge) ptn_bridge->enabled = false; - if (drm_panel_disable(ptn_bridge->panel)) { - DRM_ERROR("failed to disable panel\n"); - return; - } - gpiod_set_value(ptn_bridge->gpio_rst_n, 1); gpiod_set_value(ptn_bridge->gpio_pd_n, 0); } -static void ptn3460_post_disable(struct drm_bridge *bridge) -{ - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); - - if (drm_panel_unprepare(ptn_bridge->panel)) { - DRM_ERROR("failed to unprepare panel\n"); - return; - } -} static struct edid *ptn3460_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) @@ -245,12 +216,18 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); + enum drm_bridge_attach_flags panel_flags; int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } + /* Let this driver create connector if requested */ + panel_flags = flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR; + ret = drm_bridge_attach(bridge->encoder, ptn_bridge->panel_bridge, + bridge, panel_flags); + if (ret < 0) + return ret; + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; if (!bridge->encoder) { DRM_ERROR("Parent encoder object not found"); @@ -270,9 +247,6 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, drm_connector_attach_encoder(&ptn_bridge->connector, bridge->encoder); - if (ptn_bridge->panel) - drm_panel_attach(ptn_bridge->panel, &ptn_bridge->connector); - drm_helper_hpd_irq_event(ptn_bridge->connector.dev); return ret; @@ -280,9 +254,7 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs ptn3460_bridge_funcs = { .pre_enable = ptn3460_pre_enable, - .enable = ptn3460_enable, .disable = ptn3460_disable, - .post_disable = ptn3460_post_disable, .attach = ptn3460_bridge_attach, .get_edid = ptn3460_get_edid, }; @@ -292,6 +264,8 @@ static int ptn3460_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct ptn3460_bridge *ptn_bridge; + struct drm_bridge *panel_br
[PATCH v5 3/5] drm/bridge: tc358767: add drm_panel_bridge support
With the bridge operations implemented the last step to prepare this driver for a chained setup is the use of the bridge panel driver. The bridge panel driver is only used when a port@2 is present in the DT. So when the display driver requests a connector support both situations: - connector created by bridge panel driver - connector created by this driver And on top, support that the display driver creates the connector, which is the preferred setup. Note: the bridge panel will use the connector type from the panel. v3: - Fix wrong logic in connector creation (Laurent) v2: - Merge connector and drm_panel_bridge patches and fix so we do not create two connectors (Laurent) Signed-off-by: Sam Ravnborg Cc: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Jonas Karlman Cc: Jernej Skrabec --- drivers/gpu/drm/bridge/tc358767.c | 70 +++ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index b26c669f3e91..cbad2607ab43 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -244,8 +244,8 @@ struct tc_data { struct drm_dp_aux aux; struct drm_bridge bridge; + struct drm_bridge *panel_bridge; struct drm_connectorconnector; - struct drm_panel*panel; /* link settings */ struct tc_edp_link link; @@ -1234,13 +1234,6 @@ static int tc_stream_disable(struct tc_data *tc) return 0; } -static void tc_bridge_pre_enable(struct drm_bridge *bridge) -{ - struct tc_data *tc = bridge_to_tc(bridge); - - drm_panel_prepare(tc->panel); -} - static void tc_bridge_enable(struct drm_bridge *bridge) { struct tc_data *tc = bridge_to_tc(bridge); @@ -1264,8 +1257,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) tc_main_link_disable(tc); return; } - - drm_panel_enable(tc->panel); } static void tc_bridge_disable(struct drm_bridge *bridge) @@ -1273,8 +1264,6 @@ static void tc_bridge_disable(struct drm_bridge *bridge) struct tc_data *tc = bridge_to_tc(bridge); int ret; - drm_panel_disable(tc->panel); - ret = tc_stream_disable(tc); if (ret < 0) dev_err(tc->dev, "main link stream stop error: %d\n", ret); @@ -1284,13 +1273,6 @@ static void tc_bridge_disable(struct drm_bridge *bridge) dev_err(tc->dev, "main link disable error: %d\n", ret); } -static void tc_bridge_post_disable(struct drm_bridge *bridge) -{ - struct tc_data *tc = bridge_to_tc(bridge); - - drm_panel_unprepare(tc->panel); -} - static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adj) @@ -1354,9 +1336,11 @@ static int tc_connector_get_modes(struct drm_connector *connector) return 0; } - num_modes = drm_panel_get_modes(tc->panel, connector); - if (num_modes > 0) - return num_modes; + if (tc->panel_bridge) { + num_modes = drm_bridge_get_modes(tc->panel_bridge, connector); + if (num_modes > 0) + return num_modes; + } edid = tc_get_edid(&tc->bridge, connector); num_modes = drm_add_edid_modes(connector, edid); @@ -1396,7 +1380,7 @@ tc_connector_detect(struct drm_connector *connector, bool force) if (tc->hpd_pin >= 0) return tc_bridge_detect(&tc->bridge); - if (tc->panel) + if (tc->panel_bridge) return connector_status_connected; else return connector_status_unknown; @@ -1419,16 +1403,23 @@ static int tc_bridge_attach(struct drm_bridge *bridge, struct drm_device *drm = bridge->dev; int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; + if (tc->panel_bridge) { + enum drm_bridge_attach_flags panel_flags; + + /* If a connector is required then this driver shall create it */ + panel_flags = flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR; + ret = drm_bridge_attach(tc->bridge.encoder, tc->panel_bridge, + &tc->bridge, panel_flags); + if (ret) + return ret; } + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; + /* Create DP/eDP connector */ drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); - ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, -tc->panel ? DRM_MODE_CONNECTOR_eDP : -DRM_MODE_CONNECTOR_Displ
[PATCH v5 1/5] drm/bridge: tc358767: add detect bridge operation
Prepare the bridge driver for chained operation by adding support for the detect operation. v3: - Fix code to make it readable (Laurent) v2: - Do not announce detect operation if there is no hpd pin (Laurent) Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec --- drivers/gpu/drm/bridge/tc358767.c | 30 -- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index c2777b226c75..bde89e213882 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1369,21 +1369,13 @@ static const struct drm_connector_helper_funcs tc_connector_helper_funcs = { .get_modes = tc_connector_get_modes, }; -static enum drm_connector_status tc_connector_detect(struct drm_connector *connector, -bool force) +static enum drm_connector_status tc_bridge_detect(struct drm_bridge *bridge) { - struct tc_data *tc = connector_to_tc(connector); + struct tc_data *tc = bridge_to_tc(bridge); bool conn; u32 val; int ret; - if (tc->hpd_pin < 0) { - if (tc->panel) - return connector_status_connected; - else - return connector_status_unknown; - } - ret = regmap_read(tc->regmap, GPIOI, &val); if (ret) return connector_status_unknown; @@ -1396,6 +1388,20 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne return connector_status_disconnected; } +static enum drm_connector_status +tc_connector_detect(struct drm_connector *connector, bool force) +{ + struct tc_data *tc = connector_to_tc(connector); + + if (tc->hpd_pin >= 0) + return tc_bridge_detect(&tc->bridge); + + if (tc->panel) + return connector_status_connected; + else + return connector_status_unknown; +} + static const struct drm_connector_funcs tc_connector_funcs = { .detect = tc_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -1458,6 +1464,7 @@ static const struct drm_bridge_funcs tc_bridge_funcs = { .disable = tc_bridge_disable, .post_disable = tc_bridge_post_disable, .mode_fixup = tc_bridge_mode_fixup, + .detect = tc_bridge_detect, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) @@ -1680,6 +1687,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) return ret; tc->bridge.funcs = &tc_bridge_funcs; + if (tc->hpd_pin >= 0) + tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; + tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v5 4/5] drm/bridge: nxp-ptn3460: add get_edid bridge operation
Add the get_edid() bridge operation to prepare for use as a chained bridge. Add helper function that is also used by the connector. v2: - Fix memory leak (Laurent) - Do not save a copy of edid, read it when needed Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 43 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 438e566ce0a4..2805c8938f98 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -29,7 +29,6 @@ struct ptn3460_bridge { struct drm_connector connector; struct i2c_client *client; struct drm_bridge bridge; - struct edid *edid; struct drm_panel *panel; struct gpio_desc *gpio_pd_n; struct gpio_desc *gpio_rst_n; @@ -184,17 +183,13 @@ static void ptn3460_post_disable(struct drm_bridge *bridge) } } -static int ptn3460_get_modes(struct drm_connector *connector) +static struct edid *ptn3460_get_edid(struct drm_bridge *bridge, +struct drm_connector *connector) { - struct ptn3460_bridge *ptn_bridge; - u8 *edid; - int ret, num_modes = 0; + struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); bool power_off; - - ptn_bridge = connector_to_ptn3460(connector); - - if (ptn_bridge->edid) - return drm_add_edid_modes(connector, ptn_bridge->edid); + u8 *edid; + int ret; power_off = !ptn_bridge->enabled; ptn3460_pre_enable(&ptn_bridge->bridge); @@ -202,30 +197,40 @@ static int ptn3460_get_modes(struct drm_connector *connector) edid = kmalloc(EDID_LENGTH, GFP_KERNEL); if (!edid) { DRM_ERROR("Failed to allocate EDID\n"); - return 0; + goto out; } ret = ptn3460_read_bytes(ptn_bridge, PTN3460_EDID_ADDR, edid, - EDID_LENGTH); +EDID_LENGTH); if (ret) { kfree(edid); + edid = NULL; goto out; } - ptn_bridge->edid = (struct edid *)edid; - drm_connector_update_edid_property(connector, ptn_bridge->edid); - - num_modes = drm_add_edid_modes(connector, ptn_bridge->edid); - out: if (power_off) ptn3460_disable(&ptn_bridge->bridge); + return (struct edid *)edid; +} + +static int ptn3460_connector_get_modes(struct drm_connector *connector) +{ + struct ptn3460_bridge *ptn_bridge = connector_to_ptn3460(connector); + struct edid *edid; + int num_modes; + + edid = ptn3460_get_edid(&ptn_bridge->bridge, connector); + drm_connector_update_edid_property(connector, edid); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); + return num_modes; } static const struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = { - .get_modes = ptn3460_get_modes, + .get_modes = ptn3460_connector_get_modes, }; static const struct drm_connector_funcs ptn3460_connector_funcs = { @@ -279,6 +284,7 @@ static const struct drm_bridge_funcs ptn3460_bridge_funcs = { .disable = ptn3460_disable, .post_disable = ptn3460_post_disable, .attach = ptn3460_bridge_attach, + .get_edid = ptn3460_get_edid, }; static int ptn3460_probe(struct i2c_client *client, @@ -327,6 +333,7 @@ static int ptn3460_probe(struct i2c_client *client, } ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; + ptn_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; ptn_bridge->bridge.of_node = dev->of_node; drm_bridge_add(&ptn_bridge->bridge); -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/6] drm: dsi: Let host and device specify supported bus
Hi Paul, Thank you for the patch. On Mon, Jul 27, 2020 at 06:46:09PM +0200, Paul Cercueil wrote: > The current MIPI DSI framework can very well be used to support MIPI DBI > panels. In order to add support for the various bus types supported by > DBI, the DRM panel drivers should specify the bus type they will use, > and the DSI host drivers should specify the bus types they are > compatible with. > > The DSI host driver can then use the information provided by the DBI/DSI > device driver, such as the bus type and the number of lanes, to > configure its hardware properly. > > Signed-off-by: Paul Cercueil > --- > drivers/gpu/drm/drm_mipi_dsi.c | 9 + > include/drm/drm_mipi_dsi.h | 12 Use the mipi_dsi_* API for DBI panels will be very confusing to say the least. Can we consider a global name refactoring to clarify all this ? > 2 files changed, 21 insertions(+) > > diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c > index 5dd475e82995..11ef885de765 100644 > --- a/drivers/gpu/drm/drm_mipi_dsi.c > +++ b/drivers/gpu/drm/drm_mipi_dsi.c > @@ -281,6 +281,9 @@ int mipi_dsi_host_register(struct mipi_dsi_host *host) > { > struct device_node *node; > > + if (WARN_ON_ONCE(!host->bus_types)) > + host->bus_types = MIPI_DEVICE_TYPE_DSI; > + > for_each_available_child_of_node(host->dev->of_node, node) { > /* skip nodes without reg property */ > if (!of_find_property(node, "reg", NULL)) > @@ -323,6 +326,12 @@ int mipi_dsi_attach(struct mipi_dsi_device *dsi) > { > const struct mipi_dsi_host_ops *ops = dsi->host->ops; > > + if (WARN_ON_ONCE(!dsi->bus_type)) > + dsi->bus_type = MIPI_DEVICE_TYPE_DSI; > + > + if (!(dsi->bus_type & dsi->host->bus_types)) > + return -EINVAL; > + > if (!ops || !ops->attach) > return -ENOSYS; > > diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h > index 360e6377e84b..65d2961fc054 100644 > --- a/include/drm/drm_mipi_dsi.h > +++ b/include/drm/drm_mipi_dsi.h > @@ -63,6 +63,14 @@ struct mipi_dsi_packet { > int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, > const struct mipi_dsi_msg *msg); > > +/* MIPI bus types */ > +#define MIPI_DEVICE_TYPE_DSI BIT(0) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE1 BIT(1) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE2 BIT(2) > +#define MIPI_DEVICE_TYPE_DBI_SPI_MODE3 BIT(3) > +#define MIPI_DEVICE_TYPE_DBI_M6800 BIT(4) > +#define MIPI_DEVICE_TYPE_DBI_I8080 BIT(5) > + > /** > * struct mipi_dsi_host_ops - DSI bus operations > * @attach: attach DSI device to DSI host > @@ -94,11 +102,13 @@ struct mipi_dsi_host_ops { > * struct mipi_dsi_host - DSI host device > * @dev: driver model device node for this DSI host > * @ops: DSI host operations > + * @bus_types: Bitmask of supported MIPI bus types > * @list: list management > */ > struct mipi_dsi_host { > struct device *dev; > const struct mipi_dsi_host_ops *ops; > + unsigned int bus_types; > struct list_head list; > }; > > @@ -162,6 +172,7 @@ struct mipi_dsi_device_info { > * @host: DSI host for this peripheral > * @dev: driver model device node for this peripheral > * @name: DSI peripheral chip type > + * @bus_type: MIPI bus type (MIPI_DEVICE_TYPE_DSI/...) > * @channel: virtual channel assigned to the peripheral > * @format: pixel format for video mode > * @lanes: number of active data lanes > @@ -178,6 +189,7 @@ struct mipi_dsi_device { > struct device dev; > > char name[DSI_DEV_NAME_SIZE]; > + unsigned int bus_type; > unsigned int channel; > unsigned int lanes; > enum mipi_dsi_pixel_format format; -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 0/15] drm/bridge: support chained bridges + panel updates
Hi Laurent/all. On Sun, Jul 26, 2020 at 10:33:09PM +0200, Sam Ravnborg wrote: > The objective is that all bridge drivers shall support a chained setup > connector creation is moved to the display drivers. > This is just one step on this path. > > The general approach for the bridge drivers: > - Introduce bridge operations > - Introduce use of panel bridge and make connector creation optional > > v4: > - Dropped patch for ti-sn65dsi86. Await full conversion. > - Dropped patch for ti-tpd12s015. It was wrong (Laurent) > - Drop boe,hv070wsa-100 patch, it was applied > - Combined a few patches to fix connector created twice (Laurent) > - Fix memory leak in get_edid in several drivers (Laurent) > - Added patch to validate panel descriptions in panel-simple > - Set bridge.type in relevant drivers > > v3: > - Rebase on top of drm-misc-next > - Address kbuild test robot feedback > > v2: > - Updated bus_flags for boe,hv070wsa-100 > - Collected r-b, but did not apply patches yet > - On the panel side the panel-simple driver gained a default > connector type for all the dumb panels that do not > include so in their description. > With this change panels always provide a connector type, > and we have the potential to drop most uses of > devm_drm_panel_bridge_add_typed(). > - Added conversion of a few more bridge drivers > > Patches can build but no run-time testing. > So both test and review feedback appreciated! > > Sam > > Sam Ravnborg (15): > drm/panel: panel-simple: validate panel description > drm/panel: panel-simple: add default connector_type > drm/bridge: tc358764: drop drm_connector_(un)register > drm/bridge: tc358764: add drm_panel_bridge support > drm/bridge: tc358767: add detect bridge operation > drm/bridge: tc358767: add get_edid bridge operation > drm/bridge: tc358767: add drm_panel_bridge support > drm/bridge: parade-ps8622: add drm_panel_bridge support > drm/bridge: megachips: add helper to create connector > drm/bridge: megachips: get drm_device from bridge > drm/bridge: megachips: enable detect bridge operation > drm/bridge: megachips: add get_edid bridge operation > drm/bridge: megachips: make connector creation optional > drm/bridge: nxp-ptn3460: add get_edid bridge operation > drm/bridge: nxp-ptn3460: add drm_panel_bridge support Laurent reviewed the full series - thanks! I went ahead and applied the patches for drivers where all patches was reviewed. I will send a v5 soon for tc358767 and nxp-ptn3460 where I have fixed my brown paper bag bugs . I am very happy Laurent spotted these before we applied the patches. This also gives a good indication of the quality of the review. Sam > > .../drm/bridge/megachips-stdp-ge-b850v3-fw.c | 97 +--- > drivers/gpu/drm/bridge/nxp-ptn3460.c | 103 - > drivers/gpu/drm/bridge/parade-ps8622.c | 100 +++- > drivers/gpu/drm/bridge/tc358764.c | 110 +++--- > drivers/gpu/drm/bridge/tc358767.c | 126 > +++-- > drivers/gpu/drm/panel/panel-simple.c | 48 +++- > 6 files changed, 242 insertions(+), 342 deletions(-) > > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207383] [Regression] 5.7 amdgpu/polaris11 gpf: amdgpu_atomic_commit_tail
https://bugzilla.kernel.org/show_bug.cgi?id=207383 --- Comment #101 from Duncan (1i5t5.dun...@cox.net) --- (In reply to Nicholas Kazlauskas from comment #95) > Created attachment 290583 [details] > 0001-drm-amd-display-Force-add-all-CRTCs-to-state-when-us.patch Just booted to 5.8-rc7 with this patched in locally (and the g320+ reverts /not/ patched in). So testing, but noting again that the bug can take a couple days to trigger on my hardware, so while verifying bug-still-there /might/ be fast, verifying that it's /not/ there will take awhile. If this still bugs on me (and barring other developments first) I'll try mnrzk's patch in place of this one. Even if it's not permanent, getting it into 5.8 as a temporary fix and doing something better for 5.9 would buy us some time to develop and test the more permanent fix. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 204241] amdgpu fails to resume from suspend
https://bugzilla.kernel.org/show_bug.cgi?id=204241 --- Comment #64 from felipejfc (fjfcavalca...@gmail.com) --- (In reply to felipejfc from comment #63) > I'm having the same issue with an AMD RX5700 and kernel version 5.7.9-1 on > manjaro linux. > > for me adding kernel params 'amd_iommu=on iommu=pt' didn't solve the > problem. graphics won't turn on so monitor just keeps blinking complementing my last answer, the "fix" that worked for me was to disable IOMMU on BIOS -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 204241] amdgpu fails to resume from suspend
https://bugzilla.kernel.org/show_bug.cgi?id=204241 felipejfc (fjfcavalca...@gmail.com) changed: What|Removed |Added CC||fjfcavalca...@gmail.com --- Comment #63 from felipejfc (fjfcavalca...@gmail.com) --- I'm having the same issue with an AMD RX5700 and kernel version 5.7.9-1 on manjaro linux. for me adding kernel params 'amd_iommu=on iommu=pt' didn't solve the problem. graphics won't turn on so monitor just keeps blinking -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207901] Nouveau: In a 4 monitor setup, 1-2 displays remains black after boot
https://bugzilla.kernel.org/show_bug.cgi?id=207901 --- Comment #27 from Ilia Mirkin (imir...@alum.mit.edu) --- DP -> HDMI is, most likely, just passive, so the displays are being driven as HDMI rather than as DP. DP is the problematic protocol... -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 207901] Nouveau: In a 4 monitor setup, 1-2 displays remains black after boot
https://bugzilla.kernel.org/show_bug.cgi?id=207901 --- Comment #26 from Maurice Gale (mauricega...@gmail.com) --- Sorry for the delay and the mistake. It loaded the 5.3 kernel by default. I recreated the log using 5.7-rc5 with the i2c timeout patch. I also added the new grub options. The file size is much larger than the old one, so it should be correct this time. I noticed that I have more luck getting all monitors displayed when I do not have the Display->MiniDisplay connected (Swap it out for Display->HDMI). It seems as though mini display is causing some issues. Again, thank you so much for your help, and please let me know if you need anything else. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 08/15] drm/bridge: parade-ps8622: add drm_panel_bridge support
Hi Laurent. On Mon, Jul 27, 2020 at 12:54:08AM +0300, Laurent Pinchart wrote: > Hi Sam, > > Thank you for the patch. > > On Sun, Jul 26, 2020 at 10:33:17PM +0200, Sam Ravnborg wrote: > > Prepare the bridge driver for use in a chained setup by > > replacing direct use of drm_panel with drm_panel_bridge support. > > > > The connecter is now either created by the panel bridge or the display > > driver. So all code for connector creation in this driver is no longer > > relevant and thus dropped. > > > > The connector code had some special polling handling: > > connector.polled = DRM_CONNECTOR_POLL_HPD; > > drm_helper_hpd_irq_event(ps8622->bridge.dev); > > > > This code was most likely added to speed up detection of the connector. > > If really needed then this functionality belongs somewhere else. > > > > Note: the bridge panel will use the connector type from the panel. > > > > v2: > > - Fix to avoid creating connector twice (Laurent) > > - Drop all connector code - defer to bridge panel > > - Use panel_bridge for local variable to align with other drivers > > - Set bridge.type to DRM_MODE_CONNECTOR_LVDS; > > > > Signed-off-by: Sam Ravnborg > > Cc: Andrzej Hajda > > Cc: Neil Armstrong > > Cc: Laurent Pinchart > > Cc: Jonas Karlman > > Cc: Jernej Skrabec > > --- > > drivers/gpu/drm/bridge/parade-ps8622.c | 100 - > > 1 file changed, 13 insertions(+), 87 deletions(-) > > > > diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c > > b/drivers/gpu/drm/bridge/parade-ps8622.c > > index d789ea2a7fb9..614b19f0f1b7 100644 > > --- a/drivers/gpu/drm/bridge/parade-ps8622.c > > +++ b/drivers/gpu/drm/bridge/parade-ps8622.c > > @@ -42,10 +42,9 @@ > > #endif > > > > struct ps8622_bridge { > > - struct drm_connector connector; > > struct i2c_client *client; > > struct drm_bridge bridge; > > - struct drm_panel *panel; > > + struct drm_bridge *panel_bridge; > > struct regulator *v12; > > struct backlight_device *bl; > > > > @@ -64,12 +63,6 @@ static inline struct ps8622_bridge * > > return container_of(bridge, struct ps8622_bridge, bridge); > > } > > > > -static inline struct ps8622_bridge * > > - connector_to_ps8622(struct drm_connector *connector) > > -{ > > - return container_of(connector, struct ps8622_bridge, connector); > > -} > > - > > static int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val) > > { > > int ret; > > @@ -365,11 +358,6 @@ static void ps8622_pre_enable(struct drm_bridge > > *bridge) > > DRM_ERROR("fails to enable ps8622->v12"); > > } > > > > - if (drm_panel_prepare(ps8622->panel)) { > > - DRM_ERROR("failed to prepare panel\n"); > > - return; > > - } > > - > > gpiod_set_value(ps8622->gpio_slp, 1); > > > > /* > > @@ -399,24 +387,9 @@ static void ps8622_pre_enable(struct drm_bridge > > *bridge) > > ps8622->enabled = true; > > } > > > > -static void ps8622_enable(struct drm_bridge *bridge) > > -{ > > - struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); > > - > > - if (drm_panel_enable(ps8622->panel)) { > > - DRM_ERROR("failed to enable panel\n"); > > - return; > > - } > > -} > > - > > static void ps8622_disable(struct drm_bridge *bridge) > > { > > - struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); > > - > > - if (drm_panel_disable(ps8622->panel)) { > > - DRM_ERROR("failed to disable panel\n"); > > - return; > > - } > > + /* Delay after panel is disabled */ > > msleep(PS8622_PWMO_END_T12_MS); > > I really don't understand why a delay would be needed here. > Neither do I. I was there in the original code and I have kept it. > Reviewed-by: Laurent Pinchart Thanks. Sam > > > } > > > > @@ -436,11 +409,6 @@ static void ps8622_post_disable(struct drm_bridge > > *bridge) > > */ > > gpiod_set_value(ps8622->gpio_slp, 0); > > > > - if (drm_panel_unprepare(ps8622->panel)) { > > - DRM_ERROR("failed to unprepare panel\n"); > > - return; > > - } > > - > > if (ps8622->v12) > > regulator_disable(ps8622->v12); > > > > @@ -455,67 +423,17 @@ static void ps8622_post_disable(struct drm_bridge > > *bridge) > > msleep(PS8622_POWER_OFF_T17_MS); > > } > > > > -static int ps8622_get_modes(struct drm_connector *connector) > > -{ > > - struct ps8622_bridge *ps8622; > > - > > - ps8622 = connector_to_ps8622(connector); > > - > > - return drm_panel_get_modes(ps8622->panel, connector); > > -} > > - > > -static const struct drm_connector_helper_funcs > > ps8622_connector_helper_funcs = { > > - .get_modes = ps8622_get_modes, > > -}; > > - > > -static const struct drm_connector_funcs ps8622_connector_funcs = { > > - .fill_modes = drm_helper_probe_single_connector_modes, > > - .destroy = drm_connector_cleanup, > > - .reset = drm_atomic_helper_connector_reset, > > - .atomic_duplicate_state =
[Bug 208661] Backlight doesn't work with both nv_backlight and acpi_video
https://bugzilla.kernel.org/show_bug.cgi?id=208661 --- Comment #7 from Shannon Gaines (iknstu...@protonmail.com) --- Created attachment 290619 --> https://bugzilla.kernel.org/attachment.cgi?id=290619&action=edit Patch to add NvForceGpioReset config option I created a patch that allows users to force a GPIO reset everytime the GPU is initialized as a work-around for this bug. I've attached it. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 4/4] xen: add helpers to allocate unpopulated memory
On 27.07.20 11:13, Roger Pau Monne wrote: To be used in order to create foreign mappings. This is based on the ZONE_DEVICE facility which is used by persistent memory devices in order to create struct pages and kernel virtual mappings for the IOMEM areas of such devices. Note that on kernels without support for ZONE_DEVICE Xen will fallback to use ballooned pages in order to create foreign mappings. The newly added helpers use the same parameters as the existing {alloc/free}_xenballooned_pages functions, which allows for in-place replacement of the callers. Once a memory region has been added to be used as scratch mapping space it will no longer be released, and pages returned are kept in a linked list. This allows to have a buffer of pages and prevents resorting to frequent additions and removals of regions. If enabled (because ZONE_DEVICE is supported) the usage of the new functionality untangles Xen balloon and RAM hotplug from the usage of unpopulated physical memory ranges to map foreign pages, which is the correct thing to do in order to avoid mappings of foreign pages depend on memory hotplug. Signed-off-by: Roger Pau Monné --- I've not added a new memory_type type and just used MEMORY_DEVICE_DEVDAX which seems to be what we want for such memory regions. I'm unsure whether abusing this type is fine, or if I should instead add a specific type, maybe MEMORY_DEVICE_GENERIC? I don't think we should be using a specific Xen type at all. What about introducing MEMORY_DEVICE_VIRT? The comment for MEMORY_DEVICE_DEVDAX doesn't really fit, as there is no character device involved. In the end its the memory management maintainers to decide that. Other than that you can have my Reviewed-by: Juergen Gross Juergen ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm/drm_fb_helper: fix fbdev with sparc64
Hi Daniel On Mon, Jul 27, 2020 at 11:20:13AM +0200, Daniel Vetter wrote: > On Sat, Jul 25, 2020 at 9:10 PM Sam Ravnborg wrote: > > > > From 1323a7433691aee112a9b2df8041b5024895a77e Mon Sep 17 00:00:00 2001 > > From: Sam Ravnborg > > Date: Thu, 9 Jul 2020 21:30:16 +0200 > > Subject: [PATCH v2 1/1] drm/drm_fb_helper: fix fbdev with sparc64 > > > > Recent kernels have been reported to panic using the bochs_drm framebuffer > > under > > qemu-system-sparc64 which was bisected to commit 7a0483ac4ffc "drm/bochs: > > switch to > > generic drm fbdev emulation". The backtrace indicates that the shadow > > framebuffer > > copy in drm_fb_helper_dirty_blit_real() is trying to access the real > > framebuffer > > using a virtual address rather than use an IO access typically implemented > > using a > > physical (ASI_PHYS) access on SPARC. > > > > The fix is to replace the memcpy with memcpy_toio() from io.h. > > > > memcpy_toio() uses writeb() where the original fbdev code > > used sbus_memcpy_toio(). The latter uses sbus_writeb(). > > > > The difference between writeb() and sbus_memcpy_toio() is > > that writeb() writes bytes in little-endian, where sbus_writeb() writes > > bytes in big-endian. As endian does not matter for byte writes they are > > the same. So we can safely use memcpy_toio() here. > > > > For many architectures memcpy_toio() is a simple memcpy(). > > One side-effect that is unknown is if this has any impact on other > > architectures. > > So far the analysis tells that this change is OK for other arch's. > > but testing would be good. > > The rules are that officially we have to use the io functions for > __mmio pointers. We just drop these sparse annotations on the floor. > I'd replace this with something like: > > "Note that this only fixes bochs, in general fbdev helpers still have > issues with mixing up system memory and mmio space. Fixing that will > require a lot more work." OK, done. > > > v2: > > - Added missing __iomem cast (kernel test robot) > > - Made changelog readable and fix typos (Mark) > > - Add flag to select iomem - and set it in the bochs driver > > > > Signed-off-by: Sam Ravnborg > > Reported-by: Mark Cave-Ayland > > Reported-by: kernel test robot > > Tested-by: Mark Cave-Ayland > > Cc: Mark Cave-Ayland > > Cc: Thomas Zimmermann > > Cc: Gerd Hoffmann > > Cc: "David S. Miller" > > Cc: sparcli...@vger.kernel.org > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20200709193016.291267-1-...@ravnborg.org > > --- > > > > This fix introducing a flag in mode_config is at best a band-aid > > solution until we have a proper fix. > > We need to propagate the info about iomem so it is not a driver flag > > thing. > > > > There is also the issue with sys* versus cfb* functions, where cfb* > > functions are used for iomem. > > I did not manage to make the bochs driver work with the cfb* functions, > > for some unknown reason booting would be stuck waiting for the console > > mutex when usign the cfb* functions. > > > > I consider this fix OK to get the kernel working for sparc64 with the > > bochs driver for now. And with the fbdev_uses_iomem flag no other > > drivers will see any changes. > > > > Sam > > > > drivers/gpu/drm/bochs/bochs_kms.c | 1 + > > drivers/gpu/drm/drm_fb_helper.c | 6 +- > > include/drm/drm_mode_config.h | 9 + > > 3 files changed, 15 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/bochs/bochs_kms.c > > b/drivers/gpu/drm/bochs/bochs_kms.c > > index 05d8373888e8..079f46f5cdb6 100644 > > --- a/drivers/gpu/drm/bochs/bochs_kms.c > > +++ b/drivers/gpu/drm/bochs/bochs_kms.c > > @@ -146,6 +146,7 @@ int bochs_kms_init(struct bochs_device *bochs) > > bochs->dev->mode_config.preferred_depth = 24; > > bochs->dev->mode_config.prefer_shadow = 0; > > bochs->dev->mode_config.prefer_shadow_fbdev = 1; > > + bochs->dev->mode_config.fbdev_use_iomem = true; > > bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true; > > > > bochs->dev->mode_config.funcs = &bochs_mode_funcs; > > diff --git a/drivers/gpu/drm/drm_fb_helper.c > > b/drivers/gpu/drm/drm_fb_helper.c > > index 5609e164805f..89cfd68ef400 100644 > > --- a/drivers/gpu/drm/drm_fb_helper.c > > +++ b/drivers/gpu/drm/drm_fb_helper.c > > @@ -399,7 +399,11 @@ static void drm_fb_helper_dirty_blit_real(struct > > drm_fb_helper *fb_helper, > > unsigned int y; > > > > for (y = clip->y1; y < clip->y2; y++) { > > - memcpy(dst, src, len); > > + if (!fb_helper->dev->mode_config.fbdev_use_iomem) > > + memcpy(dst, src, len); > > + else > > + memcpy_toio((void __iomem *)dst, src, len); > > + > > src += fb->pitches[0]; > > dst += fb->pitches[0]; > > } > > diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h > > index 6c3ef49b46b3..c24c066bdd9c 100644 > >